LIBGDX Figuras 3D Mesh
UNIDADE 4: Figuras 3D. Mesh
Sumario
Introducion
No espazo en tres dimensións (no que nos movemos) os obxectos están definidos por tres dimensións espaciais (eixes X, Y, Z). Ata o de agora estabamos a visualizar gráficos que estaban definidos nos eixes x-y de tal forma que non tiñan profundidade (eixe z).
A clase que nos permite definir os puntos que conforman as figuras no espazo tridimensional denomínase Mesh.
Pero todo non vai ser tan sinxelo como isto...
Shader Program
Resulta que a partires da versión OPEN GL 2.0 os gráficos renderízanse utilizando Shader´s. Os Shader son programas escritos en linguaxe parecida a C que se denomina GLSL e que permiten modificar as propiedades dos puntos que se van renderizar podendo facer efectos moi complexos.
O proceso de aplicar un Shader Program a unha figura se divide en dúas etapas:
- Vertex Shader: aplícanse operacións a cada un dos vértices da figura. Por exemplo, poderíamos modificar a posición e tamaño dun obxecto 3D.
- Fragment Shader: é a segunda etapa. A diferenza coa anterior é que se vai aplicar a cada fragmento da figura. Por simplificar imos identificar fragmento como pixel. Como podedes pensar o custe de GPU será maior que no caso anterior, por lo que non se debe abusar deste mecanismo. Por exemplo, poderíamos cambiar a cor de cada pixel da figura.
Un exemplo do que se pode facer cós Shader: https://www.youtube.com/watch?v=JkyGTZ0992s
Por que esta explicación...?
Porque cando no seguinte punto expliquemos como renderizar unha figura sinxela coma un triángulo, teremos que engadirlle un Shader Program. Loxicamente non tedes que aprender nada del, pero si é interesante que saibades porque aparece. É obrigatorio xa que estamos a utilizar OPEN GL ES 2.0.
O Shader Program que imos utilizar non vai facer ningunha modificación, só vai copiar a posición e a cor que traian cada un dos puntos da figura a debuxar.
Máis información en:
- Información dos ShaderProgram: https://github.com/libgdx/libgdx/wiki/Shaders#a-simple-shaderprogram
- Shader: http://www.opengl.org/wiki/Shader
Definindo unha figura en 3D. A clase Mesh
Preparación: Debedes crear un novo proxecto.
Crear unha clase de nome UD4_1_Triangulos3D, que derive da clase Game e sexa chamada pola clase principal das diferentes versións (desktop, android,...).
Posición
O primeiro que imos facer vai ser definir un triángulo cun obxecto da clase Mesh. O Mesh vainos permitir representar unha figura xeométrica en tres dimensións.
Código da clase UD4_1_Triangulos3D
Obxectivo: Definir un triángulo en 3D.
1 import com.badlogic.gdx.Game;
2 import com.badlogic.gdx.Gdx;
3 import com.badlogic.gdx.graphics.GL20;
4 import com.badlogic.gdx.graphics.Mesh;
5 import com.badlogic.gdx.graphics.VertexAttribute;
6 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
7
8 /**
9 * Traballos coa clase Mesh para definir un triángulo en 3D
10 * @author ANGEL
11 */
12
13 public class UD4_1_Triangulos3D extends Game {
14
15 private Mesh triangulo1; // Definimos un obxecto pertencente á clase Mesh
16 private ShaderProgram shaderProgram;
17
18 @Override
19 public void create() {
20 // TODO Auto-generated method stub
21
22
23 // Creamos o ShaderProgram ===> NON NECESARIO MIRALO
24 String vertexShader = "attribute vec4 a_position; \n"
25 + "varying vec4 v_color; \n"
26 + "void main() \n"
27 + "{ \n"
28 + " gl_Position = a_position; \n"
29 +"} \n";
30 String fragmentShader = "#ifdef GL_ES \n"
31 + "precision mediump float; \n"
32 + "#endif \n"
33 + "varying vec4 v_color;\n"
34 + "void main() \n"
35 + "{ \n"
36 + " gl_FragColor = vec4(0,0,0,1); \n"
37 + "} \n";
38
39 // Creamos o ShaderProgram en base ós programas definidos anteriormente
40 shaderProgram = new ShaderProgram(vertexShader, fragmentShader);
41 if (shaderProgram.isCompiled() == false) {
42 Gdx.app.log("ShaderError", shaderProgram.getLog());
43 System.exit(0);
44 }
45
46 triangulo1 = new Mesh(true, 3, 3, VertexAttribute.Position());
47 triangulo1.setVertices(new float[] { -0.5f, -0.5f, 0,
48 0.5f, -0.5f, 0,
49 0, 0.5f, 0 });
50 triangulo1.setIndices(new short[] { 0, 1, 2 });
51
52 }
Analicemos o constructur empregado na creación do obxecto Mesh:
triangulo1 = new Mesh(true, 3, 3, VertexAttribute.Position());
- 1º parámetro (true): indicámoslle se é de clase ou non. Este parámetro é usado internamente por motivos de 'eficiencia' e se aplica á función glBufferData de OpenGL e normalmente sempre poñeremos true excepto no caso de usar animacións no que o mesh varía en cada frame (http://stackoverflow.com/questions/5402567/whats-glbufferdata-for-inopengl-es).
- 2º parámetro: é o número de vértices que ten a figura (no noso caso 3, un triángulo).
- 3º parámetro: é o número de índices. Os índices van a indicar en que orden se deben unir as liñas entre os vértices. No noso caso son tres índices.
- 4º parámetro: indicamos que información imos a enviarlle o mesh (pode ser a posición, a cor, a textura,...). No noso caso pasámoslle a posición dos vértices que conforman o triángulo no espazo x,y,z.. Cada vértice terá tres números (as coordenadas x,y,z)
A continuación indicamos as coordenadas x,y,z do noso triángulo.
Nota: Cabe sinalar que a cámara, por defecto, se sitúa na posición (0,0,0) mirando cara a coordenada z negativa. É dicir, se a vosa cabeza é a cámara, os vosos ollos están a mirar agora mesmo cara ó monitor. Esa liña é o eixe Z que se vai afastando con valores Z negativos.
Definimos por tanto a posición dos vértices do triángulo:
triangulo1.setVertices(new float[] { -0.5f, -0.5f, 0,
0.5f, -0.5f, 0,
0, 0.5f, 0 });
Por defecto a cámara vai visualizar a seguinte área:
Polo tanto o triángulo estará nesta posición:
Nota: A coordenada Z sempre é 0 xa que estamos a debuxar un triángulo 'plano', non unha pirámide.
A forma en como a cámara interpreta o signo positivo ou negativo das coordenadas x,y,z é o que se coñece como regra da man dereita:
Cando definimos unha cámara, por defecto, mira cara ao z negativo (ven ser coma nos mirando cara o monitor, a nosa cabeza estaría situada na coordenada z=0 e o monitor nun z cun valor negativo). Por detrás da nosa cabeza o z aumenta. O X e Y serán igual ca sempre: X positivo cara a dereita e negativo cara á esquerda e Y positivo cara arriba e negativo cara abaixo.
Seguimos co exemplo do triángulo:
O seguinte é indicarlle a orde que ten que seguir polos vértices para debuxar a figura. Os vértices empezan a numerarse polo 0.
triangulo1.setIndices(new short[] { 0, 1, 2 });
No noso caso non importaría a orden xa que sempre debuxamos un triángulo:
Agora temos que sobreescribir o método render para debuxar o triangulo1. Para facelo imos utilizar a versión de OpenGL ES 2.0.
1 @Override
2 public void render() {
3
4 Gdx.gl20.glClearColor(1f, 1f, 1f, 1f);
5 Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
6 shaderProgram.begin();
7 triangulo1.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
8 shaderProgram.end();
9
10 }
Analicemos agora o código:
- Liña 4: Indicamos a cor que queremos que teñan por defecto cada un dos puntos que se envían á GPU no formato (RGBA). Xa visto neste enlace.
- Liña 5: Esta liña borra o buffer onde se garda a información de cada punto que se vai enviar á GPU.
- Liñas 6 e 8: Todo que se queira enviar á GPU aplicándolle o ShaderProgram definido terá que estar ente o begin - end.
- Liña 7: Indicamos que queremos renderizar o Mesh. Parámetros:
- shaderProgram: Aplica o Shader Program definido.
- GL20.GL_TRIANGLES: Imos utilizar triángulos (os cadrados se poden forman con dous
triángulos).
- Valor 0: O terceiro parámetro indica o desprazamento dentro do buffer de vértices. Normalmente poñeremos 0 (é o array onde están definidos os vértices).
- Valor 3: O carto parámetro indica o nº de índices ou vértices a utilizar.
Finalmente liberaremos a memoria.
1 @Override
2 public void dispose(){
3 shaderProgram.dispose();
4 triangulo1.dispose();
5 }
Código da clase UD4_1_Triangulos3D
Obxectivo: Visualizar unha figura 3D usando a clase Mesh.
1 package com.plategaxogo3d.exemplos;
2
3 import com.badlogic.gdx.Game;
4 import com.badlogic.gdx.Gdx;
5 import com.badlogic.gdx.graphics.GL20;
6 import com.badlogic.gdx.graphics.Mesh;
7 import com.badlogic.gdx.graphics.VertexAttribute;
8 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
9
10 /**
11 * Traballos coa clase Mesh para definir un triángulo en 3D
12 * @author ANGEL
13 */
14
15 public class UD4_1_Triangulos3D extends Game {
16
17 private Mesh triangulo1; // Definimos un obxecto pertencente á clase Mesh
18 private ShaderProgram shaderProgram;
19
20 @Override
21 public void create() {
22 // TODO Auto-generated method stub
23
24 // create shader program
25 String vertexShader = "attribute vec4 a_position; \n"
26 + "varying vec4 v_color; \n"
27 + "void main() \n"
28 + "{ \n"
29 + " gl_Position = a_position; \n"
30 +"} \n";
31 String fragmentShader = "#ifdef GL_ES \n"
32 + "precision mediump float; \n"
33 + "#endif \n"
34 + "varying vec4 v_color; \n"
35 + "void main() \n"
36 + "{ \n"
37 + " gl_FragColor = vec4(0,0,0,1); \n"
38 + "} \n";
39
40 // Creamos o ShaderProgram en base ós programas definidos anteriormente
41 shaderProgram = new ShaderProgram(vertexShader, fragmentShader);
42 if (shaderProgram.isCompiled() == false) {
43 Gdx.app.log("ShaderError", shaderProgram.getLog());
44 System.exit(0);
45 }
46
47 triangulo1 = new Mesh(true, 3, 3, VertexAttribute.Position());
48 triangulo1.setVertices(new float[] { -0.5f, -0.5f, 0,
49 0.5f, -0.5f, 0,
50 0, 0.5f, 0 });
51 triangulo1.setIndices(new short[] { 0, 1, 2 });
52
53 }
54
55 @Override
56 public void render() {
57
58 Gdx.gl20.glClearColor(1f, 1f, 1f, 1f);
59 Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
60 shaderProgram.begin();
61 triangulo1.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
62 shaderProgram.end();
63
64 }
65
66 @Override
67 public void dispose(){
68 shaderProgram.dispose();
69 triangulo1.dispose();
70 }
71
72 }
Cor
Agora imos modificar a clase Mesh para indicarlle que imos a enviar información acerca da cor que van ter cada un dos vértices da figura Mesh.
Para facelo imos ter que modificar o ShaderProgram para que lle pase a cada 'fragmento' a cor definida na clase Mesh.
Código da clase UD4_1_Triangulos3D
Obxectivo: Definir unha cor en cada vértice da figura 3D.
1 @Override
2 public void create() {
3 // TODO Auto-generated method stub
4
5 // create shader program
6 String vertexShader = "attribute vec4 a_position; \n"
7 + "attribute vec4 a_color; \n"
8 + "varying vec4 v_color; \n"
9 + "void main() \n"
10 + "{ \n"
11 + " gl_Position = a_position; \n"
12 + " v_color = a_color; \n"
13 +"} \n";
14 String fragmentShader = "#ifdef GL_ES \n"
15 + "precision mediump float; \n"
16 + "#endif \n"
17 + "varying vec4 v_color; \n"
18 + "void main() \n"
19 + "{ \n"
20 + " gl_FragColor = v_color; \n"
21 + "} \n";
22
23 // Creamos o ShaderProgram en base ós programas definidos anteriormente
24 shaderProgram = new ShaderProgram(vertexShader, fragmentShader);
25 if (shaderProgram.isCompiled() == false) {
26 Gdx.app.log("ShaderError", shaderProgram.getLog());
27 System.exit(0);
28 }
29
30 // CON COR
31 triangulo1 = new Mesh(false, 3, 3, VertexAttribute.Position(),
32 VertexAttribute.ColorUnpacked());
33 triangulo1.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0, 0, 1,
34 0.5f, -0.5f, 0, 1, 0, 0, 1,
35 0, 0.5f, 0, 1, 0, 0, 1});
36 triangulo1.setIndices(new short[] { 0, 1, 2 });
37
38 }
39 @Override
40 public void render() {
41
42 Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
43 Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
44 shaderProgram.begin();
45 triangulo1.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
46 shaderProgram.end();
47
48 }
Analicemos o código:
- Liña 7: Esta variable recibe a cor que ven do Mesh (definido en cada un dos vértices).
- Liña 8: Como o dato da cor temos que pasalo ao FragmentProgram utilizamos unha variable de tipo variant.
- Liñas 12 e 20: modificamos o Shader Program para que amose a cor definida no mesh.
- Liñas 31-32: indicamos que o mesh terá como atributos a posición e a cor. Cada cor está definida por catro número no formato RGBA cun float de valor 0 a 1.
- Liñas 33-35: indicamos a posición e cor de cada vértice do triángulo. Poñemos como cor a cor vermella (1,0,0,0).
- Liña 42: Modificamos a cor de fondo polo negro para que se vexa mellor.
Se executades o programa teremos como resultado o seguinte:
Nota: O parámetro alfa indica o nivel de transparencia que pode ir dende 0 (transparente) a 1 (opaco).
Cada cor está asociada a cada un dos vértices. Se poñemos valores diferentes en cada vértice fai un varrido de cor dende un valor a outro.
1 triangulo1.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0, 0, 1,
2 0.5f, -0.5f, 0, 0, 0, 1, 1,
3 0, 0.5f, 0, 0, 1, 0, 1});
Texturas
Información sobre o manexo de texturas:
- https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson1
- https://github.com/mattdesl/lwjgl-basics/wiki/LibGDX-Meshes-Lesson-1
- http://ogldev.atspace.co.uk/www/tutorial16/tutorial16.html
- https://github.com/mattdesl/lwjgl-basics/wiki
- https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/MeshShaderTest.java
Preparación: Deberemos copiar o arquivo seguinte ó cartafol assets do proxecto Android. Xa deberedes ter este gráfico se o proxecto está xerado coa ferramenta gdx-setup.jar
Unha textura é unha imaxe que imos 'pegar' sobre un gráfico. Xa traballamos coas texturas no xogo 2D.
Imaxinade que tedes unha parede e un cartel. O cartel é a textura e a parede a unha parte da figura en 3D (Mesh).
Normalmente as texturas teñen formas cadradas ou rectangulares. Xa veremos como 'adaptamos' esas formas ás formas dun modelo 3D...
Cando falamos de texturas, as unidades nas que se miden denomínanse U e V, que serían ó equivalente ás coordenadas X / Y. Ditas coordenadas U / V teñen uns valores que se moven entre 0 e 1, como amosamos na seguinte figura:
Se queremos que dita textura se debuxe sobre un triángulo, temos que indicar as coordenadas na que se ten que debuxar a parte da textura que queiramos:
No noso caso serían as coordenadas da textura (0,1) – (1,1) – (0.5f,0) que irán en cada vértice do triángulo.
Fixarse como parte da textura vaise perder xa que a textura ten unha forma cadrada. Xa veremos máis adiante como podemos formar un cadrado con dous triángulos e desa forma a textura vai cadrar cua figura do Mesh.
A nivel de código, teremos que facer as seguintes modificacións:
Modificamos o Shader Program:
1 String vertexShader = "attribute vec4 "+ ShaderProgram.POSITION_ATTRIBUTE +";\n"
2 + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE +"; \n"
3 + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n"
4 + "varying vec4 v_color; \n"
5 + "varying vec2 v_textCoord; \n"
6 + "void main() \n"
7 + "{ \n"
8 + " gl_Position = " + ShaderProgram.POSITION_ATTRIBUTE +";\n"
9 + " v_color = " + ShaderProgram.COLOR_ATTRIBUTE +";\n"
10 + " v_textCoord = " + ShaderProgram.TEXCOORD_ATTRIBUTE+ "0; \n"
11 +"} \n";
12 String fragmentShader = "#ifdef GL_ES \n"
13 + "precision mediump float; \n"
14 + "#endif \n"
15 + "varying vec4 v_color; \n"
16 + "varying vec2 v_textCoord; \n"
17 + "uniform sampler2D u_texture; \n"
18 + "void main() \n"
19 + "{ \n"
20 + " vec4 texColor = texture2D(u_texture, v_textCoord); \n"
21 + " gl_FragColor = texColor*v_color; \n"
22 + "} \n";
Non vos preocupedes se non entendedes esta parte, xa falaremos dos Shader´s no seguinte punto. Igual que no caso das cores, temos que recoller as coordenadas das texturas (que veremos a continuación) e pasalas ó fragmentShader. Dende aquí accederemos á textura a visualizar para que cada punto se debuxe con dita textura.
Agora modificamos a definición do Mesh para indicarlle que imos a enviarlle as coordenadas da textura:'
triangulo1 = new Mesh(false, 3, 3, VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));
E agora pasamos os datos do Mesh:
triangulo1.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0, 0, 1, 0, 1,
0.5f, -0.5f, 0, 0, 0, 1, 1, 1, 1,
0, 0.5f, 0, 0, 1, 0, 1, 0.5f,0});
Lembrar que os datos da textura son os dous últimos. Estamos a indicar onde debería ir cada vértice do triángulo na textura.
- VÉRTICE 1: X=> -0.5f,Y=>-0.5f,Z=>0,RED=>1,GREEN=>0,BLUE=>0,ALFA=>1,TEXTURA_U=>0,TEXTURA_V=>1
- VÉRTICE 2: X=> 0.5f,Y=>-0.5f,Z=>0,RED=>0,GREEN=>0,BLUE=>1,ALFA=>1,TEXTURA_U=>1,TEXTURA_V=>1
- VÉRTICE 3: X=> 0,Y=>0.5f,Z=>0,RED=>0,GREEN=>1,BLUE=>0,ALFA=>1,TEXTURA_U=>0.5f,TEXTURA_V=>0
Agora temos que cargar a textura. Isto xa o fixemos no xogo 2D. Poderíamos utilizar a clase AssetManager.
Para cargar a textura creamos unha propiedade Texture:
private Texture textura;
No método create cargamos a textura dende o arquivo e a asociamos ó obxecto:
FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");
textura = new Texture(imageFileHandle);
Agora temos que debuxar a textura. Para facelo temos que habilitar o uso de texturas e 'vincular' a textura ó Mesh:
1 @Override
2 public void render() {
3
4 Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
5 Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
6 Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
7 textura.bind(0);
8 shaderProgram.begin();
9 shaderProgram.setUniformi("u_texture", 0);
10 triangulo1.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
11 shaderProgram.end();
12
13 }
Imos analizar un pouco o código:
- Liña 6: habilitamos o uso de texturas.
- Liña 7: en OPEN GL temos un conxunto de textura a utilizar. O que fai o bind é asociar a textura que cargamos a unha das texturas dispoñibles en OPEN GL. Concretamente á número 0. A cero é a textura por defecto polo que cando chamamos ó método bind poderíamos non enviarlle ningún numero.
- Liña 9: isto xa o veremos cando expliquemos o uso de Shader´s. Con esta liña estamos a 'pasar' a textura 0 (que está cargada na liña 7) ó fragmentShader para que cada punto poida coller o punto da textura que lle corresponda.
O código completo:
Código da clase UD4_1_Triangulos3D
Obxectivo: Vincular unha textura a un Mesh.
1 package com.plategaxogo3d.exemplos;
2
3 import com.badlogic.gdx.Game;
4 import com.badlogic.gdx.Gdx;
5 import com.badlogic.gdx.files.FileHandle;
6 import com.badlogic.gdx.graphics.GL20;
7 import com.badlogic.gdx.graphics.Mesh;
8 import com.badlogic.gdx.graphics.Texture;
9 import com.badlogic.gdx.graphics.VertexAttribute;
10 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
11
12 /**
13 * Traballos coa clase Mesh para definir un triángulo en 3D
14 * @author ANGEL
15 */
16
17 public class UD4_1_Triangulos3D extends Game {
18
19 private Mesh triangulo1; // Definimos un obxecto pertencente á clase Mesh
20 private ShaderProgram shaderProgram;
21 private Texture textura;
22 private Texture prueba;
23
24 @Override
25 public void create() {
26 // TODO Auto-generated method stub
27
28 // create shader program
29 String vertexShader = "attribute vec4 "+ ShaderProgram.POSITION_ATTRIBUTE +";\n"
30 + "attribute vec4 " + ShaderProgram.COLOR_ATTRIBUTE +"; \n"
31 + "attribute vec2 " + ShaderProgram.TEXCOORD_ATTRIBUTE + "0;\n"
32 + "varying vec4 v_color; \n"
33 + "varying vec2 v_textCoord; \n"
34 + "void main() \n"
35 + "{ \n"
36 + " gl_Position = " + ShaderProgram.POSITION_ATTRIBUTE +";\n"
37 + " v_color = " + ShaderProgram.COLOR_ATTRIBUTE +";\n"
38 + " v_textCoord = " + ShaderProgram.TEXCOORD_ATTRIBUTE+ "0; \n"
39 +"} \n";
40 String fragmentShader = "#ifdef GL_ES \n"
41 + "precision mediump float; \n"
42 + "#endif \n"
43 + "varying vec4 v_color; \n"
44 + "varying vec2 v_textCoord; \n"
45 + "uniform sampler2D u_texture; \n"
46 + "void main() \n"
47 + "{ \n"
48 + " vec4 texColor = texture2D(u_texture, v_textCoord); \n"
49 + " gl_FragColor = texColor*v_color; \n"
50 + "} \n";
51
52 // Creamos o ShaderProgram en base ós programas definidos anteriormente
53 shaderProgram = new ShaderProgram(vertexShader, fragmentShader);
54 if (shaderProgram.isCompiled() == false) {
55 Gdx.app.log("ShaderError", shaderProgram.getLog());
56 System.exit(0);
57 }
58
59 // CON COR
60 triangulo1 = new Mesh(false, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));
61 triangulo1.setVertices(new float[] {-0.5f, -0.5f, 0, 1, 0, 0, 1, 0, 1,
62 0.5f, -0.5f, 0, 0, 0, 1, 1, 1, 1,
63 0, 0.5f, 0, 0, 1, 0, 1, 0.5f,0});
64 triangulo1.setIndices(new short[] { 0, 1, 2 });
65
66 FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");
67 textura = new Texture(imageFileHandle);
68
69 }
70
71 @Override
72 public void render() {
73
74 Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
75 Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
76 Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
77
78 textura.bind();
79 shaderProgram.begin();
80 shaderProgram.setUniformi("u_texture", 0);
81 triangulo1.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
82 shaderProgram.end();
83 }
84
85 @Override
86 public void dispose(){
87 shaderProgram.dispose();
88 triangulo1.dispose();
89 }
90
91 }
Ó executar o código dará como resultado o seguinte:
Fixarse como a cor se aplica sobre a textura para darlle diferentes tonalidades. Isto é así porque no fragmentShader temos a seguinte liña: gl_FragColor = texColor*v_color; Se queremos que a cor non modifique a textura teríamos que poñer: gl_FragColor = texColor;
TAREFA 4.1 A FACER: Esta parte está asociada á realización dunha tarefa. En caso de decidir facer o xogo proposto non será necesario facela.
-- Ángel D. Fernández González -- (2015).