static inline void validate_light_mvi(ogles_context_t* c) { uint32_t en = c->lighting.enabledLights; while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); light_t& l = c->lighting.lights[i]; c->transforms.mvui.point4(&c->transforms.mvui, &l.objPosition, &l.position); vnorm3(l.normalizedObjPosition.v, l.objPosition.v); } }
static void lightxv(GLenum i, GLenum pname, const GLfixed *params, ogles_context_t* c) { if (ggl_unlikely(uint32_t(i-GL_LIGHT0) >= OGLES_MAX_LIGHTS)) { ogles_error(c, GL_INVALID_ENUM); return; } GLfixed* what; light_t& light = c->lighting.lights[i-GL_LIGHT0]; switch (pname) { case GL_AMBIENT: what = light.ambient.v; break; case GL_DIFFUSE: what = light.diffuse.v; break; case GL_SPECULAR: what = light.specular.v; break; case GL_POSITION: { ogles_validate_transform(c, transform_state_t::MODELVIEW); transform_t& mv = c->transforms.modelview.transform; memcpy(light.position.v, params, sizeof(light.position.v)); mv.point4(&mv, &light.position, &light.position); invalidate_lighting(c); return; } case GL_SPOT_DIRECTION: { ogles_validate_transform(c, transform_state_t::MVUI); transform_t& mvui = c->transforms.mvui; mvui.point3(&mvui, &light.spotDir, (vec4_t*)params); vnorm3(light.normalizedSpotDir.v, light.spotDir.v); invalidate_lighting(c); return; } default: lightx(i, pname, params[0], c); return; } what[0] = params[0]; what[1] = params[1]; what[2] = params[2]; what[3] = params[3]; invalidate_lighting(c); }
static void compute_lighting (GLcontext *g, GL_float color[4], GL_float position[4], GL_float normal[3], GL_material *material) { GL_float projpos[4]; GL_float primary[4]; GL_float secondary[4]; GL_float ambient[3]; GL_float diffuse[3] = { 0.0f, 0.0f, 0.0f }; GL_float specular[3] = { 0.0f, 0.0f, 0.0f }; GL_float temp[3]; GL_float E[3]; int i; /* projected position */ if (position[3] == 0.0f) { if (position[3] < 0.0f) vscale3(projpos, position, -1.0f); else vcopy3(projpos, position); vnorm3(projpos, projpos); } else { GL_float scale = 1.0f / position[3]; vscale3(projpos, position, scale); } /* global ambient */ vinit3_col(ambient, g->lighting.lightmodelambient); /* eye vector */ if (g->lighting.lightmodellocalviewer) { vscale3(E, projpos, -1.0f); vnorm3(E, E); } else { vinit3(E, 0.0f, 0.0f, 1.0f); } /* lights */ for (i = 0; i < g->lighting.maxlights; i++) { GLlight *light = &g->lighting.light[i]; if (light->enable) { GL_float lightpos[4]; GL_float L[3], H[3]; GL_float kd, ks; GL_float atten = 1.0f; GL_float dist, distsq; /* light position */ vinit_vec(lightpos, light->position); /* light vector */ if (lightpos[3] == 0.0f) { if (lightpos[3] < 0.0f) vscale3(L, lightpos, -1.0f); else vcopy3(L, lightpos); vnorm3(L, L); if (position[3] == 0.0f) { vsub3(L, L, projpos); vnorm3(L, L); } } else { if (position[3] == 0.0f) vscale3(L, projpos, -1.0f); else { GL_float scale = 1.0f / lightpos[3]; vscale3(L, lightpos, scale); vsub3(L, L, projpos); distsq = vdot3(L, L); dist = sqrt(distsq); scale = 1.0f / dist; vscale(L, L, scale); } } /* halfangle vector */ vadd3(H, L, E); vnorm3(H, H); /* diffuse reflection coefficient */ kd = vdot3(normal, L); kd = max(kd, 0.0f); /* specular reflection coefficient */ ks = vdot3(normal, H); ks = max(ks, 0.0f); ks = (kd > 0.0f) * pow(ks, material->shininess); /* attenuation */ if (lightpos[3] != 0.0f) { GL_float ac = light->constantattenuation; GL_float al = light->linearattenuation; GL_float aq = light->quadraticattenuation; if (position[3] != 0.0f) atten /= (ac + al * dist + aq * distsq); else if (al == 0.0f && aq == 0.0f) atten /= ac; else atten = 0.0f; } /* spot factor */ if (light->spotcutoff != 180.0f) { GL_float S[3], exponent, cutoffcos, anglecos; vinit3_vec(S, light->spotdirection); exponent = light->spotexponent; cutoffcos = cos(light->spotcutoff); anglecos = -vdot3(L, S); anglecos = max(anglecos, 0.0f); if (anglecos < cutoffcos) atten *= pow(anglecos, exponent); else atten = 0.0f; } /* accumulate ambient */ vinit3_col(temp, light->ambient); vscale3(temp, temp, atten); vadd3(ambient, ambient, temp); /* accumulate diffuse */ vinit3_col(temp, light->diffuse); vscale3(temp, temp, kd * atten); vadd3(diffuse, diffuse, temp); /* accumulate specular */ vinit3_col(temp, light->specular); vscale3(temp, temp, ks * atten); vadd3(specular, specular, temp); } } /* primary color */ vcopy3(primary, material->emission); vmul3(ambient, ambient, material->ambient); vadd3(primary, primary, ambient); vmul3(diffuse, diffuse, material->diffuse); vadd3(primary, primary, diffuse); primary[3] = material->diffuse[3]; /* secondary color */ vmul3(secondary, specular, material->specular); secondary[3] = 0.0f; /* computer overall color, no separate specular */ vadd(color, primary, secondary); }
void __glcore_transform_vertices (GLcontext *g) { GLrenderstate *r = g->renderstate; GL_vertex *verts = r->verts; GL_procvert *procverts = r->procverts; int i; GL_float modelview[4][4]; GL_float projection[4][4]; GL_float texture[4][4]; GL_float composite[4][4]; GL_float invmodelview[4][4]; minit(modelview, g->trans.modelview[g->trans.modelviewdepth]); minit(projection, g->trans.projection[g->trans.projectiondepth]); minit(texture, g->trans.texture[g->trans.texturedepth]); mmult(composite, projection, modelview); minvtrans(invmodelview, modelview); for (i = 0; i < r->nverts; i++) { /* position */ mmultv(procverts[i].position, composite, verts[i].position); /* eye position */ mmultv(procverts[i].eyeposition, modelview, verts[i].position); /* color */ if (g->lighting.lighting) { GL_float objnormal[4]; GL_float normal[4]; /* object space normal */ vcopy(objnormal, verts[i].normal); objnormal[3] = 0.0f; if (verts[i].position[3] != 0.0f) { objnormal[3] = -vdot3(objnormal, verts[i].position); objnormal[3] /= verts[i].position[3]; } /* eye space normal */ mmultv(normal, invmodelview, objnormal); if (g->current.normalize) vnorm3(normal, normal); /* front color */ compute_lighting(g, procverts[i].frontcolor, procverts[i].eyeposition, normal, &verts[i].frontmaterial); /* back color */ if (g->lighting.lightmodeltwoside) { vscale(normal, normal, -1.0f); compute_lighting(g, procverts[i].backcolor, procverts[i].eyeposition, normal, &verts[i].backmaterial); } } else { vcopy(procverts[i].frontcolor, verts[i].color); vcopy(procverts[i].backcolor, verts[i].color); } vclamp(procverts[i].frontcolor, procverts[i].frontcolor, 0.0f, 1.0f); vclamp(procverts[i].backcolor, procverts[i].backcolor, 0.0f, 1.0f); /* no texture coordinate generation */ /* texture coords */ mmultv(procverts[i].texcoord, texture, verts[i].texcoord); } }
void lightVertex(ogles_context_t* c, vertex_t* v) { // emission and ambient for the whole scene vec4_t r = c->lighting.implicitSceneEmissionAndAmbient; uint32_t en = c->lighting.enabledLights; if (ggl_likely(en)) { // since we do the lighting in object-space, we don't need to // transform each normal. However, we might still have to normalize // it if GL_NORMALIZE is enabled. vec4_t n; c->arrays.normal.fetch(c, n.v, c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK)); // TODO: right now we handle GL_RESCALE_NORMALS as if ti were // GL_NORMALIZE. We could optimize this by scaling mvui // appropriately instead. if (c->transforms.rescaleNormals) vnorm3(n.v, n.v); const material_t& material = c->lighting.front; const int twoSide = c->lighting.lightModel.twoSide; while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); const light_t& l = c->lighting.lights[i]; vec4_t d, t; GLfixed s; GLfixed sqDist = 0x10000; // compute vertex-to-light vector if (ggl_unlikely(l.position.w)) { // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); sqDist = dot3(d.v, d.v); vscale3(d.v, d.v, gglSqrtRecipx(sqDist)); } else { // TODO: avoid copy here d = l.normalizedObjPosition; } // ambient & diffuse s = dot3(n.v, d.v); s = (s<0) ? (twoSide?(-s):0) : s; vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v); // specular if (ggl_unlikely(s && l.implicitSpecular.v[3])) { vec4_t h; h.x = d.x; h.y = d.y; h.z = d.z + 0x10000; vnorm3(h.v, h.v); s = dot3(n.v, h.v); s = (s<0) ? (twoSide?(-s):0) : s; if (s > 0) { s = gglPowx(s, material.shininess); vsa3(t.v, l.implicitSpecular.v, s, t.v); } } // spot if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) { GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v); if (spotAtt >= l.spotCutoffCosine) { vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp)); } } // attenuation if (ggl_unlikely(l.position.w)) { if (l.rConstAttenuation) { s = l.rConstAttenuation; } else { s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]); if (l.attenuation[1]) s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s); s = gglRecipFast(s); } vscale3(t.v, t.v, s); } r.r += t.r; r.g += t.g; r.b += t.b; } } v->color.r = gglClampx(r.r); v->color.g = gglClampx(r.g); v->color.b = gglClampx(r.b); v->color.a = gglClampx(r.a); v->flags |= vertex_t::LIT; }