mirror of https://github.com/xemu-project/xemu.git
nv2a: implement FFP LIGHT_SPOT
This commit is contained in:
parent
8604d7e41e
commit
e2e3572301
|
@ -566,8 +566,31 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
|
|||
/* Everything done already */
|
||||
break;
|
||||
case LIGHT_SPOT:
|
||||
assert(false);
|
||||
/*FIXME: calculate falloff */
|
||||
/* From: https://docs.microsoft.com/en-us/windows/win32/direct3d9/attenuation-and-spotlight-factor#spotlight-factor */
|
||||
/* Note: normalizing the direction does not produce the same result as on hardware.
|
||||
* Instead, dividing the direction by 1-w produces the same result as on hardware.
|
||||
* Rationale: the w component is always close (but not equal to) the difference
|
||||
* between 1 and the the direction vector length (e.g. 1.0-2.6=-1.6, with w=-1.5).
|
||||
* So, dividing by 1-w is the same as normalizing the vector and scaling it a bit.
|
||||
* In the example: 1-(-1.5) = 2.5, 2.6/2.5 = 1.04. This also scales the subsequent
|
||||
* dot product by the same amount, effectively increasing the spotlight radius.
|
||||
*/
|
||||
qstring_append_fmt(body,
|
||||
" vec3 dir = lightSpotDirection(%d).xyz / (1.0 - lightSpotDirection(%d).w);\n"
|
||||
" float rho = dot(dir, VP);\n"
|
||||
" float theta = lightSpotFalloff(%d).x;\n"
|
||||
" float phi = lightSpotFalloff(%d).y;\n"
|
||||
" float falloff = lightSpotFalloff(%d).z;\n"
|
||||
" float cosHalfPhi = cos(phi * 0.5);\n"
|
||||
" float cosHalfTheta = cos(theta * 0.5);\n"
|
||||
" if (rho > cosHalfTheta) {\n" /* do nothing => spotlightFactor = 1 */
|
||||
" } else if (rho <= cosHalfPhi) {\n"
|
||||
" attenuation = 0.0;\n" /* spotlightFactor = 0 */
|
||||
" } else {\n"
|
||||
" float spotlightFactor = pow((rho - cosHalfPhi) / (cosHalfTheta - cosHalfPhi), falloff);\n"
|
||||
" attenuation = attenuation * spotlightFactor;\n"
|
||||
" }\n",
|
||||
i, i, i, i, i);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
|
Loading…
Reference in New Issue