188 lines
5.1 KiB
C
188 lines
5.1 KiB
C
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <GL/glew.h>
|
|
#include <GL/glu.h>
|
|
#include "readtex.h"
|
|
#include "skybox.h"
|
|
|
|
|
|
static int
|
|
load(GLenum target, const char *filename,
|
|
GLboolean flipTB, GLboolean flipLR)
|
|
{
|
|
GLint w, h;
|
|
GLenum format;
|
|
GLubyte *img = LoadRGBImage( filename, &w, &h, &format );
|
|
if (!img) {
|
|
printf("Error: couldn't load texture image %s\n", filename);
|
|
return 0;
|
|
}
|
|
assert(format == GL_RGB);
|
|
|
|
printf("Load cube face 0x%x: %s %d x %d\n", target, filename, w, h);
|
|
|
|
/* <sigh> the way the texture cube mapping works, we have to flip
|
|
* images to make things look right.
|
|
*/
|
|
if (flipTB) {
|
|
const int stride = 3 * w;
|
|
GLubyte temp[3*1024];
|
|
int i;
|
|
for (i = 0; i < h / 2; i++) {
|
|
memcpy(temp, img + i * stride, stride);
|
|
memcpy(img + i * stride, img + (h - i - 1) * stride, stride);
|
|
memcpy(img + (h - i - 1) * stride, temp, stride);
|
|
}
|
|
}
|
|
if (flipLR) {
|
|
const int stride = 3 * w;
|
|
GLubyte temp[3];
|
|
GLubyte *row;
|
|
int i, j;
|
|
for (i = 0; i < h; i++) {
|
|
row = img + i * stride;
|
|
for (j = 0; j < w / 2; j++) {
|
|
int k = w - j - 1;
|
|
temp[0] = row[j*3+0];
|
|
temp[1] = row[j*3+1];
|
|
temp[2] = row[j*3+2];
|
|
row[j*3+0] = row[k*3+0];
|
|
row[j*3+1] = row[k*3+1];
|
|
row[j*3+2] = row[k*3+2];
|
|
row[k*3+0] = temp[0];
|
|
row[k*3+1] = temp[1];
|
|
row[k*3+2] = temp[2];
|
|
}
|
|
}
|
|
}
|
|
|
|
gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img);
|
|
free(img);
|
|
return 1;
|
|
}
|
|
|
|
|
|
GLuint
|
|
LoadSkyBoxCubeTexture(const char *filePosX,
|
|
const char *fileNegX,
|
|
const char *filePosY,
|
|
const char *fileNegY,
|
|
const char *filePosZ,
|
|
const char *fileNegZ)
|
|
{
|
|
GLuint tex;
|
|
|
|
glGenTextures(1, &tex);
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,
|
|
GL_LINEAR_MIPMAP_NEAREST);
|
|
|
|
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_X, filePosX, GL_TRUE, GL_TRUE))
|
|
return 0;
|
|
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, fileNegX, GL_TRUE, GL_TRUE))
|
|
return 0;
|
|
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, filePosY, 1+GL_FALSE, GL_TRUE))
|
|
return 0;
|
|
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, fileNegY, 1+GL_FALSE, GL_TRUE))
|
|
return 0;
|
|
if (!load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, filePosZ, GL_TRUE, GL_TRUE))
|
|
return 0;
|
|
if (!load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, fileNegZ, GL_TRUE, GL_TRUE))
|
|
return 0;
|
|
|
|
return tex;
|
|
}
|
|
|
|
|
|
#define eps1 0.99
|
|
#define br 20.0 /* box radius */
|
|
|
|
void
|
|
DrawSkyBoxCubeTexture(GLuint tex)
|
|
{
|
|
struct vertex {
|
|
float x, y, z, s, t, r;
|
|
};
|
|
|
|
static const struct vertex verts[24] = {
|
|
/* +X side */
|
|
{ br, -br, -br, 1.0, -eps1, -eps1 },
|
|
{ br, -br, br, 1.0, -eps1, eps1 },
|
|
{ br, br, br, 1.0, eps1, eps1 },
|
|
{ br, br, -br, 1.0, eps1, -eps1 },
|
|
|
|
/* -X side */
|
|
{ -br, br, -br, -1.0, eps1, -eps1 },
|
|
{ -br, br, br, -1.0, eps1, eps1 },
|
|
{ -br, -br, br, -1.0, -eps1, eps1 },
|
|
{ -br, -br, -br, -1.0, -eps1, -eps1 },
|
|
|
|
/* +Y side */
|
|
{ br, br, -br, eps1, 1.0, -eps1 },
|
|
{ br, br, br, eps1, 1.0, eps1 },
|
|
{ -br, br, br, -eps1, 1.0, eps1 },
|
|
{ -br, br, -br, -eps1, 1.0, -eps1 },
|
|
|
|
/* -Y side */
|
|
{ -br, -br, -br, -eps1, -1.0, -eps1 },
|
|
{ -br, -br, br, -eps1, -1.0, eps1 },
|
|
{ br, -br, br, eps1, -1.0, eps1 },
|
|
{ br, -br, -br, eps1, -1.0, -eps1 },
|
|
|
|
/* +Z side */
|
|
{ br, -br, br, eps1, -eps1, 1.0 },
|
|
{ -br, -br, br, -eps1, -eps1, 1.0 },
|
|
{ -br, br, br, -eps1, eps1, 1.0 },
|
|
{ br, br, br, eps1, eps1, 1.0 },
|
|
|
|
/* -Z side */
|
|
{ br, br, -br, eps1, eps1, -1.0 },
|
|
{ -br, br, -br, -eps1, eps1, -1.0 },
|
|
{ -br, -br, -br, -eps1, -eps1, -1.0 },
|
|
{ br, -br, -br, eps1, -eps1, -1.0 },
|
|
};
|
|
|
|
static GLuint vbo = 0;
|
|
|
|
if (!vbo ) {
|
|
glGenBuffersARB(1, &vbo);
|
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
|
|
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts,
|
|
GL_STATIC_DRAW_ARB);
|
|
}
|
|
else {
|
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
|
|
}
|
|
|
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
glVertexPointer(3, GL_FLOAT, sizeof(struct vertex),
|
|
(void *) offsetof(struct vertex, x));
|
|
glTexCoordPointer(3, GL_FLOAT, sizeof(struct vertex),
|
|
(void *) offsetof(struct vertex, s));
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
|
|
glEnable(GL_TEXTURE_CUBE_MAP);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDrawArrays(GL_QUADS, 0, 24);
|
|
|
|
glDisable(GL_TEXTURE_CUBE_MAP);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
|
}
|
|
|