LIBGDX Shader Program

De MediaWiki
Saltar a: navegación, buscar

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 -- (2015).