Skip to content

Instantly share code, notes, and snippets.

@JayFoxRox
Last active August 29, 2015 14:02
Show Gist options
  • Save JayFoxRox/2badc7fa6c9e297349f2 to your computer and use it in GitHub Desktop.
Save JayFoxRox/2badc7fa6c9e297349f2 to your computer and use it in GitHub Desktop.
OpengGL flipped GL_TEXTURE_CUBE_MAP
/* rm -f *.trace && reset && clear && clang cubemap-flip.c -lGL -lglut -lGLU -lGLEW && apitrace trace ./a.out */
#if 0
#define FLIP
#endif
/* This was written for XQEMU so we can see what to do about cubemaps in the
upside-down cache/FBO results.
FLIP and un-FLIP-ed should behave exactly the same. Also both should match
the reference (r key to switch).
Use WASD to rotate the cube.
Results from this test (For upside-down GL cubemaps):
- Swap +Y and -Y faces while loading the textures
- Use this to sample:
vec4 flipTextureCube(samplerCube sampler, vec3 texCoord) {
return textureCube(sampler, vec3(texCoord.x,-texCoord.y,texCoord.z));
}
Still no idea about D3D cubemaps! So there might be an additional step */
/* Copyright (c) Mark J. Kilgard, 1997. */
/* Copyright (c) Jannik Vogel, 2014. */
/* This program is freely distributable without licensing fees
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
/* This program was requested by Patrick Earl; hopefully someone else
will write the equivalent Direct3D immediate mode program. */
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <stdint.h>
GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
GLfloat n[6][3] = { /* Normals for the 6 faces of a cube. */
{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} };
GLint faces[6][4] = { /* Vertex indices for the 6 faces of a cube. */
{0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
{4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} };
GLfloat v[8][3]; /* Will be filled in with X,Y,Z vertexes. */
void
drawBox(void)
{
int i;
for (i = 0; i < 6; i++) {
glBegin(GL_QUADS);
glNormal3fv(&n[i][0]);
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}
void
display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawBox();
glutSwapBuffers();
glutPostRedisplay();
}
const int SZ = 256; /* Texture size */
uint32_t val(float r, float g, float b) {
uint32_t rgba = 0xFF000000;
rgba |= (int)(b * 255.0f) << 16;
rgba |= (int)(g * 255.0f) << 8;
rgba |= (int)(r * 255.0f) << 0;
return rgba;
}
#define VAL(r,g,b) val((r) / (float)((SZ)-1),(g) / (float)((SZ)-1),(b) / (float)((SZ)-1))
#ifdef FLIP
#define ADDR(x,y) ((SZ - (y) - 1)*(SZ)+(x))
#else
#define ADDR(x,y) ((y)*(SZ)+(x))
#endif
void* posx() {
static uint32_t pixels[SZ*SZ];
int y,z;
for(y = 0; y < SZ; y++) {
for(z = 0; z < SZ; z++) {
pixels[ADDR(y,z)] = VAL(SZ-1,SZ-z-1,SZ-y-1);
}
}
return pixels;
}
void* negx() {
static uint32_t pixels[SZ*SZ];
int y,z;
for(y = 0; y < SZ; y++) {
for(z = 0; z < SZ; z++) {
pixels[ADDR(y,z)] = VAL(0,SZ-z-1,y);
}
}
return pixels;
}
void* posy() {
static uint32_t pixels[SZ*SZ];
int x,z;
for(x = 0; x < SZ; x++) {
for(z = 0; z < SZ; z++) {
pixels[ADDR(x,z)] = VAL(x,SZ-1,z);
}
}
return pixels;
}
void* negy() {
static uint32_t pixels[SZ*SZ];
int x,z;
for(x = 0; x < SZ; x++) {
for(z = 0; z < SZ; z++) {
pixels[ADDR(x,z)] = VAL(x,0,SZ-z-1);
}
}
return pixels;
}
void* posz() {
static uint32_t pixels[SZ*SZ];
int x,y;
for(x = 0; x < SZ; x++) {
for(y = 0; y < SZ; y++) {
pixels[ADDR(x,y)] = VAL(x,SZ-y-1,SZ-1);
}
}
return pixels;
}
void* negz() {
static uint32_t pixels[SZ*SZ];
int x,y;
for(x = 0; x < SZ; x++) {
for(y = 0; y < SZ; y++) {
pixels[ADDR(x,y)] = VAL(SZ-x-1,SZ-y-1,0);
}
}
return pixels;
}
GLuint prog;
void
init(void)
{
glewInit();
const char* vsh = "#version 110\n"
"varying vec3 uv;"
"void main() {"
" gl_Position = ftransform();"
" uv = gl_Vertex.xyz;"
"}";
const char* fsh = "#version 110\n"
"varying vec3 uv;"
"uniform int ref;"
"uniform samplerCube sampler;"
"vec4 flipTextureCube(samplerCube sampler, vec3 texCoord) {"
" return textureCube(sampler, vec3(texCoord.x,-texCoord.y,texCoord.z));"
"}"
"void main() {"
#ifdef FLIP
" gl_FragColor = flipTextureCube(sampler, uv);"
#else
" gl_FragColor = textureCube(sampler, uv);"
#endif
" if (ref != 0) {"
" gl_FragColor = vec4(uv.xyz*vec3(0.5)+vec3(0.5),1.0);"
" }"
"}";
prog = glCreateProgram();
GLuint s;
s = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(s, 1, &vsh, NULL);
glCompileShader(s);
glAttachShader(prog, s);
s = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(s, 1, &fsh, NULL);
glCompileShader(s);
glAttachShader(prog, s);
glLinkProgram(prog);
glUseProgram(prog);
glActiveTexture(GL_TEXTURE0);
GLuint tex;
glGenTextures(1,&tex);
glBindTexture(GL_TEXTURE_CUBE_MAP,tex);
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,posx());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,negx());
#ifdef FLIP
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,negy());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,posy());
#else
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,posy());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,negy());
#endif
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,posz());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,0,GL_RGBA,(SZ),(SZ),0,GL_RGBA,GL_UNSIGNED_BYTE,negz());
glUniform1i(glGetUniformLocation(prog,"sampler"),0);
/* Setup cube vertex data. */
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);
/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.0); /* up is in positive Y direction */
}
void keyPressed(unsigned char key, int x, int y) {
static int ref = 0;
if (key == 'r') {
ref++;
glUniform1i(glGetUniformLocation(prog,"ref"), ref & 1);
}
if (key == 'w') {
glRotatef(-10, 1.0, 0.0, 0.0);
}
if (key == 's') {
glRotatef(10, 1.0, 0.0, 0.0);
}
if (key == 'a') {
glRotatef(-10, 0.0, 1.0, 0.0);
}
if (key == 'd') {
glRotatef(10, 0.0, 1.0, 0.0);
}
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("red 3D lighted cube");
glutDisplayFunc(display);
glutKeyboardFunc(keyPressed);
init();
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment