Implement glColorMaterial

This commit is contained in:
Luke Benstead 2018-08-22 09:24:49 +01:00
parent 21f8f9d855
commit b29303fb6c
5 changed files with 101 additions and 35 deletions

View File

@ -737,7 +737,7 @@ static void light(ClipVertex* output, const GLsizei count) {
GLubyte j; GLubyte j;
for(j = 0; j < MAX_LIGHTS; ++j) { for(j = 0; j < MAX_LIGHTS; ++j) {
if(isLightEnabled(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[0] += to_add[0];
total[1] += to_add[1]; total[1] += to_add[1];

View File

@ -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 GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE;
static GLenum COLOR_CONTROL = GL_SINGLE_COLOR; static GLenum COLOR_CONTROL = GL_SINGLE_COLOR;
static GLboolean TWO_SIDED_LIGHTING = GL_FALSE; static GLboolean TWO_SIDED_LIGHTING = GL_FALSE;
static GLenum COLOR_MATERIAL_MODE = GL_AMBIENT_AND_DIFFUSE;
static LightSource LIGHTS[MAX_LIGHTS]; static LightSource LIGHTS[MAX_LIGHTS];
static Material MATERIAL; 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) { inline void initVec3(struct vec3f* v, const GLfloat* src) {
memcpy(v, src, sizeof(GLfloat) * 3); memcpy(v, src, sizeof(GLfloat) * 3);
} }
@ -240,8 +269,8 @@ static float FPOW(float b, float p) {
return FEXP(FLOG(b) * p); return FEXP(FLOG(b) * p);
} }
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) __attribute__((optimize("fast-math"))); void _glCalculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, uint8_t* bgra, 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) {
LightSource* l = &LIGHTS[light]; LightSource* l = &LIGHTS[light];
struct vec3f L = { struct vec3f L = {
@ -290,15 +319,38 @@ void calculateLightingContribution(const GLint light, const GLfloat* pos, const
GLfloat VdotR = VdotN - NdotL; GLfloat VdotR = VdotN - NdotL;
GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent); GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent);
colour[0] = l->ambient[0] * MATERIAL.ambient[0]; GLboolean colorMaterial = _glIsColorMaterialEnabled();
colour[1] = l->ambient[1] * MATERIAL.ambient[1];
colour[2] = l->ambient[2] * MATERIAL.ambient[2]; GLfloat mD [] = {
colour[3] = MATERIAL.diffuse[3]; (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) { if(NdotL >= 0) {
colour[0] += (l->diffuse[0] * MATERIAL.diffuse[0] * NdotL + l->specular[0] * MATERIAL.specular[0] * specularPower); colour[0] += (l->diffuse[0] * mD[0] * NdotL + l->specular[0] * mS[0] * specularPower);
colour[1] += (l->diffuse[1] * MATERIAL.diffuse[1] * NdotL + l->specular[1] * MATERIAL.specular[1] * specularPower); colour[1] += (l->diffuse[1] * mD[1] * NdotL + l->specular[1] * mS[1] * specularPower);
colour[2] += (l->diffuse[2] * MATERIAL.diffuse[2] * NdotL + l->specular[2] * MATERIAL.specular[2] * specularPower); colour[2] += (l->diffuse[2] * mD[2] * NdotL + l->specular[2] * mS[2] * specularPower);
} }
if(!l->is_directional) { if(!l->is_directional) {

View File

@ -112,6 +112,8 @@ typedef struct {
GLint size; GLint size;
} AttribPointer; } AttribPointer;
GLboolean _glCheckValidEnum(GLint param, GLenum* values, const char* func);
GLuint _glGetEnabledAttributes(); GLuint _glGetEnabledAttributes();
AttribPointer* _glGetVertexAttribPointer(); AttribPointer* _glGetVertexAttribPointer();
AttribPointer* _glGetDiffuseAttribPointer(); AttribPointer* _glGetDiffuseAttribPointer();
@ -132,7 +134,8 @@ GLuint _glGetMipmapLevelCount(TextureObject* obj);
GLboolean isLightingEnabled(); GLboolean isLightingEnabled();
GLboolean isLightEnabled(GLubyte light); 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(); unsigned char isClippingEnabled();
void enableClipping(unsigned char v); void enableClipping(unsigned char v);

View File

@ -25,6 +25,7 @@ pvr_poly_cxt_t* getPVRContext() {
static GLenum CULL_FACE = GL_BACK; static GLenum CULL_FACE = GL_BACK;
static GLenum FRONT_FACE = GL_CCW; static GLenum FRONT_FACE = GL_CCW;
static GLboolean CULLING_ENABLED = GL_FALSE; static GLboolean CULLING_ENABLED = GL_FALSE;
static GLboolean COLOR_MATERIAL_ENABLED = GL_FALSE;
static int _calc_pvr_face_culling() { static int _calc_pvr_face_culling() {
if(!CULLING_ENABLED) { 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}; static GLboolean TEXTURES_ENABLED [] = {GL_FALSE, GL_FALSE};
void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) {
@ -207,6 +227,10 @@ GLboolean isLightEnabled(unsigned char light) {
return LIGHT_ENABLED[light & 0xF]; return LIGHT_ENABLED[light & 0xF];
} }
GLboolean _glIsColorMaterialEnabled() {
return COLOR_MATERIAL_ENABLED;
}
static GLfloat CLEAR_COLOUR[3]; static GLfloat CLEAR_COLOUR[3];
void initContext() { void initContext() {
@ -264,6 +288,9 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
case GL_FOG: case GL_FOG:
GL_CONTEXT.gen.fog_type = PVR_FOG_TABLE; GL_CONTEXT.gen.fog_type = PVR_FOG_TABLE;
break; break;
case GL_COLOR_MATERIAL:
COLOR_MATERIAL_ENABLED = GL_TRUE;
break;
case GL_LIGHT0: case GL_LIGHT0:
case GL_LIGHT1: case GL_LIGHT1:
case GL_LIGHT2: case GL_LIGHT2:
@ -308,6 +335,9 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
case GL_FOG: case GL_FOG:
GL_CONTEXT.gen.fog_type = PVR_FOG_DISABLE; GL_CONTEXT.gen.fog_type = PVR_FOG_DISABLE;
break; break;
case GL_COLOR_MATERIAL:
COLOR_MATERIAL_ENABLED = GL_FALSE;
break;
case GL_LIGHT0: case GL_LIGHT0:
case GL_LIGHT1: case GL_LIGHT1:
case GL_LIGHT2: case GL_LIGHT2:
@ -419,6 +449,7 @@ void glPixelStorei(GLenum pname, GLint param) {
; ;
} }
/* Setup the hardware user clip rectangle. /* Setup the hardware user clip rectangle.
The minimum clip rectangle is a 32x32 area which is dependent on the tile The minimum clip rectangle is a 32x32 area which is dependent on the tile

View File

@ -108,26 +108,6 @@ TextureObject* getBoundTexture() {
return TEXTURE_UNITS[ACTIVE_TEXTURE]; 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) { void APIENTRY glActiveTextureARB(GLenum texture) {
TRACE(); TRACE();
@ -195,7 +175,7 @@ void APIENTRY glBindTexture(GLenum target, GLuint texture) {
GLenum target_values [] = {GL_TEXTURE_2D, 0}; GLenum target_values [] = {GL_TEXTURE_2D, 0};
if(check_valid_enum(target, target_values, __func__) != 0) { if(_glCheckValidEnum(target, target_values, __func__) != 0) {
return; return;
} }
@ -215,9 +195,9 @@ void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) {
GLubyte failures = 0; GLubyte failures = 0;
failures += check_valid_enum(target, target_values, __func__); failures += _glCheckValidEnum(target, target_values, __func__);
failures += check_valid_enum(pname, pname_values, __func__); failures += _glCheckValidEnum(pname, pname_values, __func__);
failures += check_valid_enum(param, param_values, __func__); failures += _glCheckValidEnum(param, param_values, __func__);
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE]; TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];