#include #include #include "glcxx.hpp" #include "GL3/gl3w.h" #include #include "glm/glm.hpp" #include "glm/gtc/matrix_transform.hpp" using namespace std; std::shared_ptr program; std::shared_ptr cube_buffer; std::shared_ptr cube_array; static struct { GLint ambient; GLint specular; GLint shininess; GLint tex; GLint projection; GLint modelview; } uniforms; glm::mat4 modelview; glm::mat4 projection; GLuint texture; GLubyte texture_data[16][16][4]; #define WIDTH 800 #define HEIGHT 800 bool init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); #if 0 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif glViewport(0, 0, WIDTH, HEIGHT); try { program = glcxx::Program::create( glcxx::Shader::create_from_file(GL_VERTEX_SHADER, "cube.v.glsl"), glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, "cube.f.glsl"), "position", 0, "normal", 1, "tex_coord", 2); uniforms.ambient = program->get_uniform_location("ambient"); uniforms.specular = program->get_uniform_location("specular"); uniforms.shininess = program->get_uniform_location("shininess"); uniforms.tex = program->get_uniform_location("tex"); uniforms.projection = program->get_uniform_location("projection"); uniforms.modelview = program->get_uniform_location("modelview"); cube_buffer = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, {-1, -1, 1, 0, 0, 1, 0, 0, 1, -1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, -1, 1, 1, 0, 0, 1, 0, 1}); cube_array = make_shared(); cube_array->bind(); cube_buffer->bind(); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), NULL); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat))); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *)(6 * sizeof(GLfloat))); projection = glm::perspective(60.0f, (float)WIDTH / (float)HEIGHT, 0.1f, 1000.0f); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { if (((j / 2) & 1) == ((i / 2) & 1)) { texture_data[i][j][0] = 255; texture_data[i][j][1] = 255; texture_data[i][j][2] = 255; texture_data[i][j][3] = 255; } else { texture_data[i][j][0] = 0; texture_data[i][j][1] = 0; texture_data[i][j][2] = 0; texture_data[i][j][3] = 0; } } } glGenTextures(1, &texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0][0][0]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } catch (glcxx::Error & e) { cerr << "glcxx error: " << e.what() << endl; return false; } return true; } static void draw_cube() { glm::mat4 modelview_backup = modelview; program->use(); cube_array->bind(); glUniform4f(uniforms.ambient, 1.0, 1.0, 1.0, 1.0); glUniform4f(uniforms.specular, 1.0, 1.0, 1.0, 1.0); glUniform1f(uniforms.shininess, 150.0); glUniform1i(uniforms.tex, 0); glUniformMatrix4fv(uniforms.modelview, 1, GL_FALSE, &modelview[0][0]); glUniformMatrix4fv(uniforms.projection, 1, GL_FALSE, &projection[0][0]); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } void display(SDL_Window * window) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); modelview = glm::translate(glm::mat4(1.0), glm::vec3(0, 0, -2)); modelview = glm::rotate(modelview, (float)(SDL_GetTicks() / 1000.0), glm::vec3(0, 1, 0)); draw_cube(); SDL_GL_SwapWindow(window); } static SDL_Event UpdateEvent; static Uint32 UpdateCallback(Uint32 interval, void * param) { SDL_PushEvent(&UpdateEvent); return interval; } int main(int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) { printf("Failed to initialize SDL!\n"); return 1; } atexit(SDL_Quit); SDL_Window * window = SDL_CreateWindow(argv[0], SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL); if (!window) { printf("Failed to create window!\n"); SDL_Quit(); return 2; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); if (gl3wInit()) { cerr << "Failed to initialize GL3W" << endl; return 2; } if (!gl3wIsSupported(3, 0)) { cerr << "OpenGL 3.0 is not supported!" << endl; return 2; } if (!init()) { return 2; } UpdateEvent.type = SDL_USEREVENT; UpdateEvent.user.code = 0; SDL_AddTimer(25, UpdateCallback, NULL); display(window); 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; if (event.key.keysym.sym == SDLK_RETURN) display(window); } else if (event.type == SDL_USEREVENT) { display(window); } } }