static inline void vmla3(GLfixed* d, const GLfixed* m0, const GLfixed* m1, const GLfixed* a) { d[0] = gglMulAddx(m0[0], m1[0], a[0]); d[1] = gglMulAddx(m0[1], m1[1], a[1]); d[2] = gglMulAddx(m0[2], m1[2], a[2]); }
void blending(context_t* c, pixel_t* fragment, pixel_t* fb) { rescale(fragment->c[0], fragment->s[0], fb->c[0], fb->s[0]); rescale(fragment->c[1], fragment->s[1], fb->c[1], fb->s[1]); rescale(fragment->c[2], fragment->s[2], fb->c[2], fb->s[2]); rescale(fragment->c[3], fragment->s[3], fb->c[3], fb->s[3]); pixel_t sf, df; blend_factor(c, &sf, c->state.blend.src, fragment, fb); blend_factor(c, &df, c->state.blend.dst, fragment, fb); fragment->c[1] = gglMulAddx(fragment->c[1], sf.c[1], gglMulx(fb->c[1], df.c[1])); fragment->c[2] = gglMulAddx(fragment->c[2], sf.c[2], gglMulx(fb->c[2], df.c[2])); fragment->c[3] = gglMulAddx(fragment->c[3], sf.c[3], gglMulx(fb->c[3], df.c[3])); if (c->state.blend.alpha_separate) { blend_factor(c, &sf, c->state.blend.src_alpha, fragment, fb); blend_factor(c, &df, c->state.blend.dst_alpha, fragment, fb); } fragment->c[0] = gglMulAddx(fragment->c[0], sf.c[0], gglMulx(fb->c[0], df.c[0])); // clamp to 1.0 if (fragment->c[0] >= (1LU<<fragment->s[0])) fragment->c[0] = (1<<fragment->s[0])-1; if (fragment->c[1] >= (1LU<<fragment->s[1])) fragment->c[1] = (1<<fragment->s[1])-1; if (fragment->c[2] >= (1LU<<fragment->s[2])) fragment->c[2] = (1<<fragment->s[2])-1; if (fragment->c[3] >= (1LU<<fragment->s[3])) fragment->c[3] = (1<<fragment->s[3])-1; }
void lightVertex(ogles_context_t* c, vertex_t* v) { // emission and ambient for the whole scene vec4_t r = c->lighting.implicitSceneEmissionAndAmbient; uint32_t en = c->lighting.enabledLights; if (ggl_likely(en)) { // since we do the lighting in object-space, we don't need to // transform each normal. However, we might still have to normalize // it if GL_NORMALIZE is enabled. vec4_t n; c->arrays.normal.fetch(c, n.v, c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK)); // TODO: right now we handle GL_RESCALE_NORMALS as if ti were // GL_NORMALIZE. We could optimize this by scaling mvui // appropriately instead. if (c->transforms.rescaleNormals) vnorm3(n.v, n.v); const material_t& material = c->lighting.front; const int twoSide = c->lighting.lightModel.twoSide; while (en) { const int i = 31 - gglClz(en); en &= ~(1<<i); const light_t& l = c->lighting.lights[i]; vec4_t d, t; GLfixed s; GLfixed sqDist = 0x10000; // compute vertex-to-light vector if (ggl_unlikely(l.position.w)) { // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v); sqDist = dot3(d.v, d.v); vscale3(d.v, d.v, gglSqrtRecipx(sqDist)); } else { // TODO: avoid copy here d = l.normalizedObjPosition; } // ambient & diffuse s = dot3(n.v, d.v); s = (s<0) ? (twoSide?(-s):0) : s; vsa3(t.v, l.implicitDiffuse.v, s, l.implicitAmbient.v); // specular if (ggl_unlikely(s && l.implicitSpecular.v[3])) { vec4_t h; h.x = d.x; h.y = d.y; h.z = d.z + 0x10000; vnorm3(h.v, h.v); s = dot3(n.v, h.v); s = (s<0) ? (twoSide?(-s):0) : s; if (s > 0) { s = gglPowx(s, material.shininess); vsa3(t.v, l.implicitSpecular.v, s, t.v); } } // spot if (ggl_unlikely(l.spotCutoff != gglIntToFixed(180))) { GLfixed spotAtt = -dot3(l.normalizedSpotDir.v, d.v); if (spotAtt >= l.spotCutoffCosine) { vscale3(t.v, t.v, gglPowx(spotAtt, l.spotExp)); } } // attenuation if (ggl_unlikely(l.position.w)) { if (l.rConstAttenuation) { s = l.rConstAttenuation; } else { s = gglMulAddx(sqDist, l.attenuation[2], l.attenuation[0]); if (l.attenuation[1]) s = gglMulAddx(gglSqrtx(sqDist), l.attenuation[1], s); s = gglRecipFast(s); } vscale3(t.v, t.v, s); } r.r += t.r; r.g += t.g; r.b += t.b; } } v->color.r = gglClampx(r.r); v->color.g = gglClampx(r.g); v->color.b = gglClampx(r.b); v->color.a = gglClampx(r.a); v->flags |= vertex_t::LIT; }
static inline void vsa3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) { d[0] = gglMulAddx(m[0], s, a[0]); d[1] = gglMulAddx(m[1], s, a[1]); d[2] = gglMulAddx(m[2], s, a[2]); }