Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / fxaa.cpp
blob2dfd58d37a9719a017b814f23019963f20f04421
1 /**
2 * \file fxaa.cpp
3 * \brief CFXAA
4 * \date 2014-08-03 21:41GMT
5 * \author Jan Boon (Kaetemi)
6 * CFXAA
7 */
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/>.
25 #include "std3d.h"
26 #include "nel/3d/fxaa.h"
28 // STL includes
30 // NeL includes
31 // #include <nel/misc/debug.h>
33 // Project includes
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"
43 using namespace std;
44 // using namespace NLMISC;
46 namespace NL3D {
48 namespace {
49 #include "fxaa_program.h"
50 } /* anonymous namespace */
54 #ifdef DEBUG_NEW
55 #define new DEBUG_NEW
56 #endif
58 namespace NL3D {
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();
70 // arbfp1
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);
78 // ps_2_0
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");
90 delete m_PP;
91 m_PP = NULL;
93 else
95 nldebug("3D: FXAA pixel program available");
99 if (!m_PP)
101 return;
104 // create vp
106 m_VP = new CVertexProgram();
107 // nelvp
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");
119 delete m_VP;
120 m_VP = NULL;
121 delete m_PP;
122 m_PP = NULL;
124 else
126 nldebug("3D: FXAA vertex program available");
130 if (!m_VP)
132 return;
135 // create material and vb
137 m_Mat = m_Driver->createMaterial();
138 m_Mat.initUnlit();
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);
161 else
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);
167 /*}*/
169 /*CVertexBuffer &vb = m_VB;
170 vb.clearValueEx();
171 vb.addValueEx(CVertexBuffer::Position, CVertexBuffer::Float3);
172 vb.addValueEx(CVertexBuffer::TexCoord0, CVertexBuffer::Float2);
173 vb.addValueEx(CVertexBuffer::TexCoord1, CVertexBuffer::Float4);
174 vb.initEx();
175 vb.setPreferredMemory(CVertexBuffer::RAMVolatile, false);
176 vb.setNumVertices(4);*/
180 CFXAA::~CFXAA()
182 nldebug("3D: Destroy FXAA");
184 if (!m_Mat.empty())
186 m_Driver->deleteMaterial(m_Mat);
189 delete m_VP;
190 m_VP = NULL;
191 delete m_PP;
192 m_PP = NULL;
194 m_Driver = NULL;
197 void CFXAA::applyEffect()
199 if (!m_PP)
200 return;
202 CDriverUser *dru = static_cast<CDriverUser *>(m_Driver);
203 IDriver *drv = dru->getDriver();
205 // backup
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;
224 float n = 0.5f;
226 //if (width != m_Width || height != m_Height)
228 // Build VB
229 m_Width = width;
230 m_Height = height;
231 CVertexBufferReadWrite vba;
232 m_VB.lock(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();
258 // debug
259 // m_Driver->clearBuffers(CRGBA(128, 128, 128, 128));
261 // activate program
262 bool vpok = drv->activeVertexProgram(m_VP);
263 nlassert(vpok);
264 bool ppok = drv->activePixelProgram(m_PP);
265 nlassert(ppok);
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);
275 // render effect
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);
286 // restore
287 m_Driver->enableFog(fogEnabled);
289 // recycle render target
290 m_Driver->getRenderTargetManager().recycleRenderTarget(otherRenderTarget);
293 } /* namespace NL3D */
295 /* end of file */