Change Encyclo button name and macros icon
[ryzomcore.git] / nel / src / 3d / driver / opengl / driver_opengl_light.cpp
bloba9b62b6b642afd34e3493d424f884c2922b6a98b
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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 "stdopengl.h"
19 #include "driver_opengl.h"
20 #include "nel/3d/light.h"
22 #ifdef DEBUG_NEW
23 #define new DEBUG_NEW
24 #endif
26 namespace NL3D {
28 #ifdef NL_STATIC
29 #ifdef USE_OPENGLES
30 namespace NLDRIVERGLES {
31 #else
32 namespace NLDRIVERGL {
33 #endif
34 #endif
36 // ***************************************************************************
37 uint CDriverGL::getMaxLight () const
39 H_AUTO_OGL(CDriverGL_getMaxLight )
40 // return min(maxLight supported by openGL, MaxLight=8).
41 return _MaxDriverLight;
45 // ***************************************************************************
46 void CDriverGL::setLight (uint8 num, const CLight& light)
48 H_AUTO_OGL(CDriverGL_setLight )
49 // bkup real light, for lightmap dynamic lighting purpose
50 if(num==0)
52 _UserLight0= light;
53 // because the GL setup change, must dirt lightmap rendering
54 _LightMapDynamicLightDirty= true;
57 setLightInternal(num, light);
61 // ***************************************************************************
62 void CDriverGL::setLightInternal(uint8 num, const CLight& light)
64 H_AUTO_OGL(CDriverGL_setLightInternal)
65 // Check light count is good
66 // nlassert (num<_MaxDriverLight);
68 // Set the light
69 if (num<_MaxDriverLight)
71 // GL light number
72 GLenum lightNum=(GLenum)(GL_LIGHT0+num);
74 // Get light mode
75 CLight::TLightMode mode=light.getMode ();
77 // Copy the mode
78 _LightMode[num]=mode;
80 // Set the ambiant color
81 GLfloat colorGL[4];
82 CRGBA colorNeL=light.getAmbiant ();
83 colorGL[0]=(float)colorNeL.R/255.f;
84 colorGL[1]=(float)colorNeL.G/255.f;
85 colorGL[2]=(float)colorNeL.B/255.f;
86 colorGL[3]=1.f;
87 glLightfv (lightNum, GL_AMBIENT, colorGL);
89 // Set the diffuse color
90 colorNeL=light.getDiffuse ();
91 colorGL[0]=(float)colorNeL.R/255.f;
92 colorGL[1]=(float)colorNeL.G/255.f;
93 colorGL[2]=(float)colorNeL.B/255.f;
94 colorGL[3]=1.f;
95 glLightfv (lightNum, GL_DIFFUSE, colorGL);
97 // Set the specular color
98 colorNeL=light.getSpecular ();
99 // don't know why, but with ATI cards, specular of 0 causes incorrect rendering (random specular is added)
100 if (_Extensions.ATITextureEnvCombine3)
102 // special case for ATI (there will be some specular, but there's a bug otherwise)
103 colorGL[0]=std::max(1.f / 1024.f, (float)colorNeL.R/255.f);
104 colorGL[1]=std::max(1.f / 1024.f, (float)colorNeL.G/255.f);
105 colorGL[2]=std::max(1.f / 1024.f, (float)colorNeL.B/255.f);
106 colorGL[3]=1.f;
108 else
110 colorGL[0]=(float)colorNeL.R/255.f;
111 colorGL[1]=(float)colorNeL.G/255.f;
112 colorGL[2]=(float)colorNeL.B/255.f;
113 colorGL[3]=1.f;
115 glLightfv (lightNum, GL_SPECULAR, colorGL);
117 // Set light attenuation
118 glLightf (lightNum, GL_CONSTANT_ATTENUATION, light.getConstantAttenuation());
119 glLightf (lightNum, GL_LINEAR_ATTENUATION, light.getLinearAttenuation());
120 glLightf (lightNum, GL_QUADRATIC_ATTENUATION, light.getQuadraticAttenuation());
122 // Set the position
123 if ((mode==CLight::DirectionalLight)||(mode==CLight::SpotLight))
125 // Get the direction of the light
126 _WorldLightDirection[num]=light.getDirection ();
129 if (mode!=CLight::DirectionalLight)
131 // Get the position of the light
132 _WorldLightPos[num]=light.getPosition ();
135 if (mode==CLight::SpotLight)
137 // Get the exponent of the spot
138 float exponent=light.getExponent ();
140 // Set it
141 glLightf (lightNum, GL_SPOT_EXPONENT, exponent);
143 // Get the cutoff of the spot
144 float cutoff=180.f*(light.getCutoff ()/(float)NLMISC::Pi);
146 // Set it
147 glLightf (lightNum, GL_SPOT_CUTOFF, cutoff);
149 else
151 // Disable spot properties
152 #ifdef USE_OPENGLES
153 glLightf (lightNum, GL_SPOT_CUTOFF, 180.f);
154 glLightf (lightNum, GL_SPOT_EXPONENT, 0.f);
155 #else
156 glLighti (lightNum, GL_SPOT_CUTOFF, 180);
157 glLighti (lightNum, GL_SPOT_EXPONENT, 0);
158 #endif
161 // Flag this light as dirt.
162 _LightDirty[num]= true;
164 // dirt the lightSetup and hence the render setup
165 _LightSetupDirty= true;
166 _RenderSetupDirty=true;
170 // ***************************************************************************
171 void CDriverGL::enableLight (uint8 num, bool enable)
173 H_AUTO_OGL(CDriverGL_enableLight )
174 // User call => set the User flag
175 if(num<_MaxDriverLight)
177 _UserLightEnable[num]= enable;
180 // enable the light in GL
181 enableLightInternal(num, enable);
183 // because the GL setup has changed, must dirt lightmap rendering
184 _LightMapDynamicLightDirty= true;
188 // ***************************************************************************
189 void CDriverGL::enableLightInternal(uint8 num, bool enable)
191 H_AUTO_OGL(CDriverGL_enableLightInternal)
192 // Check light count is good
193 // nlassert (num<_MaxDriverLight);
195 // Enable glLight
196 if (num<_MaxDriverLight)
198 _DriverGLStates.enableLight(num, enable);
200 // If this light is dirty, and reenabled, then it must be refresh at next render => set the global flag.
201 if (enable && _LightDirty[num])
203 _LightSetupDirty= true;
204 _RenderSetupDirty= true;
210 // ***************************************************************************
212 void CDriverGL::setAmbientColor (CRGBA color)
214 H_AUTO_OGL(CDriverGL_setAmbientColor )
215 // Gl array
216 GLfloat array[4];
217 array[0]=(float)color.R/255.f;
218 array[1]=(float)color.G/255.f;
219 array[2]=(float)color.B/255.f;
220 array[3]=1.f;
222 // Set the color
223 glLightModelfv (GL_LIGHT_MODEL_AMBIENT, array);
227 // ***************************************************************************
228 void CDriverGL::cleanLightSetup ()
230 H_AUTO_OGL(CDriverGL_cleanLightSetup )
231 // Should be dirty
232 nlassert (_LightSetupDirty);
234 // First light
235 bool first=true;
237 // For each lights
238 for (uint i=0; i<_MaxDriverLight; i++)
240 // Is this light enabled and dirty?
241 if (_DriverGLStates.isLightEnabled(i) && _LightDirty[i])
243 // If first light
244 if (first)
246 first=false;
248 // Push the matrix
249 glPushMatrix ();
251 // Load the view matrix
252 glLoadMatrixf (_ViewMtx.get());
255 // Light is directionnal ?
256 if (_LightMode[i]==(uint)CLight::DirectionalLight)
258 // GL vector
259 GLfloat vectorGL[4];
261 // Set the GL array
262 vectorGL[0]=-_WorldLightDirection[i].x;
263 vectorGL[1]=-_WorldLightDirection[i].y;
264 vectorGL[2]=-_WorldLightDirection[i].z;
265 vectorGL[3]=0.f;
267 // Set it
268 glLightfv ((GLenum)(GL_LIGHT0+i), (GLenum)GL_POSITION, vectorGL);
271 // Spotlight ?
272 if (_LightMode[i]==(uint)CLight::SpotLight)
274 // GL vector
275 GLfloat vectorGL[4];
277 // Set the GL array
278 vectorGL[0]=_WorldLightDirection[i].x;
279 vectorGL[1]=_WorldLightDirection[i].y;
280 vectorGL[2]=_WorldLightDirection[i].z;
282 // Set it
283 glLightfv ((GLenum)(GL_LIGHT0+i), (GLenum)GL_SPOT_DIRECTION, vectorGL);
286 // Position
287 if (_LightMode[i]!=(uint)CLight::DirectionalLight)
289 // GL vector
290 GLfloat vectorGL[4];
292 // Set the GL array
293 // Must Substract CameraPos, because ViewMtx may not be the exact view.
294 vectorGL[0]=_WorldLightPos[i].x - _PZBCameraPos.x;
295 vectorGL[1]=_WorldLightPos[i].y - _PZBCameraPos.y;
296 vectorGL[2]=_WorldLightPos[i].z - _PZBCameraPos.z;
297 vectorGL[3]=1.f;
299 // Set it
300 glLightfv ((GLenum)(GL_LIGHT0+i), (GLenum)GL_POSITION, vectorGL);
303 // Cleaned!
304 _LightDirty[i]= false;
308 // Pop old matrix
309 if (!first)
310 glPopMatrix ();
312 // Clean flag
313 _LightSetupDirty=false;
317 // ***************************************************************************
318 void CDriverGL::setLightMapDynamicLight (bool enable, const CLight& light)
320 H_AUTO_OGL(CDriverGL_setLightMapDynamicLight )
321 // just store, for future setup in lightmap material rendering
322 _LightMapDynamicLightEnabled= enable;
323 _LightMapDynamicLight= light;
324 _LightMapDynamicLightDirty= true;
328 // ***************************************************************************
329 void CDriverGL::setupLightMapDynamicLighting(bool enable)
331 H_AUTO_OGL(CDriverGL_setupLightMapDynamicLighting)
332 // start lightmap dynamic lighting
333 if(enable)
335 // disable all lights but the 0th.
336 for(uint i=1;i<_MaxDriverLight;i++)
337 enableLightInternal(i, false);
339 // if the dynamic light is really enabled
340 if(_LightMapDynamicLightEnabled)
342 // then setup and enable
343 setLightInternal(0, _LightMapDynamicLight);
344 enableLightInternal(0, true);
346 // else just disable also the light 0
347 else
349 enableLightInternal(0, false);
352 // ok it has been setup
353 _LightMapDynamicLightDirty= false;
355 // restore old lighting
356 else
358 // restore the light 0
359 setLightInternal(0, _UserLight0);
361 // restore all standard light enable states
362 for(uint i=0;i<_MaxDriverLight;i++)
363 enableLightInternal(i, _UserLightEnable[i]);
366 // in all case, must refresh render setup, cause lighting may be modified
367 refreshRenderSetup();
370 #ifdef NL_STATIC
371 } // NLDRIVERGL/ES
372 #endif
374 } // NL3D