En aquest tema, explorarem els conceptes fonamentals de la il·luminació i els materials en DirectX. Aprendrem com crear efectes de llum realistes i com aplicar materials a objectes 3D per millorar la seva aparença visual.
Objectius del Tema
- Comprendre els conceptes bàsics de la il·luminació en 3D.
- Aprendre a configurar diferents tipus de llums en DirectX.
- Aplicar materials a objectes 3D per simular diferents propietats de superfícies.
- Implementar il·luminació bàsica en una escena 3D.
Conceptes Bàsics de la Il·luminació
Tipus de Llums
En DirectX, podem utilitzar diversos tipus de llums per il·luminar una escena. Els més comuns són:
-
Llum Direccional (Directional Light):
- Simula una font de llum llunyana, com el sol.
- Tots els raigs de llum són paral·lels.
- No té posició, només direcció.
-
Llum Puntual (Point Light):
- Emana llum en totes direccions des d'un punt específic.
- Té una posició i una atenuació basada en la distància.
-
Llum de Focal (Spot Light):
- Similar a la llum puntual, però la llum es concentra en un con.
- Té una posició, direcció i angle de con.
Fórmula de la Il·luminació
La il·luminació en una escena 3D es calcula utilitzant la fórmula de la il·luminació de Phong, que inclou components ambientals, difusos i especulars:
\[ I = I_{ambient} + I_{diffuse} + I_{specular} \]
- Il·luminació Ambiental (Ambient Light): Llum uniforme que afecta tota l'escena.
- Il·luminació Difusa (Diffuse Light): Llum que depèn de l'angle entre la llum i la superfície.
- Il·luminació Especular (Specular Light): Llum reflectida que crea punts brillants.
Configuració de Llums en DirectX
Exemple de Codi: Configuració d'una Llum Direccional
// Estructura per a una llum direccional struct DirectionalLight { XMFLOAT4 Ambient; XMFLOAT4 Diffuse; XMFLOAT4 Specular; XMFLOAT3 Direction; float Pad; // Padding per alinear a 16 bytes }; // Configuració d'una llum 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.577f, -0.577f, 0.577f);
Exemple de Codi: Configuració d'una Llum Puntual
// Estructura per a una llum puntual struct PointLight { XMFLOAT4 Ambient; XMFLOAT4 Diffuse; XMFLOAT4 Specular; XMFLOAT3 Position; float Range; XMFLOAT3 Att; float Pad; // Padding per alinear a 16 bytes }; // Configuració d'una llum 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, 5.0f, 0.0f); pointLight.Range = 10.0f; pointLight.Att = XMFLOAT3(0.0f, 0.1f, 0.0f);
Aplicació de Materials
Estructura de Material
struct Material { XMFLOAT4 Ambient; XMFLOAT4 Diffuse; XMFLOAT4 Specular; // w = SpecPower XMFLOAT4 Reflect; }; // Configuració d'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);
Exemple de Codi: Aplicació de Material a un Objecte
// Assignar material a un objecte objectMaterial = mat; // Enviar material al shader cbMaterial.Ambient = objectMaterial.Ambient; cbMaterial.Diffuse = objectMaterial.Diffuse; cbMaterial.Specular = objectMaterial.Specular; cbMaterial.Reflect = objectMaterial.Reflect;
Implementació de la Il·luminació Bàsica
Vertex Shader
cbuffer cbPerObject { float4x4 gWorldViewProj; float4x4 gWorld; float4x4 gWorldInvTranspose; Material gMaterial; }; 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; // Transformar posició i normal vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz; vout.NormalW = mul(float4(vin.NormalL, 0.0f), gWorldInvTranspose).xyz; vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj); return vout; }
Pixel Shader
cbuffer cbPerFrame { DirectionalLight gDirLight; float3 gEyePosW; }; struct VertexOut { float4 PosH : SV_POSITION; float3 PosW : POSITION; float3 NormalW : NORMAL; }; float4 PS(VertexOut pin) : SV_Target { // Normalitzar la normal float3 N = normalize(pin.NormalW); // Calcular la direcció de la llum float3 L = normalize(-gDirLight.Direction); // Calcular la il·luminació difusa float diffuse = max(dot(N, L), 0.0f); // Calcular la il·luminació especular float3 R = reflect(-L, N); float3 V = normalize(gEyePosW - pin.PosW); float spec = pow(max(dot(R, V), 0.0f), gMaterial.Specular.w); // Composar la il·luminació final float4 ambient = gMaterial.Ambient * gDirLight.Ambient; float4 diffuseColor = gMaterial.Diffuse * gDirLight.Diffuse * diffuse; float4 specular = gMaterial.Specular * gDirLight.Specular * spec; return ambient + diffuseColor + specular; }
Exercici Pràctic
Objectiu
Implementar una escena 3D amb una llum direccional i aplicar materials a diversos objectes.
Passos
- Configura una llum direccional.
- Defineix materials per a diferents objectes.
- Aplica els materials als objectes.
- Implementa els shaders per calcular la il·luminació.
Solució
// Configuració de la llum 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.577f, -0.577f, 0.577f); // Configuració de materials Material mat1; mat1.Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f); mat1.Diffuse = XMFLOAT4(0.8f, 0.0f, 0.0f, 1.0f); mat1.Specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 16.0f); mat1.Reflect = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); Material mat2; mat2.Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f); mat2.Diffuse = XMFLOAT4(0.0f, 0.8f, 0.0f, 1.0f); mat2.Specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 16.0f); mat2.Reflect = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f); // Assignar materials a objectes object1Material = mat1; object2Material = mat2; // Enviar materials als shaders cbMaterial1.Ambient = object1Material.Ambient; cbMaterial1.Diffuse = object1Material.Diffuse; cbMaterial1.Specular = object1Material.Specular; cbMaterial1.Reflect = object1Material.Reflect; cbMaterial2.Ambient = object2Material.Ambient; cbMaterial2.Diffuse = object2Material.Diffuse; cbMaterial2.Specular = object2Material.Specular; cbMaterial2.Reflect = object2Material.Reflect;
Resum
En aquest tema, hem après els conceptes bàsics de la il·luminació i els materials en DirectX. Hem vist com configurar diferents tipus de llums i com aplicar materials a objectes 3D per crear efectes visuals realistes. També hem implementat shaders per calcular la il·luminació en una escena 3D. Aquests coneixements són fonamentals per crear gràfics 3D realistes i atractius en les teves aplicacions DirectX.
Curs de Programació DirectX
Mòdul 1: Introducció a DirectX
- Què és DirectX?
- Configuració de l'Entorn de Desenvolupament
- Comprendre l'API de DirectX
- Crear la Teva Primera Aplicació DirectX
Mòdul 2: Conceptes Bàsics de Direct3D
- Introducció a Direct3D
- Inicialitzar Direct3D
- Renderitzar un Triangle
- Gestionar el Bucle de Renderització
Mòdul 3: Treballar amb Shaders
Mòdul 4: Tècniques Avançades de Renderització
Mòdul 5: Models 3D i Animació
Mòdul 6: Optimització del Rendiment
- Perfilat i Depuració
- Optimitzar el Rendiment de la Renderització
- Gestió de Memòria
- Multifil en DirectX