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