mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add support for spotlights
This commit is contained in:
parent
cf5f049abd
commit
fa3a1fbd52
6 changed files with 67 additions and 8 deletions
|
@ -654,6 +654,29 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
|||
}
|
||||
break;
|
||||
|
||||
case GE_CMD_LKS0:
|
||||
case GE_CMD_LKS1:
|
||||
case GE_CMD_LKS2:
|
||||
case GE_CMD_LKS3:
|
||||
{
|
||||
int l = cmd - GE_CMD_LKS0;
|
||||
gstate_c.lightspotCoef[l] = getFloat24(data);
|
||||
if (diff)
|
||||
shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l);
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMD_LKO0:
|
||||
case GE_CMD_LKO1:
|
||||
case GE_CMD_LKO2:
|
||||
case GE_CMD_LKO3:
|
||||
{
|
||||
int l = cmd - GE_CMD_LKO0;
|
||||
gstate_c.lightangle[l] = getFloat24(data);
|
||||
if (diff)
|
||||
shaderManager_->DirtyUniform(DIRTY_LIGHT0 << l);
|
||||
}
|
||||
break;
|
||||
|
||||
case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3:
|
||||
case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3:
|
||||
|
|
|
@ -119,6 +119,10 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs)
|
|||
u_lightdir[i] = glGetUniformLocation(program, temp);
|
||||
sprintf(temp, "u_lightatt%i", i);
|
||||
u_lightatt[i] = glGetUniformLocation(program, temp);
|
||||
sprintf(temp, "u_lightangle%i", i);
|
||||
u_lightangle[i] = glGetUniformLocation(program, temp);
|
||||
sprintf(temp, "u_lightspotCoef%i", i);
|
||||
u_lightspotCoef[i] = glGetUniformLocation(program, temp);
|
||||
sprintf(temp, "u_lightambient%i", i);
|
||||
u_lightambient[i] = glGetUniformLocation(program, temp);
|
||||
sprintf(temp, "u_lightdiffuse%i", i);
|
||||
|
@ -324,6 +328,8 @@ void LinkedShader::updateUniforms() {
|
|||
if (u_lightpos[i] != -1) glUniform3fv(u_lightpos[i], 1, gstate_c.lightpos[i]);
|
||||
if (u_lightdir[i] != -1) glUniform3fv(u_lightdir[i], 1, gstate_c.lightdir[i]);
|
||||
if (u_lightatt[i] != -1) glUniform3fv(u_lightatt[i], 1, gstate_c.lightatt[i]);
|
||||
if (u_lightangle[i] != -1) glUniform1f(u_lightangle[i], gstate_c.lightangle[i]);
|
||||
if (u_lightspotCoef[i] != -1) glUniform1f(u_lightspotCoef[i], gstate_c.lightspotCoef[i]);
|
||||
if (u_lightambient[i] != -1) glUniform3fv(u_lightambient[i], 1, gstate_c.lightColor[0][i]);
|
||||
if (u_lightdiffuse[i] != -1) glUniform3fv(u_lightdiffuse[i], 1, gstate_c.lightColor[1][i]);
|
||||
if (u_lightspecular[i] != -1) glUniform3fv(u_lightspecular[i], 1, gstate_c.lightColor[2][i]);
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
int u_lightpos[4];
|
||||
int u_lightdir[4];
|
||||
int u_lightatt[4]; // attenuation
|
||||
int u_lightangle[4]; // spotlight cone angle (cosine)
|
||||
int u_lightspotCoef[4]; // spotlight dropoff
|
||||
int u_lightdiffuse[4]; // each light consist of vec4[3]
|
||||
int u_lightspecular[4]; // attenuation
|
||||
int u_lightambient[4]; // attenuation
|
||||
|
|
|
@ -288,8 +288,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
float distanceToLight = toLight.Length();
|
||||
float dot = 0.0f;
|
||||
|
||||
if (distanceToLight > 0.0f)
|
||||
{
|
||||
if (distanceToLight > 0.0f) {
|
||||
toLight /= distanceToLight;
|
||||
dot = toLight * norm;
|
||||
}
|
||||
|
@ -300,12 +299,21 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
|
|||
dot = powf(dot, specCoef_);
|
||||
|
||||
float lightScale = 1.0f;
|
||||
if (type != GE_LIGHTTYPE_DIRECTIONAL)
|
||||
{
|
||||
if (type != GE_LIGHTTYPE_DIRECTIONAL) {
|
||||
lightScale = 1.0f / (gstate_c.lightatt[l][0] + gstate_c.lightatt[l][1]*distanceToLight + gstate_c.lightatt[l][2]*distanceToLight*distanceToLight);
|
||||
if (lightScale > 1.0f) lightScale = 1.0f;
|
||||
}
|
||||
|
||||
if (type == GE_LIGHTTYPE_SPOT) {
|
||||
Vec3 lightDir = gstate_c.lightdir[l];
|
||||
lightDir.Normalize();
|
||||
float angle = toLight * lightDir;
|
||||
if (angle < gstate_c.lightangle[l])
|
||||
lightScale = 0.0f;
|
||||
else
|
||||
lightScale *= powf(angle, gstate_c.lightspotCoef[l]);
|
||||
}
|
||||
|
||||
Color4 lightDiff(gstate_c.lightColor[1][l], 0.0f);
|
||||
Color4 diff = (lightDiff * *diffuse) * (dot * lightScale);
|
||||
|
||||
|
|
|
@ -230,6 +230,8 @@ void GenerateVertexShader(int prim, char *buffer) {
|
|||
// These are needed for the full thing
|
||||
WRITE(p, "uniform vec3 u_lightdir%i;\n", i);
|
||||
WRITE(p, "uniform vec3 u_lightatt%i;\n", i);
|
||||
WRITE(p, "uniform float u_lightangle%i;\n", i);
|
||||
WRITE(p, "uniform float u_lightspotCoef%i;\n", i);
|
||||
|
||||
WRITE(p, "uniform lowp vec3 u_lightambient%i;\n", i);
|
||||
WRITE(p, "uniform lowp vec3 u_lightdiffuse%i;\n", i);
|
||||
|
@ -336,12 +338,28 @@ void GenerateVertexShader(int prim, char *buffer) {
|
|||
WRITE(p, " dot%i = pow(dot%i, u_matspecular.a);\n", i, i);
|
||||
}
|
||||
|
||||
WRITE(p, " float lightScale%i = 1.0;\n", i);
|
||||
if (type != GE_LIGHTTYPE_DIRECTIONAL) {
|
||||
// Attenuation
|
||||
// Attenuation
|
||||
switch (type) {
|
||||
case GE_LIGHTTYPE_DIRECTIONAL:
|
||||
WRITE(p, " float lightScale%i = 1.0;\n", i);
|
||||
break;
|
||||
case GE_LIGHTTYPE_POINT:
|
||||
WRITE(p, " float distance%i = length(toLight%i);\n", i, i);
|
||||
WRITE(p, " lightScale%i = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i)), 0.0, 1.0);\n", i, i, i, i, i);
|
||||
WRITE(p, " float lightScale%i = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i)), 0.0, 1.0);\n", i, i, i, i, i);
|
||||
break;
|
||||
case GE_LIGHTTYPE_SPOT:
|
||||
WRITE(p, " float lightScale%i = 0.0;\n", i);
|
||||
WRITE(p, " float angle%i = dot(normalize(u_lightdir%i), normalize(toLight%i));\n", i, i, i);
|
||||
WRITE(p, " if (angle%i >= u_lightangle%i) {\n", i, i);
|
||||
WRITE(p, " float distance%i = length(toLight%i);\n", i, i);
|
||||
WRITE(p, " lightScale%i = clamp(1.0 / dot(u_lightatt%i, vec3(1.0, distance%i, distance%i*distance%i)), 0.0, 1.0) * pow(angle%i, u_lightspotCoef%i);\n", i, i, i, i, i, i, i);
|
||||
WRITE(p, " }\n");
|
||||
break;
|
||||
default:
|
||||
// ILLEGAL
|
||||
break;
|
||||
}
|
||||
|
||||
WRITE(p, " vec3 diffuse%i = (u_lightdiffuse%i * %s) * (max(dot%i, 0.0) * lightScale%i);\n", i, i, diffuse, i, i);
|
||||
if (doSpecular) {
|
||||
WRITE(p, " vec3 halfVec%i = normalize(normalize(toLight%i) + vec3(0.0, 0.0, 1.0));\n", i, i);
|
||||
|
|
|
@ -264,6 +264,8 @@ struct GPUStateCache
|
|||
float lightdir[4][3];
|
||||
float lightatt[4][3];
|
||||
float lightColor[3][4][3]; // Ambient Diffuse Specular
|
||||
float lightangle[4]; // spotlight cone angle (cosine)
|
||||
float lightspotCoef[4]; // spotlight dropoff
|
||||
float morphWeights[8];
|
||||
|
||||
u32 curTextureWidth;
|
||||
|
|
Loading…
Add table
Reference in a new issue