Intro:
Une image numérique est composée de pixels. Lorsqu’elle est redimensionnée, le bord des formes ayant un angle particulier prend la forme d’escalier : c’est le crénelage, ou aliasing.
Explication :
Voici une technique très efficace et très performante en ressource système afin d’effectuer du rendu anti-crénelage. Elle utilise une render target et un Quad de post-traitement.
Voici le fichier ShaderTechique_Declarations.h :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//------------------------------------------------------ // FXAA shader //------------------------------------------------------ class ShaderTechnique_FXAA : public ShaderTechnique { public: ShaderTechnique_FXAA(); virtual ~ShaderTechnique_FXAA(); virtual bool Initialize() override; virtual void SetupShaderVariables(); virtual void Update(float fTimeSinceLastFrame); void SetRenderTarget(RenderTarget* pRT); void SetEnabled(bool bEnabled); bool GetEnabled(); private: D3DXMATRIX m_WorldMatrix; D3DXMATRIX m_ViewMatrix; D3DXMATRIX m_OrthoMatrix; bool m_bEnabled; }; |
Voici le fichier ShaderTechnique_FXAA.cpp :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#include "ShaderTechnique_Declarations.h" #include "Defines.h" #include "D3D10Renderer.h" ShaderTechnique_FXAA::ShaderTechnique_FXAA() : ShaderTechnique("FXAA.fx", "Render", VertexLayoutType::PT_VERTEX), m_bEnabled(true) { } ShaderTechnique_FXAA::~ShaderTechnique_FXAA() { } bool ShaderTechnique_FXAA::Initialize() { if (ShaderTechnique::Initialize() == false) { return false; } SetupShaderVariables(); return true; } void ShaderTechnique_FXAA::SetRenderTarget(RenderTarget* pRT) { SetTextureRV("TextureDiffuse", pRT->GetShaderResourceView()); } void ShaderTechnique_FXAA::SetupShaderVariables() { RegisterMatrixVariable("World", ShaderVariableType::WORLD); RegisterMatrixVariable("View", ShaderVariableType::VIEW); RegisterMatrixVariable("Projection", ShaderVariableType::PROJECTION); RegisterTextureVariable("TextureDiffuse", ShaderVariableType::ANY); RegisterVectorVariable("FrameBufferSize", ShaderVariableType::ANY); RegisterVectorVariable("Color", ShaderVariableType::ANY); RegisterScalarVariable("Enabled", ShaderVariableType::ANY); D3DXMatrixIdentity(&m_WorldMatrix); D3DXMatrixIdentity(&m_ViewMatrix); D3DXMatrixIdentity(&m_OrthoMatrix); D3DXVECTOR3 Eye(0.0f, 0.0f, 1.0f); D3DXVECTOR3 At(0.0f, 0.0f, 0.0f); D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f); D3DXMatrixLookAtLH(&m_ViewMatrix, &Eye, &At, &Up); float fViewportWidth = (float)D3D10_RENDERER->GetViewportWidth(); float fViewportHeigth = (float)D3D10_RENDERER->GetViewportHeight(); D3DXMatrixOrthoLH(&m_OrthoMatrix, fViewportWidth, fViewportHeigth, 0.01f, 20.0f); SetVector("FrameBufferSize", D3DXVECTOR2(fViewportWidth, fViewportHeigth)); } void ShaderTechnique_FXAA::Update(float fTimeSinceLastFrame) { SetMatrix("World", &m_WorldMatrix); SetMatrix("View", &m_ViewMatrix); SetMatrix("Projection", &m_OrthoMatrix); SetAutoMatrix(ShaderVariableType::ANY); } void ShaderTechnique_FXAA::SetEnabled(bool bEnabled) { SetScalar("Enabled", bEnabled); m_bEnabled = bEnabled; } bool ShaderTechnique_FXAA::GetEnabled() { return m_bEnabled; } |
Voici les bouts de code pour initialiser le shader FXAA :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
bool D3D10Renderer::Initialize(bool bFullscreen) { [...] m_pQuad = new TextureScreenQuad(); m_pQuad->Initialize(); m_pQuad->SetShaderTechnique( SHADER_MANAGER->GetShader("FXAA") ); [...] } void D3D10Renderer::Render() { [...] // Efface la surface de rendu m_pd3dDevice->ClearDepthStencilView(m_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 ); m_pd3dDevice->ClearRenderTargetView(m_pRenderTargetView, afClearColor); SCENE_MANAGER->DrawAll(fTimeSinceLastFrame); DrawTextInfo(); RenderToTexture(fTimeSinceLastFrame); UpdateWindowTitle(); m_pQuad->OnRender(fTimeSinceLastFrame); m_pSwapChain->Present(0, 0); [...] } void D3D10Renderer::RenderToTexture(float fTimeSinceLastFrame) { // Set the render target to be the render to texture. m_pQuad->GetRT()->SetRenderTarget(m_pDepthStencilView); // Clear the render to texture. m_pQuad->GetRT()->ClearRenderTarget(m_pDepthStencilView); // Render the scene now and it will draw to the render to texture instead of the back buffer. SCENE_MANAGER->DrawAll(fTimeSinceLastFrame); // Reset the render target back to the original back buffer and not the render to texture anymore. m_pd3dDevice->OMSetRenderTargets(1, &m_pRenderTargetView, m_pDepthStencilView); } |
Voici le fichier shader .fx :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
SamplerState SamplerLinear { Filter = ANISOTROPIC; AddressU = Wrap; AddressV = Wrap; MaxAnisotropy = 1; }; matrix World; matrix View; matrix Projection; Texture2D TextureDiffuse; float2 FrameBufferSize; float4 Color; bool Enabled; struct VS_INPUT { float4 Pos : POSITION; float2 Tex : TEXCOORD; }; struct PS_INPUT { float4 Pos : SV_POSITION; float2 Tex : TEXCOORD0; }; PS_INPUT VS(VS_INPUT input) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul(input.Pos, World); output.Pos = mul(output.Pos, View); output.Pos = mul(output.Pos, Projection); output.Tex = input.Tex; return output; } static const float FXAA_SPAN_MAX = 4.0; static const float FXAA_REDUCE_MUL = 1.0/8.0; static const float FXAA_REDUCE_MIN = 1.0/128.0; float4 PS(PS_INPUT input) : SV_Target { input.Tex = 1.0f - input.Tex; float3 rgbNW = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(-1.0,-1.0) / FrameBufferSize)).xyz; float3 rgbNE = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(1.0,-1.0) / FrameBufferSize)).xyz; float3 rgbSW = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(-1.0,1.0) / FrameBufferSize)).xyz; float3 rgbSE = TextureDiffuse.Sample(SamplerLinear, input.Tex + (float2(1.0,1.0) / FrameBufferSize)).xyz; float3 rgbM = TextureDiffuse.Sample(SamplerLinear, input.Tex).xyz; float3 luma = float3(0.299, 0.587, 0.114); float lumaNW = dot(rgbNW, luma); float lumaNE = dot(rgbNE, luma); float lumaSW = dot(rgbSW, luma); float lumaSE = dot(rgbSE, luma); float lumaM = dot(rgbM, luma); float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); float2 dir; dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); float dirReduce = max( (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); dir = min(float2( FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) / FrameBufferSize; float3 rgbA = (1.0/2.0) * ( TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (1.0/3.0 - 0.5)).xyz + TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (2.0/3.0 - 0.5)).xyz); float3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (0.0/3.0 - 0.5)).xyz + TextureDiffuse.Sample(SamplerLinear, input.Tex + dir * (3.0/3.0 - 0.5)).xyz); float lumaB = dot(rgbB, luma); if (Enabled) { if ((lumaB < lumaMin) || (lumaB > lumaMax)) { return float4(rgbA, 1.0f) * Color; } else { return float4(rgbB, 1.0f) * Color; } } else { return TextureDiffuse.Sample(SamplerLinear, input.Tex); } } technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } } |
Résumé :
Nous avons présenté une technique FXAA par un fichier shader .fx afin d’effectuer le rendu d’anti-crénélage.
Références :
– https://fr.wikipedia.org/wiki/Fast_approximate_anti-aliasing
– http://horde3d.org/wiki/index.php5?title=Shading_Technique_-_FXAA


