https://manuais.iessanclemente.net/index.php?title=LIBGDX_Shader_Program&feed=atom&action=historyLIBGDX Shader Program - Historial de revisiones2024-03-29T00:04:25ZHistorial de revisiones de esta página en el wikiMediaWiki 1.36.2https://manuais.iessanclemente.net/index.php?title=LIBGDX_Shader_Program&diff=48290&oldid=prevAngelfg: /* Traballando coa cámara */2014-09-23T21:26:50Z<p><span dir="auto"><span class="autocomment">Traballando coa cámara</span></span></p>
<p><b>Página nueva</b></p><div><span style="font-size:150%;">UNIDADE 2: Creando o mundo</span><br />
<br />
===Introdución===<br />
<br />
Información: https://github.com/mattdesl/lwjgl-basics/wiki/Shaders<br />
<br />
<br />
A partires da versión OPEN GL 2.0 os gráficos renderízanse utilizando Shader´s.<br />
Os [http://www.opengl.org/wiki/Shader 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.<br />
<br />
O proceso de aplicar un Shader Program a unha figura divídese en dúas etapas:<br />
<br />
* 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.<br />
* 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.<br />
<br />
===Onde gardar o Program Shader===<br />
<br />
O Shader Program pódese definir na propia clase ou ben nun arquivo externo.<br />
<br />
====Arquivo externo====<br />
<br />
* Temos que gardar o Vertex Shader nun arquivo con extensión .vert (non é obrigatorio).<br />
* Temos que gardar o Fragment Shader nun arquivo con extensión .frag (non é obrigatorio).<br />
<br />
Vexamos un exemplo sinxelo, no que simplemente asinamos a posición a cada vértice dun triángulo.<br />
<br />
<br />
'''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,...).<br />
<br />
Creamos dous arquivos que colocaremos no cartafol assets da versión Android e terán de nome:<br />
* vertex.vert<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
attribute vec4 a_position;<br />
void main() <br />
{<br />
gl_Position = a_position;<br />
}<br />
</syntaxhighlight> <br />
<br />
Comentarios do código:<br />
* 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).<br />
<br />
* 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. <br />
:Tamén poderíamos poñer: <br />
::<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
attribute vec3 a_position;<br />
void main() <br />
{<br />
gl_Position = vec4(a_position,1);<br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
<br />
* fragment.frag<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
#ifdef GL_ES <br />
precision mediump float;<br />
#endif <br />
void main() <br />
{<br />
}<br />
</syntaxhighlight> <br />
Agora mesmo non fai nada.<br />
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.<br />
<br />
====Definición interna====<br />
<br />
Tamén podemos definir o contido dos arquivos en forma de texto dentro do código da clase da seguinte forma:<br />
<br />
<br />
'''Código da clase UD4_4_ProgramShader'''<br/><br />
'''Obxectivo:''' Definimos os contidos do Program Shader internamente.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
@Override<br />
public void create() {<br />
// TODO Auto-generated method stub<br />
<br />
// create shader program<br />
String vertexShader = "attribute vec4 "+ ShaderProgram.POSITION_ATTRIBUTE +";\n"<br />
+ "void main() \n" <br />
+ "{ \n"<br />
+ " gl_Position = " + ShaderProgram.POSITION_ATTRIBUTE +";\n"<br />
+"} \n";<br />
String fragmentShader = "#ifdef GL_ES \n"<br />
+ "precision mediump float; \n" <br />
+ "#endif \n"<br />
+ "void main() \n" <br />
+ "{ \n"<br />
+ "} \n";<br />
} <br />
<br />
</syntaxhighlight> <br />
<br />
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.<br />
No exemplo anterior, poñer:<br />
:: "attribute vec4 "+ ShaderProgram.POSITION_ATTRIBUTE +";\n" <br />
é equivalente a poñer:<br />
:: "attribute vec4 a_position;\n"<br />
<br />
<br />
===Funcionamento do ShaderProgram===<br />
<br />
Unha vez decido onde vai ir o código analizaremos o funcionamento dos Shader´s.<br />
<br />
<u>Nota:</u> A partires de aquí usaremos a opción de gardar o arquivo de forma externa en dous arquivos.<br />
<br />
Como dixemos anteriormente o proceso de aplicar un shader consta de dous pasos. <br />
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.<br />
<br />
====Traballando coa posición====<br />
Inicialmente nos temos que pasarlle ó programa información como pode ser a posición de cada vértice. <br />
Para pasarlle información usaremos a liña:<br />
::'''attribute vec4 a_position;'''<br />
<br />
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).<br />
<br />
Cando definimos o Mesh da forma:<br />
<br />
::trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position());<br />
<br />
Estamos a dicir que imos enviar como datos a información da posición ó parámetro a_position definido no programa vertex.vert.<br />
<br />
O código completo:<br />
<br />
'''Código da clase UD4_4_ProgramShader'''<br/><br />
'''Obxectivo:''' Ver como funciona o Shader Program.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
import com.badlogic.gdx.Game;<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.Mesh;<br />
import com.badlogic.gdx.graphics.OrthographicCamera;<br />
import com.badlogic.gdx.graphics.VertexAttribute;<br />
import com.badlogic.gdx.graphics.glutils.ShaderProgram;<br />
<br />
/**<br />
* Funcionamento do ShaderProgram<br />
* @author ANGEL<br />
*/<br />
<br />
public class UD4_4_ProgramShader extends Game {<br />
<br />
private Mesh trianguloRed; <br />
private ShaderProgram shaderProgram;<br />
<br />
private OrthographicCamera camara2d;<br />
<br />
@Override<br />
public void create() {<br />
// TODO Auto-generated method stub<br />
<br />
shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));<br />
if (shaderProgram.isCompiled() == false) {<br />
Gdx.app.log("ShaderError", shaderProgram.getLog());<br />
System.exit(0);<br />
}<br />
<br />
trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position());<br />
trianguloRed.setVertices(new float[] {<br />
-0.5f, -0.5f, 0f,<br />
0.5f, -0.5f, 0f,<br />
0f, 0.5f, 0f, <br />
}); <br />
trianguloRed.setIndices(new short[] {0, 1, 2});<br />
<br />
<br />
}<br />
<br />
<br />
@Override<br />
public void render() {<br />
<br />
Gdx.gl20.glClearColor(1f, 1f, 1f, 1f);<br />
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);<br />
<br />
<br />
Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);<br />
<br />
shaderProgram.begin();<br />
<br />
trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);<br />
<br />
shaderProgram.end();<br />
<br />
Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);<br />
<br />
}<br />
<br />
@Override<br />
public void dispose(){<br />
shaderProgram.dispose();<br />
trianguloRed.dispose();<br />
<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight> <br />
<br />
<br />
<br />
<br />
<br />
<br />
Podemos consultar [http://en.wikibooks.org/wiki/GLSL_Programming/Vector_and_Matrix_Operations neste enlace] as operacións que podemos facer sobre os tipos de datos da linguaxe GLSL (coa que definimos o Program Shader).<br />
<br />
Por exemplo, podemos facer que o triángulo se estreita desta forma:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
attribute vec3 a_position;<br />
void main() <br />
{<br />
vec4 v = vec4(a_position,1);<br />
v.x = v.x/4;<br />
gl_Position = v; <br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
-----<br />
'''TAREFA 4.3 A FACER:''' Esta parte está asociada á realización dunha tarefa. <br />
-----<br />
<br />
====Traballando coa cor====<br />
<br />
O proceso para traballar coa cor é o mesmo que no caso da posición.<br />
<br />
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'''.<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
attribute vec4 a_color;<br />
</syntaxhighlight> <br />
<br />
<u>Nota:</u> Fixarxe como a cor é un vector4 xa que enviamos RGBA.<br />
<br />
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.<br />
<br />
Para pasalo temos que definir unha variable de tipo [http://zach.in.tu-clausthal.de/teaching/cg_literatur/glsl_tutorial/#varying 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.<br />
<br />
* Arquivo vertex.vert<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="2,3,7" ><br />
attribute vec3 a_position;<br />
attribute vec4 a_color;<br />
varying vec4 v_color;<br />
void main() <br />
{<br />
gl_Position = vec4(a_position,1);<br />
v_color = a_color;<br />
}<br />
</syntaxhighlight> <br />
<br />
Agora modificaremos o arquivo fragment.frag e recoller o dato e pasalo á variable '''gl_FragColor''', que é o que se vai pasar á GPU.<br />
<br />
* Arquivo fragment.frag<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="4,7" ><br />
#ifdef GL_ES <br />
precision mediump float;<br />
#endif <br />
varying vec4 v_color;<br />
void main() <br />
{<br />
gl_FragColor = v_color;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
Por último modificamos o Mesh para enviarlle os datos da cor:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="33-38" ><br />
package com.plategaxogo3d.exemplos;<br />
<br />
import com.badlogic.gdx.Game;<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.Mesh;<br />
import com.badlogic.gdx.graphics.OrthographicCamera;<br />
import com.badlogic.gdx.graphics.VertexAttribute;<br />
import com.badlogic.gdx.graphics.glutils.ShaderProgram;<br />
<br />
/**<br />
* Funcionamento do ShaderProgram<br />
* @author ANGEL<br />
*/<br />
<br />
public class UD4_4_ProgramShader extends Game {<br />
<br />
private Mesh trianguloRed; <br />
private ShaderProgram shaderProgram;<br />
<br />
private OrthographicCamera camara2d;<br />
<br />
@Override<br />
public void create() {<br />
// TODO Auto-generated method stub<br />
<br />
shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));<br />
if (shaderProgram.isCompiled() == false) {<br />
Gdx.app.log("ShaderError", shaderProgram.getLog());<br />
System.exit(0);<br />
}<br />
<br />
trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked());<br />
trianguloRed.setVertices(new float[] {<br />
-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f,<br />
0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f,<br />
0f, 0.5f, 0f, 1f, 0f, 0f, 1f<br />
}); <br />
trianguloRed.setIndices(new short[] {0, 1, 2});<br />
<br />
<br />
}<br />
<br />
<br />
@Override<br />
public void render() {<br />
<br />
Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);<br />
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);<br />
<br />
<br />
Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);<br />
<br />
shaderProgram.begin();<br />
<br />
trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);<br />
<br />
shaderProgram.end();<br />
<br />
Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);<br />
<br />
}<br />
<br />
@Override<br />
public void dispose(){<br />
shaderProgram.dispose();<br />
trianguloRed.dispose();<br />
<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
====Traballando coa textura====<br />
<br />
Xa vimos [http://manuais.iessanclemente.net/index.php?title=LIBGDX_Figuras_3D_Mesh#Texturas anteriormente] como asociar unha textura a un Mesh.<br />
<br />
Imos explicar un pouco en profundidade o proceso.<br />
<br />
'''Preparación:''' Deberemos copiar o arquivo seguinte ó cartafol assets do proxecto Android. Se o proxecto está xerado coa [http://manuais.iessanclemente.net/index.php?title=LIBGDX_Instalaci%C3%B3n_do_framework_LIBGDX#Xeraci.C3.B3n_dos_proxectos ferramenta de Libgdx] xa deberedes ter este gráfico.<br />
<br />
[[Imagen:Badlogic.jpg|300px|center]]<br />
<br />
O proceso é moi parecido a como fixemos coa cor, pero cunhas pequenas diferenzas.<br />
<br />
O código do Mesh será o seguinte:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));<br />
<br />
</syntaxhighlight><br />
<br />
Esta liña indica que imos enviar os datos da textura, cun identificador de 0 (TexCoords'''(0)''').<br />
<br />
Ese 0 vai pasarse como parámetro ó programa do vertex.vert, na variable a_texCoord'''X'''.<br />
Polo tanto, teremos que poñer algo como isto:<br />
<br />
* Programa vertex.vert<br />
<syntaxhighlight lang="java" line enclose="div" highlight="3,5,10" ><br />
attribute vec3 a_position;<br />
attribute vec4 a_color;<br />
attribute vec2 a_texCoord0;<br />
varying vec4 v_color;<br />
varying vec2 v_textCoord;<br />
void main() <br />
{<br />
gl_Position = vec4(a_position,1);<br />
v_color = a_color;<br />
v_textCoord = a_texCoord0;<br />
}<br />
</syntaxhighlight><br />
<br />
* Liña 3: Fixarse como as coordenadas da textura é un Vector2.<br />
* Liña 5: Definimos unha variable de tipo varying para pasarlle o valor ó programa Fragment (fragment.frag).<br />
* Liña 10: Gardamos o valor na variable v_textCoord.<br />
<br />
Ata aquí o código da clase UD4_4_ProgramShader é o seguinte:<br />
<br />
'''Código da clase UD4_4_ProgramShader'''<br/><br />
'''Obxectivo:''' Debuxar unha textura utilizando un ShaderProgram.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
public class UD4_4_ProgramShader extends Game {<br />
<br />
private Mesh trianguloRed; <br />
private ShaderProgram shaderProgram;<br />
<br />
private Texture textura;<br />
<br />
@Override<br />
public void create() {<br />
// TODO Auto-generated method stub<br />
<br />
shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));<br />
if (shaderProgram.isCompiled() == false) {<br />
Gdx.app.log("ShaderError", shaderProgram.getLog());<br />
System.exit(0);<br />
}<br />
<br />
trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));<br />
trianguloRed.setVertices(new float[] {<br />
-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 0f, 1f,<br />
0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 1f, 1f,<br />
0f, 0.5f, 0f, 1f, 0f, 0f, 1f, 0.5f,0f<br />
}); <br />
trianguloRed.setIndices(new short[] {0, 1, 2});<br />
<br />
FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");<br />
textura = new Texture(imageFileHandle);<br />
}<br />
...............<br />
}<br />
</syntaxhighlight> <br />
<br />
Imos analizar agora a parte render desta clase.<br />
<br />
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).<br />
<br />
O código sería este:<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
textura.bind(0); <br />
</syntaxhighlight> <br />
<br />
Agora temos que buscar a maneira de 'pasarlle' esta textura o programa Fragment, xa que é aquí onde asignamos a cor e a textura.<br />
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.<br />
<br />
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.<br />
<br />
A forma de pasarlle o índice é así:<br />
<syntaxhighlight lang="java" line enclose="div" highlight="2" ><br />
shaderProgram.begin();<br />
shaderProgram.setUniformi("u_texture", 0);<br />
trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);<br />
<br />
shaderProgram.end();<br />
</syntaxhighlight> <br />
<br />
* Liña 2: pasamos á variable u_texture ó valor 0 que se corresponde co índice empregado na textura con bind.<br />
<br />
Agora modificamos o programa vertex.vert para que recolla o índice e acceda á textura:<br />
<br />
* Programa fragment.frag<br />
<syntaxhighlight lang="java" line enclose="div" highlight="6,9" ><br />
#ifdef GL_ES <br />
precision mediump float;<br />
#endif <br />
varying vec4 v_color;<br />
varying vec2 v_textCoord;<br />
uniform sampler2D u_texture;<br />
void main() <br />
{<br />
vec4 texColor = texture2D(u_texture, v_textCoord);<br />
gl_FragColor = v_color*texColor;<br />
}<br />
</syntaxhighlight> <br />
<br />
* Liña 6: O índice é utilizado para acceder á textura correspondente (sampler2D é un tipo de dato co que accedemos á textura).<br />
* Liña 9: Accedemos a un punto da textura.<br />
* 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.<br />
<br />
<br />
O código completo da clase:<br />
<br />
'''Código da clase UD4_4_ProgramShader'''<br/><br />
'''Obxectivo:''' Mandar unha textura ó ShaderProgram<br />
<syntaxhighlight lang="java" line enclose="div" highlight="" ><br />
import com.badlogic.gdx.Game;<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.files.FileHandle;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.Mesh;<br />
import com.badlogic.gdx.graphics.Texture;<br />
import com.badlogic.gdx.graphics.VertexAttribute;<br />
import com.badlogic.gdx.graphics.glutils.ShaderProgram;<br />
<br />
/**<br />
* Funcionamento do ShaderProgram<br />
* @author ANGEL<br />
*/<br />
<br />
public class UD4_4_ProgramShader extends Game {<br />
<br />
private Mesh trianguloRed; <br />
private ShaderProgram shaderProgram;<br />
<br />
private Texture textura;<br />
<br />
@Override<br />
public void create() {<br />
// TODO Auto-generated method stub<br />
<br />
shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));<br />
if (shaderProgram.isCompiled() == false) {<br />
Gdx.app.log("ShaderError", shaderProgram.getLog());<br />
System.exit(0);<br />
}<br />
<br />
trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));<br />
trianguloRed.setVertices(new float[] {<br />
-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 0f, 1f,<br />
0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 1f, 1f,<br />
0f, 0.5f, 0f, 1f, 0f, 0f, 1f, 0.5f,0f<br />
}); <br />
trianguloRed.setIndices(new short[] {0, 1, 2});<br />
<br />
FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");<br />
textura = new Texture(imageFileHandle);<br />
}<br />
<br />
<br />
@Override<br />
public void render() {<br />
<br />
Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);<br />
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);<br />
<br />
<br />
Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);<br />
<br />
textura.bind(0); <br />
shaderProgram.begin();<br />
shaderProgram.setUniformi("u_texture", 0);<br />
trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);<br />
<br />
shaderProgram.end();<br />
<br />
Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);<br />
<br />
}<br />
<br />
@Override<br />
public void resize (int width,int height){<br />
// Definimos os parámetros da cámara<br />
<br />
}<br />
<br />
@Override<br />
public void dispose(){<br />
shaderProgram.dispose();<br />
trianguloRed.dispose();<br />
<br />
}<br />
<br />
}<br />
</syntaxhighlight> <br />
<br />
<br />
<br />
====Traballando coa cámara====<br />
<br />
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.<br />
<br />
Lembrar que [http://manuais.iessanclemente.net/index.php?title=LIBGDX_Camara3D#PerspectiveCamera 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.<br />
<br />
Polo tanto é necesario enviarlle as dúas matrices ó programa Vertex.vert, xa que é aquí onde posicionamos os puntos da nosa figura.<br />
<br />
Lembrar que a matriz de proxección e modelado se combinan para dar a matriz combinada a cal temos acceso a través de [http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/Camera.html#combined método combined] das cámaras.<br />
<br />
Como pasamos dita matriz ó programa Vertex.vert ?<br />
<br />
* Programa vertex.vert:<br />
<br />
<syntaxhighlight lang="java" line enclose="div" highlight="6,9" ><br />
attribute vec3 a_position;<br />
attribute vec4 a_color;<br />
attribute vec2 a_texCoord0;<br />
varying vec4 v_color;<br />
varying vec2 v_textCoord;<br />
uniform mat4 u_worldView;<br />
void main() <br />
{<br />
gl_Position = u_worldView *vec4(a_position,1);<br />
v_color = a_color;<br />
v_textCoord = a_texCoord0;<br />
}<br />
</syntaxhighlight> <br />
<br />
* Liña 6: definimos a matriz de 4x4 como de tipo uniform (vaise pasar como parámetro dende a clase).<br />
* Liña 9: multiplicamos a posición da figura Mesh pola matriz da cámara.<br />
<br />
<u><b>IMPORTANTE:</b></u> Hai que ter ven claro que as figuras en 3D se debuxan todas no punto (0,0,0).<br />
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.<br />
<br />
'''Código da clase UD4_4_ProgramShader'''<br/><br />
'''Obxectivo:''' Aplicar a matriz combinada dunha cámara ó Shader Program.<br />
<syntaxhighlight lang="java" line enclose="div" highlight="22,45,59,73-83" ><br />
import com.badlogic.gdx.Game;<br />
import com.badlogic.gdx.Gdx;<br />
import com.badlogic.gdx.files.FileHandle;<br />
import com.badlogic.gdx.graphics.GL20;<br />
import com.badlogic.gdx.graphics.Mesh;<br />
import com.badlogic.gdx.graphics.PerspectiveCamera;<br />
import com.badlogic.gdx.graphics.Texture;<br />
import com.badlogic.gdx.graphics.VertexAttribute;<br />
import com.badlogic.gdx.graphics.glutils.ShaderProgram;<br />
<br />
/**<br />
* Funcionamento do ShaderProgram<br />
* @author ANGEL<br />
*/<br />
<br />
public class UD4_4_ProgramShader extends Game {<br />
<br />
private Mesh trianguloRed; <br />
private ShaderProgram shaderProgram;<br />
<br />
private Texture textura;<br />
private PerspectiveCamera camara3d;<br />
<br />
@Override<br />
public void create() {<br />
// TODO Auto-generated method stub<br />
<br />
shaderProgram = new ShaderProgram(Gdx.files.internal("vertex.vert"), Gdx.files.internal("fragment.frag"));<br />
if (shaderProgram.isCompiled() == false) {<br />
Gdx.app.log("ShaderError", shaderProgram.getLog());<br />
System.exit(0);<br />
}<br />
<br />
trianguloRed = new Mesh(true, 3, 3, VertexAttribute.Position(), VertexAttribute.ColorUnpacked(),VertexAttribute.TexCoords(0));<br />
trianguloRed.setVertices(new float[] {<br />
-0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 0f, 1f,<br />
0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f, 1f, 1f,<br />
0f, 0.5f, 0f, 1f, 0f, 0f, 1f, 0.5f,0f<br />
}); <br />
trianguloRed.setIndices(new short[] {0, 1, 2});<br />
<br />
FileHandle imageFileHandle = Gdx.files.internal("badlogic.jpg");<br />
textura = new Texture(imageFileHandle);<br />
<br />
camara3d = new PerspectiveCamera();<br />
}<br />
<br />
<br />
@Override<br />
public void render() {<br />
<br />
Gdx.gl20.glClearColor(0f, 0f, 0f, 1f);<br />
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT|GL20.GL_DEPTH_BUFFER_BIT);<br />
<br />
<br />
Gdx.gl20.glEnable(GL20.GL_DEPTH_TEST);<br />
<br />
shaderProgram.begin();<br />
shaderProgram.setUniformMatrix("u_worldView", camara3d.combined);<br />
<br />
textura.bind(0); <br />
shaderProgram.setUniformi("u_texture", 0);<br />
<br />
trianguloRed.render(shaderProgram, GL20.GL_TRIANGLES,0,3);<br />
<br />
shaderProgram.end();<br />
<br />
Gdx.gl20.glDisable(GL20.GL_DEPTH_TEST);<br />
<br />
}<br />
<br />
@Override<br />
public void resize (int width,int height){<br />
// Definimos os parámetros da cámara<br />
float aspectRatio = (float) width / (float) height; <br />
camara3d.viewportWidth = 1f*aspectRatio;<br />
camara3d.viewportHeight = 1f;<br />
camara3d.far=1000f;<br />
camara3d.near=0.1f;<br />
camara3d.lookAt(0,0,0);<br />
camara3d.position.set(0f,0f,3f);<br />
camara3d.update();<br />
}<br />
<br />
@Override<br />
public void dispose(){<br />
shaderProgram.dispose();<br />
trianguloRed.dispose();<br />
<br />
}<br />
<br />
}<br />
<br />
</syntaxhighlight> <br />
<br />
* Liña 22: Definimos a cámara.<br />
* Liña 45: Instanciamos o obxecto.<br />
* Liñas 73-83: Actualizamos os valores da cámara. Importante chamar ó método update.<br />
* Liña 82: Mandamos a matriz ó programa vertex.vert.<br />
<br />
<br />
<br />
-----<br />
'''TAREFA 4.4 A FACER:''' Esta parte está asociada á realización dunha tarefa. <br />
-----<br />
<br />
<br />
<br />
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] -- (2014).</div>Angelfg