Els efectes de postprocessament són tècniques aplicades a les imatges renderitzades per millorar la seva qualitat visual o per afegir efectes especials. Aquestes tècniques es realitzen després que la imatge hagi estat renderitzada per la GPU, d'aquí el terme "postprocessament". En aquest mòdul, aprendrem a implementar alguns dels efectes de postprocessament més comuns utilitzant DirectX.
Conceptes Clau
- Frame Buffer Object (FBO): Un objecte que conté una imatge renderitzada que es pot utilitzar com a textura per a efectes de postprocessament.
- Shaders de Postprocessament: Shaders que s'apliquen a les imatges renderitzades per modificar-les.
- Efectes Comuns: Bloom, Motion Blur, Depth of Field, etc.
Configuració Inicial
- Crear un Frame Buffer Object (FBO)
Per aplicar efectes de postprocessament, primer hem de renderitzar la nostra escena a un FBO en lloc de directament a la pantalla.
// Crear un FBO
ID3D11Texture2D* pRenderTargetTexture = nullptr;
D3D11_TEXTURE2D_DESC textureDesc = {};
textureDesc.Width = screenWidth;
textureDesc.Height = screenHeight;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr, &pRenderTargetTexture);
if (FAILED(hr)) {
// Manejar error
}
// Crear un Render Target View (RTV)
ID3D11RenderTargetView* pRenderTargetView = nullptr;
hr = device->CreateRenderTargetView(pRenderTargetTexture, nullptr, &pRenderTargetView);
if (FAILED(hr)) {
// Manejar error
}
// Crear un Shader Resource View (SRV)
ID3D11ShaderResourceView* pShaderResourceView = nullptr;
hr = device->CreateShaderResourceView(pRenderTargetTexture, nullptr, &pShaderResourceView);
if (FAILED(hr)) {
// Manejar error
}
- Configurar el Render Target
Abans de renderitzar la nostra escena, hem de configurar el FBO com a render target.
Implementació d'Efectes de Postprocessament
- Bloom
El Bloom és un efecte que fa que les àrees brillants d'una imatge es difuminin, creant un halo de llum.
Vertex Shader
cbuffer MatrixBuffer {
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};
struct VertexInputType {
float4 position : POSITION;
float2 tex : TEXCOORD0;
};
struct PixelInputType {
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
};
PixelInputType BloomVertexShader(VertexInputType input) {
PixelInputType output;
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
output.tex = input.tex;
return output;
}Pixel Shader
Texture2D shaderTexture;
SamplerState SampleType;
float4 BloomPixelShader(PixelInputType input) : SV_TARGET {
float4 color = shaderTexture.Sample(SampleType, input.tex);
float brightness = dot(color.rgb, float3(0.2126, 0.7152, 0.0722));
if (brightness > 0.8) {
return color * 1.5;
}
return color;
}
- Motion Blur
El Motion Blur és un efecte que simula el desenfocament de moviment.
Vertex Shader
cbuffer MatrixBuffer {
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
};
struct VertexInputType {
float4 position : POSITION;
float2 tex : TEXCOORD0;
};
struct PixelInputType {
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
};
PixelInputType MotionBlurVertexShader(VertexInputType input) {
PixelInputType output;
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
output.tex = input.tex;
return output;
}Pixel Shader
Texture2D shaderTexture;
SamplerState SampleType;
float4 MotionBlurPixelShader(PixelInputType input) : SV_TARGET {
float4 color = shaderTexture.Sample(SampleType, input.tex);
float2 blurDirection = float2(0.01, 0.01); // Direcció del desenfocament
float4 blurredColor = shaderTexture.Sample(SampleType, input.tex + blurDirection);
return lerp(color, blurredColor, 0.5);
}Exercicis Pràctics
Exercici 1: Implementar un Efecte de Bloom
- Crea un FBO i configura'l com a render target.
- Escriu un shader de postprocessament que implementi l'efecte de Bloom.
- Aplica el shader a la imatge renderitzada.
Exercici 2: Implementar un Efecte de Motion Blur
- Crea un FBO i configura'l com a render target.
- Escriu un shader de postprocessament que implementi l'efecte de Motion Blur.
- Aplica el shader a la imatge renderitzada.
Solucions
Solució a l'Exercici 1
// Configuració del FBO context->OMSetRenderTargets(1, &pRenderTargetView, nullptr); // Renderitzar l'escena RenderScene(); // Aplicar l'efecte de Bloom context->PSSetShader(bloomPixelShader, nullptr, 0); context->DrawIndexed(indexCount, 0, 0);
Solució a l'Exercici 2
// Configuració del FBO context->OMSetRenderTargets(1, &pRenderTargetView, nullptr); // Renderitzar l'escena RenderScene(); // Aplicar l'efecte de Motion Blur context->PSSetShader(motionBlurPixelShader, nullptr, 0); context->DrawIndexed(indexCount, 0, 0);
Resum
En aquest mòdul, hem après a implementar efectes de postprocessament utilitzant DirectX. Hem vist com crear un FBO, configurar-lo com a render target i aplicar shaders de postprocessament per a efectes com el Bloom i el Motion Blur. Aquests efectes poden millorar significativament la qualitat visual de les nostres aplicacions gràfiques. En el següent mòdul, explorarem tècniques avançades com la tessel·lació.
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
