LIBGDX Shader Program

De Manuais Informática - IES San Clemente.
Ir a la navegación Ir a la búsqueda

UNIDADE 2: Creando o mundo

Introdución

Información: https://github.com/mattdesl/lwjgl-basics/wiki/Shaders


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 divídese 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.

Onde gardar o Program Shader

O Shader Program pódese definir na propia clase ou ben nun arquivo externo.

Arquivo externo

  • Temos que gardar o Vertex Shader nun arquivo con extensión .vert (non é obrigatorio).
  • Temos que gardar o Fragment Shader nun arquivo con extensión .frag (non é obrigatorio).

Vexamos un exemplo sinxelo, no que simplemente asinamos a posición a cada vértice dun triángulo.


Preparación: Crear unha clase de nome UD4_4_ProgramShader, que derive da clase Game e sexa chamada pola clase principal das diferentes versións (desktop, android,...).

Creamos dous arquivos que colocaremos no cartafol assets da versión Android e terán de nome:

  • vertex.vert
1 attribute vec4 a_position;
2 void main() 
3 {
4   gl_Position = a_position;
5 }

Comentarios do código:

  • Liña 4: nesta liña copiamos a posición de cada vértice a un Vec4 interno de ShaderProgram, que será o dato que envía á GPU (Graphics Procesor Unit).
  • Liña 1: definimos unha variable de tipo vec4(vector de 4 dimensións). Esta variable é un parámetro onde van chegar cada unha das posicións dos vértices definidos no Mesh. E vos estaredes preguntando, pero as posicións son Vector3(x,y,z) como pode ser que o almacene un Vector4 ? Pois debido a que internamente traballa con matrices de 4x4. O que fai é encher o último número cun 1.
Tamén poderíamos poñer:
1 attribute vec3 a_position;
2 void main() 
3 {
4   gl_Position = vec4(a_position,1);
5 }


  • fragment.frag
1 #ifdef GL_ES 
2   precision mediump float;
3 #endif  
4 void main() 
5 {
6 }

Agora mesmo non fai nada. As liñas 1 a 3 define a precisión dos vectores. Sempre se debe de poñer as liñas anteriores xa que esa é a precisión adecuada para traballar con texturas e posicións.

Definición interna

Tamén podemos definir o contido dos arquivos en forma de texto dentro do código da clase da seguinte forma:


Código da clase UD4_4_ProgramShader
Obxectivo: Definimos os contidos do Program Shader internamente.

 1 	@Override
 2 	public void create() {
 3 		// TODO Auto-generated method stub
 4 
 5 		// create shader program
 6 		String vertexShader = "attribute vec4 "+ ShaderProgram.POSITION_ATTRIBUTE +";\n"
 7 				+ "void main()					\n" 
 8 				+ "{							\n"
 9 				+ "	gl_Position = " + ShaderProgram.POSITION_ATTRIBUTE +";\n"
10 				+"}								\n";
11 		String fragmentShader = "#ifdef GL_ES 	\n"
12 				+ "precision mediump float;		\n" 
13 				+ "#endif						\n"
14 				+ "void main()					\n" 
15 				+ "{							\n"
16 				+ "}							\n";
17            }

Comentar no código que podemos facer uso das constantes da clase ShaderProgram para acceder ó nome dos atributos que van recoller os datos enviados polo Mesh de posición, cor e textura. No exemplo anterior, poñer:

"attribute vec4 "+ ShaderProgram.POSITION_ATTRIBUTE +";\n"

é equivalente a poñer:

"attribute vec4 a_position;\n"


Funcionamento do ShaderProgram

Unha vez decido onde vai ir o código analizaremos o funcionamento dos Shader´s.

Nota: A partires de aquí usaremos a opción de gardar o arquivo de forma externa en dous arquivos.

Como dixemos anteriormente o proceso de aplicar un shader consta de dous pasos. Nun primeiro paso se aplican transformacións ós vértices da figura e nun segundo paso se aplican transformacións a fragmentos (pixeles) da figura.

Traballando coa posición

Inicialmente nos temos que pasarlle ó programa información como pode ser a posición de cada vértice. Para pasarlle información usaremos a liña:

attribute vec4 a_position;

Coa palabra clave atribute estamos a definir un parámetro. Este parámetro (o da posición) ten un nome xa predefinido e un tipo (Vector4).

Cando definimos o Mesh da forma:

trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position());

Estamos a dicir que imos enviar como datos a información da posición ó parámetro a_position definido no programa vertex.vert.

O código completo:

Código da clase UD4_4_ProgramShader
Obxectivo: Ver como funciona o Shader Program.

 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.OrthographicCamera;
 6 import com.badlogic.gdx.graphics.VertexAttribute;
 7 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
 8 
 9 /**
10  *  Funcionamento do ShaderProgram
11  * @author ANGEL
12  */
13 
14 public class UD4_4_ProgramShader extends Game {
15 
16 	private Mesh trianguloRed; 
17 	private ShaderProgram shaderProgram;
18 
19 	private OrthographicCamera camara2d;
20 	
21 	@Override
22 	public void create() {
23 		// TODO Auto-generated method stub
24 
25 		shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));
26 		if (shaderProgram.isCompiled() == false) {
27 			Gdx.app.log("ShaderError", shaderProgram.getLog());
28 			System.exit(0);
29 		}
30 	
31 		trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position());
32 		trianguloRed.setVertices(new float[] {
33 				-0.5f, -0.5f, 0f,
34 				0.5f, -0.5f, 0f,
35 				0f, 0.5f, 0f, 
36 				});					
37 		trianguloRed.setIndices(new short[] {0, 1, 2});
38 	
39 		
40 	}
41 	
42 	
43 	@Override
44 	public void render() {
45 
46 		Gdx.gl20.glClearColor(1f, 1f, 1f, 1f);
47 		Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);
48 
49 
50 		Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
51 		
52 		shaderProgram.begin();
53 		
54 		trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
55 
56 		shaderProgram.end();
57 		
58 		Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);
59 
60 	}
61 	
62 	@Override
63 	public void dispose(){
64 		shaderProgram.dispose();
65 		trianguloRed.dispose();
66 
67 	}
68 
69 }




Podemos consultar neste enlace as operacións que podemos facer sobre os tipos de datos da linguaxe GLSL (coa que definimos o Program Shader).

Por exemplo, podemos facer que o triángulo se estreita desta forma:

1 attribute vec3 a_position;
2 void main() 
3 {
4   vec4 v = vec4(a_position,1);
5   v.x = v.x/4;
6   gl_Position = v; 
7 }



TAREFA 4.3 A FACER: Esta parte está asociada á realización dunha tarefa.


Traballando coa cor

O proceso para traballar coa cor é o mesmo que no caso da posición.

A nome do parámetro a definir no arquivo vertex.vert é a_color ou se estamos a definir o Program Shader internamente poderíamos utilizar a constante: ShaderProgram.COLOR_ATTRIBUTE.

1 attribute vec4 a_color;

Nota: Fixarxe como a cor é un vector4 xa que enviamos RGBA.

O parámetro temos que definilo no vertex.vert pero o valor da cor non se vai utilizar neste arquivo se non que ten que pasarse ó Fragment Shader.

Para pasalo temos que definir unha variable de tipo varying. O que facemos é pasarlle o valor (a cor) ó parámetro a_color, despois gardaremos dito valor na variable de tipo varying v_color e dende o Fragment Program (o arquivo fragment.frag) podemos acceder a dito valor.

  • Arquivo vertex.vert
1 attribute vec3 a_position;
2 attribute vec4 a_color;
3 varying vec4 v_color;
4 void main() 
5 {
6   gl_Position =  vec4(a_position,1);
7   v_color = a_color;
8 }

Agora modificaremos o arquivo fragment.frag e recoller o dato e pasalo á variable gl_FragColor, que é o que se vai pasar á GPU.

  • Arquivo fragment.frag
1 #ifdef GL_ES 
2   precision mediump float;
3 #endif  
4 varying vec4 v_color;
5 void main() 
6 {
7   gl_FragColor = v_color;
8 }


Por último modificamos o Mesh para enviarlle os datos da cor:

 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.OrthographicCamera;
 8 import com.badlogic.gdx.graphics.VertexAttribute;
 9 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
10 
11 /**
12  * Funcionamento do ShaderProgram
13  * @author ANGEL
14  */
15 
16 public class UD4_4_ProgramShader extends Game {
17 
18 	private Mesh trianguloRed; 
19 	private ShaderProgram shaderProgram;
20 
21 	private OrthographicCamera camara2d;
22 	
23 	@Override
24 	public void create() {
25 		// TODO Auto-generated method stub
26 
27 		shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));
28 		if (shaderProgram.isCompiled() == false) {
29 			Gdx.app.log("ShaderError", shaderProgram.getLog());
30 			System.exit(0);
31 		}
32 	
33 		trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked());
34 		trianguloRed.setVertices(new float[] {
35 				-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f,
36 				0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f,
37 				0f, 0.5f, 0f, 1f, 0f, 0f, 1f
38 				});					
39 		trianguloRed.setIndices(new short[] {0, 1, 2});
40 	
41 		
42 	}
43 	
44 	
45 	@Override
46 	public void render() {
47 
48 		Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
49 		Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);
50 
51 
52 		Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
53 		
54 		shaderProgram.begin();
55 		
56 		trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
57 
58 		shaderProgram.end();
59 		
60 		Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);
61 
62 	}
63 	
64 	@Override
65 	public void dispose(){
66 		shaderProgram.dispose();
67 		trianguloRed.dispose();
68 
69 	}
70 
71 }

Traballando coa textura

Xa vimos anteriormente como asociar unha textura a un Mesh.

Imos explicar un pouco en profundidade o proceso.

Preparación: Deberemos copiar o arquivo seguinte ó cartafol assets do proxecto Android. Se o proxecto está xerado coa ferramenta de Libgdx xa deberedes ter este gráfico.

Badlogic.jpg

O proceso é moi parecido a como fixemos coa cor, pero cunhas pequenas diferenzas.

O código do Mesh será o seguinte:

1 trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));

Esta liña indica que imos enviar os datos da textura, cun identificador de 0 (TexCoords(0)).

Ese 0 vai pasarse como parámetro ó programa do vertex.vert, na variable a_texCoordX. Polo tanto, teremos que poñer algo como isto:

  • Programa vertex.vert
 1 attribute vec3 a_position;
 2 attribute vec4 a_color;
 3 attribute vec2 a_texCoord0;
 4 varying vec4 v_color;
 5 varying vec2 v_textCoord;
 6 void main() 
 7 {
 8   gl_Position =  vec4(a_position,1);
 9   v_color = a_color;
10   v_textCoord = a_texCoord0;
11 }
  • Liña 3: Fixarse como as coordenadas da textura é un Vector2.
  • Liña 5: Definimos unha variable de tipo varying para pasarlle o valor ó programa Fragment (fragment.frag).
  • Liña 10: Gardamos o valor na variable v_textCoord.

Ata aquí o código da clase UD4_4_ProgramShader é o seguinte:

Código da clase UD4_4_ProgramShader
Obxectivo: Debuxar unha textura utilizando un ShaderProgram.

 1 public class UD4_4_ProgramShader extends Game {
 2 
 3 	private Mesh trianguloRed; 
 4 	private ShaderProgram shaderProgram;
 5 
 6 	private Texture textura;
 7 	
 8 	@Override
 9 	public void create() {
10 		// TODO Auto-generated method stub
11 
12 		shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));
13 		if (shaderProgram.isCompiled() == false) {
14 			Gdx.app.log("ShaderError", shaderProgram.getLog());
15 			System.exit(0);
16 		}
17 	
18 		trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));
19 		trianguloRed.setVertices(new float[] {
20 				-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 0f, 1f,
21 				0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 1f, 1f,
22 				0f, 0.5f, 0f, 1f, 0f, 0f, 1f, 0.5f,0f
23 				});					
24 		trianguloRed.setIndices(new short[] {0, 1, 2});
25 	
26 		FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");
27 		textura = new Texture(imageFileHandle);
28 	}
29         ...............
30 }

Imos analizar agora a parte render desta clase.

Para asociar unha textura a un obxecto temos que chamar ó método bind da textura. Ó facelo, indicamos un número que vai indicar á qué número de textura de OPEN GL vai asociarse. Por defecto é 0 (se non podemos nada).

O código sería este:

1 	textura.bind(0);

Agora temos que buscar a maneira de 'pasarlle' esta textura o programa Fragment, xa que é aquí onde asignamos a cor e a textura. A idea é que colla punto a punto (en texturas falamos de fragmentos) da textura e a debuxe no sitio que lle corresponda de acordo á posición indicada na figura.

Como facendo o bind xa estamos a cargar a textura en OPEN GL ES, imos a enviarlle o programa o índice utilizado, para que dende o programa Fragment accede a dita textura.

A forma de pasarlle o índice é así:

1 		shaderProgram.begin();
2 		shaderProgram.setUniformi("u_texture", 0);
3 		trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
4 
5 		shaderProgram.end();
  • Liña 2: pasamos á variable u_texture ó valor 0 que se corresponde co índice empregado na textura con bind.

Agora modificamos o programa vertex.vert para que recolla o índice e acceda á textura:

  • Programa fragment.frag
 1 #ifdef GL_ES 
 2   precision mediump float;
 3 #endif  
 4 varying vec4 v_color;
 5 varying vec2 v_textCoord;
 6 uniform sampler2D u_texture;
 7 void main() 
 8 {
 9   vec4 texColor = texture2D(u_texture, v_textCoord);
10   gl_FragColor = v_color*texColor;
11 }
  • Liña 6: O índice é utilizado para acceder á textura correspondente (sampler2D é un tipo de dato co que accedemos á textura).
  • Liña 9: Accedemos a un punto da textura.
  • Liña 10: Mandamos a textura a debuxar. Multiplicamos pola cor para tintar a textura. Se non queremos que a cor teña efecto sobre a textura podemos quitar v_color da multiplicación.


O código completo da clase:

Código da clase UD4_4_ProgramShader
Obxectivo: Mandar unha textura ó ShaderProgram

 1 import com.badlogic.gdx.Game;
 2 import com.badlogic.gdx.Gdx;
 3 import com.badlogic.gdx.files.FileHandle;
 4 import com.badlogic.gdx.graphics.GL20;
 5 import com.badlogic.gdx.graphics.Mesh;
 6 import com.badlogic.gdx.graphics.Texture;
 7 import com.badlogic.gdx.graphics.VertexAttribute;
 8 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
 9 
10 /**
11  * Funcionamento do ShaderProgram
12  * @author ANGEL
13  */
14 
15 public class UD4_4_ProgramShader extends Game {
16 
17 	private Mesh trianguloRed; 
18 	private ShaderProgram shaderProgram;
19 
20 	private Texture textura;
21 	
22 	@Override
23 	public void create() {
24 		// TODO Auto-generated method stub
25 
26 		shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));
27 		if (shaderProgram.isCompiled() == false) {
28 			Gdx.app.log("ShaderError", shaderProgram.getLog());
29 			System.exit(0);
30 		}
31 	
32 		trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));
33 		trianguloRed.setVertices(new float[] {
34 				-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 0f, 1f,
35 				0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 1f, 1f,
36 				0f, 0.5f, 0f, 1f, 0f, 0f, 1f, 0.5f,0f
37 				});					
38 		trianguloRed.setIndices(new short[] {0, 1, 2});
39 	
40 		FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");
41 		textura = new Texture(imageFileHandle);
42 	}
43 	
44 	
45 	@Override
46 	public void render() {
47 
48 		Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
49 		Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);
50 
51 
52 		Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
53 		
54 		textura.bind(0);		
55 		shaderProgram.begin();
56 		shaderProgram.setUniformi("u_texture", 0);
57 		trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
58 
59 		shaderProgram.end();
60 		
61 		Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);
62 
63 	}
64 	
65 	@Override
66 	public void resize (int width,int height){
67 		// Definimos os parámetros da cámara
68 		
69 	}
70 	
71 	@Override
72 	public void dispose(){
73 		shaderProgram.dispose();
74 		trianguloRed.dispose();
75 
76 	}
77 
78 }


Traballando coa cámara

Como último paso temos que pasarlle a matriz da cámara para que axuste cada punto da figura e os visualice no lugar correcto en función da cámara.

Lembrar que cando vimos as cámaras comentamos que para posicionar correctamente os puntos, usamos as matrices de proxección e modelado. Unha matriz servía para definir os planos far, near e viewportwidth / viewportheight (a matriz de proxección) e a outra matriz (modelado) servía para mover a cámara, rotala,...non é que servira para iso, quero dicir que cando movemos a cámara para unha posición, todos as figuras da nosa escena se teñen que debuxar de acordo á posición da cámara.

Polo tanto é necesario enviarlle as dúas matrices ó programa Vertex.vert, xa que é aquí onde posicionamos os puntos da nosa figura.

Lembrar que a matriz de proxección e modelado se combinan para dar a matriz combinada a cal temos acceso a través de método combined das cámaras.

Como pasamos dita matriz ó programa Vertex.vert ?

  • Programa vertex.vert:
 1 attribute vec3 a_position;
 2 attribute vec4 a_color;
 3 attribute vec2 a_texCoord0;
 4 varying vec4 v_color;
 5 varying vec2 v_textCoord;
 6 uniform mat4 u_worldView;
 7 void main() 
 8 {
 9   gl_Position =  u_worldView *vec4(a_position,1);
10   v_color = a_color;
11   v_textCoord = a_texCoord0;
12 }
  • Liña 6: definimos a matriz de 4x4 como de tipo uniform (vaise pasar como parámetro dende a clase).
  • Liña 9: multiplicamos a posición da figura Mesh pola matriz da cámara.

IMPORTANTE: Hai que ter ven claro que as figuras en 3D se debuxan todas no punto (0,0,0). A partires dese punto se moven de acordo a súa posición (o veremos no seguinte punto) e unha vez movidas se aplica a cámara para sacar unha 'foto' do que se ve. Lembrar que todos son operacións matemáticas feitas con matrices.

Código da clase UD4_4_ProgramShader
Obxectivo: Aplicar a matriz combinada dunha cámara ó Shader Program.

 1 import com.badlogic.gdx.Game;
 2 import com.badlogic.gdx.Gdx;
 3 import com.badlogic.gdx.files.FileHandle;
 4 import com.badlogic.gdx.graphics.GL20;
 5 import com.badlogic.gdx.graphics.Mesh;
 6 import com.badlogic.gdx.graphics.PerspectiveCamera;
 7 import com.badlogic.gdx.graphics.Texture;
 8 import com.badlogic.gdx.graphics.VertexAttribute;
 9 import com.badlogic.gdx.graphics.glutils.ShaderProgram;
10 
11 /**
12  * Funcionamento do ShaderProgram
13  * @author ANGEL
14  */
15 
16 public class UD4_4_ProgramShader extends Game {
17 
18 	private Mesh trianguloRed; 
19 	private ShaderProgram shaderProgram;
20 
21 	private Texture textura;
22 	private PerspectiveCamera camara3d;
23 	
24 	@Override
25 	public void create() {
26 		// TODO Auto-generated method stub
27 
28 		shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));
29 		if (shaderProgram.isCompiled() == false) {
30 			Gdx.app.log("ShaderError", shaderProgram.getLog());
31 			System.exit(0);
32 		}
33 	
34 		trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));
35 		trianguloRed.setVertices(new float[] {
36 				-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 0f, 1f,
37 				0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 1f, 1f,
38 				0f, 0.5f, 0f, 1f, 0f, 0f, 1f, 0.5f,0f
39 				});					
40 		trianguloRed.setIndices(new short[] {0, 1, 2});
41 	
42 		FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");
43 		textura = new Texture(imageFileHandle);
44 		
45 		camara3d = new PerspectiveCamera();
46 	}
47 	
48 	
49 	@Override
50 	public void render() {
51 
52 		Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);
53 		Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);
54 
55 
56 		Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);
57 		
58 		shaderProgram.begin();
59 		shaderProgram.setUniformMatrix("u_worldView", camara3d.combined);
60 		
61 		textura.bind(0);		
62 		shaderProgram.setUniformi("u_texture", 0);
63 		
64 		trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);
65 
66 		shaderProgram.end();
67 		
68 		Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);
69 
70 	}
71 	
72 	@Override
73 	public void resize (int width,int height){
74 		// Definimos os parámetros da cámara
75 		float aspectRatio = (float) width / (float) height; 
76 		camara3d.viewportWidth = 1f*aspectRatio;
77 		camara3d.viewportHeight = 1f;
78 		camara3d.far=1000f;
79 		camara3d.near=0.1f;
80 		camara3d.lookAt(0,0,0);
81 		camara3d.position.set(0f,0f,3f);
82 		camara3d.update();
83 	}
84 	
85 	@Override
86 	public void dispose(){
87 		shaderProgram.dispose();
88 		trianguloRed.dispose();
89 
90 	}
91 
92 }
  • Liña 22: Definimos a cámara.
  • Liña 45: Instanciamos o obxecto.
  • Liñas 73-83: Actualizamos os valores da cámara. Importante chamar ó método update.
  • Liña 82: Mandamos a matriz ó programa vertex.vert.



TAREFA 4.4 A FACER: Esta parte está asociada á realización dunha tarefa.




-- Ángel D. Fernández González -- (2014).