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

  1. Frame Buffer Object (FBO): Un objecte que conté una imatge renderitzada que es pot utilitzar com a textura per a efectes de postprocessament.
  2. Shaders de Postprocessament: Shaders que s'apliquen a les imatges renderitzades per modificar-les.
  3. Efectes Comuns: Bloom, Motion Blur, Depth of Field, etc.

Configuració Inicial

  1. 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
}

  1. Configurar el Render Target

Abans de renderitzar la nostra escena, hem de configurar el FBO com a render target.

context->OMSetRenderTargets(1, &pRenderTargetView, nullptr);

Implementació d'Efectes de Postprocessament

  1. 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;
}

  1. 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

  1. Crea un FBO i configura'l com a render target.
  2. Escriu un shader de postprocessament que implementi l'efecte de Bloom.
  3. Aplica el shader a la imatge renderitzada.

Exercici 2: Implementar un Efecte de Motion Blur

  1. Crea un FBO i configura'l com a render target.
  2. Escriu un shader de postprocessament que implementi l'efecte de Motion Blur.
  3. 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ó.

© Copyright 2024. Tots els drets reservats