En este módulo, aprenderemos sobre los conceptos fundamentales de iluminación y materiales en DirectX. La iluminación es crucial para dar realismo a las escenas 3D, y los materiales determinan cómo los objetos interactúan con la luz. Exploraremos diferentes tipos de luces y cómo configurar materiales para obtener efectos visuales deseados.

Conceptos Clave

  1. Tipos de Luces:

    • Luz Ambiental: Luz que ilumina uniformemente toda la escena.
    • Luz Direccional: Luz que simula una fuente de luz lejana, como el sol.
    • Luz Puntual: Luz que emana desde un punto en todas direcciones.
    • Luz Focal: Luz que emana desde un punto en una dirección específica, similar a un foco.
  2. Componentes de Materiales:

    • Difuso: Cómo la luz se dispersa en la superficie del objeto.
    • Especular: Cómo la luz se refleja en la superficie del objeto.
    • Emisivo: Luz que el objeto emite por sí mismo.
    • Ambiente: Cómo el objeto interactúa con la luz ambiental.

Configuración de la Iluminación

Luz Direccional

Primero, configuraremos una luz direccional en nuestra escena. La luz direccional es útil para simular la luz del sol.

// Estructura para definir una luz direccional
struct DirectionalLight
{
    XMFLOAT4 Ambient;
    XMFLOAT4 Diffuse;
    XMFLOAT4 Specular;
    XMFLOAT3 Direction;
    float Pad; // Padding para alineación
};

// Definición de una luz direccional
DirectionalLight dirLight;
dirLight.Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
dirLight.Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
dirLight.Specular = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);
dirLight.Direction = XMFLOAT3(0.57735f, -0.57735f, 0.57735f); // Normalizado

Luz Puntual

La luz puntual emite luz desde un punto en todas direcciones, similar a una bombilla.

// Estructura para definir una luz puntual
struct PointLight
{
    XMFLOAT4 Ambient;
    XMFLOAT4 Diffuse;
    XMFLOAT4 Specular;
    XMFLOAT3 Position;
    float Range;
    XMFLOAT3 Att;
    float Pad; // Padding para alineación
};

// Definición de una luz puntual
PointLight pointLight;
pointLight.Ambient = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
pointLight.Diffuse = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);
pointLight.Specular = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
pointLight.Position = XMFLOAT3(0.0f, 1.0f, 0.0f);
pointLight.Range = 10.0f;
pointLight.Att = XMFLOAT3(0.0f, 0.1f, 0.0f); // Atenuación

Configuración de Materiales

Los materiales determinan cómo los objetos reflejan la luz. Aquí configuramos un material básico.

// Estructura para definir un material
struct Material
{
    XMFLOAT4 Ambient;
    XMFLOAT4 Diffuse;
    XMFLOAT4 Specular; // w = SpecPower
    XMFLOAT4 Reflect;
};

// Definición de un material
Material mat;
mat.Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
mat.Diffuse = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.0f);
mat.Specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 16.0f); // SpecPower = 16
mat.Reflect = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);

Ejemplo Práctico: Aplicando Iluminación y Materiales

Vamos a combinar la luz direccional y el material en un shader simple.

Vertex Shader

cbuffer cbPerObject
{
    float4x4 gWorldViewProj;
    float4x4 gWorld;
};

struct VertexIn
{
    float3 PosL : POSITION;
    float3 NormalL : NORMAL;
};

struct VertexOut
{
    float4 PosH : SV_POSITION;
    float3 PosW : POSITION;
    float3 NormalW : NORMAL;
};

VertexOut VS(VertexIn vin)
{
    VertexOut vout;
    vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
    vout.NormalW = mul(float4(vin.NormalL, 0.0f), gWorld).xyz;
    vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
    return vout;
}

Pixel Shader

cbuffer cbPerFrame
{
    DirectionalLight gDirLight;
    float3 gEyePosW;
};

cbuffer cbPerObject
{
    Material gMaterial;
};

struct VertexOut
{
    float4 PosH : SV_POSITION;
    float3 PosW : POSITION;
    float3 NormalW : NORMAL;
};

float4 PS(VertexOut pin) : SV_Target
{
    float3 N = normalize(pin.NormalW);
    float3 L = normalize(gDirLight.Direction);
    float3 V = normalize(gEyePosW - pin.PosW);
    float3 R = reflect(-L, N);

    // Ambient
    float4 ambient = gMaterial.Ambient * gDirLight.Ambient;

    // Diffuse
    float4 diffuse = gMaterial.Diffuse * gDirLight.Diffuse * saturate(dot(N, L));

    // Specular
    float4 spec = gMaterial.Specular * gDirLight.Specular * pow(saturate(dot(R, V)), gMaterial.Specular.w);

    return ambient + diffuse + spec;
}

Ejercicio Práctico

Ejercicio 1: Añadir una Luz Puntual

  1. Objetivo: Añadir una luz puntual a la escena y ajustar los materiales para ver el efecto.
  2. Instrucciones:
    • Define una estructura PointLight en el shader.
    • Añade una instancia de PointLight en el buffer constante.
    • Modifica el pixel shader para incluir la contribución de la luz puntual.

Solución

cbuffer cbPerFrame
{
    DirectionalLight gDirLight;
    PointLight gPointLight;
    float3 gEyePosW;
};

float4 PS(VertexOut pin) : SV_Target
{
    float3 N = normalize(pin.NormalW);
    float3 L = normalize(gDirLight.Direction);
    float3 V = normalize(gEyePosW - pin.PosW);
    float3 R = reflect(-L, N);

    // Ambient
    float4 ambient = gMaterial.Ambient * gDirLight.Ambient;

    // Diffuse
    float4 diffuse = gMaterial.Diffuse * gDirLight.Diffuse * saturate(dot(N, L));

    // Specular
    float4 spec = gMaterial.Specular * gDirLight.Specular * pow(saturate(dot(R, V)), gMaterial.Specular.w);

    // Point Light Contribution
    float3 P = gPointLight.Position - pin.PosW;
    float d = length(P);
    P /= d; // Normalize P
    float attenuation = 1.0f / (gPointLight.Att.x + gPointLight.Att.y * d + gPointLight.Att.z * d * d);
    float4 pointDiffuse = gMaterial.Diffuse * gPointLight.Diffuse * saturate(dot(N, P)) * attenuation;
    float4 pointSpec = gMaterial.Specular * gPointLight.Specular * pow(saturate(dot(reflect(-P, N), V)), gMaterial.Specular.w) * attenuation;

    return ambient + diffuse + spec + pointDiffuse + pointSpec;
}

Conclusión

En esta sección, hemos aprendido sobre los diferentes tipos de luces y cómo configurar materiales en DirectX. Hemos visto cómo aplicar estos conceptos en shaders para crear efectos de iluminación realistas. En el siguiente módulo, exploraremos técnicas avanzadas de iluminación, como el mapeo de sombras, para mejorar aún más la calidad visual de nuestras escenas.

© Copyright 2024. Todos los derechos reservados