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