GLSL Variables Uniform

Las variables de tipo uniform permiten la comunicación entre la CPU y la GPU, estas variables mantienen su valor durante la ejecución del shader, las variables son declaradas usando la palabra reservada uniform, el shader no puede cambiar el valor de estas variables, sin embargo si es posible asignarle un valor inicial.

En el tutorial anterior vimos como podíamos establecer un color diferente para cada vértice del triángulo que desplegamos en pantalla, esta vez veremos cómo podemos establecer un color sólido para la figura desde el código C/C++ de OpenGL, aprenderemos a usar las variables uniform.

const GLchar* fragment_shader_source =
{
    "out vec4 frag_color;                     \n"
    "                                         \n"
    "uniform vec4 solid_color = vec4(1.0);    \n"
    "                                         \n"
    "void main(void)                          \n"
    "{                                        \n"
    "   frag_color = solid_color;             \n"
    "}                                        \n"
};

solid_color es una variable tipo uniform, su valor inicial es vec4(1.0, 1.0, 1.0, 1.0), en lugar de pintar el triángulo con el color de cada vértice lo haremos con este color, ahora veamos cómo podemos cambiar este color desde código C/C++.

GLint solid_color_loc = glGetUniformLocation(program, "solid_color");
if (solid_color_loc != -1) {
     const GLfloat color[] = { 1.0, 1.0, 0.0, 1.0 };
     glUniform4fv(solid_color_loc, 1, color);
}

Para obtener la ubicación de la variable llamada solid_color usaremos la función glGetUniformLocation(), indicamos el shader program y el nombre de la variable que deseamos, esta función devuelve la ubicación, si no encuentra la variable retorna -1.

Una vez tenemos la ubicación usamos la función glUniform4fv() para establecer el nuevo valor de esta variable, indicamos la ubicación, la cantidad de datos, y finalmente indicamos el nuevo color.


Establecer Variables Uniform


Para cambiar el valor de una variable tipo uniform contamos con la función glUniform{1,2,3,4}{f,i,ui}( ) que tiene diversas variantes, el número indica la cantidad de componentes { 1, 2, 3, 4 } y la letra el tipo de datos { f, i, ui } para flotante, entero y entero sin signo.

uniform float fTime;
uniform int   iIndex;
uniform vec4  vColorValue;
uniform bool  bSomeFlag;

Obtener la ubicación de cada una de estas variables, si este fragmento de código fuese un shader válido:

GLint locTime, locIndex, locColor, locFlag;
locTime = glGetUniformLocation(myShader, "fTime");
locIndex = glGetUniformLocation(myShader, "iIndex");
locColor = glGetUniformLocation(myShader, "vColorValue");
locFlag = glGetUniformLocation(myShader, "bSomeFlag");
...
...
glUseProgram(myShader);
glUniform1f(locTime, 45.2f);
glUniform1i(locIndex, 42);
glUniform4f(locColor, 1.0f, 0.0f, 0.0f, 1.0f);
glUniform1i(locFlag, GL_FALSE);

Las variables booleanas las establecemos como valores enteros con valor de 0 para false y valor mayor que cero para true.

Establecer Arreglos Uniform


Usando la función glUniform{1,2,3,4}{f,i,ui}v( ), termina con la letra v a deferencia de la anterior, esta función nos permite indicar un puntero que contiene los datos a establecer, como primer parámetro indicamos la ubicación de la variable uniform, luego el parámetro que indica el tamaño del arreglo, al final pasamos el puntero al arreglo.

// GLSL Shader Code
uniform vec4 vColor;
uniform vec4 vColors[2];

// C/C++ OpenGL Code
GLfloat vColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
glUniform4fv(color_loc, 1, vColor);

GLfloat vColors[4][2] = { { 1.0f, 1.0f, 1.0f, 1.0f } ,
                          { 1.0f, 0.0f, 0.0f, 1.0f } };
glUniform4fv(colors_loc, 2, vColors);

Establecer Matrices Uniform


Establecemos matrices de un modo parecido a los arreglos, el nombre de la función lleva la palabra Matrix y el número indica el tamaño en columnas y filas de la matriz, ejemplo: glUniformMatrix2fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m) para una matriz 2x2, glUniformMatrix2x4fv() para una de 2x4.

Los parámetros tienen el mismo propósito que indicamos para los arreglos, salvo transpose que si lo establecemos a true convierte la matriz en su traspuesta.

glUniformMatrix2fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
glUniformMatrix3fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m);
glUniformMatrix4fv(GLint location, GLuint count, GLboolean transpose, const GLfloat *m);

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

tkinter Canvas

Histogramas OpenCV Python

Python Binance API