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); 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); 47 static inline void vss3(GLfixed* d, 48 const GLfixed* m, GLfixed s, const GLfixed* a); 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 108 void ogles_uninit_light(ogles_context_t* /*c*/) 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 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]); 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; 219 // Vector from object to viewer, in eye coordinates 220 while (en) { 221 const int i = 31 - gglClz(en); 222 en &= ~(1<<i); 223 light_t& l = c->lighting.lights[i]; 224 #if OBJECT_SPACE_LIGHTING 225 c->transforms.mvui.point4(&c->transforms.mvui, 226 &l.objPosition, &l.position); 227 #else 228 l.objPosition = l.position; 229 #endif 230 vnorm3(l.normalizedObjPosition.v, l.objPosition.v); 231 } 232 const vec4_t eyeViewer = { 0, 0, 0x10000, 0 }; 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 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 288 void lightVertexNop(ogles_context_t*, vertex_t* /*v*/) 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); 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; 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; 348 const vec4_t objViewer = c->lighting.objViewer; 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)); 358 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 364 // GL_NORMALIZE. We could optimize this by scaling mvui 365 // appropriately instead. 366 if (c->transforms.rescaleNormals) 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)) { 383 // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex 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 390 vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); 391 #endif 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); 403 404 // specular 405 if (ggl_unlikely(s && l.implicitSpecular.v[3])) { 406 vec4_t h; 407 h.x = d.x + objViewer.x; 408 h.y = d.y + objViewer.y; 409 h.z = d.z + objViewer.z; 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; 538 mv.point4(&mv, &light.position, reinterpret_cast<vec4_t const*>(params)); 539 invalidate_lighting(c); 540 return; 541 } 542 case GL_SPOT_DIRECTION: { 543 #if OBJECT_SPACE_LIGHTING 544 ogles_validate_transform(c, transform_state_t::MVUI); 545 transform_t& mvui = c->transforms.mvui; 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 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: 774 what = c->lighting.front.ambient.v; 775 other = c->lighting.front.diffuse.v; 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: 814 what = c->lighting.front.ambient.v; 815 other = c->lighting.front.diffuse.v; 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 } 884