diff options
Diffstat (limited to 'rwsdk/include/d3d8/baaplylt.c')
-rw-r--r-- | rwsdk/include/d3d8/baaplylt.c | 793 |
1 files changed, 793 insertions, 0 deletions
diff --git a/rwsdk/include/d3d8/baaplylt.c b/rwsdk/include/d3d8/baaplylt.c new file mode 100644 index 00000000..ad518e6a --- /dev/null +++ b/rwsdk/include/d3d8/baaplylt.c @@ -0,0 +1,793 @@ + +/* If this file is used outside of the core RW SDK, + * the following things need to be defined + */ +#if (!defined(RWASSERT)) +#define RWASSERT(_assertval) /* No op */ +#endif +#if (!defined(RWFUNCTION)) +#define RWFUNCTION(_rwfunctionstring) /* No op */ +#endif +#if (!defined(RWRETURN)) +#define RWRETURN(_rwreturnval) return(_rwreturnval) +#endif +#if (!defined(RWRETURNVOID)) +#define RWRETURNVOID() return +#endif + +/* These are used by specular lighting, + * sorry I have to leave them in here... IDBS + * I'll make it neater when I have time. + */ +#if (!defined(FALLOFFAMBIENT)) +#define FALLOFFAMBIENT() /* No op */ +#endif +#if (!defined(FALLOFFDIRECTIONAL)) +#define FALLOFFDIRECTIONAL() /* No op */ +#endif +#if (!defined(FALLOFFPOINT)) +#define FALLOFFPOINT() /* No op */ +#endif +#if (!defined(FALLOFFSPOT)) +#define FALLOFFSPOT() /* No op */ +#endif +#if (!defined(FALLOFFSOFTSPOT)) +#define FALLOFFSOFTSPOT() /* No op */ +#endif + +/*************************************************************************** + _rwApplyAmbientLight + + On entry : Instanced data + : Light + : Optional inverse object matrix + : (to transform light to object space) + : Inverse scale of object + : Surface properties of the light + On exit : + */ + +static void +_rwApplyAmbientLight(VERTSARG, + const void *voidLight, + const RwMatrix * __RWUNUSED__ inverseMat, + RwReal __RWUNUSED__ invScale, + const RwSurfaceProperties * surfaceProps) +{ + CAMVERTDECL; + NUMVERTDECL; + const RpLight *light = (const RpLight *) voidLight; + RwReal scale; + RwV3d vertToLight; + + RWFUNCTION(RWSTRING("_rwApplyAmbientLight")); + RWASSERT(light); + RWASSERT(surfaceProps); + + CAMVERTINIT(); + NUMVERTINIT(); + + /* No directional component: + * (this is used in CAMVERTADDRGBA in a specular lighting node) */ + vertToLight.x = 0; + vertToLight.y = 0; + vertToLight.z = 0; + + /* rpLIGHTAMBIENT - Constant illumination on all vertices + */ + if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) + { + scale = 255.0f * light->color.red * surfaceProps->ambient; + + /* Ambient light affects all vertices the same */ + while (numVert--) + { + RwReal lum = scale; + +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFAMBIENT + CAMVERTADDRGBA(1, 1, 1, 0); + CAMVERTINC(); + } + } + else + /* perform for coloured lights */ + { + scale = 255.0f * surfaceProps->ambient; + + /* Ambient light affects all vertices the same */ + while (numVert--) + { + RwReal lum = scale; + +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFAMBIENT + CAMVERTADDRGBA(light->color.red, light->color.green, + light->color.blue, 0); + CAMVERTINC(); + } + } + RWRETURNVOID(); +} + +/*************************************************************************** + _rwApplyDirectionalLight + + On entry : Instanced data + : Light + : Optional inverse object matrix + : (to transform light to object space) + : Inverse scale of object + : Surface properties of the light + On exit : + */ + +static void +_rwApplyDirectionalLight(VERTSARG, + const void *voidLight, + const RwMatrix * inverseMat, + RwReal __RWUNUSED__ invScale, + const RwSurfaceProperties * surfaceProps) +{ + OBJCAMVERTDECL; + NUMVERTDECL; + const RpLight *light = (const RpLight *) voidLight; + RwV3d vertToLight; + RwReal scale; + RwReal dot; + RwFrame *lightFrame; + + RWFUNCTION(RWSTRING("_rwApplyDirectionalLight")); + RWASSERT(light); + RWASSERT(surfaceProps); + + OBJCAMVERTINIT(); + NUMVERTINIT(); + + /* rpLIGHTDIRECTIONAL - Lighting scaled by dot product + * of vertex normal and light lookAt vector. + */ + /* This may not have a frame - we need to check */ + lightFrame = RpLightGetFrame(light); + if (lightFrame) + { + vertToLight = RwFrameGetLTM(lightFrame)->at; + + /* Transform the light into object space if necessary */ + if (inverseMat) + { + RwV3dTransformVectors(&vertToLight, &vertToLight, 1, inverseMat); + _rwV3dNormalize(&vertToLight, &vertToLight); + } + + /* Vert TO light */ + RwV3dScale(&vertToLight, &vertToLight, -1); + + /* Optimise for grey lights? */ + if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) + { + /* Use one of the light colour intensities as general intensity */ + /* light vector tests are to be identical to others */ + scale = 255.0f * light->color.red * surfaceProps->diffuse; + + /* Loop through each of the vertices */ + while (numVert--) + { + RwV3d objNormal; + + OBJVERTGETNORMAL(&objNormal); + /* Calculate angle between vertex normal and light vector */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + + /* Ensure vector is facing light, + * don't light areas not facing */ + + if (dot > 0.0f) + { + RwReal lum = dot * scale; + +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFDIRECTIONAL + CAMVERTADDRGBA(1, 1, 1, 0); + } + + /* Next vertex */ + OBJCAMVERTINC(); + } + } + else + /* perform for coloured lights */ + { + scale = 255.0f * surfaceProps->diffuse; + + /* Loop through each of the vertices */ + while (numVert--) + { + RwV3d objNormal; + + OBJVERTGETNORMAL(&objNormal); + /* Calculate angle between vertex normal and light vector */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + + /* Ensure vector is facing light, + * don't light areas not facing */ + + if (dot > 0.0f) + { + RwReal lum = dot * scale; + +#define FALLOFFCALC FALLOFFDIRECTIONAL + CAMVERTADDRGBA(light->color.red, light->color.green, + light->color.blue, 0); + } + + /* Next vertex */ + OBJCAMVERTINC(); + } + } + } + + RWRETURNVOID(); +} + +/*************************************************************************** + _rwApplyPointLight + + On entry : Instanced data + : Light + : Optional inverse object matrix + : (to transform light to object space) + : Inverse scale of object + : Surface properties of the light + On exit : + */ + +static void +_rwApplyPointLight(VERTSARG, const void *voidLight, + const RwMatrix * inverseMat, + RwReal invScale, const RwSurfaceProperties * surfaceProps) +{ + OBJCAMVERTDECL; + NUMVERTDECL; + const RpLight *light = (const RpLight *) voidLight; + RwReal scale, recipRad; + RwV3d lightPos, vertToLight; + RwReal radSquared; + + RWFUNCTION(RWSTRING("_rwApplyPointLight")); + RWASSERT(light); + RWASSERT(surfaceProps); + + OBJCAMVERTINIT(); + NUMVERTINIT(); + + /* rpLIGHTPOINT - Linear falloff with distance, scaled by + * dot product of vertex normal and light to vertex vector. + */ + lightPos = RwFrameGetLTM(RpLightGetFrame(light))->pos; + + if (inverseMat) + { + RwReal scaledRad; + + scaledRad = ((light->radius) * (invScale)); + radSquared = ((scaledRad) * (scaledRad)); + recipRad = (((RwReal) (1)) / (scaledRad)); + + /* Transform light into object space */ + RwV3dTransformPoints(&lightPos, &lightPos, 1, inverseMat); + } + else + { + radSquared = ((light->radius) * (light->radius)); + recipRad = (((RwReal) (1)) / (light->radius)); + } + + if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) + { + /* The scale encapsulates the common elements to do + * with light intensity and surface lighting properties + */ + scale = + ((((RwReal) (255)) * (light->color.red))) * + (surfaceProps->diffuse); + + while (numVert--) + { + RwV3d objVertex, objNormal; + RwReal dot, dist2; + + OBJVERTGETPOS(&objVertex); + OBJVERTGETNORMAL(&objNormal); + + /* Discover the vector between vertex and light and it's length */ + RwV3dSub(&vertToLight, &lightPos, &objVertex); + + /* Ensure that this vertex is facing the light source */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + if (dot > 0.0f) + { + /* Ensure vertex lies within the light's radius */ + dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); + if (dist2 < radSquared) + { + RwReal lum; + RwReal recipDist; + RwReal dist; + + rwSqrt(&dist, dist2); + recipDist = + (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; + + /* + * The following simplifies down to: + * + * -scale * + * (dot/dist) * + * (1 - dist/lightRadius) + * + * Where + * scale + * takes care of the light intensity and + * diffuse lighting coefficient + * (dot/dist) + * is a normalised dot product of + * light->vertex vector and vertex normal + * (1 - dist/lightRadius) + * is a linear falloff factor + */ + lum = scale * dot * (recipDist - recipRad); + + /* Calculate the luminance at vertex */ +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFPOINT + CAMVERTADDRGBA(1, 1, 1, 0); + } + } + + OBJCAMVERTINC(); + } + } + else + { + scale = (((RwReal) (255)) * (surfaceProps->diffuse)); + + while (numVert--) + { + RwV3d objVertex, objNormal; + RwReal dot, dist2; + + OBJVERTGETPOS(&objVertex); + OBJVERTGETNORMAL(&objNormal); + + /* Discover the vector between vertex and light and it's length */ + RwV3dSub(&vertToLight, &lightPos, &objVertex); + + /* Ensure that this vertex is facing the light source */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + if (dot > 0.0f) + { + dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); + + /* Ensure vertex lies within the light's radius */ + if (dist2 < radSquared) + { + RwReal lum; + RwReal recipDist; + RwReal dist; + + /* Only now calculate the actual length of vector */ + rwSqrt(&dist, dist2); + recipDist = + (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; + + lum = scale * dot * (recipDist - recipRad); + /* Alter the luminance according to light colour */ +#define FALLOFFCALC FALLOFFPOINT + CAMVERTADDRGBA(light->color.red, light->color.green, + light->color.blue, 0); + } + } + + /* Next point */ + OBJCAMVERTINC(); + } + } + RWRETURNVOID(); +} + +/*************************************************************************** + _rwApplySpotLight + + On entry : Instanced data + : Light + : Optional inverse object matrix + : (to transform light to object space) + : Inverse scale of object + : Surface properties of the light + On exit : + */ + +static void +_rwApplySpotLight(VERTSARG, + const void *voidLight, + const RwMatrix * inverseMat, + RwReal invScale, const RwSurfaceProperties * surfaceProps) +{ + OBJCAMVERTDECL; + NUMVERTDECL; + const RpLight *light = (const RpLight *) voidLight; + RwReal recipRad; + RwReal radSquared; + RwV3d lightPos, at; + + RWFUNCTION(RWSTRING("_rwApplySpotLight")); + RWASSERT(light); + RWASSERT(surfaceProps); + + OBJCAMVERTINIT(); + NUMVERTINIT(); + + /* rpLIGHTSPOT - Linear falloff with distance, cone to restrict + * angle that light has effect, constant intensity across cone, + * scaled by dot product of vertex normal and light to vertex vector. + */ + + lightPos = RwFrameGetLTM(RpLightGetFrame(light))->pos; + at = RwFrameGetLTM(RpLightGetFrame(light))->at; + + if (inverseMat) + { + RwReal scaledRad; + + scaledRad = ((light->radius) * (invScale)); + recipRad = (((RwReal) (1)) / (scaledRad)); + radSquared = ((scaledRad) * (scaledRad)); + + /* Transform light into object space */ + /* The at is required to ensure within cone */ + RwV3dTransformPoints(&lightPos, &lightPos, 1, inverseMat); + RwV3dTransformVectors(&at, &at, 1, inverseMat); + _rwV3dNormalize(&at, &at); + } + else + { + recipRad = (((RwReal) (1)) / (light->radius)); + radSquared = ((light->radius) * (light->radius)); + } + + if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) + { + RwReal scale = + + ((RwReal) 255) * (light->color.red) * (surfaceProps->diffuse); + + while (numVert--) + { + RwV3d vertToLight, objVertex, objNormal; + RwReal dot; + + OBJVERTGETPOS(&objVertex); + OBJVERTGETNORMAL(&objNormal); + + /* Find the squared distance from light point to vertex */ + RwV3dSub(&vertToLight, &lightPos, &objVertex); + + /* Ensure that this vertex is facing the light source */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + if (dot > 0.0f) + { + RwReal dist2; + + /* Ensure vertex lies within the light's radius */ + dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); + if (dist2 < radSquared) + { + RwReal dist; + RwReal compare; + RwReal proj; + + rwSqrt(&dist, dist2); + compare = dist * light->minusCosAngle; + proj = RwV3dDotProduct(&vertToLight, &at); + + if (proj < compare) + { + RwReal lum; + RwReal recipDist; + + /* Get the real distance from the light + * to the vertex (not squared) */ + recipDist = + (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; + + /* This model is the same as the point source + * inside the cone, zero outside the cone */ + lum = scale * dot * (recipDist - recipRad); +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFSPOT + CAMVERTADDRGBA(1, 1, 1, 0); + } + } + /* Next vertex */ + OBJCAMVERTINC(); + } + } + } + else + { + RwReal scale = + + (((RwReal) (255)) * (surfaceProps->diffuse)); + + while (numVert--) + { + RwV3d vertToLight, objVertex, objNormal; + RwReal dot; + + OBJVERTGETPOS(&objVertex); + OBJVERTGETNORMAL(&objNormal); + + /* Find the squared distance from light point to vertex */ + RwV3dSub(&vertToLight, &lightPos, &objVertex); + + /* Ensure that this vertex is facing the light source */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + if (dot > 0.0f) + { + RwReal dist2; + + /* Ensure vertex lies within the light's radius */ + dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); + if (dist2 < radSquared) + { + RwReal dist; + RwReal compare; + RwReal proj; + + rwSqrt(&dist, dist2); + compare = dist * light->minusCosAngle; + proj = RwV3dDotProduct(&vertToLight, &at); + + if (proj < compare) + { + RwReal lum; + RwReal recipDist; + + recipDist = + (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; + + /* This model is the same as the point source + * inside the cone, zero outside the cone */ + lum = scale * dot * (recipDist - recipRad); + + /* Introduce the light colours as a + * scaling factor for luminance */ +#define FALLOFFCALC FALLOFFSPOT + CAMVERTADDRGBA(light->color.red, + light->color.green, light->color.blue, + 0); + } + } + } + + /* Next */ + OBJCAMVERTINC(); + } + } + + RWRETURNVOID(); +} + +/*************************************************************************** + _rwApplySpotSoftLight + + On entry : Instanced data + : Light + : Optional inverse object matrix + : (to transform light to object space) + : Inverse scale of object + : Surface properties of the light + On exit : + */ + +static void +_rwApplySpotSoftLight(VERTSARG, const void *voidLight, + const RwMatrix * inverseMat, RwReal invScale, + const RwSurfaceProperties * surfaceProps) +{ + OBJCAMVERTDECL; + NUMVERTDECL; + const RpLight *light = (const RpLight *) voidLight; + RwReal recipRad; + RwReal radSquared; + RwV3d lightPos, at; + + RWFUNCTION(RWSTRING("_rwApplySpotSoftLight")); + RWASSERT(light); + RWASSERT(surfaceProps); + + OBJCAMVERTINIT(); + NUMVERTINIT(); + + /* rpLIGHTSPOTSOFT - Linear falloff with distance, cone to restrict + * angle that light has effect, falloff to edge of cone, scaled by + * dot product of vertex normal and light to vertex vector. + */ + + lightPos = RwFrameGetLTM(RpLightGetFrame(light))->pos; + at = RwFrameGetLTM(RpLightGetFrame(light))->at; + + if (inverseMat) + { + RwReal scaledRad; + + scaledRad = ((light->radius) * (invScale)); + recipRad = (((RwReal) (1)) / (scaledRad)); + radSquared = ((scaledRad) * (scaledRad)); + + /* Transform light into object space */ + /* The at is required to ensure within cone */ + RwV3dTransformPoints(&lightPos, &lightPos, 1, inverseMat); + RwV3dTransformVectors(&at, &at, 1, inverseMat); + _rwV3dNormalize(&at, &at); + } + else + { + recipRad = 1.0f / light->radius; + radSquared = light->radius * light->radius; + } + + if (rwObjectTestPrivateFlags(light, rpLIGHTPRIVATENOCHROMA)) + { + RwReal scale = + + ((RwReal) 255) * (light->color.red) * (surfaceProps->diffuse); + + while (numVert--) + { + RwV3d vertToLight, objVertex, objNormal; + RwReal dot; + + OBJVERTGETPOS(&objVertex); + OBJVERTGETNORMAL(&objNormal); + + /* Find the squared distance from light point to vertex */ + RwV3dSub(&vertToLight, &lightPos, &objVertex); + + /* Ensure that this vertex is facing the light source */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + if (dot > 0.0f) + { + RwReal dist2; + + /* Ensure vertex lies within the light's radius */ + dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); + if (dist2 < radSquared) + { + RwReal dist; + RwReal compare; + RwReal proj; + + rwSqrt(&dist, dist2); + compare = dist * light->minusCosAngle; + proj = RwV3dDotProduct(&vertToLight, &at); + + if (proj < compare) + { + RwReal lum; + RwReal recipDist; + RwReal normalise; + + recipDist = + (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; + + /* This model is the same as the point source + * inside the cone, zero outside the cone */ + lum = scale * dot * (recipDist - recipRad); + + /* It has an extra term for quadratic falloff + * across the cone though */ + normalise = (dist + compare); + RWASSERT(normalise >= 0.0f); + if (normalise > 0.0f) + { + normalise = (dist + proj) / normalise; + + normalise *= normalise; + lum *= (((RwReal) 1) - normalise); + } + +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFSOFTSPOT + CAMVERTADDRGBA(1, 1, 1, 0); + } + } + } + + /* Next */ + OBJCAMVERTINC(); + } + } + + else + { + RwReal scale = 255.0f * surfaceProps->diffuse; + + while (numVert--) + { + RwV3d vertToLight, objVertex, objNormal; + RwReal dot; + + OBJVERTGETPOS(&objVertex); + OBJVERTGETNORMAL(&objNormal); + + /* Find the squared distance from light point to vertex */ + RwV3dSub(&vertToLight, &lightPos, &objVertex); + + /* Ensure that this vertex is facing the light source */ + dot = RwV3dDotProduct(&vertToLight, &objNormal); + if (dot > 0.0f) + { + RwReal dist2; + + /* Ensure vertex lies within the light's radius */ + dist2 = RwV3dDotProduct(&vertToLight, &vertToLight); + if (dist2 < radSquared) + { + RwReal dist; + RwReal compare; + RwReal proj; + + rwSqrt(&dist, dist2); + compare = dist * light->minusCosAngle; + proj = RwV3dDotProduct(&vertToLight, &at); + + if (proj < compare) + { + + RwReal lum; + RwReal normalise; + RwReal recipDist; + + /* Get the real distance from the light + * to the vertex (not squared) */ + recipDist = + (dist > 0.0f) ? (((RwReal) 1) / dist) : 0.0f; + + /* This model is the same as the point source + * inside the cone, zero outside the cone */ + lum = scale * dot * (recipDist - recipRad); + + /* It has an extra term for quadratic falloff + * across the cone though */ + /* It has an extra term for quadratic falloff + * across the cone though */ + normalise = (dist + compare); + RWASSERT(normalise >= 0.0f); + if (normalise > 0.0f) + { + normalise = (dist + proj) / normalise; + + normalise *= normalise; + lum *= (((RwReal) 1) - normalise); + + } + /* Introduce the light colours as a + * scaling factor for luminance */ +#undef FALLOFFCALC +#define FALLOFFCALC FALLOFFSOFTSPOT + CAMVERTADDRGBA(light->color.red, + light->color.green, + light->color.blue, 0); + } + } + } + + /* Next */ + OBJCAMVERTINC(); + } + } + + RWRETURNVOID(); +} |