2 * \file stereo_debugger.cpp
3 * \brief CStereoDebugger
4 * \date 2013-07-03 20:17GMT
5 * \author Jan Boon (Kaetemi)
9 // NeL - MMORPG Framework <https://wiki.ryzom.dev/>
10 // Copyright (C) 2013-2014 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/>.
27 #include "nel/3d/stereo_debugger.h"
32 // #include <nel/misc/debug.h>
35 #include "nel/3d/u_camera.h"
36 #include "nel/3d/u_driver.h"
37 #include "nel/3d/material.h"
38 #include "nel/3d/texture_bloom.h"
39 #include "nel/3d/texture_user.h"
40 #include "nel/3d/driver_user.h"
41 #include "nel/3d/u_texture.h"
42 #include "nel/3d/render_target_manager.h"
45 // using namespace NLMISC;
55 const char *a_arbfp1
=
57 "PARAM c[1] = { { 1, 0, 0.5 } };\n"
61 "TEX R0, fragment.texcoord[0], texture[0], 2D;\n"
62 "TEX R1, fragment.texcoord[0], texture[1], 2D;\n"
65 "MUL R1, R1, c[0].z;\n"
67 "CMP R2, -R2, c[0].x, c[0].y;\n"
68 "ADD_SAT R2.x, R2, R2.y;\n"
69 "ADD_SAT R2.x, R2, R2.z;\n"
70 "ADD_SAT R2.x, R2, R2.w;\n"
72 "CMP R2.x, -R2, c[0].y, c[0];\n"
74 "CMP R2.x, -R0, c[0].y, c[0];\n"
76 "MAD R0.y, R1, c[0].z, c[0].z;\n"
77 "CMP R0, -R2.x, R1, R0;\n"
78 "MAD R1.x, R0, c[0].z, c[0].z;\n"
79 "CMP result.color.x, -R2, R1, R0;\n"
80 "MOV result.color.yzw, R0;\n"
83 const char *a_ps_2_0
=
85 // cgc version 3.1.0013, build date Apr 18 2012
86 // command line args: -profile ps_2_0
87 // source file: pp_stereo_debug.cg
88 //vendor NVIDIA Corporation
91 //program pp_stereo_debug
92 //semantic pp_stereo_debug.cTex0 : TEX0
93 //semantic pp_stereo_debug.cTex1 : TEX1
94 //var float2 texCoord : $vin.TEXCOORD0 : TEX0 : 0 : 1
95 //var sampler2D cTex0 : TEX0 : texunit 0 : 1 : 1
96 //var sampler2D cTex1 : TEX1 : texunit 1 : 2 : 1
97 //var float4 oCol : $vout.COLOR : COL : 3 : 1
98 //const c[0] = 0 1 0.5
101 "def c0, 0.00000000, 1.00000000, 0.50000000, 0\n"
109 "cmp r0, -r0, c0.x, c0.y\n"
110 "add_pp_sat r0.x, r0, r0.y\n"
111 "add_pp_sat r0.x, r0, r0.z\n"
112 "add_pp_sat r0.x, r0, r0.w\n"
114 "cmp_pp r0.x, -r0, c0.y, c0\n"
117 "mad r2.y, r1, c0.z, c0.z\n"
118 "cmp r2, -r0.x, r1, r2\n"
119 "mad r1.x, r2, c0.z, c0.z\n"
121 "cmp r0.x, -r0, r1, r2\n"
124 class CStereoDebuggerFactory
: public IStereoDeviceFactory
127 IStereoDisplay
*createDevice() const
129 return new CStereoDebugger();
133 } /* anonymous namespace */
135 CStereoDebugger::CStereoDebugger() : m_Driver(NULL
), m_Stage(0), m_SubStage(0), m_LeftTexU(NULL
), m_RightTexU(NULL
), m_PixelProgram(NULL
)
140 CStereoDebugger::~CStereoDebugger()
144 m_Driver
->deleteMaterial(m_Mat
);
147 delete m_PixelProgram
;
148 m_PixelProgram
= NULL
;
153 /// Sets driver and generates necessary render targets
154 void CStereoDebugger::setDriver(NL3D::UDriver
*driver
)
156 nlassert(!m_PixelProgram
);
159 NL3D::IDriver
*drvInternal
= (static_cast<CDriverUser
*>(driver
))->getDriver();
161 if (drvInternal
->supportBloomEffect() && drvInternal
->supportNonPowerOfTwoTextures())
163 m_PixelProgram
= new CPixelProgram();
166 IProgram::CSource
*source
= new IProgram::CSource();
167 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
168 source
->Profile
= IProgram::arbfp1
;
169 source
->setSourcePtr(a_arbfp1
);
170 m_PixelProgram
->addSource(source
);
174 IProgram::CSource
*source
= new IProgram::CSource();
175 source
->Features
.MaterialFlags
= CProgramFeatures::TextureStages
;
176 source
->Profile
= IProgram::ps_2_0
;
177 source
->setSourcePtr(a_ps_2_0
);
178 m_PixelProgram
->addSource(source
);
180 if (!drvInternal
->compilePixelProgram(m_PixelProgram
))
182 nlwarning("No supported pixel program for stereo debugger");
184 delete m_PixelProgram
;
185 m_PixelProgram
= NULL
;
191 m_Mat
= m_Driver
->createMaterial();
193 m_Mat
.setColor(CRGBA::White
);
194 m_Mat
.setBlend (false);
195 m_Mat
.setAlphaTest (false);
196 NL3D::CMaterial
*mat
= m_Mat
.getObjectPtr();
197 mat
->setShader(NL3D::CMaterial::Normal
);
198 mat
->setBlendFunc(CMaterial::one
, CMaterial::zero
);
199 mat
->setZWrite(false);
200 mat
->setZFunc(CMaterial::always
);
201 mat
->setDoubleSided(true);
203 m_QuadUV
.V0
= CVector(0.f
, 0.f
, 0.5f
);
204 m_QuadUV
.V1
= CVector(1.f
, 0.f
, 0.5f
);
205 m_QuadUV
.V2
= CVector(1.f
, 1.f
, 0.5f
);
206 m_QuadUV
.V3
= CVector(0.f
, 1.f
, 0.5f
);
208 m_QuadUV
.Uv0
= CUV(0.f
, 0.f
);
209 m_QuadUV
.Uv1
= CUV(1.f
, 0.f
);
210 m_QuadUV
.Uv2
= CUV(1.f
, 1.f
);
211 m_QuadUV
.Uv3
= CUV(0.f
, 1.f
);
215 bool CStereoDebugger::attachToDisplay()
220 void CStereoDebugger::detachFromDisplay()
225 void CStereoDebugger::getTextures()
227 nlassert(!m_LeftTexU
);
228 nlassert(!m_RightTexU
);
229 uint32 width
, height
;
230 m_Driver
->getWindowSize(width
, height
);
231 m_LeftTexU
= m_Driver
->getRenderTargetManager().getRenderTarget(width
, height
);
232 m_RightTexU
= m_Driver
->getRenderTargetManager().getRenderTarget(width
, height
);
233 NL3D::CMaterial
*mat
= m_Mat
.getObjectPtr();
234 mat
->setTexture(0, m_LeftTexU
->getITexture());
235 mat
->setTexture(1, m_RightTexU
->getITexture());
238 void CStereoDebugger::recycleTextures()
240 nlassert(m_LeftTexU
);
241 nlassert(m_RightTexU
);
242 m_Mat
.getObjectPtr()->setTexture(0, NULL
);
243 m_Mat
.getObjectPtr()->setTexture(1, NULL
);
244 m_Driver
->getRenderTargetManager().recycleRenderTarget(m_LeftTexU
);
245 m_Driver
->getRenderTargetManager().recycleRenderTarget(m_RightTexU
);
251 void CStereoDebugger::releaseTextures()
255 m_Mat.getObjectPtr()->setTexture(0, NULL);
256 m_Mat.getObjectPtr()->setTexture(1, NULL);
257 m_Driver->deleteMaterial(m_Mat);
262 m_LeftTex = NULL; // CSmartPtr
266 m_RightTex = NULL; // CSmartPtr
269 void CStereoDebugger::initTextures()
271 uint32 width, height;
272 m_Driver->getWindowSize(width, height);
273 NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
275 m_LeftTex = new CTextureBloom();
276 m_LeftTex->setRenderTarget(true);
277 m_LeftTex->setReleasable(false);
278 m_LeftTex->resize(width, height);
279 m_LeftTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
280 m_LeftTex->setWrapS(ITexture::Clamp);
281 m_LeftTex->setWrapT(ITexture::Clamp);
282 drvInternal->setupTexture(*m_LeftTex);
283 m_LeftTexU = new CTextureUser(m_LeftTex);
284 nlassert(!drvInternal->isTextureRectangle(m_LeftTex)); // not allowed
286 m_RightTex = new CTextureBloom();
287 m_RightTex->setRenderTarget(true);
288 m_RightTex->setReleasable(false);
289 m_RightTex->resize(width, height);
290 m_RightTex->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
291 m_RightTex->setWrapS(ITexture::Clamp);
292 m_RightTex->setWrapT(ITexture::Clamp);
293 drvInternal->setupTexture(*m_RightTex);
294 m_RightTexU = new CTextureUser(m_RightTex);
295 nlassert(!drvInternal->isTextureRectangle(m_RightTex)); // not allowed
298 void CStereoDebugger::setTextures()
300 NL3D::CMaterial *mat = m_Mat.getObjectPtr();
301 mat->setTexture(0, m_LeftTex);
302 mat->setTexture(1, m_RightTex);
305 void CStereoDebugger::verifyTextures()
309 uint32 width, height;
310 m_Driver->getWindowSize(width, height);
311 if (m_LeftTex->getWidth() != width
312 || m_RightTex->getWidth() != width
313 || m_LeftTex->getHeight() != height
314 || m_RightTex->getHeight() != height)
316 nldebug("Rebuild textures");
324 /// Gets the required screen resolution for this device
325 bool CStereoDebugger::getScreenResolution(uint
&width
, uint
&height
)
330 /// Set latest camera position etcetera
331 void CStereoDebugger::updateCamera(uint cid
, const NL3D::UCamera
*camera
)
333 m_Frustum
[cid
] = camera
->getFrustum();
336 /// Get the frustum to use for clipping
337 void CStereoDebugger::getClippingFrustum(uint cid
, NL3D::UCamera
*camera
) const
342 /// Get the original frustum of the camera
343 void CStereoDebugger::getOriginalFrustum(uint cid
, NL3D::UCamera
*camera
) const
345 // do nothing, as we never modified it
348 /// Is there a next pass
349 bool CStereoDebugger::nextPass()
351 if (m_Driver
->getPolygonMode() == UDriver::Filled
)
390 /// Gets the current viewport
391 const NL3D::CViewport
&CStereoDebugger::getCurrentViewport() const
393 if (m_Stage
% 2) return m_LeftViewport
;
394 else return m_RightViewport
;
397 /// Gets the current camera frustum
398 const NL3D::CFrustum
&CStereoDebugger::getCurrentFrustum(uint cid
) const
400 return m_Frustum
[cid
];
403 /// Gets the current camera frustum
404 void CStereoDebugger::getCurrentFrustum(uint cid
, NL3D::UCamera
*camera
) const
409 /// Gets the current camera matrix
410 void CStereoDebugger::getCurrentMatrix(uint cid
, NL3D::UCamera
*camera
) const
415 /// At the start of a new render target
416 bool CStereoDebugger::wantClear()
423 bool CStereoDebugger::wantScene()
429 /// The 3D scene end (after multiple wantScene)
430 bool CStereoDebugger::wantSceneEffects()
435 /// Interface within the 3D scene
436 bool CStereoDebugger::wantInterface3D()
443 bool CStereoDebugger::wantInterface2D()
449 bool CStereoDebugger::isSceneFirst()
454 bool CStereoDebugger::isSceneLast()
459 /// Returns true if a new render target was set, always fase if not using render targets
460 bool CStereoDebugger::beginRenderTarget()
462 if (m_Stage
!= 3 && m_Driver
&& (m_Driver
->getPolygonMode() == UDriver::Filled
))
464 if (!m_LeftTexU
) getTextures();
465 if (m_Stage
% 2) static_cast<CDriverUser
*>(m_Driver
)->setRenderTarget(*m_RightTexU
, 0, 0, 0, 0);
466 else static_cast<CDriverUser
*>(m_Driver
)->setRenderTarget(*m_LeftTexU
, 0, 0, 0, 0);
472 /// Returns true if a render target was fully drawn, always false if not using render targets
473 bool CStereoDebugger::endRenderTarget()
475 if (m_Stage
!= 3 && m_Driver
&& (m_Driver
->getPolygonMode() == UDriver::Filled
))
478 (static_cast<CDriverUser
*>(m_Driver
))->setRenderTarget(cu
);
479 bool fogEnabled
= m_Driver
->fogEnabled();
480 m_Driver
->enableFog(false);
482 m_Driver
->setMatrixMode2D11();
483 CViewport vp
= CViewport();
484 m_Driver
->setViewport(vp
);
485 uint32 width
, height
;
486 NL3D::IDriver
*drvInternal
= (static_cast<CDriverUser
*>(m_Driver
))->getDriver();
487 NL3D::CMaterial
*mat
= m_Mat
.getObjectPtr();
488 mat
->setTexture(0, m_LeftTexU
->getITexture());
489 mat
->setTexture(1, m_RightTexU
->getITexture());
490 drvInternal
->activePixelProgram(m_PixelProgram
);
492 m_Driver
->drawQuad(m_QuadUV
, m_Mat
);
494 drvInternal
->activePixelProgram(NULL
);
495 m_Driver
->enableFog(fogEnabled
);
503 void CStereoDebugger::listDevices(std::vector
<CStereoDeviceInfo
> &devicesOut
)
505 CStereoDeviceInfo devInfo
;
506 devInfo
.Factory
= new CStereoDebuggerFactory();
507 devInfo
.Library
= CStereoDeviceInfo::NeL3D
;
508 devInfo
.Class
= CStereoDeviceInfo::StereoDisplay
;
509 devInfo
.Manufacturer
= "NeL";
510 devInfo
.ProductName
= "Stereo Debugger";
511 devInfo
.Serial
= "NL-3D-DEBUG";
512 devInfo
.AllowAuto
= false;
513 devicesOut
.push_back(devInfo
);
516 } /* namespace NL3D */
518 #endif /* #if !FINAL_VERSION */