El mapeo de entorno es una técnica avanzada de renderizado que se utiliza para simular reflejos en superficies. Esta técnica es especialmente útil para crear efectos realistas en objetos metálicos, vidrios y superficies reflectantes en general. En este tema, aprenderemos los conceptos básicos del mapeo de entorno, cómo implementarlo en OpenGL y algunos ejercicios prácticos para reforzar el aprendizaje.

Conceptos Clave

  1. Mapeo de Entorno: Técnica que utiliza una textura especial (mapa de entorno) para simular reflejos en una superficie.
  2. Mapas de Cubo (Cube Maps): Texturas que representan el entorno en seis direcciones (arriba, abajo, izquierda, derecha, adelante, atrás).
  3. Reflejos: Efecto visual que simula la reflexión de un entorno en una superficie.

Configuración Inicial

Antes de comenzar con el mapeo de entorno, asegúrate de tener configurado tu entorno de desarrollo con OpenGL y de tener una comprensión básica de texturas y sombreado.

Paso 1: Crear un Mapa de Cubo

Un mapa de cubo es una textura que contiene seis imágenes, cada una representando una cara de un cubo. Estas imágenes se utilizan para simular el entorno alrededor de un objeto.

GLuint cubemapTexture;
glGenTextures(1, &cubemapTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);

int width, height, nrChannels;
unsigned char *data;
std::vector<std::string> faces = {
    "right.jpg",
    "left.jpg",
    "top.jpg",
    "bottom.jpg",
    "front.jpg",
    "back.jpg"
};

for (unsigned int i = 0; i < faces.size(); i++) {
    data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
    if (data) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        stbi_image_free(data);
    } else {
        std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
        stbi_image_free(data);
    }
}

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

Paso 2: Crear un Shader para el Mapeo de Entorno

Necesitamos un shader que utilice el mapa de cubo para calcular los reflejos en la superficie del objeto.

Vertex Shader:

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;

out vec3 WorldPos;
out vec3 Normal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main() {
    WorldPos = vec3(model * vec4(aPos, 1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;  
    gl_Position = projection * view * vec4(WorldPos, 1.0);
}

Fragment Shader:

#version 330 core
out vec4 FragColor;

in vec3 WorldPos;
in vec3 Normal;

uniform samplerCube skybox;
uniform vec3 cameraPos;

void main() {
    vec3 I = normalize(WorldPos - cameraPos);
    vec3 R = reflect(I, normalize(Normal));
    FragColor = texture(skybox, R);
}

Paso 3: Renderizar el Objeto con el Mapa de Entorno

Finalmente, renderizamos el objeto utilizando el shader y el mapa de cubo.

// Configurar el shader y las matrices de transformación
shader.use();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
shader.setMat4("model", model);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
shader.setVec3("cameraPos", camera.Position);

// Vincular el mapa de cubo
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
shader.setInt("skybox", 0);

// Renderizar el objeto
renderObject();

Ejercicio Práctico

Ejercicio 1: Implementar Mapeo de Entorno en un Objeto Esférico

  1. Objetivo: Implementar el mapeo de entorno en una esfera para simular reflejos.
  2. Pasos:
    • Cargar las texturas del mapa de cubo.
    • Crear los shaders necesarios.
    • Renderizar una esfera utilizando el mapa de cubo.

Código de Ejemplo:

// Cargar texturas del mapa de cubo
// (Código similar al proporcionado anteriormente)

// Crear shaders
// (Código similar al proporcionado anteriormente)

// Renderizar la esfera
shader.use();
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
shader.setMat4("model", model);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
shader.setVec3("cameraPos", camera.Position);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
shader.setInt("skybox", 0);

renderSphere();

Solución

Asegúrate de seguir los pasos proporcionados y verificar que las texturas del mapa de cubo se carguen correctamente. Si encuentras algún error, revisa los caminos de las texturas y asegúrate de que los shaders estén correctamente compilados.

Conclusión

El mapeo de entorno es una técnica poderosa para simular reflejos realistas en superficies. En este tema, hemos aprendido a crear un mapa de cubo, escribir shaders para el mapeo de entorno y renderizar objetos con reflejos. Practica estos conceptos y experimenta con diferentes texturas y objetos para dominar esta técnica.

En el próximo tema, exploraremos los Shaders de Cómputo, una herramienta avanzada para realizar cálculos complejos en la GPU.

© Copyright 2024. Todos los derechos reservados