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 // ***************************************************************************
40 const D3DLIGHTTYPE RemapLightTypeNeL2D3D
[3]=
42 D3DLIGHT_DIRECTIONAL
, // CLight::DirectionalLight
43 D3DLIGHT_POINT
, // CLight::PointLight
44 D3DLIGHT_SPOT
, // CLight::SpotLight
48 // ***************************************************************************
49 void CDriverD3D::setLight (uint8 index
, const CLight
&light
)
51 H_AUTO_D3D(CDriverD3D_setLight
);
52 // bkup real light, for lightmap dynamic lighting purpose
56 // because the D3D setup change, must dirt lightmap rendering
57 _LightMapDynamicLightDirty
= true;
60 setLightInternal(index
, light
);
64 // ***************************************************************************
65 void CDriverD3D::enableLight (uint8 index
, bool enable
)
67 H_AUTO_D3D(CDriverD3D_enableLight
);
68 // User call => set the User flag
71 _UserLightEnable
[index
]= enable
;
74 // enable the light in D3D
75 enableLightInternal(index
, enable
);
77 // because the D3D setup has changed, must dirt lightmap rendering
78 _LightMapDynamicLightDirty
= true;
81 static const float sqrtFLT_MAX
= (float) sqrtf(FLT_MAX
);
83 // ***************************************************************************
84 void CDriverD3D::setLightInternal (uint8 index
, const CLight
&light
)
86 H_AUTO_D3D(CDriverD3D_setLightInternal
);
87 nlassert (_DeviceInterface
);
91 D3DLIGHT9
&lightRef
= _LightCache
[index
].Light
;
92 lightRef
.Type
= RemapLightTypeNeL2D3D
[light
.getMode ()];
93 NL_D3DCOLORVALUE_RGBA(lightRef
.Diffuse
, light
.getDiffuse());
94 NL_D3DCOLORVALUE_RGBA(lightRef
.Specular
, light
.getSpecular());
95 NL_D3DCOLORVALUE_RGBA(lightRef
.Ambient
, light
.getAmbiant());
96 CVector vect
= light
.getPosition();
97 NL_D3DVECTOR_VECTOR (lightRef
.Position
, vect
);
98 vect
= light
.getDirection();
99 NL_D3DVECTOR_VECTOR (lightRef
.Direction
, vect
);
100 lightRef
.Range
= sqrtFLT_MAX
;
101 lightRef
.Falloff
= 1;
102 lightRef
.Attenuation0
= light
.getConstantAttenuation();
103 lightRef
.Attenuation1
= light
.getLinearAttenuation();
104 lightRef
.Attenuation2
= light
.getQuadraticAttenuation();
105 if (lightRef
.Type
== D3DLIGHT_SPOT
)
107 lightRef
.Phi
= light
.getCutoff();
108 float divid
=light
.getExponent();
111 float hotSpotAngle
= (float)acos(exp(log (0.9)/divid
));
112 lightRef
.Theta
= hotSpotAngle
;
116 lightRef
.Phi
= (float) NLMISC::Pi
* 0.5f
;
117 lightRef
.Theta
= (float) NLMISC::Pi
* 0.25f
;
121 _LightCache
[index
].SettingsTouched
= true;
123 // Touch only if enabled
124 if (_LightCache
[index
].Enabled
)
125 touchRenderVariable (&_LightCache
[index
]);
129 // ***************************************************************************
130 void CDriverD3D::enableLightInternal (uint8 index
, bool enable
)
132 H_AUTO_D3D(CDriverD3D_enableLightInternal
);
133 nlassert (_DeviceInterface
);
136 if (_LightCache
[index
].Enabled
!= enable
)
138 _LightCache
[index
].Enabled
= enable
;
139 _LightCache
[index
].EnabledTouched
= true;
140 touchRenderVariable (&_LightCache
[index
]);
145 // ***************************************************************************
146 uint
CDriverD3D::getMaxLight () const
148 H_AUTO_D3D(CDriverD3D_getMaxLight
);
152 // ***************************************************************************
153 void CDriverD3D::setAmbientColor (CRGBA color
)
155 H_AUTO_D3D(CDriverD3D_setAmbientColor
);
156 setRenderState(D3DRS_AMBIENT
, NL_D3DCOLOR_RGBA(color
));
160 // ***************************************************************************
161 void CDriverD3D::setLightMapDynamicLight (bool enable
, const CLight
& light
)
163 H_AUTO_D3D(CDriverD3D_setLightMapDynamicLight
);
164 // just store, for future setup in lightmap material rendering
165 _LightMapDynamicLightEnabled
= enable
;
166 _LightMapDynamicLight
= light
;
167 _LightMapDynamicLightDirty
= true;
171 // ***************************************************************************
172 void CDriverD3D::setupLightMapDynamicLighting(bool enable
)
174 H_AUTO_D3D(CDriverD3D_setupLightMapDynamicLighting
);
175 // start lightmap dynamic lighting
178 // disable all lights but the 0th.
179 for(uint i
=1;i
<_MaxLight
;++i
)
180 enableLightInternal(uint8(i
), false);
182 // if the dynamic light is really enabled
183 if(_LightMapDynamicLightEnabled
)
185 // then setup and enable
186 setLightInternal(0, _LightMapDynamicLight
);
187 enableLightInternal(0, true);
189 // else just disable also the light 0
192 enableLightInternal(0, false);
195 // ok it has been setup
196 _LightMapDynamicLightDirty
= false;
198 // restore old lighting
201 // restore the light 0
202 setLightInternal(0, _UserLight0
);
204 // restore all standard light enable states
205 for(uint i
=0;i
<_MaxLight
;++i
)
206 enableLightInternal(uint8(i
), _UserLightEnable
[i
]);