diff --git a/GL/draw.c b/GL/draw.c index 24ba531..1492814 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -737,7 +737,7 @@ static void light(ClipVertex* output, const GLsizei count) { GLubyte j; for(j = 0; j < MAX_LIGHTS; ++j) { if(isLightEnabled(j)) { - calculateLightingContribution(j, ES->xyz, ES->n, to_add); + _glCalculateLightingContribution(j, ES->xyz, ES->n, vertex->bgra, to_add); total[0] += to_add[0]; total[1] += to_add[1]; diff --git a/GL/lighting.c b/GL/lighting.c index 59376b0..d7fd520 100644 --- a/GL/lighting.c +++ b/GL/lighting.c @@ -8,6 +8,7 @@ static GLfloat SCENE_AMBIENT [] = {0.2, 0.2, 0.2, 1.0}; static GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE; static GLenum COLOR_CONTROL = GL_SINGLE_COLOR; static GLboolean TWO_SIDED_LIGHTING = GL_FALSE; +static GLenum COLOR_MATERIAL_MODE = GL_AMBIENT_AND_DIFFUSE; static LightSource LIGHTS[MAX_LIGHTS]; static Material MATERIAL; @@ -210,6 +211,34 @@ void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) { } } +void glColorMaterial(GLenum face, GLenum mode) { + if(face != GL_FRONT_AND_BACK) { + _glKosThrowError(GL_INVALID_ENUM, __func__); + _glKosPrintError(); + return; + } + + GLenum validModes[] = {GL_AMBIENT, GL_DIFFUSE, GL_AMBIENT_AND_DIFFUSE, GL_EMISSION, GL_SPECULAR, 0}; + + if(_glCheckValidEnum(mode, validModes, __func__) != 0) { + return; + } + + COLOR_MATERIAL_MODE = mode; +} + +static inline GLboolean isDiffuseColorMaterial() { + return (COLOR_MATERIAL_MODE == GL_DIFFUSE || COLOR_MATERIAL_MODE == GL_AMBIENT_AND_DIFFUSE); +} + +static inline GLboolean isAmbientColorMaterial() { + return (COLOR_MATERIAL_MODE == GL_AMBIENT || COLOR_MATERIAL_MODE == GL_AMBIENT_AND_DIFFUSE); +} + +static inline GLboolean isSpecularColorMaterial() { + return (COLOR_MATERIAL_MODE == GL_SPECULAR); +} + inline void initVec3(struct vec3f* v, const GLfloat* src) { memcpy(v, src, sizeof(GLfloat) * 3); } @@ -240,8 +269,8 @@ static float FPOW(float b, float p) { return FEXP(FLOG(b) * p); } -void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) __attribute__((optimize("fast-math"))); -void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) { +void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, GLfloat* colour) __attribute__((optimize("fast-math"))); +void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, GLfloat* colour) { LightSource* l = &LIGHTS[light]; struct vec3f L = { @@ -290,15 +319,38 @@ void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat VdotR = VdotN - NdotL; GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent); - colour[0] = l->ambient[0] * MATERIAL.ambient[0]; - colour[1] = l->ambient[1] * MATERIAL.ambient[1]; - colour[2] = l->ambient[2] * MATERIAL.ambient[2]; - colour[3] = MATERIAL.diffuse[3]; + 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] * MATERIAL.diffuse[0] * NdotL + l->specular[0] * MATERIAL.specular[0] * specularPower); - colour[1] += (l->diffuse[1] * MATERIAL.diffuse[1] * NdotL + l->specular[1] * MATERIAL.specular[1] * specularPower); - colour[2] += (l->diffuse[2] * MATERIAL.diffuse[2] * NdotL + l->specular[2] * MATERIAL.specular[2] * specularPower); + 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) { diff --git a/GL/private.h b/GL/private.h index e153f32..e5b3363 100644 --- a/GL/private.h +++ b/GL/private.h @@ -112,6 +112,8 @@ typedef struct { GLint size; } AttribPointer; +GLboolean _glCheckValidEnum(GLint param, GLenum* values, const char* func); + GLuint _glGetEnabledAttributes(); AttribPointer* _glGetVertexAttribPointer(); AttribPointer* _glGetDiffuseAttribPointer(); @@ -132,7 +134,8 @@ GLuint _glGetMipmapLevelCount(TextureObject* obj); GLboolean isLightingEnabled(); GLboolean isLightEnabled(GLubyte light); -void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour); +GLboolean _glIsColorMaterialEnabled(); +void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, GLfloat* colour); unsigned char isClippingEnabled(); void enableClipping(unsigned char v); diff --git a/GL/state.c b/GL/state.c index 13eb477..12169f9 100644 --- a/GL/state.c +++ b/GL/state.c @@ -25,6 +25,7 @@ pvr_poly_cxt_t* getPVRContext() { static GLenum CULL_FACE = GL_BACK; static GLenum FRONT_FACE = GL_CCW; static GLboolean CULLING_ENABLED = GL_FALSE; +static GLboolean COLOR_MATERIAL_ENABLED = GL_FALSE; static int _calc_pvr_face_culling() { if(!CULLING_ENABLED) { @@ -116,6 +117,25 @@ static void _updatePVRBlend(pvr_poly_cxt_t* context) { } } +GLboolean _glCheckValidEnum(GLint param, GLenum* values, const char* func) { + GLubyte found = 0; + while(*values != 0) { + if(*values == param) { + found++; + break; + } + values++; + } + + if(!found) { + _glKosThrowError(GL_INVALID_ENUM, func); + _glKosPrintError(); + return GL_TRUE; + } + + return GL_FALSE; +} + static GLboolean TEXTURES_ENABLED [] = {GL_FALSE, GL_FALSE}; void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { @@ -207,6 +227,10 @@ GLboolean isLightEnabled(unsigned char light) { return LIGHT_ENABLED[light & 0xF]; } +GLboolean _glIsColorMaterialEnabled() { + return COLOR_MATERIAL_ENABLED; +} + static GLfloat CLEAR_COLOUR[3]; void initContext() { @@ -264,6 +288,9 @@ GLAPI void APIENTRY glEnable(GLenum cap) { case GL_FOG: GL_CONTEXT.gen.fog_type = PVR_FOG_TABLE; break; + case GL_COLOR_MATERIAL: + COLOR_MATERIAL_ENABLED = GL_TRUE; + break; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: @@ -308,6 +335,9 @@ GLAPI void APIENTRY glDisable(GLenum cap) { case GL_FOG: GL_CONTEXT.gen.fog_type = PVR_FOG_DISABLE; break; + case GL_COLOR_MATERIAL: + COLOR_MATERIAL_ENABLED = GL_FALSE; + break; case GL_LIGHT0: case GL_LIGHT1: case GL_LIGHT2: @@ -419,6 +449,7 @@ void glPixelStorei(GLenum pname, GLint param) { ; } + /* Setup the hardware user clip rectangle. The minimum clip rectangle is a 32x32 area which is dependent on the tile diff --git a/GL/texture.c b/GL/texture.c index 7bf4748..264c126 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -108,26 +108,6 @@ TextureObject* getBoundTexture() { return TEXTURE_UNITS[ACTIVE_TEXTURE]; } -GLubyte check_valid_enum(GLint param, GLenum* values, const char* func) { - GLubyte found = 0; - while(*values != 0) { - if(*values == param) { - found++; - break; - } - values++; - } - - if(!found) { - _glKosThrowError(GL_INVALID_ENUM, func); - _glKosPrintError(); - return 1; - } - - return 0; -} - - void APIENTRY glActiveTextureARB(GLenum texture) { TRACE(); @@ -195,7 +175,7 @@ void APIENTRY glBindTexture(GLenum target, GLuint texture) { GLenum target_values [] = {GL_TEXTURE_2D, 0}; - if(check_valid_enum(target, target_values, __func__) != 0) { + if(_glCheckValidEnum(target, target_values, __func__) != 0) { return; } @@ -215,9 +195,9 @@ void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) { GLubyte failures = 0; - failures += check_valid_enum(target, target_values, __func__); - failures += check_valid_enum(pname, pname_values, __func__); - failures += check_valid_enum(param, param_values, __func__); + failures += _glCheckValidEnum(target, target_values, __func__); + failures += _glCheckValidEnum(pname, pname_values, __func__); + failures += _glCheckValidEnum(param, param_values, __func__); TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];