#include #include #include #include #include #include #include #include #include #include //defines #define BOX_ARRAY_SIZE 5 #define MAX_X 2 #define MAX_Z 2 #define MAX_TEXTURES 1 #define FOV 70.0f #define ASPECT_RATIO 800.0f/600.0f typedef struct Box { M3DVector4f position; float rotationOffset, xoffset, zoffset; int texture; } Box; //struct for vertices typedef struct Vertex { M3DVector3f position; M3DVector2f texCoord; } Vertex; //A gigantic global to hold all my stuff static struct { struct { M3DMatrix44f projection; M3DMatrix44f camera; M3DMatrix44f modelViewProjection; } modelviewProjection; GLuint htextures[MAX_TEXTURES]; GLuint hvBuffer, hiBuffer,htcBuffer,hitcBuffer; struct { GLint m4ModelViewProjection; GLint colorMap; } uniforms; struct { GLint vVertex, vTexCoord; } attributes; struct { GLuint hVertexShader, hFragmentShader, hProgram; } shader; Vertex points[36]; } resources; //make a simple box object, this si currently irrelevant bool readShader(char* name, char** destination) { FILE *shader; char* shaderText, *nullOffset; size_t result; long size; shader = fopen(name, "rb"); if(shader == NULL) return false; fseek(shader, 0, SEEK_END); size=ftell(shader); rewind(shader); *destination = (char*) malloc(sizeof(char)*(size + 1)); result = fread(*destination, 1, size, shader); nullOffset = (char*)(*destination + sizeof(char)*(size)); *nullOffset='\0'; fprintf(stdout, *destination); fclose(shader); return true; }; //boring copypasted tga loading utiilty static short le_short(unsigned char *bytes) { return bytes[0] | ((char)bytes[1] << 8); }; void *read_tga(const char *filename, int *width, int *height) { struct tga_header { char id_length; char color_map_type; char data_type_code; unsigned char color_map_origin[2]; unsigned char color_map_length[2]; char color_map_depth; unsigned char x_origin[2]; unsigned char y_origin[2]; unsigned char width[2]; unsigned char height[2]; char bits_per_pixel; char image_descriptor; } header; int i, color_map_size, pixels_size; FILE *f; size_t read; void *pixels; f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "Unable to open %s for reading\n", filename); return NULL; } read = fread(&header, 1, sizeof(header), f); if (read != sizeof(header)) { fprintf(stderr, "%s has incomplete tga header\n", filename); fclose(f); return NULL; } if (header.data_type_code != 2) { fprintf(stderr, "%s is not an uncompressed RGB tga file\n", filename); fclose(f); return NULL; } if (header.bits_per_pixel != 24) { fprintf(stderr, "%s is not a 24-bit uncompressed RGB tga file\n", filename); fclose(f); return NULL; } for (i = 0; i < header.id_length; ++i) if (getc(f) == EOF) { fprintf(stderr, "%s has incomplete id string\n", filename); fclose(f); return NULL; } color_map_size = le_short(header.color_map_length) * (header.color_map_depth/8); for (i = 0; i < color_map_size; ++i) if (getc(f) == EOF) { fprintf(stderr, "%s has incomplete color map\n", filename); fclose(f); return NULL; } *width = le_short(header.width); *height = le_short(header.height); pixels_size = *width * *height * (header.bits_per_pixel/8); pixels = malloc(pixels_size); read = fread(pixels, 1, pixels_size, f); if (read != pixels_size) { fprintf(stderr, "%s has incomplete image\n", filename); fclose(f); free(pixels); return NULL; } return pixels; }; int shaderSetup() { char* shaderSrc = NULL; GLint shaderStatus; //read the vertex shader if (!readShader("vertexShader.vs", &shaderSrc)) { fprintf(stderr, "Vertex Shader Not Found"); return -1; }; //compile and bind it resources.shader.hVertexShader=glCreateShader(GL_VERTEX_SHADER); glShaderSource(resources.shader.hVertexShader, 1, (const GLchar**)&shaderSrc, NULL); glCompileShader(resources.shader.hVertexShader); //check for compiling errors glGetShaderiv(resources.shader.hVertexShader, GL_COMPILE_STATUS, &shaderStatus); if(shaderStatus==GL_FALSE) { char infoLog[1024]; glGetShaderInfoLog(resources.shader.hVertexShader, 1024, NULL, infoLog); fprintf(stderr, "Failed to compile shader:\n%s", infoLog); return -1; }; //free the pointer free(shaderSrc); //same thing again, not sure why I didn't make it more efficient if(!readShader("fragmentShader.fs", &shaderSrc)) { fprintf(stderr, "Fragment Shader Not Found"); return -1; }; //same thing resources.shader.hFragmentShader=glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(resources.shader.hFragmentShader, 1, (const GLchar**)&shaderSrc, NULL); glCompileShader(resources.shader.hFragmentShader); //check for more fun glGetShaderiv(resources.shader.hFragmentShader, GL_COMPILE_STATUS, &shaderStatus); if(shaderStatus==GL_FALSE) { char infoLog[1024]; glGetShaderInfoLog(resources.shader.hFragmentShader, 1024, NULL, infoLog); fprintf(stderr, "Failed to compile shader:\n%s", infoLog); return -1; }; //refree the pointer free(shaderSrc); //create a program, bind shaders to it resources.shader.hProgram=glCreateProgram(); glAttachShader(resources.shader.hProgram, resources.shader.hVertexShader); glAttachShader(resources.shader.hProgram, resources.shader.hFragmentShader); //link it glLinkProgram(resources.shader.hProgram); //clean up glDeleteShader(resources.shader.hFragmentShader); glDeleteShader(resources.shader.hVertexShader); //final error check glGetProgramiv(resources.shader.hProgram, GL_LINK_STATUS, &shaderStatus); if(shaderStatus == GL_FALSE) { char infoLog[1024]; glGetProgramInfoLog(resources.shader.hProgram, 1024, NULL, infoLog); fprintf(stderr, "The program failed to link:\n%s", infoLog); return -1; }; //dig around for attributes and uniforms. resources.attributes.vVertex=glGetAttribLocation(resources.shader.hProgram, "vVertex"); resources.attributes.vTexCoord=glGetAttribLocation(resources.shader.hProgram, "vTexCoord"); //not sure if these are binding correctly. resources.uniforms.m4ModelViewProjection=glGetUniformLocation(resources.shader.hProgram, "m4ModelViewProjection"); resources.uniforms.colorMap=glGetUniformLocation(resources.shader.hProgram, "colorMap"); }; void textureSetup() { glGenTextures(4, resources.htextures); //load image int width, height; void *soviet = read_tga("soviet.tga", &width, &height); if(!soviet) { fprintf(stderr, "could not load texture"); }; glBindTexture(GL_TEXTURE_2D, resources.htextures[0]); //set up the right texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //load texture into thing glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, soviet); free(soviet); if(resources.htextures[0]==0) fprintf(stderr, "failure"); }; void makeBuffer(GLuint &handle, void* data, GLenum target, GLsizei bufferSize) { glGenBuffers(1, &handle); glBindBuffer(target, handle); glBufferData(target,bufferSize,data,GL_STATIC_DRAW); }; void testRender() { glClearColor(.25f, 0.35f, 0.15f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glUniformMatrix4fv(resources.uniforms.m4ModelViewProjection, 1, GL_FALSE, (const GLfloat*)resources.modelviewProjection.modelViewProjection); glEnableVertexAttribArray(resources.attributes.vTexCoord); glEnableVertexAttribArray(resources.attributes.vVertex); //deal with vTexCoord first glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,resources.hiBuffer); glBindBuffer(GL_ARRAY_BUFFER, resources.htcBuffer); glVertexAttribPointer(resources.attributes.vTexCoord,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*2,(void*)0); //now the other one glBindBuffer(GL_ARRAY_BUFFER,resources.hvBuffer); glVertexAttribPointer(resources.attributes.vVertex,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*3,(void*)0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, resources.htextures[0]); glUniform1i(resources.uniforms.colorMap, 0); glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (void*)0); //clean up a bit }; int main(int argc, char* argv) { Box boxes[BOX_ARRAY_SIZE]; srand(time(NULL)); sf::Window frame(sf::VideoMode(800, 600, 32), "3D Textured Box Thing"); sf::Event action; frame.UseVerticalSync(true); GLenum err=glewInit(); if(GLEW_OK != err) return 1; glEnable(GL_DEPTH_TEST); //glEnable(GL_CULL_FACE); shaderSetup(); textureSetup(); //setup boxes, five of them. This number is to change with array size for(int i = 0; i