1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stddirect3d.h"
19 #include "nel/3d/vertex_buffer.h"
20 #include "nel/3d/light.h"
21 #include "nel/3d/index_buffer.h"
22 #include "nel/misc/rect.h"
23 #include "nel/3d/viewport.h"
24 #include "nel/3d/scissor.h"
25 #include "nel/3d/u_driver.h"
27 #include "driver_direct3d.h"
34 using namespace NLMISC
;
39 // ***************************************************************************
41 void CDriverD3D::updateMatrices ()
43 H_AUTO_D3D(CDriver3D_updateMatrices
);
44 // Update view model matrix
45 D3DXMatrixMultiply (&_D3DModelView
, &(_MatrixCache
[remapMatrixIndex (D3DTS_WORLD
)].Matrix
), &(_MatrixCache
[remapMatrixIndex (D3DTS_VIEW
)].Matrix
));
47 // Update view model projection matrix
48 _D3DModelViewProjection
= _D3DModelView
;
49 D3DXMatrixMultiply (&_D3DModelViewProjection
, &_D3DModelViewProjection
, &(_MatrixCache
[remapMatrixIndex (D3DTS_PROJECTION
)].Matrix
));
51 // Update the inverted view model matrix
52 D3DXMatrixInverse (&_D3DInvModelView
, NULL
, &_D3DModelView
);
54 // Update the normalize state
55 setRenderState (D3DRS_NORMALIZENORMALS
, (_UserViewMtx
.hasScalePart() || _UserModelMtx
.hasScalePart() || _ForceNormalize
)?TRUE
:FALSE
);
58 // ***************************************************************************
60 void CDriverD3D::updateProjectionMatrix ()
62 H_AUTO_D3D(CDriver3D_updateProjectionMatrix
);
63 float left
= _FrustumLeft
;
64 float right
= _FrustumRight
;
65 float top
= _FrustumTop
;
66 float bottom
= _FrustumBottom
;
68 if (_RenderTarget
.Texture
)
71 // Get the render target size
74 getRenderTargetSize (clientWidth
, clientHeight
);
76 // In D3D, the center of the first screen pixel is [0.0,0.0]. Is NeL it is [0.5,0.5]
77 const float addW
= (right
-left
)/(2*(_Viewport
.getWidth() * (float)clientWidth
));
78 const float addH
= (bottom
-top
)/(2*(_Viewport
.getHeight() * (float)clientHeight
));
85 D3DXMATRIX projection
;
86 if (_FrustumPerspective
)
88 D3DXMatrixPerspectiveOffCenterLH (&projection
, left
, right
, bottom
, top
, _FrustumZNear
, _FrustumZFar
);
92 D3DXMatrixOrthoOffCenterLH (&projection
, left
, right
, bottom
, top
, _FrustumZNear
, _FrustumZFar
);
94 setMatrix (D3DTS_PROJECTION
, projection
);
96 // Backup znear and zfar for zbias setup
97 _OODeltaZ
= 1 / (_FrustumZFar
- _FrustumZNear
);
102 // ***************************************************************************
104 void CDriverD3D::setFrustum(float left
, float right
, float bottom
, float top
, float znear
, float zfar
, bool perspective
)
106 H_AUTO_D3D(CDriverD3D_setFrustum
)
108 _FrustumRight
= right
;
110 _FrustumBottom
= bottom
;
111 _FrustumZNear
= znear
;
113 _FrustumPerspective
= perspective
;
114 updateProjectionMatrix ();
118 // ***************************************************************************
120 void CDriverD3D::setFrustumMatrix(CMatrix
&frustumMatrix
)
122 H_AUTO_D3D(CDriverD3D_setFrustum
)
124 frustumMatrix
.transpose();
125 setMatrix (D3DTS_PROJECTION
, D3DXMATRIX(frustumMatrix
.get()));
128 // ***************************************************************************
130 CMatrix
CDriverD3D::getFrustumMatrix()
132 H_AUTO_D3D(CDriverD3D_getFrustum
)
134 CMatrix frustumMatrix
;
135 frustumMatrix
.set((float *)_MatrixCache
[D3DTS_PROJECTION
].Matrix
.m
);
136 frustumMatrix
.transpose();
138 return frustumMatrix
;
141 // ***************************************************************************
143 void CDriverD3D::setupViewMatrix(const CMatrix
& mtx
)
145 H_AUTO_D3D(CDriverD3D_setupViewMatrix
)
146 // Remember the view matrix
148 _PZBCameraPos
= CVector::Null
;
150 // Set the driver matrix
152 NL_D3D_MATRIX (view
, mtx
);
154 // Pass to directx matrix basis
155 swap (view
._12
, view
._13
);
156 swap (view
._22
, view
._23
);
157 swap (view
._32
, view
._33
);
158 swap (view
._42
, view
._43
);
160 setMatrix (D3DTS_VIEW
, view
);
162 // Set the spacular matrix
165 specularTex
.setPos(CVector(0.0f
,0.0f
,0.0f
));
166 specularTex
.invert();
167 NL_D3D_MATRIX (_D3DSpecularWorldTex
, specularTex
);
172 // ***************************************************************************
174 void CDriverD3D::setupViewMatrixEx(const CMatrix
& mtx
, const CVector
&cameraPos
)
176 H_AUTO_D3D(CDriverD3D_setupViewMatrixEx
)
177 // Remeber the view matrix
179 _PZBCameraPos
= cameraPos
;
181 // Set the driver matrix
183 NL_D3D_MATRIX (view
, mtx
);
185 // Pass to directx matrix basis
186 swap (view
._12
, view
._13
);
187 swap (view
._22
, view
._23
);
188 swap (view
._32
, view
._33
);
189 swap (view
._42
, view
._43
);
191 // Reset the viewMtx position.
196 setMatrix (D3DTS_VIEW
, view
);
198 // Set the spacular matrix
201 NL_D3D_MATRIX (_D3DSpecularWorldTex
, specularTex
);
202 swap (_D3DSpecularWorldTex
._12
, _D3DSpecularWorldTex
._13
);
203 swap (_D3DSpecularWorldTex
._22
, _D3DSpecularWorldTex
._23
);
204 swap (_D3DSpecularWorldTex
._32
, _D3DSpecularWorldTex
._33
);
205 swap (_D3DSpecularWorldTex
._42
, _D3DSpecularWorldTex
._43
);
206 _D3DSpecularWorldTex
._41
= 0;
207 _D3DSpecularWorldTex
._42
= 0;
208 _D3DSpecularWorldTex
._43
= 0;
210 D3DXMatrixInverse ( &_D3DSpecularWorldTex
, NULL
, &_D3DSpecularWorldTex
);
211 swap (_D3DSpecularWorldTex
._12
, _D3DSpecularWorldTex
._13
);
212 swap (_D3DSpecularWorldTex
._22
, _D3DSpecularWorldTex
._23
);
213 swap (_D3DSpecularWorldTex
._32
, _D3DSpecularWorldTex
._33
);
214 swap (_D3DSpecularWorldTex
._42
, _D3DSpecularWorldTex
._43
);
219 // ***************************************************************************
221 void CDriverD3D::setupModelMatrix(const CMatrix
& mtx
)
223 H_AUTO_D3D(CDriverD3D_setupModelMatrix
)
225 _NbSetupModelMatrixCall
++;
227 // Remeber the model matrix
231 NL_D3D_MATRIX (world
, mtx
);
233 // Remove from position the camera position
234 world
._41
-= _PZBCameraPos
.x
;
235 world
._42
-= _PZBCameraPos
.y
;
236 world
._43
-= _PZBCameraPos
.z
;
238 setMatrix (D3DTS_WORLD
, world
);
243 // ***************************************************************************
245 CMatrix
CDriverD3D::getViewMatrix() const
247 H_AUTO_D3D(CDriverD3D_getViewMatrix
)
251 // ***************************************************************************
253 void CDriverD3D::forceNormalize(bool normalize
)
255 H_AUTO_D3D(CDriverD3D_forceNormalize
)
256 _ForceNormalize
= normalize
;
260 // ***************************************************************************
262 bool CDriverD3D::isForceNormalize() const
264 H_AUTO_D3D(CDriverD3D_isForceNormalize
)
265 return _RenderStateCache
[D3DRS_NORMALIZENORMALS
].Value
!= FALSE
;
270 // ***************************************************************************
272 void CDriverD3D::setupScissor (const class CScissor
& scissor
)
274 H_AUTO_D3D(CDriverD3D_setupScissor
)
275 if (!_ScissorTouched
&&
276 _Scissor
.X
== scissor
.X
&&
277 _Scissor
.Y
== scissor
.Y
&&
278 _Scissor
.Width
== scissor
.Width
&&
279 _Scissor
.Height
== scissor
.Height
281 nlassert (_DeviceInterface
);
284 _ScissorTouched
= false;
287 float width
= scissor
.Width
;
288 float height
= scissor
.Height
;
290 if(x
==0 && y
==0 && width
==1 && height
==1)
292 setRenderState (D3DRS_SCISSORTESTENABLE
, FALSE
);
298 // Get the render target size
301 getRenderTargetSize (clientWidth
, clientHeight
);
306 rect
.left
=(int)floor((float)clientWidth
* x
+ 0.5f
);
307 clamp (rect
.left
, 0, (int)clientWidth
);
308 if (_RenderTarget
.Texture
)
309 rect
.top
=(int)floor((float)clientHeight
* y
+ 0.5f
);
311 rect
.top
=(int)floor((float)clientHeight
* (1-y
-height
) + 0.5f
);
312 clamp (rect
.top
, 0, (int)clientHeight
);
314 rect
.right
=(int)floor((float)clientWidth
* (x
+width
) + 0.5f
);
315 clamp (rect
.right
, 0, (int)clientWidth
);
316 if (_RenderTarget
.Texture
)
317 rect
.bottom
=(int)floor((float)clientHeight
* (y
+height
) + 0.5f
);
319 rect
.bottom
=(int)floor((float)clientHeight
* (1-y
) + 0.5f
);
320 clamp (rect
.bottom
, 0, (int)clientHeight
);
323 H_AUTO_D3D(CDriverD3D_setupScissorDevice
)
324 _DeviceInterface
->SetScissorRect (&rect
);
326 setRenderState (D3DRS_SCISSORTESTENABLE
, TRUE
);
331 // Backup the scissor
335 // ***************************************************************************
337 void CDriverD3D::setupViewport (const class CViewport
& viewport
)
339 H_AUTO_D3D(CDriverD3D_setupViewport
)
343 // Get the render target size
346 getRenderTargetSize (clientWidth
, clientHeight
);
353 viewport
.getValues (x
, y
, width
, height
);
355 // Get integer values
356 int ix
=(int)((float)clientWidth
*x
);
357 clamp (ix
, 0, (int)clientWidth
);
359 if (_RenderTarget
.Texture
)
360 iy
=(int)((float)clientHeight
*y
);
362 iy
=(int)((float)clientHeight
*(1.f
-(y
+height
)));
363 clamp (iy
, 0, (int)clientHeight
);
364 int iwidth
=(int)((float)clientWidth
*width
);
365 clamp (iwidth
, 0, (int)clientWidth
-ix
);
366 int iheight
=(int)((float)clientHeight
*height
);
367 clamp (iheight
, 0, (int)clientHeight
-iy
);
369 // Setup D3D viewport
372 _D3DViewport
.Width
= iwidth
;
373 _D3DViewport
.Height
= iheight
;
374 _D3DViewport
.MinZ
= _DepthRangeNear
;
375 _D3DViewport
.MaxZ
= _DepthRangeFar
;
376 _DeviceInterface
->SetViewport (&_D3DViewport
);
378 // Backup the viewport
379 _Viewport
= viewport
;
381 updateProjectionMatrix ();
384 // ***************************************************************************
385 void CDriverD3D::setDepthRange(float znear
, float zfar
)
387 H_AUTO_D3D(CDriverD3D_setDepthRange
)
388 nlassert(znear
!= zfar
);
391 #ifdef NL_D3D_USE_RENDER_STATE_CACHE
392 NL_D3D_CACHE_TEST(CacheTest_DepthRange
, znear
!= _DepthRangeNear
|| zfar
!= _DepthRangeFar
)
395 _DepthRangeNear
= znear
;
396 _DepthRangeFar
= zfar
;
397 _D3DViewport
.MinZ
= _DepthRangeNear
;
398 _D3DViewport
.MaxZ
= _DepthRangeFar
;
399 _DeviceInterface
->SetViewport (&_D3DViewport
);
403 // ***************************************************************************
404 void CDriverD3D::getDepthRange(float &znear
, float &zfar
) const
406 H_AUTO_D3D(CDriverD3D_getDepthRange
)
407 znear
= _DepthRangeNear
;
408 zfar
= _DepthRangeFar
;
411 // ***************************************************************************
413 void CDriverD3D::getViewport(CViewport
&viewport
)
415 H_AUTO_D3D(CDriverD3D_getViewport
)
416 viewport
= _Viewport
;
419 // ***************************************************************************