Rewrite the lighting code
This commit is contained in:
parent
00c38edba9
commit
b82d28130d
25
GL/draw.c
25
GL/draw.c
|
@ -935,11 +935,6 @@ static void light(SubmissionTarget* target) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
float xyz[3];
|
|
||||||
float n[3];
|
|
||||||
} EyeSpaceData;
|
|
||||||
|
|
||||||
static AlignedVector* eye_space_data = NULL;
|
static AlignedVector* eye_space_data = NULL;
|
||||||
|
|
||||||
if(!eye_space_data) {
|
if(!eye_space_data) {
|
||||||
|
@ -966,25 +961,7 @@ static void light(SubmissionTarget* target) {
|
||||||
for(i = 0; i < target->count; ++i, ++vertex, ++ES) {
|
for(i = 0; i < target->count; ++i, ++vertex, ++ES) {
|
||||||
/* We ignore diffuse colour when lighting is enabled. If GL_COLOR_MATERIAL is enabled
|
/* We ignore diffuse colour when lighting is enabled. If GL_COLOR_MATERIAL is enabled
|
||||||
* then the lighting calculation should possibly take it into account */
|
* then the lighting calculation should possibly take it into account */
|
||||||
|
_glCalculateLighting(ES, vertex);
|
||||||
GLfloat total [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
||||||
GLfloat to_add [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
||||||
GLubyte j;
|
|
||||||
for(j = 0; j < MAX_LIGHTS; ++j) {
|
|
||||||
if(_glIsLightEnabled(j)) {
|
|
||||||
_glCalculateLightingContribution(j, ES->xyz, ES->n, vertex->bgra, to_add);
|
|
||||||
|
|
||||||
total[0] += to_add[0];
|
|
||||||
total[1] += to_add[1];
|
|
||||||
total[2] += to_add[2];
|
|
||||||
total[3] += to_add[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vertex->bgra[A8IDX] = (GLubyte) (255.0f * fminf(total[3], 1.0f));
|
|
||||||
vertex->bgra[R8IDX] = (GLubyte) (255.0f * fminf(total[0], 1.0f));
|
|
||||||
vertex->bgra[G8IDX] = (GLubyte) (255.0f * fminf(total[1], 1.0f));
|
|
||||||
vertex->bgra[B8IDX] = (GLubyte) (255.0f * fminf(total[2], 1.0f));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
224
GL/lighting.c
224
GL/lighting.c
|
@ -281,98 +281,148 @@ static inline float FPOW(float b, float p) {
|
||||||
return FEXP(FLOG(b) * p);
|
return FEXP(FLOG(b) * p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, GLfloat* colour) __attribute__((optimize("fast-math")));
|
void _glCalculateLighting(EyeSpaceData* ES, Vertex* vertex) {
|
||||||
void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, GLfloat* colour) {
|
|
||||||
LightSource* l = &LIGHTS[light];
|
|
||||||
|
|
||||||
struct vec3f L = {
|
/* Before we begin, lets fiddle some pointers if COLOR_MATERIAL
|
||||||
l->position[0],
|
* is enabled */
|
||||||
l->position[1],
|
|
||||||
l->position[2]
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!l->is_directional) {
|
const GLboolean colorMaterial = _glIsColorMaterialEnabled();
|
||||||
L.x -= pos[0];
|
const GLboolean isDiffuseCM = isDiffuseColorMaterial();
|
||||||
L.y -= pos[1];
|
const GLboolean isAmbientCM = isAmbientColorMaterial();
|
||||||
L.z -= pos[2];
|
const GLboolean isSpecularCM = isSpecularColorMaterial();
|
||||||
|
|
||||||
|
static GLfloat CM[4];
|
||||||
|
|
||||||
|
if(colorMaterial) {
|
||||||
|
CM[0] = ((GLfloat) vertex->bgra[R8IDX]) / 255.0f;
|
||||||
|
CM[1] = ((GLfloat) vertex->bgra[G8IDX]) / 255.0f;
|
||||||
|
CM[2] = ((GLfloat) vertex->bgra[B8IDX]) / 255.0f;
|
||||||
|
CM[3] = ((GLfloat) vertex->bgra[A8IDX]) / 255.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct vec3f N = {
|
const GLfloat* MD = (colorMaterial && isDiffuseCM) ? CM : MATERIAL.diffuse;
|
||||||
normal[0],
|
const GLfloat* MA = (colorMaterial && isAmbientCM) ? CM : MATERIAL.ambient;
|
||||||
normal[1],
|
const GLfloat* MS = (colorMaterial && isSpecularCM) ? CM : MATERIAL.specular;
|
||||||
normal[2]
|
|
||||||
};
|
|
||||||
|
|
||||||
struct vec3f V = {
|
/* Right..
|
||||||
pos[0],
|
*
|
||||||
pos[1],
|
* global propertie:
|
||||||
pos[2]
|
*
|
||||||
};
|
* acs - Global Ambient
|
||||||
|
*
|
||||||
|
* vertex-specific properties:
|
||||||
|
*
|
||||||
|
* ecm - Material Emission
|
||||||
|
* acm - Material Ambient
|
||||||
|
* dcm - Material Diffuse
|
||||||
|
* n - Normal
|
||||||
|
* V - Vertex Position
|
||||||
|
* VPe - Vector from V to eye point (0, 0, 0, -1) basically negative V
|
||||||
|
*
|
||||||
|
* light-specifc properties:
|
||||||
|
*
|
||||||
|
* att - Attenution
|
||||||
|
* acli - Light Ambient
|
||||||
|
* Ppli - Light Position
|
||||||
|
* dcli - Light Diffuse
|
||||||
|
* fi - 1/0 facing light or not
|
||||||
|
* VPpli - Vector from V to Ppli
|
||||||
|
* ndotPpli - Dot product between n and Ppli
|
||||||
|
* hi -
|
||||||
|
* PpliV - vector from Ppli to V
|
||||||
|
*/
|
||||||
|
|
||||||
GLfloat d;
|
|
||||||
vec3f_length(L.x, L.y, L.z, d);
|
|
||||||
|
|
||||||
GLfloat oneOverL = 1.0f / d;
|
/* Each colour component is calculated in its own scope
|
||||||
|
* so that the SH4 float registers don't get flooded */
|
||||||
L.x *= oneOverL;
|
#define LIGHT_COMPONENT(C) { \
|
||||||
L.y *= oneOverL;
|
const GLfloat acm = MA[C]; \
|
||||||
L.z *= oneOverL;
|
const GLfloat dcm = MD[C]; \
|
||||||
|
const GLfloat scm = MS[C]; \
|
||||||
vec3f_normalize(V.x, V.y, V.z);
|
const GLfloat scli = light->specular[C]; \
|
||||||
|
const GLfloat dcli = light->diffuse[C]; \
|
||||||
GLfloat NdotL, VdotN;
|
const GLfloat acli = light->ambient[C]; \
|
||||||
vec3f_dot(N.x, N.y, N.z, L.x, L.y, L.z, NdotL);
|
const GLfloat srm = MATERIAL.exponent; \
|
||||||
vec3f_dot(V.x, V.y, V.z, N.x, N.y, N.z, VdotN);
|
\
|
||||||
|
final[C] += (att * spot * ( \
|
||||||
GLfloat VdotR = VdotN - NdotL;
|
(acm * acli) + (ndotVPpli * dcm * dcli) + \
|
||||||
GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent);
|
(FPOW((fi * ndothi), srm) * scm * scli) \
|
||||||
|
)); \
|
||||||
GLboolean colorMaterial = _glIsColorMaterialEnabled();
|
|
||||||
|
|
||||||
GLfloat mD [] = {
|
|
||||||
(colorMaterial && isDiffuseColorMaterial()) ? ((GLfloat)bgra[R8IDX]) / 255.0f : MATERIAL.diffuse[0],
|
|
||||||
(colorMaterial && isDiffuseColorMaterial()) ? ((GLfloat)bgra[G8IDX]) / 255.0f : MATERIAL.diffuse[1],
|
|
||||||
(colorMaterial && isDiffuseColorMaterial()) ? ((GLfloat)bgra[B8IDX]) / 255.0f : MATERIAL.diffuse[2],
|
|
||||||
(colorMaterial && isDiffuseColorMaterial()) ? ((GLfloat)bgra[A8IDX]) / 255.0f : MATERIAL.diffuse[3]
|
|
||||||
};
|
|
||||||
|
|
||||||
GLfloat mA [] = {
|
|
||||||
(colorMaterial && isAmbientColorMaterial()) ? ((GLfloat)bgra[R8IDX]) / 255.0f : MATERIAL.ambient[0],
|
|
||||||
(colorMaterial && isAmbientColorMaterial()) ? ((GLfloat)bgra[G8IDX]) / 255.0f : MATERIAL.ambient[1],
|
|
||||||
(colorMaterial && isAmbientColorMaterial()) ? ((GLfloat)bgra[B8IDX]) / 255.0f : MATERIAL.ambient[2],
|
|
||||||
(colorMaterial && isAmbientColorMaterial()) ? ((GLfloat)bgra[A8IDX]) / 255.0f : MATERIAL.ambient[3]
|
|
||||||
};
|
|
||||||
|
|
||||||
GLfloat mS [] = {
|
|
||||||
(colorMaterial && isSpecularColorMaterial()) ? ((GLfloat)bgra[R8IDX]) / 255.0f : MATERIAL.specular[0],
|
|
||||||
(colorMaterial && isSpecularColorMaterial()) ? ((GLfloat)bgra[G8IDX]) / 255.0f : MATERIAL.specular[1],
|
|
||||||
(colorMaterial && isSpecularColorMaterial()) ? ((GLfloat)bgra[B8IDX]) / 255.0f : MATERIAL.specular[2],
|
|
||||||
(colorMaterial && isSpecularColorMaterial()) ? ((GLfloat)bgra[A8IDX]) / 255.0f : MATERIAL.specular[3]
|
|
||||||
};
|
|
||||||
|
|
||||||
colour[0] = l->ambient[0] * mA[0];
|
|
||||||
colour[1] = l->ambient[1] * mA[1];
|
|
||||||
colour[2] = l->ambient[2] * mA[2];
|
|
||||||
colour[3] = mD[3];
|
|
||||||
|
|
||||||
if(NdotL >= 0) {
|
|
||||||
colour[0] += (l->diffuse[0] * mD[0] * NdotL + l->specular[0] * mS[0] * specularPower);
|
|
||||||
colour[1] += (l->diffuse[1] * mD[1] * NdotL + l->specular[1] * mS[1] * specularPower);
|
|
||||||
colour[2] += (l->diffuse[2] * mD[2] * NdotL + l->specular[2] * mS[2] * specularPower);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!l->is_directional) {
|
|
||||||
GLfloat att = (
|
|
||||||
1.0f / (l->constant_attenuation + (l->linear_attenuation * d) + (l->quadratic_attenuation * d * d))
|
|
||||||
);
|
|
||||||
|
|
||||||
colour[0] *= att;
|
|
||||||
colour[1] *= att;
|
|
||||||
colour[2] *= att;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(colour[0] > 1.0f) colour[0] = 1.0f;
|
|
||||||
if(colour[1] > 1.0f) colour[1] = 1.0f;
|
|
||||||
if(colour[2] > 1.0f) colour[2] = 1.0f;
|
|
||||||
if(colour[3] > 1.0f) colour[3] = 1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GLfloat* n = ES->n;
|
||||||
|
const GLfloat* V = ES->xyz;
|
||||||
|
|
||||||
|
GLfloat Vpe [] = {-V[0], -V[1], -V[2]};
|
||||||
|
GLfloat VpeL;
|
||||||
|
vec3f_length(Vpe[0], Vpe[1], Vpe[2], VpeL);
|
||||||
|
Vpe[0] /= VpeL;
|
||||||
|
Vpe[1] /= VpeL;
|
||||||
|
Vpe[2] /= VpeL;
|
||||||
|
|
||||||
|
GLfloat final[4] = {
|
||||||
|
MATERIAL.emissive[0] + (MA[0] * SCENE_AMBIENT[0]),
|
||||||
|
MATERIAL.emissive[1] + (MA[1] * SCENE_AMBIENT[1]),
|
||||||
|
MATERIAL.emissive[2] + (MA[2] * SCENE_AMBIENT[2]),
|
||||||
|
MD[3] // GL spec says alpha is always from the diffuse
|
||||||
|
};
|
||||||
|
|
||||||
|
GLubyte i;
|
||||||
|
for(i = 0; i < MAX_LIGHTS; ++i) {
|
||||||
|
if(!_glIsLightEnabled(i)) continue;
|
||||||
|
|
||||||
|
const LightSource* light = &LIGHTS[i];
|
||||||
|
|
||||||
|
const GLfloat* Ppli = light->position;
|
||||||
|
GLfloat VPpli [] = {
|
||||||
|
Ppli[0] - V[0],
|
||||||
|
Ppli[1] - V[1],
|
||||||
|
Ppli[2] - V[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
GLfloat VPpliL;
|
||||||
|
vec3f_length(VPpli[0], VPpli[1], VPpli[2], VPpliL);
|
||||||
|
|
||||||
|
VPpli[0] /= VPpliL;
|
||||||
|
VPpli[1] /= VPpliL;
|
||||||
|
VPpli[2] /= VPpliL;
|
||||||
|
|
||||||
|
GLfloat ndotVPpli;
|
||||||
|
vec3f_dot(n[0], n[1], n[2], VPpli[0], VPpli[1], VPpli[2], ndotVPpli);
|
||||||
|
|
||||||
|
const GLfloat k0 = light->constant_attenuation;
|
||||||
|
const GLfloat k1 = light->linear_attenuation;
|
||||||
|
const GLfloat k2 = light->quadratic_attenuation;
|
||||||
|
const GLfloat att = (light->position[3] == 0) ? 1.0f : 1.0f / k0 + (k1 * VPpliL) + (k2 * VPpliL * VPpliL);
|
||||||
|
const GLfloat spot = 1.0f; // FIXME: Spotlights
|
||||||
|
|
||||||
|
const GLfloat fi = (ndotVPpli == 0) ? 0 : 1;
|
||||||
|
|
||||||
|
GLfloat hi [3];
|
||||||
|
if(!VIEWER_IN_EYE_COORDINATES) {
|
||||||
|
// FIXME: Docs show power of T or something?
|
||||||
|
hi[0] = VPpli[0] + 0;
|
||||||
|
hi[1] = VPpli[1] + 0;
|
||||||
|
hi[2] = VPpli[2] + 1;
|
||||||
|
} else {
|
||||||
|
hi[0] = VPpli[0] + Vpe[0];
|
||||||
|
hi[1] = VPpli[1] + Vpe[1];
|
||||||
|
hi[2] = VPpli[2] + Vpe[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
GLfloat ndothi;
|
||||||
|
vec3f_dot(n[0], n[1], n[2], hi[0], hi[1], hi[2], ndothi);
|
||||||
|
|
||||||
|
LIGHT_COMPONENT(0);
|
||||||
|
LIGHT_COMPONENT(1);
|
||||||
|
LIGHT_COMPONENT(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LIGHT_COMPONENT
|
||||||
|
|
||||||
|
vertex->bgra[R8IDX] = (GLubyte)(fminf(final[0] * 255.0f, 255.0f));
|
||||||
|
vertex->bgra[G8IDX] = (GLubyte)(fminf(final[1] * 255.0f, 255.0f));
|
||||||
|
vertex->bgra[B8IDX] = (GLubyte)(fminf(final[2] * 255.0f, 255.0f));
|
||||||
|
vertex->bgra[A8IDX] = (GLubyte)(fminf(final[3] * 255.0f, 255.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,13 @@ GLuint _glGetMipmapLevelCount(TextureObject* obj);
|
||||||
GLboolean _glIsLightingEnabled();
|
GLboolean _glIsLightingEnabled();
|
||||||
GLboolean _glIsLightEnabled(GLubyte light);
|
GLboolean _glIsLightEnabled(GLubyte light);
|
||||||
GLboolean _glIsColorMaterialEnabled();
|
GLboolean _glIsColorMaterialEnabled();
|
||||||
void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, GLfloat* colour);
|
|
||||||
|
typedef struct {
|
||||||
|
float xyz[3];
|
||||||
|
float n[3];
|
||||||
|
} EyeSpaceData;
|
||||||
|
|
||||||
|
extern void _glCalculateLighting(EyeSpaceData* ES, Vertex* vertex);
|
||||||
|
|
||||||
unsigned char _glIsClippingEnabled();
|
unsigned char _glIsClippingEnabled();
|
||||||
void _glEnableClipping(unsigned char v);
|
void _glEnableClipping(unsigned char v);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user