blob: 8ae32cc0f0e11d966a0c4fe60954373a3dcccc02 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/* libs/opengles/light.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <stdio.h>
19#include "context.h"
20#include "fp.h"
21#include "light.h"
22#include "state.h"
23#include "matrix.h"
24
25
26#if defined(__arm__) && defined(__thumb__)
27#warning "light.cpp should not be compiled in thumb on ARM."
28#endif
29
30namespace android {
31
32// ----------------------------------------------------------------------------
33
34static void invalidate_lighting(ogles_context_t* c);
35static void lightVertexValidate(ogles_context_t* c, vertex_t* v);
36static void lightVertexNop(ogles_context_t* c, vertex_t* v);
37static void lightVertex(ogles_context_t* c, vertex_t* v);
38static void lightVertexMaterial(ogles_context_t* c, vertex_t* v);
39
40static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041
42static __attribute__((noinline))
43void vnorm3(GLfixed* d, const GLfixed* a);
44
45static inline void vsa3(GLfixed* d,
46 const GLfixed* m, GLfixed s, const GLfixed* a);
Mathias Agopian69ca17a2009-06-02 22:05:04 -070047static inline void vss3(GLfixed* d,
48 const GLfixed* m, GLfixed s, const GLfixed* a);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049static inline void vmla3(GLfixed* d,
50 const GLfixed* m0, const GLfixed* m1, const GLfixed* a);
51static inline void vmul3(GLfixed* d,
52 const GLfixed* m0, const GLfixed* m1);
53
54static GLfixed fog_linear(ogles_context_t* c, GLfixed z);
55static GLfixed fog_exp(ogles_context_t* c, GLfixed z);
56static GLfixed fog_exp2(ogles_context_t* c, GLfixed z);
57
58
59// ----------------------------------------------------------------------------
60
61static void init_white(vec4_t& c) {
62 c.r = c.g = c.b = c.a = 0x10000;
63}
64
65void ogles_init_light(ogles_context_t* c)
66{
67 for (unsigned int i=0 ; i<OGLES_MAX_LIGHTS ; i++) {
68 c->lighting.lights[i].ambient.a = 0x10000;
69 c->lighting.lights[i].position.z = 0x10000;
70 c->lighting.lights[i].spotDir.z = -0x10000;
71 c->lighting.lights[i].spotCutoff = gglIntToFixed(180);
72 c->lighting.lights[i].attenuation[0] = 0x10000;
73 }
74 init_white(c->lighting.lights[0].diffuse);
75 init_white(c->lighting.lights[0].specular);
76
77 c->lighting.front.ambient.r =
78 c->lighting.front.ambient.g =
79 c->lighting.front.ambient.b = gglFloatToFixed(0.2f);
80 c->lighting.front.ambient.a = 0x10000;
81 c->lighting.front.diffuse.r =
82 c->lighting.front.diffuse.g =
83 c->lighting.front.diffuse.b = gglFloatToFixed(0.8f);
84 c->lighting.front.diffuse.a = 0x10000;
85 c->lighting.front.specular.a = 0x10000;
86 c->lighting.front.emission.a = 0x10000;
87
88 c->lighting.lightModel.ambient.r =
89 c->lighting.lightModel.ambient.g =
90 c->lighting.lightModel.ambient.b = gglFloatToFixed(0.2f);
91 c->lighting.lightModel.ambient.a = 0x10000;
92
93 c->lighting.colorMaterial.face = GL_FRONT_AND_BACK;
94 c->lighting.colorMaterial.mode = GL_AMBIENT_AND_DIFFUSE;
95
96 c->fog.mode = GL_EXP;
97 c->fog.fog = fog_exp;
98 c->fog.density = 0x10000;
99 c->fog.end = 0x10000;
100 c->fog.invEndMinusStart = 0x10000;
101
102 invalidate_lighting(c);
103
104 c->rasterizer.procs.shadeModel(c, GL_SMOOTH);
105 c->lighting.shadeModel = GL_SMOOTH;
106}
107
108void ogles_uninit_light(ogles_context_t* c)
109{
110}
111
112static inline int32_t clampF(GLfixed f) CONST;
113int32_t clampF(GLfixed f) {
114 f = (f & ~(f>>31));
115 if (f >= 0x10000)
116 f = 0x10000;
117 return f;
118}
119
120static GLfixed fog_linear(ogles_context_t* c, GLfixed z) {
121 return clampF(gglMulx((c->fog.end - ((z<0)?-z:z)), c->fog.invEndMinusStart));
122}
123
124static GLfixed fog_exp(ogles_context_t* c, GLfixed z) {
125 const float e = fixedToFloat(gglMulx(c->fog.density, ((z<0)?-z:z)));
126 return clampF(gglFloatToFixed(fastexpf(-e)));
127}
128
129static GLfixed fog_exp2(ogles_context_t* c, GLfixed z) {
130 const float e = fixedToFloat(gglMulx(c->fog.density, z));
131 return clampF(gglFloatToFixed(fastexpf(-e*e)));
132}
133
134// ----------------------------------------------------------------------------
135#if 0
136#pragma mark -
137#pragma mark math helpers
138#endif
139
140static inline
141void vscale3(GLfixed* d, const GLfixed* m, GLfixed s) {
142 d[0] = gglMulx(m[0], s);
143 d[1] = gglMulx(m[1], s);
144 d[2] = gglMulx(m[2], s);
145}
146
147static inline
148void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
149 d[0] = gglMulAddx(m[0], s, a[0]);
150 d[1] = gglMulAddx(m[1], s, a[1]);
151 d[2] = gglMulAddx(m[2], s, a[2]);
152}
153
154static inline
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700155void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
156 d[0] = gglMulSubx(m[0], s, a[0]);
157 d[1] = gglMulSubx(m[1], s, a[1]);
158 d[2] = gglMulSubx(m[2], s, a[2]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800159}
160
161static inline
162void vmla3(GLfixed* d,
163 const GLfixed* m0, const GLfixed* m1, const GLfixed* a)
164{
165 d[0] = gglMulAddx(m0[0], m1[0], a[0]);
166 d[1] = gglMulAddx(m0[1], m1[1], a[1]);
167 d[2] = gglMulAddx(m0[2], m1[2], a[2]);
168}
169
170static inline
171void vmul3(GLfixed* d, const GLfixed* m0, const GLfixed* m1) {
172 d[0] = gglMulx(m0[0], m1[0]);
173 d[1] = gglMulx(m0[1], m1[1]);
174 d[2] = gglMulx(m0[2], m1[2]);
175}
176
177void vnorm3(GLfixed* d, const GLfixed* a)
178{
179 // we must take care of overflows when normalizing a vector
180 GLfixed n;
181 int32_t x = a[0]; x = x>=0 ? x : -x;
182 int32_t y = a[1]; y = y>=0 ? y : -y;
183 int32_t z = a[2]; z = z>=0 ? z : -z;
184 if (ggl_likely(x<=0x6800 && y<=0x6800 && z<= 0x6800)) {
185 // in this case this will all fit on 32 bits
186 n = x*x + y*y + z*z;
187 n = gglSqrtRecipx(n);
188 n <<= 8;
189 } else {
190 // here norm^2 is at least 0x7EC00000 (>>32 == 0.495117)
191 n = vsquare3(x, y, z);
192 n = gglSqrtRecipx(n);
193 }
194 vscale3(d, a, n);
195}
196
197// ----------------------------------------------------------------------------
198#if 0
199#pragma mark -
200#pragma mark lighting equations
201#endif
202
203static inline void light_picker(ogles_context_t* c)
204{
205 if (ggl_likely(!c->lighting.enable)) {
206 c->lighting.lightVertex = lightVertexNop;
207 return;
208 }
209 if (c->lighting.colorMaterial.enable) {
210 c->lighting.lightVertex = lightVertexMaterial;
211 } else {
212 c->lighting.lightVertex = lightVertex;
213 }
214}
215
216static inline void validate_light_mvi(ogles_context_t* c)
217{
218 uint32_t en = c->lighting.enabledLights;
219 while (en) {
220 const int i = 31 - gglClz(en);
221 en &= ~(1<<i);
222 light_t& l = c->lighting.lights[i];
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700223 c->transforms.mvui.point4(&c->transforms.mvui,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800224 &l.objPosition, &l.position);
225 vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
226 }
227}
228
229static inline void validate_light(ogles_context_t* c)
230{
231 // if colorMaterial is enabled, we get the color from the vertex
232 if (!c->lighting.colorMaterial.enable) {
233 material_t& material = c->lighting.front;
234 uint32_t en = c->lighting.enabledLights;
235 while (en) {
236 const int i = 31 - gglClz(en);
237 en &= ~(1<<i);
238 light_t& l = c->lighting.lights[i];
239 vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
240 vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
241 vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
242
243 // this is just a flag to tell if we have a specular component
244 l.implicitSpecular.v[3] =
245 l.implicitSpecular.r |
246 l.implicitSpecular.g |
247 l.implicitSpecular.b;
248
249 l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0;
250 if (l.rConstAttenuation)
251 l.rConstAttenuation = gglRecipFast(l.attenuation[0]);
252 }
253 // emission and ambient for the whole scene
254 vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
255 c->lighting.lightModel.ambient.v,
256 material.ambient.v,
257 material.emission.v);
258 c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
259 }
260 validate_light_mvi(c);
261}
262
263void invalidate_lighting(ogles_context_t* c)
264{
265 // TODO: pick lightVertexValidate or lightVertexValidateMVI
266 // instead of systematically the heavier lightVertexValidate()
267 c->lighting.lightVertex = lightVertexValidate;
268}
269
270void ogles_invalidate_lighting_mvui(ogles_context_t* c)
271{
272 invalidate_lighting(c);
273}
274
275void lightVertexNop(ogles_context_t*, vertex_t* v)
276{
277 // we should never end-up here
278}
279
280void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v)
281{
282 validate_light_mvi(c);
283 light_picker(c);
284 c->lighting.lightVertex(c, v);
285}
286
287void lightVertexValidate(ogles_context_t* c, vertex_t* v)
288{
289 validate_light(c);
290 light_picker(c);
291 c->lighting.lightVertex(c, v);
292}
293
294void lightVertexMaterial(ogles_context_t* c, vertex_t* v)
295{
296 // fetch the material color
297 const GLvoid* cp = c->arrays.color.element(
298 v->index & vertex_cache_t::INDEX_MASK);
299 c->arrays.color.fetch(c, v->color.v, cp);
300
301 // acquire the color-material from the vertex
302 material_t& material = c->lighting.front;
303 material.ambient =
304 material.diffuse = v->color;
305 // implicit arguments need to be computed per/vertex
306 uint32_t en = c->lighting.enabledLights;
307 while (en) {
308 const int i = 31 - gglClz(en);
309 en &= ~(1<<i);
310 light_t& l = c->lighting.lights[i];
311 vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
312 vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
313 vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
Mathias Agopian50aba6d2009-06-02 22:51:09 -0700314 // this is just a flag to tell if we have a specular component
315 l.implicitSpecular.v[3] =
316 l.implicitSpecular.r |
317 l.implicitSpecular.g |
318 l.implicitSpecular.b;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800319 }
320 // emission and ambient for the whole scene
321 vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
322 c->lighting.lightModel.ambient.v,
323 material.ambient.v,
324 material.emission.v);
325 c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a;
326
327 // now we can light our vertex as usual
328 lightVertex(c, v);
329}
330
331void lightVertex(ogles_context_t* c, vertex_t* v)
332{
333 // emission and ambient for the whole scene
334 vec4_t r = c->lighting.implicitSceneEmissionAndAmbient;
335
336 uint32_t en = c->lighting.enabledLights;
337 if (ggl_likely(en)) {
338 // since we do the lighting in object-space, we don't need to
339 // transform each normal. However, we might still have to normalize
340 // it if GL_NORMALIZE is enabled.
341 vec4_t n;
342 c->arrays.normal.fetch(c, n.v,
343 c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700344
345 // TODO: right now we handle GL_RESCALE_NORMALS as if ti were
346 // GL_NORMALIZE. We could optimize this by scaling mvui
347 // appropriately instead.
348 if (c->transforms.rescaleNormals)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800349 vnorm3(n.v, n.v);
350
351 const material_t& material = c->lighting.front;
352 const int twoSide = c->lighting.lightModel.twoSide;
353
354 while (en) {
355 const int i = 31 - gglClz(en);
356 en &= ~(1<<i);
357 const light_t& l = c->lighting.lights[i];
358
359 vec4_t d, t;
360 GLfixed s;
361 GLfixed sqDist = 0x10000;
362
363 // compute vertex-to-light vector
364 if (ggl_unlikely(l.position.w)) {
Mathias Agopian69ca17a2009-06-02 22:05:04 -0700365 // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
366 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800367 sqDist = dot3(d.v, d.v);
368 vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
369 } else {
370 // TODO: avoid copy here
371 d = l.normalizedObjPosition;
372 }
373
374 // ambient & diffuse
375 s = dot3(n.v, d.v);
376 s = (s<0) ? (twoSide?(-s):0) : s;
377 vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v);
378
379 // specular
380 if (ggl_unlikely(s && l.implicitSpecular.v[3])) {
381 vec4_t h;
382 h.x = d.x;
383 h.y = d.y;
384 h.z = d.z + 0x10000;
385 vnorm3(h.v, h.v);
386 s = dot3(n.v, h.v);
387 s = (s<0) ? (twoSide?(-s):0) : s;
388 if (s > 0) {
389 s = gglPowx(s, material.shininess);
390 vsa3(t.v, l.implicitSpecular.v, s, t.v);
391 }
392 }
393
394 // spot
395 if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) {
396 GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v);
397 if (spotAtt >= l.spotCutoffCosine) {
398 vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp));
399 }
400 }
401
402 // attenuation
403 if (ggl_unlikely(l.position.w)) {
404 if (l.rConstAttenuation) {
405 s = l.rConstAttenuation;
406 } else {
407 s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]);
408 if (l.attenuation[1])
409 s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s);
410 s = gglRecipFast(s);
411 }
412 vscale3(t.v, t.v, s);
413 }
414
415 r.r += t.r;
416 r.g += t.g;
417 r.b += t.b;
418 }
419 }
420 v->color.r = gglClampx(r.r);
421 v->color.g = gglClampx(r.g);
422 v->color.b = gglClampx(r.b);
423 v->color.a = gglClampx(r.a);
424 v->flags |= vertex_t::LIT;
425}
426
427static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c)
428{
429 if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) {
430 ogles_error(c, GL_INVALID_ENUM);
431 return;
432 }
433 c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE;
434 invalidate_lighting(c);
435}
436
437static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c)
438{
439 if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
440 ogles_error(c, GL_INVALID_ENUM);
441 return;
442 }
443
444 light_t& light = c->lighting.lights[i-GL_LIGHT0];
445 const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f);
446 switch (pname) {
447 case GL_SPOT_EXPONENT:
448 if (GGLfixed(param) >= gglIntToFixed(128)) {
449 ogles_error(c, GL_INVALID_VALUE);
450 return;
451 }
452 light.spotExp = param;
453 break;
454 case GL_SPOT_CUTOFF:
455 if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) {
456 ogles_error(c, GL_INVALID_VALUE);
457 return;
458 }
459 light.spotCutoff = param;
460 light.spotCutoffCosine =
461 gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param));
462 break;
463 case GL_CONSTANT_ATTENUATION:
464 if (param < 0) {
465 ogles_error(c, GL_INVALID_VALUE);
466 return;
467 }
468 light.attenuation[0] = param;
469 break;
470 case GL_LINEAR_ATTENUATION:
471 if (param < 0) {
472 ogles_error(c, GL_INVALID_VALUE);
473 return;
474 }
475 light.attenuation[1] = param;
476 break;
477 case GL_QUADRATIC_ATTENUATION:
478 if (param < 0) {
479 ogles_error(c, GL_INVALID_VALUE);
480 return;
481 }
482 light.attenuation[2] = param;
483 break;
484 default:
485 ogles_error(c, GL_INVALID_ENUM);
486 return;
487 }
488 invalidate_lighting(c);
489}
490
491static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c)
492{
493 if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) {
494 ogles_error(c, GL_INVALID_ENUM);
495 return;
496 }
497
498 GLfixed* what;
499 light_t& light = c->lighting.lights[i-GL_LIGHT0];
500 switch (pname) {
501 case GL_AMBIENT:
502 what = light.ambient.v;
503 break;
504 case GL_DIFFUSE:
505 what = light.diffuse.v;
506 break;
507 case GL_SPECULAR:
508 what = light.specular.v;
509 break;
510 case GL_POSITION: {
511 ogles_validate_transform(c, transform_state_t::MODELVIEW);
512 transform_t& mv = c->transforms.modelview.transform;
513 memcpy(light.position.v, params, sizeof(light.position.v));
514 mv.point4(&mv, &light.position, &light.position);
515 invalidate_lighting(c);
516 return;
517 }
518 case GL_SPOT_DIRECTION: {
519 ogles_validate_transform(c, transform_state_t::MVUI);
520 transform_t& mvui = c->transforms.mvui;
521 mvui.point3(&mvui, &light.spotDir, (vec4_t*)params);
522 vnorm3(light.normalizedSpotDir.v, light.spotDir.v);
523 invalidate_lighting(c);
524 return;
525 }
526 default:
527 lightx(i, pname, params[0], c);
528 return;
529 }
530 what[0] = params[0];
531 what[1] = params[1];
532 what[2] = params[2];
533 what[3] = params[3];
534 invalidate_lighting(c);
535}
536
537static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c)
538{
539 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
540 ogles_error(c, GL_INVALID_ENUM);
541 return;
542 }
543 if (ggl_unlikely(pname != GL_SHININESS)) {
544 ogles_error(c, GL_INVALID_ENUM);
545 return;
546 }
547 c->lighting.front.shininess = param;
548 invalidate_lighting(c);
549}
550
551static void fogx(GLenum pname, GLfixed param, ogles_context_t* c)
552{
553 switch (pname) {
554 case GL_FOG_DENSITY:
555 if (param >= 0) {
556 c->fog.density = param;
557 break;
558 }
559 ogles_error(c, GL_INVALID_VALUE);
560 break;
561 case GL_FOG_START:
562 c->fog.start = param;
563 c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
564 break;
565 case GL_FOG_END:
566 c->fog.end = param;
567 c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
568 break;
569 case GL_FOG_MODE:
570 switch (param) {
571 case GL_LINEAR:
572 c->fog.mode = param;
573 c->fog.fog = fog_linear;
574 break;
575 case GL_EXP:
576 c->fog.mode = param;
577 c->fog.fog = fog_exp;
578 break;
579 case GL_EXP2:
580 c->fog.mode = param;
581 c->fog.fog = fog_exp2;
582 break;
583 default:
584 ogles_error(c, GL_INVALID_ENUM);
585 break;
586 }
587 break;
588 default:
589 ogles_error(c, GL_INVALID_ENUM);
590 break;
591 }
592}
593
594// ----------------------------------------------------------------------------
595}; // namespace android
596// ----------------------------------------------------------------------------
597
598using namespace android;
599
600#if 0
601#pragma mark -
602#pragma mark lighting APIs
603#endif
604
605void glShadeModel(GLenum mode)
606{
607 ogles_context_t* c = ogles_context_t::get();
608 if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) {
609 ogles_error(c, GL_INVALID_ENUM);
610 return;
611 }
612 c->lighting.shadeModel = mode;
613}
614
615void glLightModelf(GLenum pname, GLfloat param)
616{
617 ogles_context_t* c = ogles_context_t::get();
618 lightModelx(pname, gglFloatToFixed(param), c);
619}
620
621void glLightModelx(GLenum pname, GLfixed param)
622{
623 ogles_context_t* c = ogles_context_t::get();
624 lightModelx(pname, param, c);
625}
626
627void glLightModelfv(GLenum pname, const GLfloat *params)
628{
629 ogles_context_t* c = ogles_context_t::get();
630 if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
631 lightModelx(pname, gglFloatToFixed(params[0]), c);
632 return;
633 }
634
635 if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
636 ogles_error(c, GL_INVALID_ENUM);
637 return;
638 }
639
640 c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]);
641 c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]);
642 c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]);
643 c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]);
644 invalidate_lighting(c);
645}
646
647void glLightModelxv(GLenum pname, const GLfixed *params)
648{
649 ogles_context_t* c = ogles_context_t::get();
650 if (pname == GL_LIGHT_MODEL_TWO_SIDE) {
651 lightModelx(pname, params[0], c);
652 return;
653 }
654
655 if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) {
656 ogles_error(c, GL_INVALID_ENUM);
657 return;
658 }
659
660 c->lighting.lightModel.ambient.r = params[0];
661 c->lighting.lightModel.ambient.g = params[1];
662 c->lighting.lightModel.ambient.b = params[2];
663 c->lighting.lightModel.ambient.a = params[3];
664 invalidate_lighting(c);
665}
666
667// ----------------------------------------------------------------------------
668#if 0
669#pragma mark -
670#endif
671
672void glLightf(GLenum i, GLenum pname, GLfloat param)
673{
674 ogles_context_t* c = ogles_context_t::get();
675 lightx(i, pname, gglFloatToFixed(param), c);
676}
677
678void glLightx(GLenum i, GLenum pname, GLfixed param)
679{
680 ogles_context_t* c = ogles_context_t::get();
681 lightx(i, pname, param, c);
682}
683
684void glLightfv(GLenum i, GLenum pname, const GLfloat *params)
685{
686 ogles_context_t* c = ogles_context_t::get();
687 switch (pname) {
688 case GL_SPOT_EXPONENT:
689 case GL_SPOT_CUTOFF:
690 case GL_CONSTANT_ATTENUATION:
691 case GL_LINEAR_ATTENUATION:
692 case GL_QUADRATIC_ATTENUATION:
693 lightx(i, pname, gglFloatToFixed(params[0]), c);
694 return;
695 }
696
697 GLfixed paramsx[4];
698 paramsx[0] = gglFloatToFixed(params[0]);
699 paramsx[1] = gglFloatToFixed(params[1]);
700 paramsx[2] = gglFloatToFixed(params[2]);
701 if (pname != GL_SPOT_DIRECTION)
702 paramsx[3] = gglFloatToFixed(params[3]);
703
704 lightxv(i, pname, paramsx, c);
705}
706
707void glLightxv(GLenum i, GLenum pname, const GLfixed *params)
708{
709 ogles_context_t* c = ogles_context_t::get();
710 lightxv(i, pname, params, c);
711}
712
713// ----------------------------------------------------------------------------
714#if 0
715#pragma mark -
716#endif
717
718void glMaterialf(GLenum face, GLenum pname, GLfloat param)
719{
720 ogles_context_t* c = ogles_context_t::get();
721 materialx(face, pname, gglFloatToFixed(param), c);
722}
723
724void glMaterialx(GLenum face, GLenum pname, GLfixed param)
725{
726 ogles_context_t* c = ogles_context_t::get();
727 materialx(face, pname, param, c);
728}
729
730void glMaterialfv(
731 GLenum face, GLenum pname, const GLfloat *params)
732{
733 ogles_context_t* c = ogles_context_t::get();
734 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
735 ogles_error(c, GL_INVALID_ENUM);
736 return;
737 }
738 GLfixed* what=0;
739 GLfixed* other=0;
740 switch (pname) {
741 case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
742 case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
743 case GL_SPECULAR: what = c->lighting.front.specular.v; break;
744 case GL_EMISSION: what = c->lighting.front.emission.v; break;
745 case GL_AMBIENT_AND_DIFFUSE:
746 what = c->lighting.front.ambient.v; break;
747 other = c->lighting.front.diffuse.v; break;
748 break;
749 case GL_SHININESS:
750 c->lighting.front.shininess = gglFloatToFixed(params[0]);
751 invalidate_lighting(c);
752 return;
753 default:
754 ogles_error(c, GL_INVALID_ENUM);
755 return;
756 }
757 what[0] = gglFloatToFixed(params[0]);
758 what[1] = gglFloatToFixed(params[1]);
759 what[2] = gglFloatToFixed(params[2]);
760 what[3] = gglFloatToFixed(params[3]);
761 if (other) {
762 other[0] = what[0];
763 other[1] = what[1];
764 other[2] = what[2];
765 other[3] = what[3];
766 }
767 invalidate_lighting(c);
768}
769
770void glMaterialxv(
771 GLenum face, GLenum pname, const GLfixed *params)
772{
773 ogles_context_t* c = ogles_context_t::get();
774 if (ggl_unlikely(face != GL_FRONT_AND_BACK)) {
775 ogles_error(c, GL_INVALID_ENUM);
776 return;
777 }
778 GLfixed* what=0;
779 GLfixed* other=0;
780 switch (pname) {
781 case GL_AMBIENT: what = c->lighting.front.ambient.v; break;
782 case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break;
783 case GL_SPECULAR: what = c->lighting.front.specular.v; break;
784 case GL_EMISSION: what = c->lighting.front.emission.v; break;
785 case GL_AMBIENT_AND_DIFFUSE:
786 what = c->lighting.front.ambient.v; break;
787 other= c->lighting.front.diffuse.v; break;
788 break;
789 case GL_SHININESS:
790 c->lighting.front.shininess = gglFloatToFixed(params[0]);
791 invalidate_lighting(c);
792 return;
793 default:
794 ogles_error(c, GL_INVALID_ENUM);
795 return;
796 }
797 what[0] = params[0];
798 what[1] = params[1];
799 what[2] = params[2];
800 what[3] = params[3];
801 if (other) {
802 other[0] = what[0];
803 other[1] = what[1];
804 other[2] = what[2];
805 other[3] = what[3];
806 }
807 invalidate_lighting(c);
808}
809
810// ----------------------------------------------------------------------------
811#if 0
812#pragma mark -
813#pragma mark fog
814#endif
815
816void glFogf(GLenum pname, GLfloat param) {
817 ogles_context_t* c = ogles_context_t::get();
818 GLfixed paramx = (GLfixed)param;
819 if (pname != GL_FOG_MODE)
820 paramx = gglFloatToFixed(param);
821 fogx(pname, paramx, c);
822}
823
824void glFogx(GLenum pname, GLfixed param) {
825 ogles_context_t* c = ogles_context_t::get();
826 fogx(pname, param, c);
827}
828
829void glFogfv(GLenum pname, const GLfloat *params)
830{
831 ogles_context_t* c = ogles_context_t::get();
832 if (pname != GL_FOG_COLOR) {
833 GLfixed paramx = (GLfixed)params[0];
834 if (pname != GL_FOG_MODE)
835 paramx = gglFloatToFixed(params[0]);
836 fogx(pname, paramx, c);
837 return;
838 }
839 GLfixed paramsx[4];
840 paramsx[0] = gglFloatToFixed(params[0]);
841 paramsx[1] = gglFloatToFixed(params[1]);
842 paramsx[2] = gglFloatToFixed(params[2]);
843 paramsx[3] = gglFloatToFixed(params[3]);
844 c->rasterizer.procs.fogColor3xv(c, paramsx);
845}
846
847void glFogxv(GLenum pname, const GLfixed *params)
848{
849 ogles_context_t* c = ogles_context_t::get();
850 if (pname != GL_FOG_COLOR) {
851 fogx(pname, params[0], c);
852 return;
853 }
854 c->rasterizer.procs.fogColor3xv(c, params);
855}