4 * \date 2014-08-03 21:41GMT
5 * \author Jan Boon (Kaetemi)
9 // NeL - MMORPG Framework <https://wiki.ryzom.dev/>
10 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
12 // This program is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU Affero General Public License as
14 // published by the Free Software Foundation, either version 3 of the
15 // License, or (at your option) any later version.
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Affero General Public License for more details.
22 // You should have received a copy of the GNU Affero General Public License
23 // along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "nel/3d/fxaa.h"
31 // #include <nel/misc/debug.h>
34 #include "nel/3d/u_camera.h"
35 #include "nel/3d/u_driver.h"
36 #include "nel/3d/material.h"
37 #include "nel/3d/texture_bloom.h"
38 #include "nel/3d/texture_user.h"
39 #include "nel/3d/driver_user.h"
40 #include "nel/3d/u_texture.h"
41 #include "nel/3d/render_target_manager.h"
44 // using namespace NLMISC;
49 #include "fxaa_program.h"
50 } /* anonymous namespace */
60 CFXAA::CFXAA(NL3D::UDriver
*driver
) : m_Driver(driver
), m_VP(NULL
), m_PP(NULL
), m_Width(~0), m_Height(~0)
62 nldebug("3D: Create FXAA");
64 CDriverUser
*dru
= static_cast<CDriverUser
*>(driver
);
65 NL3D::IDriver
*drv
= (dru
)->getDriver();
67 if (drv
->supportBloomEffect() && drv
->supportNonPowerOfTwoTextures())
69 m_PP
= new CPixelProgram();
72 IProgram::CSource
*source
= new IProgram::CSource();
73 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
74 source
->Profile
= IProgram::arbfp1
;
75 source
->setSourcePtr(a_arbfp1
);
76 m_PP
->addSource(source
);
80 IProgram::CSource
*source
= new IProgram::CSource();
81 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
82 source
->Profile
= IProgram::ps_2_0
;
83 source
->setSourcePtr(a_ps_2_0
);
84 m_PP
->addSource(source
);
86 if (!drv
->compilePixelProgram(m_PP
))
88 nlwarning("3D: No supported pixel program for FXAA effect");
95 nldebug("3D: FXAA pixel program available");
106 m_VP
= new CVertexProgram();
109 IProgram::CSource
*source
= new IProgram::CSource();
110 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
111 source
->Profile
= IProgram::nelvp
;
112 source
->setSourcePtr(a_nelvp
);
113 m_VP
->addSource(source
);
115 if (!drv
->compileVertexProgram(m_VP
))
117 nlwarning("3D: No supported vertex program for FXAA effect");
126 nldebug("3D: FXAA vertex program available");
135 // create material and vb
137 m_Mat
= m_Driver
->createMaterial();
139 m_Mat
.setColor(CRGBA::White
);
140 m_Mat
.setBlend (false);
141 m_Mat
.setAlphaTest (false);
142 NL3D::CMaterial
*mat
= m_Mat
.getObjectPtr();
143 mat
->setShader(NL3D::CMaterial::Normal
);
144 mat
->setBlendFunc(CMaterial::one
, CMaterial::zero
);
145 mat
->setZWrite(false);
146 mat
->setZFunc(CMaterial::always
);
147 mat
->setDoubleSided(true);
149 m_QuadUV
.V0
= CVector(0.f
, 0.f
, 0.5f
);
150 m_QuadUV
.V1
= CVector(1.f
, 0.f
, 0.5f
);
151 m_QuadUV
.V2
= CVector(1.f
, 1.f
, 0.5f
);
152 m_QuadUV
.V3
= CVector(0.f
, 1.f
, 0.5f
);
154 /*if (drv->textureCoordinateAlternativeMode())
156 m_QuadUV.Uv0 = CUV(0.f, 1.f);
157 m_QuadUV.Uv1 = CUV(1.f, 1.f);
158 m_QuadUV.Uv2 = CUV(1.f, 0.f);
159 m_QuadUV.Uv3 = CUV(0.f, 0.f);
163 m_QuadUV
.Uv0
= CUV(0.f
, 0.f
);
164 m_QuadUV
.Uv1
= CUV(1.f
, 0.f
);
165 m_QuadUV
.Uv2
= CUV(1.f
, 1.f
);
166 m_QuadUV
.Uv3
= CUV(0.f
, 1.f
);
169 /*CVertexBuffer &vb = m_VB;
171 vb.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3);
172 vb.addValueEx(CVertexBuffer::TexCoord0, CVertexBuffer::Float2);
173 vb.addValueEx(CVertexBuffer::TexCoord1, CVertexBuffer::Float4);
175 vb.setPreferredMemory(CVertexBuffer::RAMVolatile, false);
176 vb.setNumVertices(4);*/
182 nldebug("3D: Destroy FXAA");
186 m_Driver
->deleteMaterial(m_Mat
);
197 void CFXAA::applyEffect()
202 CDriverUser
*dru
= static_cast<CDriverUser
*>(m_Driver
);
203 IDriver
*drv
= dru
->getDriver();
206 bool fogEnabled
= m_Driver
->fogEnabled();
207 m_Driver
->enableFog(false);
209 NL3D::ITexture
*renderTarget
= drv
->getRenderTarget();
210 nlassert(renderTarget
);
211 nlassert(renderTarget
->isBloomTexture());
213 uint width
= renderTarget
->getWidth();
214 uint height
= renderTarget
->getHeight();
215 bool mode2D
= static_cast<CTextureBloom
*>(renderTarget
)->isMode2D();
216 nlassert(renderTarget
->getUploadFormat() == ITexture::Auto
);
218 float fwidth
= (float)width
;
219 float fheight
= (float)height
;
220 float pwidth
= 1.0f
/ fwidth
;
221 float pheight
= 1.0f
/ fheight
;
222 float hpwidth
= pwidth
* 0.5f
;
223 float hpheight
= pheight
* 0.5f
;
226 //if (width != m_Width || height != m_Height)
231 CVertexBufferReadWrite vba;
233 vba.setValueFloat3Ex(CVertexBuffer::Position, 0, 0.f, 0.f, 0.5f); // BL
234 vba.setValueFloat3Ex(CVertexBuffer::Position, 1, 1.f, 0.f, 0.5f); // BR
235 vba.setValueFloat3Ex(CVertexBuffer::Position, 2, 1.f, 1.f, 0.5f); // TR
236 vba.setValueFloat3Ex(CVertexBuffer::Position, 3, 0.f, 1.f, 0.5f); // TL
237 vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 0, 0.f, 0.f);
238 vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 1, 1.f, 0.f);
239 vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 2, 1.f, 1.f);
240 vba.setValueFloat2Ex(CVertexBuffer::TexCoord0, 3, 0.f, 1.f);
241 vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 0, 0.f - hpwidth, 0.f - hpheight, 0.f + hpwidth, 0.f + hpheight);
242 vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 1, 1.f - hpwidth, 0.f - hpheight, 1.f + hpwidth, 0.f + hpheight);
243 vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 2, 1.f - hpwidth, 1.f - hpheight, 1.f + hpwidth, 1.f + hpheight);
244 vba.setValueFloat4Ex(CVertexBuffer::TexCoord1, 3, 0.f - hpwidth, 1.f - hpheight, 0.f + hpwidth, 1.f + hpheight);
247 // create render target
248 CTextureUser
*otherRenderTarget
= m_Driver
->getRenderTargetManager().getRenderTarget(width
, height
, mode2D
);
249 nlassert(otherRenderTarget
);
251 // swap render target
252 CTextureUser texNull
;
253 dru
->setRenderTarget(texNull
);
254 drv
->swapTextureHandle(*renderTarget
, *otherRenderTarget
->getITexture());
255 drv
->setRenderTarget(renderTarget
);
256 m_Driver
->setMatrixMode2D11();
259 // m_Driver->clearBuffers(CRGBA(128, 128, 128, 128));
262 bool vpok
= drv
->activeVertexProgram(m_VP
);
264 bool ppok
= drv
->activePixelProgram(m_PP
);
266 /*drv->setUniform4f(IDriver::PixelProgram, 0, -n / fwidth, -n / fheight, n / fwidth, n / fheight); // fxaaConsoleRcpFrameOpt
267 drv->setUniform4f(IDriver::PixelProgram, 1, -2.0f / fwidth, -2.0f / fheight, 2.0f / fwidth, 2.0f / fheight); // fxaaConsoleRcpFrameOpt2*/
268 drv
->setUniform2f(IDriver::PixelProgram
, 0, 1.0f
/ fwidth
, 1.0f
/ fheight
); // fxaaQualityRcpFrame
269 drv
->setUniform1f(IDriver::PixelProgram
, 1, 0.75f
); // fxaaQualitySubpix
270 drv
->setUniform1f(IDriver::PixelProgram
, 2, 0.166f
); // fxaaQualityEdgeThreshold
271 drv
->setUniform1f(IDriver::PixelProgram
, 3, 0.0833f
); // fxaaQualityEdgeThresholdMin
272 drv
->setUniformMatrix(IDriver::VertexProgram
, 0, IDriver::ModelViewProjection
, IDriver::Identity
);
273 // drv->setUniform4f(IDriver::VertexProgram, 9, -hpwidth, -hpheight, hpwidth, hpheight);
276 m_Mat
.getObjectPtr()->setTexture(0, otherRenderTarget
->getITexture());
277 /*drv->activeVertexBuffer(m_VB);
278 drv->renderRawQuads(*m_Mat.getObjectPtr(), 0, 1);*/
279 m_Driver
->drawQuad(m_QuadUV
, m_Mat
);
280 m_Mat
.getObjectPtr()->setTexture(0, NULL
);
282 // deactivate program
283 drv
->activeVertexProgram(NULL
);
284 drv
->activePixelProgram(NULL
);
287 m_Driver
->enableFog(fogEnabled
);
289 // recycle render target
290 m_Driver
->getRenderTargetManager().recycleRenderTarget(otherRenderTarget
);
293 } /* namespace NL3D */