/* libs/opengles/light.cpp ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #include <stdio.h> #include "context.h" #include "fp.h" #include "light.h" #include "state.h" #include "matrix.h" #if defined(__arm__) && defined(__thumb__) #warning "light.cpp should not be compiled in thumb on ARM." #endif namespace android { // ---------------------------------------------------------------------------- static void invalidate_lighting(ogles_context_t* c); static void lightVertexValidate(ogles_context_t* c, vertex_t* v); static void lightVertexNop(ogles_context_t* c, vertex_t* v); static void lightVertex(ogles_context_t* c, vertex_t* v); static void lightVertexMaterial(ogles_context_t* c, vertex_t* v); static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s); static __attribute__((noinline)) void vnorm3(GLfixed* d, const GLfixed* a); static inline void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a); static inline void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a); static inline void vmla3(GLfixed* d, const GLfixed* m0, const GLfixed* m1, const GLfixed* a); static inline void vmul3(GLfixed* d, const GLfixed* m0, const GLfixed* m1); static GLfixed fog_linear(ogles_context_t* c, GLfixed z); static GLfixed fog_exp(ogles_context_t* c, GLfixed z); static GLfixed fog_exp2(ogles_context_t* c, GLfixed z); // ---------------------------------------------------------------------------- static void init_white(vec4_t& c) { c.r = c.g = c.b = c.a = 0x10000; } void ogles_init_light(ogles_context_t* c) { for (unsigned int i=0 ; i<OGLES_MAX_LIGHTS ; i++) { c->lighting.lights[i].ambient.a = 0x10000; c->lighting.lights[i].position.z = 0x10000; c->lighting.lights[i].spotDir.z = -0x10000; c->lighting.lights[i].spotCutoff = gglIntToFixed(180); c->lighting.lights[i].attenuation[0] = 0x10000; } init_white(c->lighting.lights[0].diffuse); init_white(c->lighting.lights[0].specular); c->lighting.front.ambient.r = c->lighting.front.ambient.g = c->lighting.front.ambient.b = gglFloatToFixed(0.2f); c->lighting.front.ambient.a = 0x10000; c->lighting.front.diffuse.r = c->lighting.front.diffuse.g = c->lighting.front.diffuse.b = gglFloatToFixed(0.8f); c->lighting.front.diffuse.a = 0x10000; c->lighting.front.specular.a = 0x10000; c->lighting.front.emission.a = 0x10000; c->lighting.lightModel.ambient.r = c->lighting.lightModel.ambient.g = c->lighting.lightModel.ambient.b = gglFloatToFixed(0.2f); c->lighting.lightModel.ambient.a = 0x10000; c->lighting.colorMaterial.face = GL_FRONT_AND_BACK; c->lighting.colorMaterial.mode = GL_AMBIENT_AND_DIFFUSE; c->fog.mode = GL_EXP; c->fog.fog = fog_exp; c->fog.density = 0x10000; c->fog.end = 0x10000; c->fog.invEndMinusStart = 0x10000; invalidate_lighting(c); c->rasterizer.procs.shadeModel(c, GL_SMOOTH); c->lighting.shadeModel = GL_SMOOTH; } void ogles_uninit_light(ogles_context_t* /*c*/) { } static inline int32_t clampF(GLfixed f) CONST; int32_t clampF(GLfixed f) { f = (f & ~(f>>31)); if (f >= 0x10000) f = 0x10000; return f; } static GLfixed fog_linear(ogles_context_t* c, GLfixed z) { return clampF(gglMulx((c->fog.end - ((z<0)?-z:z)), c->fog.invEndMinusStart)); } static GLfixed fog_exp(ogles_context_t* c, GLfixed z) { const float e = fixedToFloat(gglMulx(c->fog.density, ((z<0)?-z:z))); return clampF(gglFloatToFixed(fastexpf(-e))); } static GLfixed fog_exp2(ogles_context_t* c, GLfixed z) { const float e = fixedToFloat(gglMulx(c->fog.density, z)); return clampF(gglFloatToFixed(fastexpf(-e*e))); } // ---------------------------------------------------------------------------- #if 0 #pragma mark - #pragma mark math helpers #endif static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s) { d[0] = gglMulx(m[0], s); d[1] = gglMulx(m[1], s); d[2] = gglMulx(m[2], s); } static inline void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) { d[0] = gglMulAddx(m[0], s, a[0]); d[1] = gglMulAddx(m[1], s, a[1]); d[2] = gglMulAddx(m[2], s, a[2]); } static inline void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) { d[0] = gglMulSubx(m[0], s, a[0]); d[1] = gglMulSubx(m[1], s, a[1]); d[2] = gglMulSubx(m[2], s, a[2]); } static inline void vmla3(GLfixed* d, const GLfixed* m0, const GLfixed* m1, const GLfixed* a) { d[0] = gglMulAddx(m0[0], m1[0], a[0]); d[1] = gglMulAddx(m0[1], m1[1], a[1]); d[2] = gglMulAddx(m0[2], m1[2], a[2]); } static inline void vmul3(GLfixed* d, const GLfixed* m0, const GLfixed* m1) { d[0] = gglMulx(m0[0], m1[0]); d[1] = gglMulx(m0[1], m1[1]); d[2] = gglMulx(m0[2], m1[2]); } void vnorm3(GLfixed* d, const GLfixed* a) { // we must take care of overflows when normalizing a vector GLfixed n; int32_t x = a[0]; x = x>=0 ? x : -x; int32_t y = a[1]; y = y>=0 ? y : -y; int32_t z = a[2]; z = z>=0 ? z : -z; if (ggl_likely(x<=0x6800 && y<=0x6800 && z<= 0x6800)) { // in this case this will all fit on 32 bits n = x*x + y*y + z*z; n = gglSqrtRecipx(n); n <<= 8; } else { // here norm^2 is at least 0x7EC00000 (>>32 == 0.495117) n = vsquare3(x, y, z); n = gglSqrtRecipx(n); } vscale3(d, a, n); } // ---------------------------------------------------------------------------- #if 0 #pragma mark - #pragma mark lighting equations #endif static inline void light_picker(ogles_context_t* c) { if (ggl_likely(!c->lighting.enable)) { c->lighting.lightVertex = lightVertexNop; return; } if (c->lighting.colorMaterial.enable) { c->lighting.lightVertex = lightVertexMaterial; } else { c->lighting.lightVertex = lightVertex; } } static inline void validate_light_mvi(ogles_context_t* c) { uint32_t en = c->lighting.enabledLights; // Vector from object to viewer, in eye coordinates while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); light_t& l = c->lighting.lights[i]; #if OBJECT_SPACE_LIGHTING c->transforms.mvui.point4(&c->transforms.mvui, &l.objPosition, &l.position); #else l.objPosition = l.position; #endif vnorm3(l.normalizedObjPosition.v, l.objPosition.v); } const vec4_t eyeViewer = { 0, 0, 0x10000, 0 }; #if OBJECT_SPACE_LIGHTING c->transforms.mvui.point3(&c->transforms.mvui, &c->lighting.objViewer, &eyeViewer); vnorm3(c->lighting.objViewer.v, c->lighting.objViewer.v); #else c->lighting.objViewer = eyeViewer; #endif } static inline void validate_light(ogles_context_t* c) { // if colorMaterial is enabled, we get the color from the vertex if (!c->lighting.colorMaterial.enable) { material_t& material = c->lighting.front; uint32_t en = c->lighting.enabledLights; while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); light_t& l = c->lighting.lights[i]; vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v); vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v); vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); // this is just a flag to tell if we have a specular component l.implicitSpecular.v[3] = l.implicitSpecular.r | l.implicitSpecular.g | l.implicitSpecular.b; l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0; if (l.rConstAttenuation) l.rConstAttenuation = gglRecipFast(l.attenuation[0]); } // emission and ambient for the whole scene vmla3( c->lighting.implicitSceneEmissionAndAmbient.v, c->lighting.lightModel.ambient.v, material.ambient.v, material.emission.v); c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a; } validate_light_mvi(c); } void invalidate_lighting(ogles_context_t* c) { // TODO: pick lightVertexValidate or lightVertexValidateMVI // instead of systematically the heavier lightVertexValidate() c->lighting.lightVertex = lightVertexValidate; } void ogles_invalidate_lighting_mvui(ogles_context_t* c) { invalidate_lighting(c); } void lightVertexNop(ogles_context_t*, vertex_t* /*v*/) { // we should never end-up here } void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v) { validate_light_mvi(c); light_picker(c); c->lighting.lightVertex(c, v); } void lightVertexValidate(ogles_context_t* c, vertex_t* v) { validate_light(c); light_picker(c); c->lighting.lightVertex(c, v); } void lightVertexMaterial(ogles_context_t* c, vertex_t* v) { // fetch the material color const GLvoid* cp = c->arrays.color.element( v->index & vertex_cache_t::INDEX_MASK); c->arrays.color.fetch(c, v->color.v, cp); // acquire the color-material from the vertex material_t& material = c->lighting.front; material.ambient = material.diffuse = v->color; // implicit arguments need to be computed per/vertex uint32_t en = c->lighting.enabledLights; while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); light_t& l = c->lighting.lights[i]; vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v); vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v); vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); // this is just a flag to tell if we have a specular component l.implicitSpecular.v[3] = l.implicitSpecular.r | l.implicitSpecular.g | l.implicitSpecular.b; } // emission and ambient for the whole scene vmla3( c->lighting.implicitSceneEmissionAndAmbient.v, c->lighting.lightModel.ambient.v, material.ambient.v, material.emission.v); c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a; // now we can light our vertex as usual lightVertex(c, v); } void lightVertex(ogles_context_t* c, vertex_t* v) { // emission and ambient for the whole scene vec4_t r = c->lighting.implicitSceneEmissionAndAmbient; const vec4_t objViewer = c->lighting.objViewer; uint32_t en = c->lighting.enabledLights; if (ggl_likely(en)) { // since we do the lighting in object-space, we don't need to // transform each normal. However, we might still have to normalize // it if GL_NORMALIZE is enabled. vec4_t n; c->arrays.normal.fetch(c, n.v, c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK)); #if !OBJECT_SPACE_LIGHTING c->transforms.mvui.point3(&c->transforms.mvui, &n, &n); #endif // TODO: right now we handle GL_RESCALE_NORMALS as if it were // GL_NORMALIZE. We could optimize this by scaling mvui // appropriately instead. if (c->transforms.rescaleNormals) vnorm3(n.v, n.v); const material_t& material = c->lighting.front; const int twoSide = c->lighting.lightModel.twoSide; while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); const light_t& l = c->lighting.lights[i]; vec4_t d, t; GLfixed s; GLfixed sqDist = 0x10000; // compute vertex-to-light vector if (ggl_unlikely(l.position.w)) { // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex #if !OBJECT_SPACE_LIGHTING vec4_t o; const transform_t& mv = c->transforms.modelview.transform; mv.point4(&mv, &o, &v->obj); vss3(d.v, l.objPosition.v, o.w, o.v); #else vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); #endif sqDist = dot3(d.v, d.v); vscale3(d.v, d.v, gglSqrtRecipx(sqDist)); } else { // TODO: avoid copy here d = l.normalizedObjPosition; } // ambient & diffuse s = dot3(n.v, d.v); s = (s<0) ? (twoSide?(-s):0) : s; vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v); // specular if (ggl_unlikely(s && l.implicitSpecular.v[3])) { vec4_t h; h.x = d.x + objViewer.x; h.y = d.y + objViewer.y; h.z = d.z + objViewer.z; vnorm3(h.v, h.v); s = dot3(n.v, h.v); s = (s<0) ? (twoSide?(-s):0) : s; if (s > 0) { s = gglPowx(s, material.shininess); vsa3(t.v, l.implicitSpecular.v, s, t.v); } } // spot if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) { GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v); if (spotAtt >= l.spotCutoffCosine) { vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp)); } } // attenuation if (ggl_unlikely(l.position.w)) { if (l.rConstAttenuation) { s = l.rConstAttenuation; } else { s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]); if (l.attenuation[1]) s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s); s = gglRecipFast(s); } vscale3(t.v, t.v, s); } r.r += t.r; r.g += t.g; r.b += t.b; } } v->color.r = gglClampx(r.r); v->color.g = gglClampx(r.g); v->color.b = gglClampx(r.b); v->color.a = gglClampx(r.a); v->flags |= vertex_t::LIT; } static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c) { if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) { ogles_error(c, GL_INVALID_ENUM); return; } c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE; invalidate_lighting(c); } static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c) { if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { ogles_error(c, GL_INVALID_ENUM); return; } light_t& light = c->lighting.lights[i-GL_LIGHT0]; const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f); switch (pname) { case GL_SPOT_EXPONENT: if (GGLfixed(param) >= gglIntToFixed(128)) { ogles_error(c, GL_INVALID_VALUE); return; } light.spotExp = param; break; case GL_SPOT_CUTOFF: if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) { ogles_error(c, GL_INVALID_VALUE); return; } light.spotCutoff = param; light.spotCutoffCosine = gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param)); break; case GL_CONSTANT_ATTENUATION: if (param < 0) { ogles_error(c, GL_INVALID_VALUE); return; } light.attenuation[0] = param; break; case GL_LINEAR_ATTENUATION: if (param < 0) { ogles_error(c, GL_INVALID_VALUE); return; } light.attenuation[1] = param; break; case GL_QUADRATIC_ATTENUATION: if (param < 0) { ogles_error(c, GL_INVALID_VALUE); return; } light.attenuation[2] = param; break; default: ogles_error(c, GL_INVALID_ENUM); return; } invalidate_lighting(c); } static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c) { if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { ogles_error(c, GL_INVALID_ENUM); return; } GLfixed* what; light_t& light = c->lighting.lights[i-GL_LIGHT0]; switch (pname) { case GL_AMBIENT: what = light.ambient.v; break; case GL_DIFFUSE: what = light.diffuse.v; break; case GL_SPECULAR: what = light.specular.v; break; case GL_POSITION: { ogles_validate_transform(c, transform_state_t::MODELVIEW); transform_t& mv = c->transforms.modelview.transform; mv.point4(&mv, &light.position, reinterpret_cast<vec4_t const*>(params)); invalidate_lighting(c); return; } case GL_SPOT_DIRECTION: { #if OBJECT_SPACE_LIGHTING ogles_validate_transform(c, transform_state_t::MVUI); transform_t& mvui = c->transforms.mvui; mvui.point3(&mvui, &light.spotDir, reinterpret_cast<vec4_t const*>(params)); #else light.spotDir = *reinterpret_cast<vec4_t const*>(params); #endif vnorm3(light.normalizedSpotDir.v, light.spotDir.v); invalidate_lighting(c); return; } default: lightx(i, pname, params[0], c); return; } what[0] = params[0]; what[1] = params[1]; what[2] = params[2]; what[3] = params[3]; invalidate_lighting(c); } static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c) { if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { ogles_error(c, GL_INVALID_ENUM); return; } if (ggl_unlikely(pname != GL_SHININESS)) { ogles_error(c, GL_INVALID_ENUM); return; } c->lighting.front.shininess = param; invalidate_lighting(c); } static void fogx(GLenum pname, GLfixed param, ogles_context_t* c) { switch (pname) { case GL_FOG_DENSITY: if (param >= 0) { c->fog.density = param; break; } ogles_error(c, GL_INVALID_VALUE); break; case GL_FOG_START: c->fog.start = param; c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); break; case GL_FOG_END: c->fog.end = param; c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); break; case GL_FOG_MODE: switch (param) { case GL_LINEAR: c->fog.mode = param; c->fog.fog = fog_linear; break; case GL_EXP: c->fog.mode = param; c->fog.fog = fog_exp; break; case GL_EXP2: c->fog.mode = param; c->fog.fog = fog_exp2; break; default: ogles_error(c, GL_INVALID_ENUM); break; } break; default: ogles_error(c, GL_INVALID_ENUM); break; } } // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- using namespace android; #if 0 #pragma mark - #pragma mark lighting APIs #endif void glShadeModel(GLenum mode) { ogles_context_t* c = ogles_context_t::get(); if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) { ogles_error(c, GL_INVALID_ENUM); return; } c->lighting.shadeModel = mode; } void glLightModelf(GLenum pname, GLfloat param) { ogles_context_t* c = ogles_context_t::get(); lightModelx(pname, gglFloatToFixed(param), c); } void glLightModelx(GLenum pname, GLfixed param) { ogles_context_t* c = ogles_context_t::get(); lightModelx(pname, param, c); } void glLightModelfv(GLenum pname, const GLfloat *params) { ogles_context_t* c = ogles_context_t::get(); if (pname == GL_LIGHT_MODEL_TWO_SIDE) { lightModelx(pname, gglFloatToFixed(params[0]), c); return; } if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { ogles_error(c, GL_INVALID_ENUM); return; } c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]); c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]); c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]); c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]); invalidate_lighting(c); } void glLightModelxv(GLenum pname, const GLfixed *params) { ogles_context_t* c = ogles_context_t::get(); if (pname == GL_LIGHT_MODEL_TWO_SIDE) { lightModelx(pname, params[0], c); return; } if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { ogles_error(c, GL_INVALID_ENUM); return; } c->lighting.lightModel.ambient.r = params[0]; c->lighting.lightModel.ambient.g = params[1]; c->lighting.lightModel.ambient.b = params[2]; c->lighting.lightModel.ambient.a = params[3]; invalidate_lighting(c); } // ---------------------------------------------------------------------------- #if 0 #pragma mark - #endif void glLightf(GLenum i, GLenum pname, GLfloat param) { ogles_context_t* c = ogles_context_t::get(); lightx(i, pname, gglFloatToFixed(param), c); } void glLightx(GLenum i, GLenum pname, GLfixed param) { ogles_context_t* c = ogles_context_t::get(); lightx(i, pname, param, c); } void glLightfv(GLenum i, GLenum pname, const GLfloat *params) { ogles_context_t* c = ogles_context_t::get(); switch (pname) { case GL_SPOT_EXPONENT: case GL_SPOT_CUTOFF: case GL_CONSTANT_ATTENUATION: case GL_LINEAR_ATTENUATION: case GL_QUADRATIC_ATTENUATION: lightx(i, pname, gglFloatToFixed(params[0]), c); return; } GLfixed paramsx[4]; paramsx[0] = gglFloatToFixed(params[0]); paramsx[1] = gglFloatToFixed(params[1]); paramsx[2] = gglFloatToFixed(params[2]); if (pname != GL_SPOT_DIRECTION) paramsx[3] = gglFloatToFixed(params[3]); lightxv(i, pname, paramsx, c); } void glLightxv(GLenum i, GLenum pname, const GLfixed *params) { ogles_context_t* c = ogles_context_t::get(); lightxv(i, pname, params, c); } // ---------------------------------------------------------------------------- #if 0 #pragma mark - #endif void glMaterialf(GLenum face, GLenum pname, GLfloat param) { ogles_context_t* c = ogles_context_t::get(); materialx(face, pname, gglFloatToFixed(param), c); } void glMaterialx(GLenum face, GLenum pname, GLfixed param) { ogles_context_t* c = ogles_context_t::get(); materialx(face, pname, param, c); } void glMaterialfv( GLenum face, GLenum pname, const GLfloat *params) { ogles_context_t* c = ogles_context_t::get(); if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { ogles_error(c, GL_INVALID_ENUM); return; } GLfixed* what=0; GLfixed* other=0; switch (pname) { case GL_AMBIENT: what = c->lighting.front.ambient.v; break; case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break; case GL_SPECULAR: what = c->lighting.front.specular.v; break; case GL_EMISSION: what = c->lighting.front.emission.v; break; case GL_AMBIENT_AND_DIFFUSE: what = c->lighting.front.ambient.v; other = c->lighting.front.diffuse.v; break; case GL_SHININESS: c->lighting.front.shininess = gglFloatToFixed(params[0]); invalidate_lighting(c); return; default: ogles_error(c, GL_INVALID_ENUM); return; } what[0] = gglFloatToFixed(params[0]); what[1] = gglFloatToFixed(params[1]); what[2] = gglFloatToFixed(params[2]); what[3] = gglFloatToFixed(params[3]); if (other) { other[0] = what[0]; other[1] = what[1]; other[2] = what[2]; other[3] = what[3]; } invalidate_lighting(c); } void glMaterialxv( GLenum face, GLenum pname, const GLfixed *params) { ogles_context_t* c = ogles_context_t::get(); if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { ogles_error(c, GL_INVALID_ENUM); return; } GLfixed* what=0; GLfixed* other=0; switch (pname) { case GL_AMBIENT: what = c->lighting.front.ambient.v; break; case GL_DIFFUSE: what = c->lighting.front.diffuse.v; break; case GL_SPECULAR: what = c->lighting.front.specular.v; break; case GL_EMISSION: what = c->lighting.front.emission.v; break; case GL_AMBIENT_AND_DIFFUSE: what = c->lighting.front.ambient.v; other = c->lighting.front.diffuse.v; break; case GL_SHININESS: c->lighting.front.shininess = gglFloatToFixed(params[0]); invalidate_lighting(c); return; default: ogles_error(c, GL_INVALID_ENUM); return; } what[0] = params[0]; what[1] = params[1]; what[2] = params[2]; what[3] = params[3]; if (other) { other[0] = what[0]; other[1] = what[1]; other[2] = what[2]; other[3] = what[3]; } invalidate_lighting(c); } // ---------------------------------------------------------------------------- #if 0 #pragma mark - #pragma mark fog #endif void glFogf(GLenum pname, GLfloat param) { ogles_context_t* c = ogles_context_t::get(); GLfixed paramx = (GLfixed)param; if (pname != GL_FOG_MODE) paramx = gglFloatToFixed(param); fogx(pname, paramx, c); } void glFogx(GLenum pname, GLfixed param) { ogles_context_t* c = ogles_context_t::get(); fogx(pname, param, c); } void glFogfv(GLenum pname, const GLfloat *params) { ogles_context_t* c = ogles_context_t::get(); if (pname != GL_FOG_COLOR) { GLfixed paramx = (GLfixed)params[0]; if (pname != GL_FOG_MODE) paramx = gglFloatToFixed(params[0]); fogx(pname, paramx, c); return; } GLfixed paramsx[4]; paramsx[0] = gglFloatToFixed(params[0]); paramsx[1] = gglFloatToFixed(params[1]); paramsx[2] = gglFloatToFixed(params[2]); paramsx[3] = gglFloatToFixed(params[3]); c->rasterizer.procs.fogColor3xv(c, paramsx); } void glFogxv(GLenum pname, const GLfixed *params) { ogles_context_t* c = ogles_context_t::get(); if (pname != GL_FOG_COLOR) { fogx(pname, params[0], c); return; } c->rasterizer.procs.fogColor3xv(c, params); }