4.3. Técnicas de sombreado | Graficacion OpenGL C++ Ejemplos

 Las técnicas de sombreado en OpenGL permiten crear efectos de sombreado más complejos y realistas que los modelos básicos de iluminación. En OpenGL, se pueden utilizar dos técnicas de sombreado: sombreado por vértice y sombreado por fragmento.



El sombreado por vértice es una técnica de sombreado en la que se calcula el color de un vértice en función de la iluminación de los vértices adyacentes. En el sombreado por vértice, el cálculo del color se realiza una vez por vértice, lo que lo hace más eficiente que el sombreado por fragmento. Sin embargo, el sombreado por vértice puede producir efectos de sombreado más toscos y menos realistas que el sombreado por fragmento.


El sombreado por fragmento es una técnica de sombreado en la que se calcula el color de cada fragmento de píxel en función de la iluminación de la escena. En el sombreado por fragmento, el cálculo del color se realiza para cada fragmento de píxel, lo que lo hace más preciso y detallado que el sombreado por vértice. Sin embargo, el sombreado por fragmento puede ser más costoso en términos de recursos de procesamiento.



En OpenGL, se pueden implementar técnicas de sombreado por vértice y por fragmento utilizando el lenguaje de sombreado GLSL (OpenGL Shading Language). GLSL es un lenguaje de programación que permite definir sombreadores personalizados y ejecutarlos en la GPU para calcular la iluminación y los efectos de sombreado de los objetos tridimensionales.


A continuación, se muestra un ejemplo de cómo implementar el sombreado por fragmento en OpenGL utilizando GLSL:


```c++

// Cargar y compilar el sombreador de vértices

GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

glShaderSource(vertexShader, 1, &vertexShaderCode, NULL);

glCompileShader(vertexShader);


// Cargar y compilar el sombreador de fragmentos

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

glShaderSource(fragmentShader, 1, &fragmentShaderCode, NULL);

glCompileShader(fragmentShader);


// Vincular los sombreadores a un programa

GLuint shaderProgram = glCreateProgram();

glAttachShader(shaderProgram, vertexShader);

glAttachShader(shaderProgram, fragmentShader);

glLinkProgram(shaderProgram);

glUseProgram(shaderProgram);


// Especificar la posición del vértice y la normal

GLint posAttrib = glGetAttribLocation(shaderProgram, "position");

glEnableVertexAttribArray(posAttrib);

glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);


GLint normAttrib = glGetAttribLocation(shaderProgram, "normal");

glEnableVertexAttribArray(normAttrib);

glVertexAttribPointer(normAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));


// Especificar la fuente de luz y la posición de la cámara

GLint lightPosUniform = glGetUniformLocation(shaderProgram, "lightPos");

GLint viewPosUniform = glGetUniformLocation(shaderProgram, "viewPos");

glUniform3f(lightPosUniform, 0.0f, 0.0f, 1.0f);

glUniform3f(viewPosUniform, 0.0f, 0.0f, 1.0f);

// Especificar las propiedades del material

GLint matAmbientUniform = glGetUniformLocation(shaderProgram, "material.ambient");

GLint matDiffuseUniform = glGetUniformLocation(shaderProgram, "material.diffuse");

GLint matSpecularUniform = glGetUniformLocation(shaderProgram, "material.specular");

GLint matShineUniform = glGetUniformLocation(shaderProgram, "material.shininess");

glUniform3f(matAmbientUniform, 0.2f, 0.2f, 0.2f);

glUniform3f(matDiffuseUniform, 1.0f, 0.5f, 0.31f);

glUniform3f(matSpecularUniform, 1.0f, 0.5f, 0.31f);

glUniform1f(matShineUniform, 32.0f);


// Especificar la intensidad de la luz ambiental

GLint ambientStrengthUniform = glGetUniformLocation(shaderProgram, "ambientStrength");

glUniform1f(ambientStrengthUniform, 0.1f);


// Especificar el modelo de sombreado

GLint lightingModelUniform = glGetUniformLocation(shaderProgram, "lightingModel");

glUniform1i(lightingModelUniform, 1);


// Dibujar la malla de triángulos

glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);

```


En este ejemplo, se carga y compila un sombreador de vértices y un sombreador de fragmentos utilizando las funciones `glCreateShader()`, `glShaderSource()` y `glCompileShader()`. Luego, se vinculan los sombreadores a un programa utilizando la función `glCreateProgram()` y las funciones `glAttachShader()` y `glLinkProgram()`.


A continuación, se especifican la posición del vértice y la normal utilizando las funciones `glGetAttribLocation()`, `glEnableVertexAttribArray()` y `glVertexAttribPointer()`. Luego, se especifica la fuente de luz y la posición de la cámara utilizando las funciones `glGetUniformLocation()` y `glUniform3f()`.


Luego, se especifican las propiedades del material utilizando las funciones `glGetUniformLocation()` y `glUniform3f()` y `glUniform1f()`. Se especifica la intensidad de la luz ambiental utilizando la función `glUniform1f()`.


Finalmente, se dibuja la malla de triángulos utilizando la función `glDrawElements()`.


Es importante destacar que la implementación de sombreado en OpenGL utilizando GLSL puede requerir una mayor carga de procesamiento y una mayor complejidad en la programación. Sin embargo, puede ser una técnica muy efectiva para crear objetos tridimensionales con mayor realismo visual y efectos de sombreado más complejos.

Comentarios