Merge branch 'fog_fix' into 'master'
Fixed OpenGL Fog implementation + Added New Sample See merge request simulant/GLdc!155
This commit is contained in:
commit
6bd42b87b9
@ -197,6 +197,7 @@ gen_sample(nehe06_vq samples/nehe06_vq/main.c)
|
|||||||
gen_sample(nehe06_4444twid samples/nehe06_4444twid/main.c)
|
gen_sample(nehe06_4444twid samples/nehe06_4444twid/main.c)
|
||||||
gen_sample(nehe08 samples/nehe08/main.c samples/nehe08/pvr-texture.c)
|
gen_sample(nehe08 samples/nehe08/main.c samples/nehe08/pvr-texture.c)
|
||||||
gen_sample(nehe10 samples/nehe10/main.c samples/loadbmp.c)
|
gen_sample(nehe10 samples/nehe10/main.c samples/loadbmp.c)
|
||||||
|
gen_sample(nehe16 samples/nehe16/main.c samples/nehe16/pvr-texture.c)
|
||||||
gen_sample(nehe20 samples/nehe20/main.c samples/loadbmp.c)
|
gen_sample(nehe20 samples/nehe20/main.c samples/loadbmp.c)
|
||||||
gen_sample(ortho2d samples/ortho2d/main.c)
|
gen_sample(ortho2d samples/ortho2d/main.c)
|
||||||
gen_sample(paletted samples/paletted/main.c)
|
gen_sample(paletted samples/paletted/main.c)
|
||||||
|
|||||||
175
GL/fog.c
175
GL/fog.c
@ -1,73 +1,138 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
TODO: glGetX() fog values
|
||||||
|
*/
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
static GLfloat FOG_START = 0.0f;
|
static struct {
|
||||||
static GLfloat FOG_END = 1.0f;
|
GLfloat START;
|
||||||
static GLfloat FOG_DENSITY = 1.0f;
|
GLfloat END;
|
||||||
static GLenum FOG_MODE = GL_EXP;
|
GLfloat DENSITY;
|
||||||
static GLfloat FOG_COLOR [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
GLenum MODE;
|
||||||
|
GLfloat COLOR[4];
|
||||||
|
} FOG = {
|
||||||
|
0.0f, 1.0f, 1.0f, GL_EXP, { 0.0f, 0.0f, 0.0f, 0.0f }
|
||||||
|
};
|
||||||
|
|
||||||
static void updatePVRFog() {
|
static void updatePVRFog(void) {
|
||||||
if(FOG_MODE == GL_LINEAR) {
|
switch(FOG.MODE) {
|
||||||
GPUSetFogLinear(FOG_START, FOG_END);
|
case GL_LINEAR:
|
||||||
} else if(FOG_MODE == GL_EXP) {
|
GPUSetFogLinear(FOG.START, FOG.END);
|
||||||
GPUSetFogExp(FOG_DENSITY);
|
break;
|
||||||
} else if(FOG_MODE == GL_EXP2) {
|
|
||||||
GPUSetFogExp2(FOG_DENSITY);
|
case GL_EXP:
|
||||||
|
GPUSetFogExp(FOG.DENSITY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_EXP2:
|
||||||
|
GPUSetFogExp2(FOG.DENSITY);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
GPUSetFogColor(FOG_COLOR[3], FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2]);
|
|
||||||
|
GPUSetFogColor(FOG.COLOR[3], FOG.COLOR[0], FOG.COLOR[1], FOG.COLOR[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIENTRY glFogf(GLenum pname, GLfloat param) {
|
void APIENTRY glFogf(GLenum pname, GLfloat param) {
|
||||||
switch(pname) {
|
switch(pname) {
|
||||||
case GL_FOG_MODE: {
|
case GL_FOG_DENSITY:
|
||||||
FOG_MODE = (GLenum) param;
|
if(FOG.DENSITY != param) {
|
||||||
updatePVRFog();
|
if(param < 0.0f)
|
||||||
} break;
|
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||||
case GL_FOG_DENSITY: {
|
else {
|
||||||
FOG_DENSITY = param;
|
FOG.DENSITY = param;
|
||||||
updatePVRFog();
|
updatePVRFog();
|
||||||
} break;
|
}
|
||||||
case GL_FOG_START: {
|
}
|
||||||
FOG_START = param;
|
break;
|
||||||
updatePVRFog();
|
|
||||||
} break;
|
case GL_FOG_START:
|
||||||
case GL_FOG_END: {
|
if(FOG.START != param) {
|
||||||
FOG_END = param;
|
FOG.START = param;
|
||||||
updatePVRFog();
|
updatePVRFog();
|
||||||
} break;
|
}
|
||||||
case GL_FOG_INDEX:
|
break;
|
||||||
default: {
|
|
||||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
case GL_FOG_END:
|
||||||
}
|
if(FOG.END != param) {
|
||||||
|
FOG.END = param;
|
||||||
|
updatePVRFog();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIENTRY glFogi(GLenum pname, GLint param) {
|
void APIENTRY glFogi(GLenum pname, GLint param) {
|
||||||
glFogf(pname, (GLfloat) param);
|
switch(pname) {
|
||||||
}
|
case GL_FOG_DENSITY:
|
||||||
|
case GL_FOG_START:
|
||||||
|
case GL_FOG_END:
|
||||||
|
glFogf(pname, (GLfloat)param);
|
||||||
|
break;
|
||||||
|
|
||||||
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
|
case GL_FOG_MODE:
|
||||||
if(pname == GL_FOG_COLOR) {
|
if(FOG.MODE != param) {
|
||||||
FOG_COLOR[0] = params[0];
|
switch(param) {
|
||||||
FOG_COLOR[1] = params[1];
|
case GL_LINEAR:
|
||||||
FOG_COLOR[2] = params[2];
|
case GL_EXP:
|
||||||
FOG_COLOR[3] = params[3];
|
case GL_EXP2:
|
||||||
updatePVRFog();
|
FOG.MODE = param;
|
||||||
} else {
|
updatePVRFog();
|
||||||
glFogf(pname, *params);
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GL_FOG_INDEX:
|
||||||
|
default:
|
||||||
|
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
|
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
|
||||||
if(pname == GL_FOG_COLOR) {
|
switch(pname) {
|
||||||
FOG_COLOR[0] = ((GLfloat) params[0]) / (GLfloat) INT_MAX;
|
case GL_FOG_COLOR: {
|
||||||
FOG_COLOR[1] = ((GLfloat) params[1]) / (GLfloat) INT_MAX;
|
GLfloat color[] = {
|
||||||
FOG_COLOR[2] = ((GLfloat) params[2]) / (GLfloat) INT_MAX;
|
CLAMP(params[0], 0.0f, 1.0f),
|
||||||
FOG_COLOR[3] = ((GLfloat) params[3]) / (GLfloat) INT_MAX;
|
CLAMP(params[1], 0.0f, 1.0f),
|
||||||
updatePVRFog();
|
CLAMP(params[2], 0.0f, 1.0f),
|
||||||
} else {
|
CLAMP(params[3], 0.0f, 1.0f)
|
||||||
glFogi(pname, *params);
|
};
|
||||||
|
|
||||||
|
if(memcmp(color, FOG.COLOR, sizeof(float) * 4)) {
|
||||||
|
memcpy(FOG.COLOR, color, sizeof(float) * 4);
|
||||||
|
updatePVRFog();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
glFogf(pname, *params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
|
||||||
|
switch(pname) {
|
||||||
|
case GL_FOG_COLOR: {
|
||||||
|
GLfloat color[] = {
|
||||||
|
(GLfloat)params[0] / (GLfloat)INT_MAX,
|
||||||
|
(GLfloat)params[1] / (GLfloat)INT_MAX,
|
||||||
|
(GLfloat)params[2] / (GLfloat)INT_MAX,
|
||||||
|
(GLfloat)params[3] / (GLfloat)INT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
glFogfv(pname, color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
glFogi(pname, *params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
247
samples/nehe16/main.c
Normal file
247
samples/nehe16/main.c
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
KallistiOS 2.0.0
|
||||||
|
|
||||||
|
nehe16.c
|
||||||
|
(c)2025 Falco Girgis
|
||||||
|
(c)2014 Josh Pearson
|
||||||
|
(c)2001 Benoit Miller
|
||||||
|
(c)2000 Jeff Molofee
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <GL/glkos.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
|
||||||
|
#ifdef __DREAMCAST__
|
||||||
|
#include <kos.h>
|
||||||
|
extern uint8 romdisk[];
|
||||||
|
KOS_INIT_ROMDISK(romdisk);
|
||||||
|
#define IMG_PATH "/rd/glass.pvr"
|
||||||
|
#else
|
||||||
|
#define IMG_PATH "../samples/nehe08/romdisk/glass.pvr"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Simple GL example to demonstrate fog (PVR table fog).
|
||||||
|
|
||||||
|
Essentially the same thing as NeHe's lesson16 code.
|
||||||
|
To learn more, go to http://nehe.gamedev.net/.
|
||||||
|
|
||||||
|
DPAD controls the cube rotation, button A & B control the depth
|
||||||
|
of the cube, button X toggles fog on/off, and button Y toggles fog type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static GLfloat xrot; /* X Rotation */
|
||||||
|
static GLfloat yrot; /* Y Rotation */
|
||||||
|
static GLfloat xspeed; /* X Rotation Speed */
|
||||||
|
static GLfloat yspeed; /* Y Rotation Speed */
|
||||||
|
static GLfloat z = -5.0f; /* Depth Into The Screen */
|
||||||
|
|
||||||
|
static GLuint texture; /* Storage For Texture */
|
||||||
|
|
||||||
|
/* Storage For Three Types Of Fog */
|
||||||
|
GLuint fogType = 0; /* use GL_EXP initially */
|
||||||
|
GLuint fogMode[] = { GL_EXP, GL_EXP2, GL_LINEAR };
|
||||||
|
char cfogMode[3][10] = {"GL_EXP ", "GL_EXP2 ", "GL_LINEAR" };
|
||||||
|
GLfloat fogColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; /* Fog Color */
|
||||||
|
int fog = GL_TRUE;
|
||||||
|
|
||||||
|
/* Load a PVR texture - located in pvr-texture.c */
|
||||||
|
extern GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap);
|
||||||
|
|
||||||
|
void draw_gl(void) {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0.0f, 0.0f, z);
|
||||||
|
|
||||||
|
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
|
||||||
|
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
/* Front Face */
|
||||||
|
glNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||||
|
/* Back Face */
|
||||||
|
glNormal3f(0.0f, 0.0f, -1.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||||
|
/* Top Face */
|
||||||
|
glNormal3f(0.0f, 1.0f, 0.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||||
|
/* Bottom Face */
|
||||||
|
glNormal3f(0.0f, -1.0f, 0.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||||
|
/* Right face */
|
||||||
|
glNormal3f(1.0f, 0.0f, 0.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||||
|
/* Left Face */
|
||||||
|
glNormal3f(-1.0f, 0.0f, 0.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
xrot += xspeed;
|
||||||
|
yrot += yspeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
GLboolean xp = GL_FALSE;
|
||||||
|
GLboolean yp = GL_FALSE;
|
||||||
|
|
||||||
|
printf("nehe16 beginning\n");
|
||||||
|
|
||||||
|
/* Get basic stuff initialized */
|
||||||
|
glKosInit();
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluPerspective(45.0f, 640.0f / 480.0f, 0.1f, 100.0f);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glShadeModel(GL_SMOOTH);
|
||||||
|
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
|
glClearDepth(1.0f);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
|
glColor4f(1.0f, 1.0f, 1.0f, 0.5);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||||
|
|
||||||
|
/* Enable Lighting and GL_LIGHT0 */
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
|
||||||
|
/* Set up the fog */
|
||||||
|
glFogi(GL_FOG_MODE, fogMode[fogType]); /* Fog Mode */
|
||||||
|
glFogfv(GL_FOG_COLOR, fogColor); /* Set Fog Color */
|
||||||
|
glFogf(GL_FOG_DENSITY, 0.35f); /* How Dense The Fog is */
|
||||||
|
glHint(GL_FOG_HINT, GL_DONT_CARE); /* Fog Hint Value */
|
||||||
|
glFogf(GL_FOG_START, 0.0f); /* Fog Start Depth */
|
||||||
|
glFogf(GL_FOG_END, 5.0f); /* Fog End Depth */
|
||||||
|
glEnable(GL_FOG); /* Enables GL_FOG */
|
||||||
|
|
||||||
|
/* Set up the textures */
|
||||||
|
texture = glTextureLoadPVR(IMG_PATH, 0, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
#ifdef __DREAMCAST__
|
||||||
|
maple_device_t *cont;
|
||||||
|
cont_state_t *state;
|
||||||
|
|
||||||
|
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||||
|
|
||||||
|
/* Check key status */
|
||||||
|
state = (cont_state_t *)maple_dev_status(cont);
|
||||||
|
|
||||||
|
if(!state) {
|
||||||
|
printf("Error reading controller\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state->start)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(state->a) {
|
||||||
|
if(z >= -15.0f) z -= 0.02f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state->b) {
|
||||||
|
if(z <= 0.0f) z += 0.02f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(state->x && !xp) {
|
||||||
|
xp = GL_TRUE;
|
||||||
|
fogType = (fogType + 1) % 3;
|
||||||
|
glFogi(GL_FOG_MODE, fogMode[fogType]);
|
||||||
|
printf("%s\n", cfogMode[fogType]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!state->x)
|
||||||
|
xp = GL_FALSE;
|
||||||
|
|
||||||
|
if(state->y && !yp) {
|
||||||
|
yp = GL_TRUE;
|
||||||
|
fog = !fog;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!state->y)
|
||||||
|
yp = GL_FALSE;
|
||||||
|
|
||||||
|
if(state->dpad_up)
|
||||||
|
xspeed -= 0.1f;
|
||||||
|
|
||||||
|
if(state->dpad_down)
|
||||||
|
xspeed += 0.1f;
|
||||||
|
|
||||||
|
if(state->dpad_left)
|
||||||
|
yspeed -= 0.1f;
|
||||||
|
|
||||||
|
if(state->dpad_right)
|
||||||
|
yspeed += 0.1f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Switch fog off/on */
|
||||||
|
if(fog) {
|
||||||
|
glEnable(GL_FOG);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glDisable(GL_FOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the GL "scene" */
|
||||||
|
draw_gl();
|
||||||
|
|
||||||
|
/* Finish the frame */
|
||||||
|
glKosSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
176
samples/nehe16/pvr-texture.c
Normal file
176
samples/nehe16/pvr-texture.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
KallistiOS 2.0.0
|
||||||
|
|
||||||
|
pvr-texture.c
|
||||||
|
(c)2014 Josh PH3NOM Pearson
|
||||||
|
|
||||||
|
Load A PVR Texture to the PVR using Open GL
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "GL/gl.h"
|
||||||
|
#include "GL/glu.h"
|
||||||
|
#include "GL/glkos.h"
|
||||||
|
#include "GL/glext.h"
|
||||||
|
|
||||||
|
#define PVR_HDR_SIZE 0x20
|
||||||
|
#define MAX(x, y) ((x > y) ? x : y)
|
||||||
|
|
||||||
|
static GLuint PVR_TextureHeight(unsigned char *HDR);
|
||||||
|
static GLuint PVR_TextureWidth(unsigned char *HDR);
|
||||||
|
static GLuint PVR_TextureFormat(unsigned char *HDR);
|
||||||
|
|
||||||
|
static GLuint _glGetMipmapLevelCount(GLuint width, GLuint height) {
|
||||||
|
return 1 + floor(log2(MAX(width, height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint _glGetMipmapDataSize(GLuint width, GLuint height) {
|
||||||
|
GLuint size = 0;
|
||||||
|
|
||||||
|
GLuint i = 0;
|
||||||
|
|
||||||
|
for(; i < _glGetMipmapLevelCount(width, height); ++i) {
|
||||||
|
size += (width * height * 2);
|
||||||
|
|
||||||
|
if(width > 1) {
|
||||||
|
width /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height > 1) {
|
||||||
|
height /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load a PVR texture file into memory, and then bind the texture to Open GL.
|
||||||
|
fname is the name of the PVR texture file to be opened and read.
|
||||||
|
isMipMapped should be passed as 1 if the texture contains MipMap levels, 0 otherwise.
|
||||||
|
glMipMap should be passed as 1 if Open GL should calculate the Mipmap levels, 0 otherwise */
|
||||||
|
GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap) {
|
||||||
|
FILE *tex = NULL;
|
||||||
|
uint16_t *TEX0 = NULL;
|
||||||
|
uint8_t HDR[PVR_HDR_SIZE];
|
||||||
|
GLuint texID, texSize, texW, texH, texFormat;
|
||||||
|
|
||||||
|
/* Open the PVR texture file, and get its file size */
|
||||||
|
tex = fopen(fname, "rb");
|
||||||
|
|
||||||
|
if(tex == NULL) {
|
||||||
|
printf("FILE READ ERROR: %s\n", fname);
|
||||||
|
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(tex, 0, SEEK_END);
|
||||||
|
texSize = ftell(tex) - PVR_HDR_SIZE;
|
||||||
|
fseek(tex, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* Read in the PVR texture file header */
|
||||||
|
fread(HDR, 1, PVR_HDR_SIZE, tex);
|
||||||
|
|
||||||
|
/* Extract some information from the PVR texture file header */
|
||||||
|
texW = PVR_TextureWidth(HDR);
|
||||||
|
texH = PVR_TextureHeight(HDR);
|
||||||
|
texFormat = PVR_TextureFormat(HDR);
|
||||||
|
|
||||||
|
/* Allocate Some Memory for the texture. If we are using Open GL to build the MipMap,
|
||||||
|
we need to allocate enough space to hold the MipMap texture levels. */
|
||||||
|
if(!isMipMapped && glMipMap)
|
||||||
|
TEX0 = malloc(_glGetMipmapDataSize(texW, texH));
|
||||||
|
else
|
||||||
|
TEX0 = malloc(texSize);
|
||||||
|
|
||||||
|
fread(TEX0, 1, texSize, tex); /* Read in the PVR texture data */
|
||||||
|
|
||||||
|
/* Generate and bind a texture as normal for Open GL */
|
||||||
|
glGenTextures(1, &texID);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texID);
|
||||||
|
|
||||||
|
if(texFormat != GL_UNSIGNED_SHORT_5_6_5)
|
||||||
|
glCompressedTexImage2DARB(GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
texFormat,
|
||||||
|
texW,
|
||||||
|
texH,
|
||||||
|
0,
|
||||||
|
texSize,
|
||||||
|
TEX0);
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "%x\n", texFormat);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_RGB,
|
||||||
|
texW, texH,
|
||||||
|
0,
|
||||||
|
GL_RGB,
|
||||||
|
texFormat,
|
||||||
|
TEX0);
|
||||||
|
if(!isMipMapped && glMipMap)
|
||||||
|
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(TEX0);
|
||||||
|
|
||||||
|
return texID;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint PVR_TextureFormat(unsigned char *HDR) {
|
||||||
|
GLuint color = (GLuint)HDR[PVR_HDR_SIZE - 8];
|
||||||
|
GLuint format = (GLuint)HDR[PVR_HDR_SIZE - 7];
|
||||||
|
|
||||||
|
GLboolean twiddled = format == 0x01;
|
||||||
|
GLboolean compressed = (format == 0x10 || format == 0x03);
|
||||||
|
|
||||||
|
if(compressed) {
|
||||||
|
if(twiddled) {
|
||||||
|
switch(color) {
|
||||||
|
case 0x0: {
|
||||||
|
return GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||||
|
} break;
|
||||||
|
case 0x01: {
|
||||||
|
return GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
||||||
|
} break;
|
||||||
|
case 0x02: {
|
||||||
|
return GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Invalid texture format");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch(color) {
|
||||||
|
case 0: {
|
||||||
|
return GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||||
|
} break;
|
||||||
|
case 1: {
|
||||||
|
return GL_COMPRESSED_RGB_565_VQ_KOS;
|
||||||
|
} break;
|
||||||
|
case 2: {
|
||||||
|
return GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Invalid texture format");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(color == 1) {
|
||||||
|
return GL_UNSIGNED_SHORT_5_6_5;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint PVR_TextureWidth(unsigned char *HDR) {
|
||||||
|
return (GLuint)HDR[PVR_HDR_SIZE - 4] | HDR[PVR_HDR_SIZE - 3] << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint PVR_TextureHeight(unsigned char *HDR) {
|
||||||
|
return (GLuint)HDR[PVR_HDR_SIZE - 2] | HDR[PVR_HDR_SIZE - 1] << 8;
|
||||||
|
}
|
||||||
BIN
samples/nehe16/romdisk/glass.pvr
Normal file
BIN
samples/nehe16/romdisk/glass.pvr
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user