| /* 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; |
| while (en) { |
| const int i = 31 - gglClz(en); |
| en &= ~(1<<i); |
| light_t& l = c->lighting.lights[i]; |
| c->transforms.mvui.point4(&c->transforms.mvui, |
| &l.objPosition, &l.position); |
| vnorm3(l.normalizedObjPosition.v, l.objPosition.v); |
| } |
| } |
| |
| 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; |
| |
| 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)); |
| |
| // TODO: right now we handle GL_RESCALE_NORMALS as if ti 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 |
| vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); |
| 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; |
| h.y = d.y; |
| h.z = d.z + 0x10000; |
| 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; |
| memcpy(light.position.v, params, sizeof(light.position.v)); |
| mv.point4(&mv, &light.position, &light.position); |
| invalidate_lighting(c); |
| return; |
| } |
| case GL_SPOT_DIRECTION: { |
| ogles_validate_transform(c, transform_state_t::MVUI); |
| transform_t& mvui = c->transforms.mvui; |
| mvui.point3(&mvui, &light.spotDir, (vec4_t*)params); |
| 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; break; |
| other = c->lighting.front.diffuse.v; break; |
| 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; break; |
| other= c->lighting.front.diffuse.v; break; |
| 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); |
| } |