| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* 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 |  | 
 | 30 | namespace android { | 
 | 31 |  | 
 | 32 | // ---------------------------------------------------------------------------- | 
 | 33 |  | 
 | 34 | static void invalidate_lighting(ogles_context_t* c); | 
 | 35 | static void lightVertexValidate(ogles_context_t* c, vertex_t* v); | 
 | 36 | static void lightVertexNop(ogles_context_t* c, vertex_t* v); | 
 | 37 | static void lightVertex(ogles_context_t* c, vertex_t* v); | 
 | 38 | static void lightVertexMaterial(ogles_context_t* c, vertex_t* v); | 
 | 39 |  | 
 | 40 | static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 41 |  | 
 | 42 | static __attribute__((noinline)) | 
 | 43 | void vnorm3(GLfixed* d, const GLfixed* a); | 
 | 44 |  | 
 | 45 | static inline void vsa3(GLfixed* d, | 
 | 46 |     const GLfixed* m, GLfixed s, const GLfixed* a); | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 47 | static inline void vss3(GLfixed* d, | 
 | 48 |     const GLfixed* m, GLfixed s, const GLfixed* a); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 49 | static inline void vmla3(GLfixed* d, | 
 | 50 |     const GLfixed* m0, const GLfixed* m1, const GLfixed* a); | 
 | 51 | static inline void vmul3(GLfixed* d, | 
 | 52 |     const GLfixed* m0, const GLfixed* m1); | 
 | 53 |  | 
 | 54 | static GLfixed fog_linear(ogles_context_t* c, GLfixed z); | 
 | 55 | static GLfixed fog_exp(ogles_context_t* c, GLfixed z); | 
 | 56 | static GLfixed fog_exp2(ogles_context_t* c, GLfixed z); | 
 | 57 |  | 
 | 58 |  | 
 | 59 | // ---------------------------------------------------------------------------- | 
 | 60 |  | 
 | 61 | static void init_white(vec4_t& c) { | 
 | 62 |     c.r = c.g = c.b = c.a = 0x10000; | 
 | 63 | } | 
 | 64 |  | 
 | 65 | void 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 |  | 
| Mark Salyzyn | 92dc3fc | 2014-03-12 13:12:44 -0700 | [diff] [blame] | 108 | void ogles_uninit_light(ogles_context_t* /*c*/) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 109 | { | 
 | 110 | } | 
 | 111 |  | 
 | 112 | static inline int32_t clampF(GLfixed f) CONST; | 
 | 113 | int32_t clampF(GLfixed f) { | 
 | 114 |     f = (f & ~(f>>31)); | 
 | 115 |     if (f >= 0x10000) | 
 | 116 |         f = 0x10000; | 
 | 117 |     return f; | 
 | 118 | } | 
 | 119 |  | 
 | 120 | static 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 |  | 
 | 124 | static 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 |  | 
 | 129 | static 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 |  | 
 | 140 | static inline | 
 | 141 | void 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 |  | 
 | 147 | static inline | 
 | 148 | void 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 |  | 
 | 154 | static inline | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 155 | void 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 Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 159 | } | 
 | 160 |  | 
 | 161 | static inline | 
 | 162 | void 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 |  | 
 | 170 | static inline | 
 | 171 | void 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 |  | 
 | 177 | void 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 |  | 
 | 203 | static 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 |  | 
 | 216 | static inline void validate_light_mvi(ogles_context_t* c) | 
 | 217 | { | 
 | 218 |     uint32_t en = c->lighting.enabledLights; | 
| Martin Storsjo | e03eaa1 | 2009-08-11 18:01:14 +0200 | [diff] [blame] | 219 |     // Vector from object to viewer, in eye coordinates | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 220 |     while (en) { | 
 | 221 |         const int i = 31 - gglClz(en); | 
 | 222 |         en &= ~(1<<i); | 
 | 223 |         light_t& l = c->lighting.lights[i]; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 224 | #if OBJECT_SPACE_LIGHTING | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 225 |         c->transforms.mvui.point4(&c->transforms.mvui, | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 226 |                 &l.objPosition, &l.position); | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 227 | #else | 
 | 228 |         l.objPosition = l.position; | 
 | 229 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 230 |         vnorm3(l.normalizedObjPosition.v, l.objPosition.v); | 
 | 231 |     } | 
| Dan Stoza | 51de481 | 2016-01-08 10:52:16 -0800 | [diff] [blame] | 232 |     const vec4_t eyeViewer = {{{ 0, 0, 0x10000, 0 }}}; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 233 | #if OBJECT_SPACE_LIGHTING | 
 | 234 |     c->transforms.mvui.point3(&c->transforms.mvui, | 
 | 235 |             &c->lighting.objViewer, &eyeViewer); | 
 | 236 |     vnorm3(c->lighting.objViewer.v, c->lighting.objViewer.v); | 
 | 237 | #else | 
 | 238 |     c->lighting.objViewer = eyeViewer; | 
 | 239 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 240 | } | 
 | 241 |  | 
 | 242 | static inline void validate_light(ogles_context_t* c) | 
 | 243 | { | 
 | 244 |     // if colorMaterial is enabled, we get the color from the vertex | 
 | 245 |     if (!c->lighting.colorMaterial.enable) { | 
 | 246 |         material_t& material = c->lighting.front; | 
 | 247 |         uint32_t en = c->lighting.enabledLights; | 
 | 248 |         while (en) { | 
 | 249 |             const int i = 31 - gglClz(en); | 
 | 250 |             en &= ~(1<<i); | 
 | 251 |             light_t& l = c->lighting.lights[i]; | 
 | 252 |             vmul3(l.implicitAmbient.v,  material.ambient.v,  l.ambient.v); | 
 | 253 |             vmul3(l.implicitDiffuse.v,  material.diffuse.v,  l.diffuse.v); | 
 | 254 |             vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); | 
 | 255 |              | 
 | 256 |             // this is just a flag to tell if we have a specular component | 
 | 257 |             l.implicitSpecular.v[3] = | 
 | 258 |                     l.implicitSpecular.r | | 
 | 259 |                     l.implicitSpecular.g | | 
 | 260 |                     l.implicitSpecular.b; | 
 | 261 |              | 
 | 262 |             l.rConstAttenuation = (l.attenuation[1] | l.attenuation[2])==0; | 
 | 263 |             if (l.rConstAttenuation) | 
 | 264 |                 l.rConstAttenuation = gglRecipFast(l.attenuation[0]); | 
 | 265 |         } | 
 | 266 |         // emission and ambient for the whole scene | 
 | 267 |         vmla3(  c->lighting.implicitSceneEmissionAndAmbient.v, | 
 | 268 |                 c->lighting.lightModel.ambient.v, | 
 | 269 |                 material.ambient.v,  | 
 | 270 |                 material.emission.v); | 
 | 271 |         c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a; | 
 | 272 |     } | 
 | 273 |     validate_light_mvi(c); | 
 | 274 | } | 
 | 275 |  | 
 | 276 | void invalidate_lighting(ogles_context_t* c) | 
 | 277 | { | 
 | 278 |     // TODO: pick lightVertexValidate or lightVertexValidateMVI | 
 | 279 |     // instead of systematically the heavier lightVertexValidate() | 
 | 280 |     c->lighting.lightVertex = lightVertexValidate; | 
 | 281 | } | 
 | 282 |  | 
 | 283 | void ogles_invalidate_lighting_mvui(ogles_context_t* c) | 
 | 284 | { | 
 | 285 |     invalidate_lighting(c); | 
 | 286 | } | 
 | 287 |  | 
| Mark Salyzyn | 92dc3fc | 2014-03-12 13:12:44 -0700 | [diff] [blame] | 288 | void lightVertexNop(ogles_context_t*, vertex_t* /*v*/) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 289 | { | 
 | 290 |     // we should never end-up here | 
 | 291 | } | 
 | 292 |  | 
 | 293 | void lightVertexValidateMVI(ogles_context_t* c, vertex_t* v) | 
 | 294 | { | 
 | 295 |     validate_light_mvi(c); | 
 | 296 |     light_picker(c); | 
 | 297 |     c->lighting.lightVertex(c, v); | 
 | 298 | } | 
 | 299 |  | 
 | 300 | void lightVertexValidate(ogles_context_t* c, vertex_t* v) | 
 | 301 | { | 
 | 302 |     validate_light(c); | 
 | 303 |     light_picker(c); | 
 | 304 |     c->lighting.lightVertex(c, v); | 
 | 305 | } | 
 | 306 |  | 
 | 307 | void lightVertexMaterial(ogles_context_t* c, vertex_t* v) | 
 | 308 | { | 
 | 309 |     // fetch the material color | 
 | 310 |     const GLvoid* cp = c->arrays.color.element( | 
 | 311 |             v->index & vertex_cache_t::INDEX_MASK); | 
 | 312 |     c->arrays.color.fetch(c, v->color.v, cp); | 
 | 313 |  | 
 | 314 |     // acquire the color-material from the vertex | 
 | 315 |     material_t& material = c->lighting.front; | 
 | 316 |     material.ambient = | 
 | 317 |     material.diffuse = v->color; | 
 | 318 |     // implicit arguments need to be computed per/vertex | 
 | 319 |     uint32_t en = c->lighting.enabledLights; | 
 | 320 |     while (en) { | 
 | 321 |         const int i = 31 - gglClz(en); | 
 | 322 |         en &= ~(1<<i); | 
 | 323 |         light_t& l = c->lighting.lights[i]; | 
 | 324 |         vmul3(l.implicitAmbient.v,  material.ambient.v,  l.ambient.v); | 
 | 325 |         vmul3(l.implicitDiffuse.v,  material.diffuse.v,  l.diffuse.v); | 
 | 326 |         vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v); | 
| Mathias Agopian | 50aba6d | 2009-06-02 22:51:09 -0700 | [diff] [blame] | 327 |         // this is just a flag to tell if we have a specular component | 
 | 328 |         l.implicitSpecular.v[3] = | 
 | 329 |                 l.implicitSpecular.r | | 
 | 330 |                 l.implicitSpecular.g | | 
 | 331 |                 l.implicitSpecular.b; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 332 |     } | 
 | 333 |     // emission and ambient for the whole scene | 
 | 334 |     vmla3(  c->lighting.implicitSceneEmissionAndAmbient.v, | 
 | 335 |             c->lighting.lightModel.ambient.v, | 
 | 336 |             material.ambient.v,  | 
 | 337 |             material.emission.v); | 
 | 338 |     c->lighting.implicitSceneEmissionAndAmbient.a = material.diffuse.a; | 
 | 339 |  | 
 | 340 |     // now we can light our vertex as usual | 
 | 341 |     lightVertex(c, v); | 
 | 342 | } | 
 | 343 |  | 
 | 344 | void lightVertex(ogles_context_t* c, vertex_t* v) | 
 | 345 | { | 
 | 346 |     // emission and ambient for the whole scene | 
 | 347 |     vec4_t r = c->lighting.implicitSceneEmissionAndAmbient; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 348 |     const vec4_t objViewer = c->lighting.objViewer; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 349 |  | 
 | 350 |     uint32_t en = c->lighting.enabledLights; | 
 | 351 |     if (ggl_likely(en)) { | 
 | 352 |         // since we do the lighting in object-space, we don't need to | 
 | 353 |         // transform each normal. However, we might still have to normalize | 
 | 354 |         // it if GL_NORMALIZE is enabled. | 
 | 355 |         vec4_t n; | 
 | 356 |         c->arrays.normal.fetch(c, n.v, | 
 | 357 |             c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK)); | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 358 |  | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 359 | #if !OBJECT_SPACE_LIGHTING | 
 | 360 |         c->transforms.mvui.point3(&c->transforms.mvui, &n, &n); | 
 | 361 | #endif | 
 | 362 |  | 
 | 363 |         // TODO: right now we handle GL_RESCALE_NORMALS as if it were | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 364 |         // GL_NORMALIZE. We could optimize this by  scaling mvui  | 
 | 365 |         // appropriately instead. | 
 | 366 |         if (c->transforms.rescaleNormals) | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 367 |             vnorm3(n.v, n.v); | 
 | 368 |  | 
 | 369 |         const material_t& material = c->lighting.front; | 
 | 370 |         const int twoSide = c->lighting.lightModel.twoSide; | 
 | 371 |  | 
 | 372 |         while (en) { | 
 | 373 |             const int i = 31 - gglClz(en); | 
 | 374 |             en &= ~(1<<i); | 
 | 375 |             const light_t& l = c->lighting.lights[i]; | 
 | 376 |              | 
 | 377 |             vec4_t d, t; | 
 | 378 |             GLfixed s; | 
 | 379 |             GLfixed sqDist = 0x10000; | 
 | 380 |  | 
 | 381 |             // compute vertex-to-light vector | 
 | 382 |             if (ggl_unlikely(l.position.w)) { | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 383 |                 // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex | 
| Martin Storsjo | d5b1cda | 2012-04-24 00:50:56 +0300 | [diff] [blame] | 384 | #if !OBJECT_SPACE_LIGHTING | 
 | 385 |                 vec4_t o; | 
 | 386 |                 const transform_t& mv = c->transforms.modelview.transform; | 
 | 387 |                 mv.point4(&mv, &o, &v->obj); | 
 | 388 |                 vss3(d.v, l.objPosition.v, o.w, o.v); | 
 | 389 | #else | 
| Mathias Agopian | 69ca17a | 2009-06-02 22:05:04 -0700 | [diff] [blame] | 390 |                 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); | 
| Martin Storsjo | d5b1cda | 2012-04-24 00:50:56 +0300 | [diff] [blame] | 391 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 392 |                 sqDist = dot3(d.v, d.v); | 
 | 393 |                 vscale3(d.v, d.v, gglSqrtRecipx(sqDist)); | 
 | 394 |             } else { | 
 | 395 |                 // TODO: avoid copy here | 
 | 396 |                 d = l.normalizedObjPosition; | 
 | 397 |             } | 
 | 398 |  | 
 | 399 |             // ambient & diffuse | 
 | 400 |             s = dot3(n.v, d.v); | 
 | 401 |             s = (s<0) ? (twoSide?(-s):0) : s; | 
 | 402 |             vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v); | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 403 |  | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 404 |             // specular | 
 | 405 |             if (ggl_unlikely(s && l.implicitSpecular.v[3])) { | 
 | 406 |                 vec4_t h; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 407 |                 h.x = d.x + objViewer.x; | 
 | 408 |                 h.y = d.y + objViewer.y; | 
 | 409 |                 h.z = d.z + objViewer.z; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 410 |                 vnorm3(h.v, h.v); | 
 | 411 |                 s = dot3(n.v, h.v); | 
 | 412 |                 s = (s<0) ? (twoSide?(-s):0) : s; | 
 | 413 |                 if (s > 0) { | 
 | 414 |                     s = gglPowx(s, material.shininess); | 
 | 415 |                     vsa3(t.v, l.implicitSpecular.v, s, t.v); | 
 | 416 |                 } | 
 | 417 |             } | 
 | 418 |  | 
 | 419 |             // spot | 
 | 420 |             if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) { | 
 | 421 |                 GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v); | 
 | 422 |                 if (spotAtt >= l.spotCutoffCosine) { | 
 | 423 |                     vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp)); | 
 | 424 |                 } | 
 | 425 |             } | 
 | 426 |  | 
 | 427 |             // attenuation | 
 | 428 |             if (ggl_unlikely(l.position.w)) { | 
 | 429 |                 if (l.rConstAttenuation) { | 
 | 430 |                     s = l.rConstAttenuation; | 
 | 431 |                 } else { | 
 | 432 |                     s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]); | 
 | 433 |                     if (l.attenuation[1]) | 
 | 434 |                         s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s); | 
 | 435 |                     s = gglRecipFast(s); | 
 | 436 |                 } | 
 | 437 |                 vscale3(t.v, t.v, s); | 
 | 438 |             } | 
 | 439 |  | 
 | 440 |             r.r += t.r; | 
 | 441 |             r.g += t.g; | 
 | 442 |             r.b += t.b; | 
 | 443 |         } | 
 | 444 |     } | 
 | 445 |     v->color.r = gglClampx(r.r); | 
 | 446 |     v->color.g = gglClampx(r.g); | 
 | 447 |     v->color.b = gglClampx(r.b); | 
 | 448 |     v->color.a = gglClampx(r.a); | 
 | 449 |     v->flags |= vertex_t::LIT; | 
 | 450 | } | 
 | 451 |  | 
 | 452 | static void lightModelx(GLenum pname, GLfixed param, ogles_context_t* c) | 
 | 453 | { | 
 | 454 |     if (ggl_unlikely(pname != GL_LIGHT_MODEL_TWO_SIDE)) { | 
 | 455 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 456 |         return; | 
 | 457 |     } | 
 | 458 |     c->lighting.lightModel.twoSide = param ? GL_TRUE : GL_FALSE; | 
 | 459 |     invalidate_lighting(c); | 
 | 460 | } | 
 | 461 |  | 
 | 462 | static void lightx(GLenum i, GLenum pname, GLfixed param, ogles_context_t* c) | 
 | 463 | { | 
 | 464 |     if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { | 
 | 465 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 466 |         return; | 
 | 467 |     } | 
 | 468 |  | 
 | 469 |     light_t& light = c->lighting.lights[i-GL_LIGHT0]; | 
 | 470 |     const GLfixed kDegToRad = GLfixed((M_PI * gglIntToFixed(1)) / 180.0f); | 
 | 471 |     switch (pname) { | 
 | 472 |     case GL_SPOT_EXPONENT: | 
 | 473 |         if (GGLfixed(param) >= gglIntToFixed(128)) { | 
 | 474 |             ogles_error(c, GL_INVALID_VALUE); | 
 | 475 |             return; | 
 | 476 |         } | 
 | 477 |         light.spotExp = param; | 
 | 478 |         break; | 
 | 479 |     case GL_SPOT_CUTOFF: | 
 | 480 |         if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) { | 
 | 481 |             ogles_error(c, GL_INVALID_VALUE); | 
 | 482 |             return; | 
 | 483 |         } | 
 | 484 |         light.spotCutoff = param; | 
 | 485 |         light.spotCutoffCosine =  | 
 | 486 |                 gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param)); | 
 | 487 |         break; | 
 | 488 |     case GL_CONSTANT_ATTENUATION: | 
 | 489 |         if (param < 0) { | 
 | 490 |             ogles_error(c, GL_INVALID_VALUE); | 
 | 491 |             return; | 
 | 492 |         } | 
 | 493 |         light.attenuation[0] = param; | 
 | 494 |         break; | 
 | 495 |     case GL_LINEAR_ATTENUATION: | 
 | 496 |         if (param < 0) { | 
 | 497 |             ogles_error(c, GL_INVALID_VALUE); | 
 | 498 |             return; | 
 | 499 |         } | 
 | 500 |         light.attenuation[1] = param; | 
 | 501 |         break; | 
 | 502 |     case GL_QUADRATIC_ATTENUATION: | 
 | 503 |         if (param < 0) { | 
 | 504 |             ogles_error(c, GL_INVALID_VALUE); | 
 | 505 |             return; | 
 | 506 |         } | 
 | 507 |         light.attenuation[2] = param; | 
 | 508 |         break; | 
 | 509 |     default: | 
 | 510 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 511 |         return; | 
 | 512 |     } | 
 | 513 |     invalidate_lighting(c); | 
 | 514 | } | 
 | 515 |  | 
 | 516 | static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c) | 
 | 517 | { | 
 | 518 |     if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { | 
 | 519 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 520 |         return; | 
 | 521 |     } | 
 | 522 |  | 
 | 523 |     GLfixed* what; | 
 | 524 |     light_t& light = c->lighting.lights[i-GL_LIGHT0]; | 
 | 525 |     switch (pname) { | 
 | 526 |     case GL_AMBIENT: | 
 | 527 |         what = light.ambient.v; | 
 | 528 |         break; | 
 | 529 |     case GL_DIFFUSE: | 
 | 530 |         what = light.diffuse.v; | 
 | 531 |         break; | 
 | 532 |     case GL_SPECULAR: | 
 | 533 |         what = light.specular.v; | 
 | 534 |         break; | 
 | 535 |     case GL_POSITION: { | 
 | 536 |         ogles_validate_transform(c, transform_state_t::MODELVIEW); | 
 | 537 |         transform_t& mv = c->transforms.modelview.transform; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 538 |         mv.point4(&mv, &light.position, reinterpret_cast<vec4_t const*>(params)); | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 539 |         invalidate_lighting(c); | 
 | 540 |         return; | 
 | 541 |     } | 
 | 542 |     case GL_SPOT_DIRECTION: { | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 543 | #if OBJECT_SPACE_LIGHTING | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 544 |         ogles_validate_transform(c, transform_state_t::MVUI); | 
 | 545 |         transform_t& mvui = c->transforms.mvui; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 546 |         mvui.point3(&mvui, &light.spotDir, reinterpret_cast<vec4_t const*>(params)); | 
 | 547 | #else | 
 | 548 |         light.spotDir = *reinterpret_cast<vec4_t const*>(params); | 
 | 549 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 550 |         vnorm3(light.normalizedSpotDir.v, light.spotDir.v); | 
 | 551 |         invalidate_lighting(c); | 
 | 552 |         return; | 
 | 553 |     } | 
 | 554 |     default: | 
 | 555 |         lightx(i, pname, params[0], c); | 
 | 556 |         return; | 
 | 557 |     } | 
 | 558 |     what[0] = params[0]; | 
 | 559 |     what[1] = params[1]; | 
 | 560 |     what[2] = params[2]; | 
 | 561 |     what[3] = params[3]; | 
 | 562 |     invalidate_lighting(c); | 
 | 563 | } | 
 | 564 |  | 
 | 565 | static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c) | 
 | 566 | { | 
 | 567 |     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { | 
 | 568 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 569 |         return; | 
 | 570 |     } | 
 | 571 |     if (ggl_unlikely(pname != GL_SHININESS)) { | 
 | 572 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 573 |         return; | 
 | 574 |     } | 
 | 575 |     c->lighting.front.shininess = param; | 
 | 576 |     invalidate_lighting(c); | 
 | 577 | } | 
 | 578 |  | 
 | 579 | static void fogx(GLenum pname, GLfixed param, ogles_context_t* c) | 
 | 580 | { | 
 | 581 |     switch (pname) { | 
 | 582 |     case GL_FOG_DENSITY: | 
 | 583 |         if (param >= 0) { | 
 | 584 |             c->fog.density = param; | 
 | 585 |             break; | 
 | 586 |         } | 
 | 587 |         ogles_error(c, GL_INVALID_VALUE); | 
 | 588 |         break; | 
 | 589 |     case GL_FOG_START: | 
 | 590 |         c->fog.start = param; | 
 | 591 |         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); | 
 | 592 |         break; | 
 | 593 |     case GL_FOG_END: | 
 | 594 |         c->fog.end = param; | 
 | 595 |         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); | 
 | 596 |         break; | 
 | 597 |     case GL_FOG_MODE: | 
 | 598 |         switch (param) { | 
 | 599 |         case GL_LINEAR: | 
 | 600 |             c->fog.mode = param; | 
 | 601 |             c->fog.fog = fog_linear; | 
 | 602 |             break; | 
 | 603 |         case GL_EXP: | 
 | 604 |             c->fog.mode = param; | 
 | 605 |             c->fog.fog = fog_exp; | 
 | 606 |             break; | 
 | 607 |         case GL_EXP2: | 
 | 608 |             c->fog.mode = param; | 
 | 609 |             c->fog.fog = fog_exp2; | 
 | 610 |             break; | 
 | 611 |         default: | 
 | 612 |             ogles_error(c, GL_INVALID_ENUM); | 
 | 613 |             break; | 
 | 614 |         } | 
 | 615 |         break; | 
 | 616 |     default: | 
 | 617 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 618 |         break; | 
 | 619 |     } | 
 | 620 | } | 
 | 621 |  | 
 | 622 | // ---------------------------------------------------------------------------- | 
 | 623 | }; // namespace android | 
 | 624 | // ---------------------------------------------------------------------------- | 
 | 625 |  | 
 | 626 | using namespace android; | 
 | 627 |  | 
 | 628 | #if 0 | 
 | 629 | #pragma mark - | 
 | 630 | #pragma mark lighting APIs | 
 | 631 | #endif | 
 | 632 |  | 
 | 633 | void glShadeModel(GLenum mode) | 
 | 634 | { | 
 | 635 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 636 |     if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) { | 
 | 637 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 638 |         return; | 
 | 639 |     } | 
 | 640 |     c->lighting.shadeModel = mode; | 
 | 641 | } | 
 | 642 |  | 
 | 643 | void glLightModelf(GLenum pname, GLfloat param) | 
 | 644 | { | 
 | 645 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 646 |     lightModelx(pname, gglFloatToFixed(param), c); | 
 | 647 | } | 
 | 648 |  | 
 | 649 | void glLightModelx(GLenum pname, GLfixed param) | 
 | 650 | { | 
 | 651 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 652 |     lightModelx(pname, param, c); | 
 | 653 | } | 
 | 654 |  | 
 | 655 | void glLightModelfv(GLenum pname, const GLfloat *params) | 
 | 656 | { | 
 | 657 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 658 |     if (pname == GL_LIGHT_MODEL_TWO_SIDE) { | 
 | 659 |         lightModelx(pname, gglFloatToFixed(params[0]), c); | 
 | 660 |         return; | 
 | 661 |     } | 
 | 662 |  | 
 | 663 |     if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { | 
 | 664 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 665 |         return; | 
 | 666 |     } | 
 | 667 |  | 
 | 668 |     c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]); | 
 | 669 |     c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]); | 
 | 670 |     c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]); | 
 | 671 |     c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]); | 
 | 672 |     invalidate_lighting(c); | 
 | 673 | } | 
 | 674 |  | 
 | 675 | void glLightModelxv(GLenum pname, const GLfixed *params) | 
 | 676 | { | 
 | 677 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 678 |     if (pname == GL_LIGHT_MODEL_TWO_SIDE) { | 
 | 679 |         lightModelx(pname, params[0], c); | 
 | 680 |         return; | 
 | 681 |     } | 
 | 682 |  | 
 | 683 |     if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { | 
 | 684 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 685 |         return; | 
 | 686 |     } | 
 | 687 |  | 
 | 688 |     c->lighting.lightModel.ambient.r = params[0]; | 
 | 689 |     c->lighting.lightModel.ambient.g = params[1]; | 
 | 690 |     c->lighting.lightModel.ambient.b = params[2]; | 
 | 691 |     c->lighting.lightModel.ambient.a = params[3]; | 
 | 692 |     invalidate_lighting(c); | 
 | 693 | } | 
 | 694 |  | 
 | 695 | // ---------------------------------------------------------------------------- | 
 | 696 | #if 0 | 
 | 697 | #pragma mark - | 
 | 698 | #endif | 
 | 699 |  | 
 | 700 | void glLightf(GLenum i, GLenum pname, GLfloat param) | 
 | 701 | { | 
 | 702 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 703 |     lightx(i, pname, gglFloatToFixed(param), c); | 
 | 704 | } | 
 | 705 |  | 
 | 706 | void glLightx(GLenum i, GLenum pname, GLfixed param) | 
 | 707 | { | 
 | 708 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 709 |     lightx(i, pname, param, c); | 
 | 710 | } | 
 | 711 |  | 
 | 712 | void glLightfv(GLenum i, GLenum pname, const GLfloat *params) | 
 | 713 | { | 
 | 714 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 715 |     switch (pname) { | 
 | 716 |     case GL_SPOT_EXPONENT: | 
 | 717 |     case GL_SPOT_CUTOFF: | 
 | 718 |     case GL_CONSTANT_ATTENUATION: | 
 | 719 |     case GL_LINEAR_ATTENUATION: | 
 | 720 |     case GL_QUADRATIC_ATTENUATION: | 
 | 721 |         lightx(i, pname, gglFloatToFixed(params[0]), c); | 
 | 722 |         return; | 
 | 723 |     } | 
 | 724 |  | 
 | 725 |     GLfixed paramsx[4]; | 
 | 726 |     paramsx[0] = gglFloatToFixed(params[0]); | 
 | 727 |     paramsx[1] = gglFloatToFixed(params[1]); | 
 | 728 |     paramsx[2] = gglFloatToFixed(params[2]); | 
 | 729 |     if (pname != GL_SPOT_DIRECTION) | 
 | 730 |         paramsx[3] = gglFloatToFixed(params[3]); | 
 | 731 |  | 
 | 732 |     lightxv(i, pname, paramsx, c); | 
 | 733 | } | 
 | 734 |  | 
 | 735 | void glLightxv(GLenum i, GLenum pname, const GLfixed *params) | 
 | 736 | { | 
 | 737 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 738 |     lightxv(i, pname, params, c); | 
 | 739 | } | 
 | 740 |  | 
 | 741 | // ---------------------------------------------------------------------------- | 
 | 742 | #if 0 | 
 | 743 | #pragma mark - | 
 | 744 | #endif | 
 | 745 |  | 
 | 746 | void glMaterialf(GLenum face, GLenum pname, GLfloat param) | 
 | 747 | { | 
 | 748 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 749 |     materialx(face, pname, gglFloatToFixed(param), c); | 
 | 750 | } | 
 | 751 |  | 
 | 752 | void glMaterialx(GLenum face, GLenum pname, GLfixed param) | 
 | 753 | { | 
 | 754 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 755 |     materialx(face, pname, param, c); | 
 | 756 | } | 
 | 757 |  | 
 | 758 | void glMaterialfv( | 
 | 759 |     GLenum face, GLenum pname, const GLfloat *params) | 
 | 760 | { | 
 | 761 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 762 |     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { | 
 | 763 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 764 |         return; | 
 | 765 |     } | 
 | 766 |     GLfixed* what=0; | 
 | 767 |     GLfixed* other=0; | 
 | 768 |     switch (pname) { | 
 | 769 |     case GL_AMBIENT:    what = c->lighting.front.ambient.v; break; | 
 | 770 |     case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break; | 
 | 771 |     case GL_SPECULAR:   what = c->lighting.front.specular.v; break; | 
 | 772 |     case GL_EMISSION:   what = c->lighting.front.emission.v; break; | 
 | 773 |     case GL_AMBIENT_AND_DIFFUSE: | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 774 |         what  = c->lighting.front.ambient.v; | 
 | 775 |         other = c->lighting.front.diffuse.v; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 776 |         break; | 
 | 777 |     case GL_SHININESS: | 
 | 778 |         c->lighting.front.shininess = gglFloatToFixed(params[0]); | 
 | 779 |         invalidate_lighting(c); | 
 | 780 |         return; | 
 | 781 |     default: | 
 | 782 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 783 |         return; | 
 | 784 |     } | 
 | 785 |     what[0] = gglFloatToFixed(params[0]); | 
 | 786 |     what[1] = gglFloatToFixed(params[1]); | 
 | 787 |     what[2] = gglFloatToFixed(params[2]); | 
 | 788 |     what[3] = gglFloatToFixed(params[3]); | 
 | 789 |     if (other) { | 
 | 790 |         other[0] = what[0]; | 
 | 791 |         other[1] = what[1]; | 
 | 792 |         other[2] = what[2]; | 
 | 793 |         other[3] = what[3]; | 
 | 794 |     } | 
 | 795 |     invalidate_lighting(c); | 
 | 796 | } | 
 | 797 |  | 
 | 798 | void glMaterialxv( | 
 | 799 |     GLenum face, GLenum pname, const GLfixed *params) | 
 | 800 | { | 
 | 801 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 802 |     if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { | 
 | 803 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 804 |         return; | 
 | 805 |     } | 
 | 806 |     GLfixed* what=0; | 
 | 807 |     GLfixed* other=0; | 
 | 808 |     switch (pname) { | 
 | 809 |     case GL_AMBIENT:    what = c->lighting.front.ambient.v; break; | 
 | 810 |     case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break; | 
 | 811 |     case GL_SPECULAR:   what = c->lighting.front.specular.v; break; | 
 | 812 |     case GL_EMISSION:   what = c->lighting.front.emission.v; break; | 
 | 813 |     case GL_AMBIENT_AND_DIFFUSE: | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 814 |         what  = c->lighting.front.ambient.v; | 
 | 815 |         other = c->lighting.front.diffuse.v; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 816 |         break; | 
 | 817 |     case GL_SHININESS: | 
 | 818 |         c->lighting.front.shininess = gglFloatToFixed(params[0]); | 
 | 819 |         invalidate_lighting(c); | 
 | 820 |         return; | 
 | 821 |     default: | 
 | 822 |         ogles_error(c, GL_INVALID_ENUM); | 
 | 823 |         return; | 
 | 824 |     } | 
 | 825 |     what[0] = params[0]; | 
 | 826 |     what[1] = params[1]; | 
 | 827 |     what[2] = params[2]; | 
 | 828 |     what[3] = params[3]; | 
 | 829 |     if (other) { | 
 | 830 |         other[0] = what[0]; | 
 | 831 |         other[1] = what[1]; | 
 | 832 |         other[2] = what[2]; | 
 | 833 |         other[3] = what[3]; | 
 | 834 |     } | 
 | 835 |     invalidate_lighting(c); | 
 | 836 | } | 
 | 837 |  | 
 | 838 | // ---------------------------------------------------------------------------- | 
 | 839 | #if 0 | 
 | 840 | #pragma mark - | 
 | 841 | #pragma mark fog | 
 | 842 | #endif | 
 | 843 |  | 
 | 844 | void glFogf(GLenum pname, GLfloat param) { | 
 | 845 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 846 |     GLfixed paramx = (GLfixed)param; | 
 | 847 |     if (pname != GL_FOG_MODE) | 
 | 848 |         paramx = gglFloatToFixed(param); | 
 | 849 |     fogx(pname, paramx, c); | 
 | 850 | } | 
 | 851 |  | 
 | 852 | void glFogx(GLenum pname, GLfixed param) { | 
 | 853 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 854 |     fogx(pname, param, c); | 
 | 855 | } | 
 | 856 |  | 
 | 857 | void glFogfv(GLenum pname, const GLfloat *params) | 
 | 858 | { | 
 | 859 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 860 |     if (pname != GL_FOG_COLOR) { | 
 | 861 |         GLfixed paramx = (GLfixed)params[0]; | 
 | 862 |         if (pname != GL_FOG_MODE) | 
 | 863 |             paramx = gglFloatToFixed(params[0]); | 
 | 864 |         fogx(pname, paramx, c); | 
 | 865 |         return; | 
 | 866 |     } | 
 | 867 |     GLfixed paramsx[4]; | 
 | 868 |     paramsx[0] = gglFloatToFixed(params[0]); | 
 | 869 |     paramsx[1] = gglFloatToFixed(params[1]); | 
 | 870 |     paramsx[2] = gglFloatToFixed(params[2]); | 
 | 871 |     paramsx[3] = gglFloatToFixed(params[3]); | 
 | 872 |     c->rasterizer.procs.fogColor3xv(c, paramsx); | 
 | 873 | } | 
 | 874 |  | 
 | 875 | void glFogxv(GLenum pname, const GLfixed *params) | 
 | 876 | { | 
 | 877 |     ogles_context_t* c = ogles_context_t::get(); | 
 | 878 |     if (pname != GL_FOG_COLOR) { | 
 | 879 |         fogx(pname, params[0], c); | 
 | 880 |         return; | 
 | 881 |     } | 
 | 882 |     c->rasterizer.procs.fogColor3xv(c, params); | 
 | 883 | } |