| 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 | c044ae5 | 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]; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 470 | switch (pname) { | 
|  | 471 | case GL_SPOT_EXPONENT: | 
|  | 472 | if (GGLfixed(param) >= gglIntToFixed(128)) { | 
|  | 473 | ogles_error(c, GL_INVALID_VALUE); | 
|  | 474 | return; | 
|  | 475 | } | 
|  | 476 | light.spotExp = param; | 
|  | 477 | break; | 
|  | 478 | case GL_SPOT_CUTOFF: | 
|  | 479 | if (param!=gglIntToFixed(180) && GGLfixed(param)>=gglIntToFixed(90)) { | 
|  | 480 | ogles_error(c, GL_INVALID_VALUE); | 
|  | 481 | return; | 
|  | 482 | } | 
|  | 483 | light.spotCutoff = param; | 
|  | 484 | light.spotCutoffCosine = | 
|  | 485 | gglFloatToFixed(cosinef((M_PI/(180.0f*65536.0f))*param)); | 
|  | 486 | break; | 
|  | 487 | case GL_CONSTANT_ATTENUATION: | 
|  | 488 | if (param < 0) { | 
|  | 489 | ogles_error(c, GL_INVALID_VALUE); | 
|  | 490 | return; | 
|  | 491 | } | 
|  | 492 | light.attenuation[0] = param; | 
|  | 493 | break; | 
|  | 494 | case GL_LINEAR_ATTENUATION: | 
|  | 495 | if (param < 0) { | 
|  | 496 | ogles_error(c, GL_INVALID_VALUE); | 
|  | 497 | return; | 
|  | 498 | } | 
|  | 499 | light.attenuation[1] = param; | 
|  | 500 | break; | 
|  | 501 | case GL_QUADRATIC_ATTENUATION: | 
|  | 502 | if (param < 0) { | 
|  | 503 | ogles_error(c, GL_INVALID_VALUE); | 
|  | 504 | return; | 
|  | 505 | } | 
|  | 506 | light.attenuation[2] = param; | 
|  | 507 | break; | 
|  | 508 | default: | 
|  | 509 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 510 | return; | 
|  | 511 | } | 
|  | 512 | invalidate_lighting(c); | 
|  | 513 | } | 
|  | 514 |  | 
|  | 515 | static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c) | 
|  | 516 | { | 
|  | 517 | if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { | 
|  | 518 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 519 | return; | 
|  | 520 | } | 
|  | 521 |  | 
|  | 522 | GLfixed* what; | 
|  | 523 | light_t& light = c->lighting.lights[i-GL_LIGHT0]; | 
|  | 524 | switch (pname) { | 
|  | 525 | case GL_AMBIENT: | 
|  | 526 | what = light.ambient.v; | 
|  | 527 | break; | 
|  | 528 | case GL_DIFFUSE: | 
|  | 529 | what = light.diffuse.v; | 
|  | 530 | break; | 
|  | 531 | case GL_SPECULAR: | 
|  | 532 | what = light.specular.v; | 
|  | 533 | break; | 
|  | 534 | case GL_POSITION: { | 
|  | 535 | ogles_validate_transform(c, transform_state_t::MODELVIEW); | 
|  | 536 | transform_t& mv = c->transforms.modelview.transform; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 537 | 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] | 538 | invalidate_lighting(c); | 
|  | 539 | return; | 
|  | 540 | } | 
|  | 541 | case GL_SPOT_DIRECTION: { | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 542 | #if OBJECT_SPACE_LIGHTING | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 543 | ogles_validate_transform(c, transform_state_t::MVUI); | 
|  | 544 | transform_t& mvui = c->transforms.mvui; | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 545 | mvui.point3(&mvui, &light.spotDir, reinterpret_cast<vec4_t const*>(params)); | 
|  | 546 | #else | 
|  | 547 | light.spotDir = *reinterpret_cast<vec4_t const*>(params); | 
|  | 548 | #endif | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 549 | vnorm3(light.normalizedSpotDir.v, light.spotDir.v); | 
|  | 550 | invalidate_lighting(c); | 
|  | 551 | return; | 
|  | 552 | } | 
|  | 553 | default: | 
|  | 554 | lightx(i, pname, params[0], c); | 
|  | 555 | return; | 
|  | 556 | } | 
|  | 557 | what[0] = params[0]; | 
|  | 558 | what[1] = params[1]; | 
|  | 559 | what[2] = params[2]; | 
|  | 560 | what[3] = params[3]; | 
|  | 561 | invalidate_lighting(c); | 
|  | 562 | } | 
|  | 563 |  | 
|  | 564 | static void materialx(GLenum face, GLenum pname, GLfixed param, ogles_context_t* c) | 
|  | 565 | { | 
|  | 566 | if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { | 
|  | 567 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 568 | return; | 
|  | 569 | } | 
|  | 570 | if (ggl_unlikely(pname != GL_SHININESS)) { | 
|  | 571 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 572 | return; | 
|  | 573 | } | 
|  | 574 | c->lighting.front.shininess = param; | 
|  | 575 | invalidate_lighting(c); | 
|  | 576 | } | 
|  | 577 |  | 
|  | 578 | static void fogx(GLenum pname, GLfixed param, ogles_context_t* c) | 
|  | 579 | { | 
|  | 580 | switch (pname) { | 
|  | 581 | case GL_FOG_DENSITY: | 
|  | 582 | if (param >= 0) { | 
|  | 583 | c->fog.density = param; | 
|  | 584 | break; | 
|  | 585 | } | 
|  | 586 | ogles_error(c, GL_INVALID_VALUE); | 
|  | 587 | break; | 
|  | 588 | case GL_FOG_START: | 
|  | 589 | c->fog.start = param; | 
|  | 590 | c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); | 
|  | 591 | break; | 
|  | 592 | case GL_FOG_END: | 
|  | 593 | c->fog.end = param; | 
|  | 594 | c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start); | 
|  | 595 | break; | 
|  | 596 | case GL_FOG_MODE: | 
|  | 597 | switch (param) { | 
|  | 598 | case GL_LINEAR: | 
|  | 599 | c->fog.mode = param; | 
|  | 600 | c->fog.fog = fog_linear; | 
|  | 601 | break; | 
|  | 602 | case GL_EXP: | 
|  | 603 | c->fog.mode = param; | 
|  | 604 | c->fog.fog = fog_exp; | 
|  | 605 | break; | 
|  | 606 | case GL_EXP2: | 
|  | 607 | c->fog.mode = param; | 
|  | 608 | c->fog.fog = fog_exp2; | 
|  | 609 | break; | 
|  | 610 | default: | 
|  | 611 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 612 | break; | 
|  | 613 | } | 
|  | 614 | break; | 
|  | 615 | default: | 
|  | 616 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 617 | break; | 
|  | 618 | } | 
|  | 619 | } | 
|  | 620 |  | 
|  | 621 | // ---------------------------------------------------------------------------- | 
|  | 622 | }; // namespace android | 
|  | 623 | // ---------------------------------------------------------------------------- | 
|  | 624 |  | 
|  | 625 | using namespace android; | 
|  | 626 |  | 
|  | 627 | #if 0 | 
|  | 628 | #pragma mark - | 
|  | 629 | #pragma mark lighting APIs | 
|  | 630 | #endif | 
|  | 631 |  | 
|  | 632 | void glShadeModel(GLenum mode) | 
|  | 633 | { | 
|  | 634 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 635 | if (ggl_unlikely(mode != GL_SMOOTH && mode != GL_FLAT)) { | 
|  | 636 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 637 | return; | 
|  | 638 | } | 
|  | 639 | c->lighting.shadeModel = mode; | 
|  | 640 | } | 
|  | 641 |  | 
|  | 642 | void glLightModelf(GLenum pname, GLfloat param) | 
|  | 643 | { | 
|  | 644 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 645 | lightModelx(pname, gglFloatToFixed(param), c); | 
|  | 646 | } | 
|  | 647 |  | 
|  | 648 | void glLightModelx(GLenum pname, GLfixed param) | 
|  | 649 | { | 
|  | 650 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 651 | lightModelx(pname, param, c); | 
|  | 652 | } | 
|  | 653 |  | 
|  | 654 | void glLightModelfv(GLenum pname, const GLfloat *params) | 
|  | 655 | { | 
|  | 656 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 657 | if (pname == GL_LIGHT_MODEL_TWO_SIDE) { | 
|  | 658 | lightModelx(pname, gglFloatToFixed(params[0]), c); | 
|  | 659 | return; | 
|  | 660 | } | 
|  | 661 |  | 
|  | 662 | if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { | 
|  | 663 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 664 | return; | 
|  | 665 | } | 
|  | 666 |  | 
|  | 667 | c->lighting.lightModel.ambient.r = gglFloatToFixed(params[0]); | 
|  | 668 | c->lighting.lightModel.ambient.g = gglFloatToFixed(params[1]); | 
|  | 669 | c->lighting.lightModel.ambient.b = gglFloatToFixed(params[2]); | 
|  | 670 | c->lighting.lightModel.ambient.a = gglFloatToFixed(params[3]); | 
|  | 671 | invalidate_lighting(c); | 
|  | 672 | } | 
|  | 673 |  | 
|  | 674 | void glLightModelxv(GLenum pname, const GLfixed *params) | 
|  | 675 | { | 
|  | 676 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 677 | if (pname == GL_LIGHT_MODEL_TWO_SIDE) { | 
|  | 678 | lightModelx(pname, params[0], c); | 
|  | 679 | return; | 
|  | 680 | } | 
|  | 681 |  | 
|  | 682 | if (ggl_unlikely(pname != GL_LIGHT_MODEL_AMBIENT)) { | 
|  | 683 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 684 | return; | 
|  | 685 | } | 
|  | 686 |  | 
|  | 687 | c->lighting.lightModel.ambient.r = params[0]; | 
|  | 688 | c->lighting.lightModel.ambient.g = params[1]; | 
|  | 689 | c->lighting.lightModel.ambient.b = params[2]; | 
|  | 690 | c->lighting.lightModel.ambient.a = params[3]; | 
|  | 691 | invalidate_lighting(c); | 
|  | 692 | } | 
|  | 693 |  | 
|  | 694 | // ---------------------------------------------------------------------------- | 
|  | 695 | #if 0 | 
|  | 696 | #pragma mark - | 
|  | 697 | #endif | 
|  | 698 |  | 
|  | 699 | void glLightf(GLenum i, GLenum pname, GLfloat param) | 
|  | 700 | { | 
|  | 701 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 702 | lightx(i, pname, gglFloatToFixed(param), c); | 
|  | 703 | } | 
|  | 704 |  | 
|  | 705 | void glLightx(GLenum i, GLenum pname, GLfixed param) | 
|  | 706 | { | 
|  | 707 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 708 | lightx(i, pname, param, c); | 
|  | 709 | } | 
|  | 710 |  | 
|  | 711 | void glLightfv(GLenum i, GLenum pname, const GLfloat *params) | 
|  | 712 | { | 
|  | 713 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 714 | switch (pname) { | 
|  | 715 | case GL_SPOT_EXPONENT: | 
|  | 716 | case GL_SPOT_CUTOFF: | 
|  | 717 | case GL_CONSTANT_ATTENUATION: | 
|  | 718 | case GL_LINEAR_ATTENUATION: | 
|  | 719 | case GL_QUADRATIC_ATTENUATION: | 
|  | 720 | lightx(i, pname, gglFloatToFixed(params[0]), c); | 
|  | 721 | return; | 
|  | 722 | } | 
|  | 723 |  | 
|  | 724 | GLfixed paramsx[4]; | 
|  | 725 | paramsx[0] = gglFloatToFixed(params[0]); | 
|  | 726 | paramsx[1] = gglFloatToFixed(params[1]); | 
|  | 727 | paramsx[2] = gglFloatToFixed(params[2]); | 
|  | 728 | if (pname != GL_SPOT_DIRECTION) | 
|  | 729 | paramsx[3] = gglFloatToFixed(params[3]); | 
|  | 730 |  | 
|  | 731 | lightxv(i, pname, paramsx, c); | 
|  | 732 | } | 
|  | 733 |  | 
|  | 734 | void glLightxv(GLenum i, GLenum pname, const GLfixed *params) | 
|  | 735 | { | 
|  | 736 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 737 | lightxv(i, pname, params, c); | 
|  | 738 | } | 
|  | 739 |  | 
|  | 740 | // ---------------------------------------------------------------------------- | 
|  | 741 | #if 0 | 
|  | 742 | #pragma mark - | 
|  | 743 | #endif | 
|  | 744 |  | 
|  | 745 | void glMaterialf(GLenum face, GLenum pname, GLfloat param) | 
|  | 746 | { | 
|  | 747 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 748 | materialx(face, pname, gglFloatToFixed(param), c); | 
|  | 749 | } | 
|  | 750 |  | 
|  | 751 | void glMaterialx(GLenum face, GLenum pname, GLfixed param) | 
|  | 752 | { | 
|  | 753 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 754 | materialx(face, pname, param, c); | 
|  | 755 | } | 
|  | 756 |  | 
|  | 757 | void glMaterialfv( | 
|  | 758 | GLenum face, GLenum pname, const GLfloat *params) | 
|  | 759 | { | 
|  | 760 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 761 | if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { | 
|  | 762 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 763 | return; | 
|  | 764 | } | 
|  | 765 | GLfixed* what=0; | 
|  | 766 | GLfixed* other=0; | 
|  | 767 | switch (pname) { | 
|  | 768 | case GL_AMBIENT:    what = c->lighting.front.ambient.v; break; | 
|  | 769 | case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break; | 
|  | 770 | case GL_SPECULAR:   what = c->lighting.front.specular.v; break; | 
|  | 771 | case GL_EMISSION:   what = c->lighting.front.emission.v; break; | 
|  | 772 | case GL_AMBIENT_AND_DIFFUSE: | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 773 | what  = c->lighting.front.ambient.v; | 
|  | 774 | other = c->lighting.front.diffuse.v; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 775 | break; | 
|  | 776 | case GL_SHININESS: | 
|  | 777 | c->lighting.front.shininess = gglFloatToFixed(params[0]); | 
|  | 778 | invalidate_lighting(c); | 
|  | 779 | return; | 
|  | 780 | default: | 
|  | 781 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 782 | return; | 
|  | 783 | } | 
|  | 784 | what[0] = gglFloatToFixed(params[0]); | 
|  | 785 | what[1] = gglFloatToFixed(params[1]); | 
|  | 786 | what[2] = gglFloatToFixed(params[2]); | 
|  | 787 | what[3] = gglFloatToFixed(params[3]); | 
|  | 788 | if (other) { | 
|  | 789 | other[0] = what[0]; | 
|  | 790 | other[1] = what[1]; | 
|  | 791 | other[2] = what[2]; | 
|  | 792 | other[3] = what[3]; | 
|  | 793 | } | 
|  | 794 | invalidate_lighting(c); | 
|  | 795 | } | 
|  | 796 |  | 
|  | 797 | void glMaterialxv( | 
|  | 798 | GLenum face, GLenum pname, const GLfixed *params) | 
|  | 799 | { | 
|  | 800 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 801 | if (ggl_unlikely(face != GL_FRONT_AND_BACK)) { | 
|  | 802 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 803 | return; | 
|  | 804 | } | 
|  | 805 | GLfixed* what=0; | 
|  | 806 | GLfixed* other=0; | 
|  | 807 | switch (pname) { | 
|  | 808 | case GL_AMBIENT:    what = c->lighting.front.ambient.v; break; | 
|  | 809 | case GL_DIFFUSE:    what = c->lighting.front.diffuse.v; break; | 
|  | 810 | case GL_SPECULAR:   what = c->lighting.front.specular.v; break; | 
|  | 811 | case GL_EMISSION:   what = c->lighting.front.emission.v; break; | 
|  | 812 | case GL_AMBIENT_AND_DIFFUSE: | 
| Mathias Agopian | 04a3f57 | 2010-02-02 18:48:15 -0800 | [diff] [blame] | 813 | what  = c->lighting.front.ambient.v; | 
|  | 814 | other = c->lighting.front.diffuse.v; | 
| The Android Open Source Project | edbf3b6 | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 815 | break; | 
|  | 816 | case GL_SHININESS: | 
|  | 817 | c->lighting.front.shininess = gglFloatToFixed(params[0]); | 
|  | 818 | invalidate_lighting(c); | 
|  | 819 | return; | 
|  | 820 | default: | 
|  | 821 | ogles_error(c, GL_INVALID_ENUM); | 
|  | 822 | return; | 
|  | 823 | } | 
|  | 824 | what[0] = params[0]; | 
|  | 825 | what[1] = params[1]; | 
|  | 826 | what[2] = params[2]; | 
|  | 827 | what[3] = params[3]; | 
|  | 828 | if (other) { | 
|  | 829 | other[0] = what[0]; | 
|  | 830 | other[1] = what[1]; | 
|  | 831 | other[2] = what[2]; | 
|  | 832 | other[3] = what[3]; | 
|  | 833 | } | 
|  | 834 | invalidate_lighting(c); | 
|  | 835 | } | 
|  | 836 |  | 
|  | 837 | // ---------------------------------------------------------------------------- | 
|  | 838 | #if 0 | 
|  | 839 | #pragma mark - | 
|  | 840 | #pragma mark fog | 
|  | 841 | #endif | 
|  | 842 |  | 
|  | 843 | void glFogf(GLenum pname, GLfloat param) { | 
|  | 844 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 845 | GLfixed paramx = (GLfixed)param; | 
|  | 846 | if (pname != GL_FOG_MODE) | 
|  | 847 | paramx = gglFloatToFixed(param); | 
|  | 848 | fogx(pname, paramx, c); | 
|  | 849 | } | 
|  | 850 |  | 
|  | 851 | void glFogx(GLenum pname, GLfixed param) { | 
|  | 852 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 853 | fogx(pname, param, c); | 
|  | 854 | } | 
|  | 855 |  | 
|  | 856 | void glFogfv(GLenum pname, const GLfloat *params) | 
|  | 857 | { | 
|  | 858 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 859 | if (pname != GL_FOG_COLOR) { | 
|  | 860 | GLfixed paramx = (GLfixed)params[0]; | 
|  | 861 | if (pname != GL_FOG_MODE) | 
|  | 862 | paramx = gglFloatToFixed(params[0]); | 
|  | 863 | fogx(pname, paramx, c); | 
|  | 864 | return; | 
|  | 865 | } | 
|  | 866 | GLfixed paramsx[4]; | 
|  | 867 | paramsx[0] = gglFloatToFixed(params[0]); | 
|  | 868 | paramsx[1] = gglFloatToFixed(params[1]); | 
|  | 869 | paramsx[2] = gglFloatToFixed(params[2]); | 
|  | 870 | paramsx[3] = gglFloatToFixed(params[3]); | 
|  | 871 | c->rasterizer.procs.fogColor3xv(c, paramsx); | 
|  | 872 | } | 
|  | 873 |  | 
|  | 874 | void glFogxv(GLenum pname, const GLfixed *params) | 
|  | 875 | { | 
|  | 876 | ogles_context_t* c = ogles_context_t::get(); | 
|  | 877 | if (pname != GL_FOG_COLOR) { | 
|  | 878 | fogx(pname, params[0], c); | 
|  | 879 | return; | 
|  | 880 | } | 
|  | 881 | c->rasterizer.procs.fogColor3xv(c, params); | 
|  | 882 | } |