From: Eleni Maria Stea Date: Tue, 6 Nov 2018 11:01:04 +0000 (+0200) Subject: testing compressed cubemaps X-Git-Url: https://eleni.mutantstargoat.com/git/?p=cubetest;a=commitdiff_plain;h=eb60ee34b34e1a87fb9be4454400cf38af95569a testing compressed cubemaps --- eb60ee34b34e1a87fb9be4454400cf38af95569a diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d266bea --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +# -- options -- +PREFIX = /usr/local +opt = -O3 +dbg = -g +# ------------- + +src = $(wildcard src/*.cc) +obj = $(src:.cc=.o) +dep = $(obj:.o=.d) +bin = cubetest + +CXXFLAGS = -pedantic -Wall $(opt) $(dbg) $(inc) +LDFLAGS = -lGL -lGLU -lglut + +$(bin): $(obj) + $(CXX) -o $@ $(obj) $(LDFLAGS) + +-include $(dep) + +%.d: %.c + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +%.d: %.cc + @$(CPP) $(CXXFLAGS) $< -MM -MT $(@:.d=.o) >$@ + +.PHONY: clean +clean: + rm -f $(obj) $(bin) + +.PHONY: cleandep +cleandep: + rm -f $(dep) + +.PHONY: install +install: $(bin) + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp $(bin) $(DESTDIR)$(PREFIX)/bin/$(bin) + +.PHONY: uninstall +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/$(bin) diff --git a/data/back.tex b/data/back.tex new file mode 100644 index 0000000..5aa4b22 Binary files /dev/null and b/data/back.tex differ diff --git a/data/down.tex b/data/down.tex new file mode 100644 index 0000000..93451b9 Binary files /dev/null and b/data/down.tex differ diff --git a/data/front.tex b/data/front.tex new file mode 100644 index 0000000..3cefd65 Binary files /dev/null and b/data/front.tex differ diff --git a/data/left.tex b/data/left.tex new file mode 100644 index 0000000..224d7db Binary files /dev/null and b/data/left.tex differ diff --git a/data/right.tex b/data/right.tex new file mode 100644 index 0000000..a40d554 Binary files /dev/null and b/data/right.tex differ diff --git a/data/up.tex b/data/up.tex new file mode 100644 index 0000000..1aa400f Binary files /dev/null and b/data/up.tex differ diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..d176b42 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include + +static bool init(); +static void cleanup(); +static unsigned int load_cubemap(); + +static void display(); +static void reshape(int x, int y); +static void keyboard(unsigned char key, int x, int y); +static void mouse(int bn, int state, int x, int y); +static void motion(int x, int y); + +struct Texture { + unsigned int id; + int width; + int height; + unsigned int format; + unsigned int size; + unsigned char *data; +}; + +struct Header { + char magic[8]; + uint32_t glfmt; + uint16_t flags; + uint16_t levels; + uint32_t width, height; + struct { + uint32_t offset, size; + } datadesc[20]; + char unused[8]; +}; + +static unsigned int cubemap; +static float cam_phi, cam_theta; + +int main(int argc, char **argv) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); + glutInitWindowSize(1024, 768); + glutCreateWindow("cubetest"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyboard); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + if(!init()) + return 1; + + atexit(cleanup); + + glutMainLoop(); + return 0; +} + +static bool load_teximage(const char *fname, Texture *tex) +{ + FILE *fp; + if(!(fp = fopen(fname, "rb"))) { + fprintf(stderr, "failed to open file: %s: %s\n", fname, strerror(errno)); + return false; + } + + Header hdr; + if(fread(&hdr, 1, sizeof hdr, fp) != sizeof hdr) { + fprintf(stderr, "failed to read image file header: %s: %s\n", fname, strerror(errno)); + fclose(fp); + return false; + } + if(memcmp(hdr.magic, "COMPTEX0", sizeof hdr.magic) != 0 || hdr.levels < 0 || + hdr.levels > 20 || !hdr.datadesc[0].size) { + fprintf(stderr, "%s is not a compressed texture file, or is corrupted\n", fname); + fclose(fp); + return false; + } + + tex->data = new unsigned char[hdr.datadesc[0].size]; + + if(fread(tex->data, 1, hdr.datadesc[0].size, fp) != hdr.datadesc[0].size) { + fprintf(stderr, "unexpected EOF while reading texture: %s\n", fname); + fclose(fp); + delete [] tex->data; + return false; + } + + tex->width = hdr.width; + tex->height = hdr.height; + tex->format = hdr.glfmt; + tex->size = hdr.datadesc[0].size; + + fclose(fp); + + return true; +} + +static unsigned int load_cubemap() +{ + static const char *names[6] = {"data/right.tex", "data/left.tex", "data/up.tex", + "data/down.tex", "data/back.tex", "data/front.tex"}; + + Texture tex; + glGenTextures(1, &tex.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, tex.id); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + for(int i=0; i<6; i++) { + if(!load_teximage(names[i], &tex)) { + glDeleteTextures(1, &tex.id); + return 0; + } + unsigned int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i; + glCompressedTexImage2D(face, 0, tex.format, tex.width, tex.height, 0, tex.size, tex.data); + delete [] tex.data; + } + + return tex.id; +} + +static bool init() +{ + if(!(cubemap = load_cubemap())) { + return false; + } + glEnable(GL_TEXTURE_CUBE_MAP); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + + float planes[][4] = {{1, 0, 0, 0}, {0,1, 0, 0}, {0, 0, 1, 0}}; + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + + glTexGenfv(GL_S, GL_OBJECT_PLANE, planes[0]); + glTexGenfv(GL_T, GL_OBJECT_PLANE, planes[1]); + glTexGenfv(GL_R, GL_OBJECT_PLANE, planes[2]); + + return true; +} + +static void cleanup() +{ + glDeleteTextures(1, &cubemap); +} + +static void display() +{ + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glRotatef(cam_phi, 1, 0, 0); + glRotatef(cam_theta, 0, 1, 0); + + glutSolidSphere(10, 10, 5); + + glutSwapBuffers(); +} + +static void reshape(int x, int y) +{ + glViewport(0, 0, x, y); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(45, (float)x / (float)y, 0.5, 100); +} + +static void keyboard(unsigned char key, int x, int y) +{ + switch(key) { + case 27: + exit(0); + default: + break; + } +} + +static int prev_x, prev_y; +static bool bnstate[6]; + +static void mouse(int bn, int state, int x, int y) +{ + prev_x = x; + prev_y = y; + bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN; +} + +static void motion(int x, int y) +{ + if(bnstate[0]) { + cam_phi += (y - prev_y) * 0.5; + cam_theta += (x - prev_x) * 0.5; + + if(cam_phi < -90) cam_phi = -90; + if(cam_phi > 90) cam_phi = 90; + + glutPostRedisplay(); + } + + prev_y = y; + prev_x = x; +}