Con el tiempo se han desarrollado muchas ténicas de renderizado gracias a los shaders que han permitido llegar al nivel de detalle que podemos ver en los juegos actuales.
En el caso de OpenGL, vamos a introducir 2 tipos de shaders inicialmente, los VertexShaders que se ejecutan por cada vértice que le introduzcamos al pipeline (este término se usa en muchos de los artículos que encontraréis por internet y se refiere al trabajo en cadena que acaba con el renderizado final) y, por otra parte, los FragmentShaders (PixelShaders en Directx) que se ejecutan por cada 'fragmento' que se renderice, estos fragmentos los podemos identificar por píxeles por ahora aunque no lo son al 100%.
Al igual que hicimos con las texturas, lo primero será cargar los shaders que vamos a usar que, en este caso serán 2:
-VertexShader:
string dsVertexShader = @"Tan solo realiza 2 acciones, asigna el color del vertice entrante al del vertice saliente y le asigna a la posición del vertice en pantalla la función fttransform() que lo que hace es multiplicar el vector de posición por las matrices de transformación necesarias, estas mtrices las explicaremos más adelante también para poder realizar operaciones más complejas en los shaders.
void main()
{
gl_FrontColor = gl_Color;
gl_Position = ftransform();
}"
-FragmentShader:
string dsFragmentShader = @"
void main()
{
gl_FragColor = gl_Color;
}"
Que simplemente le asigna al color de salida el color que le llega de entrada. Es decir, no se realiza ninguna operación con el color.
Ahora crearemos una función para crear un shader a partir de un string:
int LoadShader(string fsShader, ShaderType foType)Usando estas funciones:
{
int id = GL.CreateShader(foType);
GL.ShaderSource(id, fsShader);
GL.CompileShader(id);
return id;
}
int vertexShader = LoadShader(dsVertexShader, ShaderType.VertexShader);
int pixelShader = LoadShader(dsFragmentShader, ShaderType.FragmentShader);
Ahora, una vez cargados los shaders hay que crear un programa que los contenga:
int CreateProgram(int fiVertexShader, int fiFragmentShader)Usando esta función compilaremos los dos shaders en un programa:
{
int program = GL.CreateProgram();
GL.AttachShader(program, fiVertexShader);
GL.AttachShader(program, fiFragmentShader);
GL.LinkProgram(program);
GL.UseProgram(program);
string programInfoLog;
GL.GetProgramInfoLog(program, out programInfoLog);
//La variable programInfoLog contiene los errores producidos en el shader en caso de haberlos al compilar
return program;
}
int diProgram = CreateProgram(vertexShader, pixelShader);Si esto que acabamos de hacer lo incluimos en el OnLoad() de nuestra clase base, conseguiremos que se usen estos dos shaders para renderizar los dos triangulos del post anterior pero sin texturizar. Ahora, para jugar un poco podríamos modificar el FragmentShader por ejemplo así:
gl_FragColor = gl_Color*0.5;Esto oscurecerá un poco los colores de manera que observaremos que realmente es el FragmentShader el que está decidiendo los colores a renderizar.
Hemos transformado nuestro pequeño componente renderizador de la Fixed Function Pipeline a la Programable Pipeline lo que os ayudará a saber que esto solo significa que se están usando shaders para el renderizado, estos términos también los veréis aparecer en muchos de los artículos que circulan por internet.
Eso es todo por hoy, tendremos que seguir con el texturiado con shaders pero eso, será en otro post.
Estupendo socio, otra entrada en la que sigo los pasos y me compila todo estupendamente. La cosa es que aún no le encuentro mucha utiilidad a los Shaders, simplemente me cambia el contraste de la imagen si modifico el multiplicador del FragmentShader.
ResponderEliminarA ver si en el siguiente tuto le veo alguna utilidad práctica al utilizar los Shaders con las texturas.
Increible saga de tutos de OpenTK socio, ojalá nunca se acabe. Saludos! ^^
Hola. ojalá sigan los tutoriales, es el año 2016 y ando empezando en opengl y c#
ResponderEliminar