#define GL_GLEXT_PROTOTYPES #include #include #include #include #include #include #include "../glslUtil/glslUtil.h" #include #include using namespace std; #define WIDTH 800 #define HEIGHT 600 #define STRIDE(a, b) ((unsigned long)(b) - (unsigned long)(a)) #define OFFSET(a, b) ((const GLvoid *)STRIDE((a), (b))) const GLfloat data[][2][3] = { {{-1.0, -0.6, 0.0}, {0, 0, 1}}, {{-0.2, -0.6, 0.0}, {0, 0, 1}}, {{-0.6, 0.6, 0.0}, {0, 0, 1}}, {{0.2, -0.6, 0.0}, {0, 0.7071, 0.7071}}, {{1.0, -0.6, 0.0}, {0, 0.7071, 0.7071}}, {{0.6, 0.6, -10.0}, {0, 0.7071, 0.7071}} }; const GLushort indices[] = { 0, 1, 2, 3, 4, 5 }; GLuint program, vs, fs, data_vbo, index_vbo; GLint ambient_loc, diffuse_loc, specular_loc, shininess_loc, projection_loc, modelview_loc; enum Locations { LOC_POSITION, LOC_NORMAL }; static guMatrix4x4 projection; static guMatrix4x4 modelview; char * loadFile(const char *fname) { struct stat st; if (stat(fname, &st) != 0) return NULL; if (st.st_size <= 0) return NULL; char * buff = new char[st.st_size + 1]; int fd = open(fname, O_RDONLY); read(fd, buff, st.st_size); close(fd); buff[st.st_size] = '\0'; return buff; } char *getShaderLog(GLuint id) { GLint log_length; glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length); if (log_length > 0) { char *log = new char[log_length]; glGetShaderInfoLog(id, log_length, &log_length, log); return log; } return NULL; } char *getProgramLog(GLuint id) { GLint log_length; glGetProgramiv(id, GL_INFO_LOG_LENGTH, &log_length); if (log_length > 0) { char *log = new char[log_length]; glGetProgramInfoLog(id, log_length, &log_length, log); return log; } return NULL; } GLuint makeShader(GLenum shaderType, const char *fname) { GLuint id; const char *source; GLint status; id = glCreateShader(shaderType); if (id <= 0) { cerr << "Error creating shader object" << endl; goto out; } source = loadFile(fname); if (source == NULL) { fprintf(stderr, "Error reading file '%s'\n", fname); goto cleanup_shader; } glShaderSource(id, 1, &source, NULL); delete[] source; glCompileShader(id); glGetShaderiv(id, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { cerr << "Error compiling shader" << endl; char *log = getShaderLog(id); cerr << "Shader Log:" << endl << log << endl; delete[] log; goto cleanup_shader; } return id; cleanup_shader: glDeleteShader(id); out: return 0; } GLuint makeBuffer(GLenum target, const void *ptr, size_t sz) { GLuint id; glGenBuffers(1, &id); glBindBuffer(target, id); glBufferData(target, sz, ptr, GL_STATIC_DRAW); return id; } bool init(int width, int height) { glClearColor (0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glViewport(0, 0, WIDTH, HEIGHT); guMatrixLoadIdentity(&projection); guMatrixLoadIdentity(&modelview); float near = 0.1; float scale = near * 0.577 * 2; float aspect = (float)width / (float)height; guMatrixFrustum(&projection, -aspect * scale, aspect * scale, -scale, scale, near, 1000.0); #if 0 guPerspective(&projection, 60, (float)width / (float)height, 0.1, 1000.0); #endif guMatrixTranslate(&modelview, 0, 0, -1); // guMatrixTranslate(&modelview, 1, 0.3, 0); vs = makeShader(GL_VERTEX_SHADER, "v_shader.glsl"); fs = makeShader(GL_FRAGMENT_SHADER, "f_shader.glsl"); if (vs <= 0 || fs <= 0) { return false; } program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glBindAttribLocation(program, LOC_POSITION, "pos"); glBindAttribLocation(program, LOC_NORMAL, "normal"); glLinkProgram(program); GLint link_status; glGetProgramiv(program, GL_LINK_STATUS, &link_status); if (link_status != GL_TRUE) { char *log = getProgramLog(program); cerr << "Program log:" << endl << log << endl; delete[] log; glDeleteShader(vs); glDeleteShader(fs); return false; } guUniformLocation locs[] = { {&ambient_loc, "ambient"}, {&diffuse_loc, "diffuse"}, {&specular_loc, "specular"}, {&shininess_loc, "shininess"}, {&projection_loc, "projection"}, {&modelview_loc, "modelview"}, {NULL, NULL} }; guGetUniformLocations(program, locs); glUseProgram(program); glUniform4f(ambient_loc, 0.2, 0.2, 0.2, 1.0); glUniform4f(diffuse_loc, 1.0, 0.6, 0.0, 1.0); glUniform4f(specular_loc, 1.0, 1.0, 1.0, 1.0); glUniform1f(shininess_loc, 85.0); glUniformMatrix4fv(projection_loc, 1, GL_FALSE, &projection[0][0]); glUniformMatrix4fv(modelview_loc, 1, GL_FALSE, &modelview[0][0]); data_vbo = makeBuffer(GL_ARRAY_BUFFER, data, sizeof(data)); index_vbo = makeBuffer(GL_ELEMENT_ARRAY_BUFFER, indices, sizeof(indices)); return true; } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(program); glBindBuffer(GL_ARRAY_BUFFER, data_vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_vbo); glEnableVertexAttribArray(LOC_POSITION); glEnableVertexAttribArray(LOC_NORMAL); glVertexAttribPointer(LOC_POSITION, 3, GL_FLOAT, GL_FALSE, STRIDE(&data[0], &data[1]), OFFSET(&data[0], &data[0][0])); glVertexAttribPointer(LOC_NORMAL, 3, GL_FLOAT, GL_FALSE, STRIDE(&data[0], &data[1]), OFFSET(&data[0], &data[0][1])); glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_SHORT, OFFSET(&indices, &indices[0])); SDL_GL_SwapBuffers(); } int main(int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO)) { printf("Failed to initialize SDL!\n"); return 1; } atexit(SDL_Quit); SDL_Surface *screen; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if (!(screen = SDL_SetVideoMode(WIDTH, HEIGHT, 16, SDL_OPENGL))) { printf("Failed to set video mode!\n"); SDL_Quit(); return 2; } SDL_WM_SetCaption(argv[0], argv[0]); if (!init(WIDTH, HEIGHT)) return 2; display(); SDL_Event event; while (SDL_WaitEvent(&event)) { if (event.type == SDL_QUIT) break; else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_ESCAPE) break; } } }