Ejemplo n.º 1
0
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);
    }
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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);
    }
}
Ejemplo n.º 5
0
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;
}