El mapatge d'ombres és una tècnica avançada de renderització que permet crear ombres realistes en una escena 3D. Aquesta tècnica és àmpliament utilitzada en motors de jocs i aplicacions gràfiques per millorar la percepció de profunditat i realisme.

Conceptes Clau

  1. Shadow Map (Mapa d'Ombres): Una textura que emmagatzema la informació de profunditat des de la perspectiva de la font de llum.
  2. Passada de Profunditat: La primera passada de renderització on es genera el shadow map.
  3. Passada de Renderització: La segona passada on es compara la profunditat dels píxels amb el shadow map per determinar si un píxel està a l'ombra.

Passos per Implementar el Mapatge d'Ombres

  1. Crear el Shadow Map

Primer, hem de crear una textura que servirà com a shadow map. Aquesta textura emmagatzemarà la informació de profunditat des de la perspectiva de la font de llum.

// Crear una textura per al shadow map
D3D11_TEXTURE2D_DESC shadowMapDesc = {};
shadowMapDesc.Width = SHADOW_MAP_WIDTH;
shadowMapDesc.Height = SHADOW_MAP_HEIGHT;
shadowMapDesc.MipLevels = 1;
shadowMapDesc.ArraySize = 1;
shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
shadowMapDesc.SampleDesc.Count = 1;
shadowMapDesc.Usage = D3D11_USAGE_DEFAULT;
shadowMapDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;

ID3D11Texture2D* shadowMapTexture;
device->CreateTexture2D(&shadowMapDesc, nullptr, &shadowMapTexture);

  1. Configurar la Vista de la Font de Llum

Hem de configurar una matriu de vista i projecció des de la perspectiva de la font de llum.

// Configurar la matriu de vista de la font de llum
XMVECTOR lightPosition = XMVectorSet(0.0f, 10.0f, 0.0f, 1.0f);
XMVECTOR lightTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

XMMATRIX lightViewMatrix = XMMatrixLookAtLH(lightPosition, lightTarget, lightUp);

// Configurar la matriu de projecció de la font de llum
XMMATRIX lightProjectionMatrix = XMMatrixOrthographicLH(20.0f, 20.0f, 1.0f, 100.0f);

  1. Renderitzar la Passada de Profunditat

Renderitzem la escena des de la perspectiva de la font de llum per generar el shadow map.

// Configurar el render target per al shadow map
context->OMSetRenderTargets(0, nullptr, shadowMapDepthStencilView);
context->ClearDepthStencilView(shadowMapDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

// Configurar les matrius de vista i projecció de la font de llum
cbLightViewProjection.lightView = XMMatrixTranspose(lightViewMatrix);
cbLightViewProjection.lightProjection = XMMatrixTranspose(lightProjectionMatrix);
context->UpdateSubresource(lightViewProjectionBuffer, 0, nullptr, &cbLightViewProjection, 0, 0);

// Renderitzar la escena per generar el shadow map
RenderScene(context, shadowMapShader);

  1. Aplicar el Shadow Map en la Passada de Renderització

En la passada de renderització, utilitzem el shadow map per determinar si un píxel està a l'ombra.

// Configurar el shader resource view del shadow map
context->PSSetShaderResources(1, 1, &shadowMapSRV);

// Configurar les matrius de vista i projecció de la càmera
cbCameraViewProjection.cameraView = XMMatrixTranspose(cameraViewMatrix);
cbCameraViewProjection.cameraProjection = XMMatrixTranspose(cameraProjectionMatrix);
context->UpdateSubresource(cameraViewProjectionBuffer, 0, nullptr, &cbCameraViewProjection, 0, 0);

// Renderitzar la escena amb el shadow map
RenderScene(context, mainShader);

Exercici Pràctic

Objectiu

Implementar el mapatge d'ombres en una escena 3D simple amb una font de llum direccional.

Passos

  1. Crear el Shadow Map: Seguint els passos descrits anteriorment, crea una textura per al shadow map.
  2. Configurar la Vista de la Font de Llum: Configura les matrius de vista i projecció des de la perspectiva de la font de llum.
  3. Renderitzar la Passada de Profunditat: Renderitza la escena des de la perspectiva de la font de llum per generar el shadow map.
  4. Aplicar el Shadow Map: Utilitza el shadow map en la passada de renderització per determinar si els píxels estan a l'ombra.

Solució

// Pas 1: Crear el Shadow Map
D3D11_TEXTURE2D_DESC shadowMapDesc = {};
shadowMapDesc.Width = SHADOW_MAP_WIDTH;
shadowMapDesc.Height = SHADOW_MAP_HEIGHT;
shadowMapDesc.MipLevels = 1;
shadowMapDesc.ArraySize = 1;
shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
shadowMapDesc.SampleDesc.Count = 1;
shadowMapDesc.Usage = D3D11_USAGE_DEFAULT;
shadowMapDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;

ID3D11Texture2D* shadowMapTexture;
device->CreateTexture2D(&shadowMapDesc, nullptr, &shadowMapTexture);

// Pas 2: Configurar la Vista de la Font de Llum
XMVECTOR lightPosition = XMVectorSet(0.0f, 10.0f, 0.0f, 1.0f);
XMVECTOR lightTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

XMMATRIX lightViewMatrix = XMMatrixLookAtLH(lightPosition, lightTarget, lightUp);
XMMATRIX lightProjectionMatrix = XMMatrixOrthographicLH(20.0f, 20.0f, 1.0f, 100.0f);

// Pas 3: Renderitzar la Passada de Profunditat
context->OMSetRenderTargets(0, nullptr, shadowMapDepthStencilView);
context->ClearDepthStencilView(shadowMapDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

cbLightViewProjection.lightView = XMMatrixTranspose(lightViewMatrix);
cbLightViewProjection.lightProjection = XMMatrixTranspose(lightProjectionMatrix);
context->UpdateSubresource(lightViewProjectionBuffer, 0, nullptr, &cbLightViewProjection, 0, 0);

RenderScene(context, shadowMapShader);

// Pas 4: Aplicar el Shadow Map
context->PSSetShaderResources(1, 1, &shadowMapSRV);

cbCameraViewProjection.cameraView = XMMatrixTranspose(cameraViewMatrix);
cbCameraViewProjection.cameraProjection = XMMatrixTranspose(cameraProjectionMatrix);
context->UpdateSubresource(cameraViewProjectionBuffer, 0, nullptr, &cbCameraViewProjection, 0, 0);

RenderScene(context, mainShader);

Errors Comuns i Consells

  1. Resolució del Shadow Map: Una resolució massa baixa pot causar artefactes d'ombres. Ajusta la resolució segons les necessitats de la teva aplicació.
  2. Bias de Profunditat: Un bias inadequat pot causar ombres incorrectes. Experimenta amb diferents valors de bias per trobar el més adequat.
  3. Aliasing: Utilitza tècniques com el PCF (Percentage Closer Filtering) per suavitzar les ombres i reduir l'aliasing.

Conclusió

El mapatge d'ombres és una tècnica poderosa per afegir realisme a les escenes 3D. Comprendre i implementar aquesta tècnica és essencial per a qualsevol desenvolupador que treballi amb gràfics 3D avançats. Amb la pràctica, podràs crear ombres realistes i millorar significativament la qualitat visual de les teves aplicacions.

© Copyright 2024. Tots els drets reservats