void game_init(int* argc, char** argv, const char* title) { glutInit(argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutInitWindowSize(800, 600); glutInitContextVersion(3, 1); glutInitContextProfile(GLUT_FORWARD_COMPATIBLE); glutInitContextProfile(GLUT_CORE_PROFILE); glutCreateWindow(title); glewExperimental = true; glewInit(); glutKeyboardFunc(keyboard_down); glutKeyboardUpFunc(keyboard_up); glutSpecialFunc(keyboard_special_down); glutSpecialUpFunc(keyboard_special_up); glutCloseFunc(window_close); glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); bodies = list_new(); body_program = pipeline_new( shader_new(SHADER_VERTEX, "body.vert"), shader_new(SHADER_FRAGMENT, "body.frag")); glGenVertexArrays(1, &body_vao); glBindVertexArray(body_vao); pipeline_attribute(body_program, "coord", 0); pipeline_attribute(body_program, "color", 1); }
void game_init(GameState* gs) { // Bind tiles vbo glGenBuffers(1, &gs->tiles_vbo); glBindBuffer(GL_ARRAY_BUFFER, gs->tiles_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(TILES_VBO)*sizeof(float), TILES_VBO, GL_STATIC_DRAW); gs->tiles_sheet = bitmap_load("bmp/tiles.bmp"); gs->tiles_program = pipeline_new( shader_new(SHADER_VERTEX, "shader/tiles.vert"), shader_new(SHADER_FRAGMENT, "shader/tiles.frag")); pipeline_attribute(gs->tiles_program, "coord", 0); pipeline_attribute(gs->tiles_program, "st", 1); pipeline_uniform(gs->tiles_program, "pos", 0); pipeline_uniform(gs->tiles_program, "tex", 1); pipeline_uniform(gs->tiles_program, "tile", 2); // Bind player vbo glGenBuffers(1, &gs->player_vbo); glBindBuffer(GL_ARRAY_BUFFER, gs->player_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(PLAYER_VBO)*sizeof(float), PLAYER_VBO, GL_STATIC_DRAW); // load player spritesheet gs->player_spritesheet = bitmap_load("bmp/player.bmp"); gs->player_x = gs->player_y = 0; gs->player_vx = gs->player_vy = 0; // create player render pipeline gs->player_program = pipeline_new( shader_new(SHADER_VERTEX, "shader/player.vert"), shader_new(SHADER_FRAGMENT, "shader/player.frag")); pipeline_attribute(gs->player_program, "coord", 0); pipeline_attribute(gs->player_program, "st", 1); pipeline_uniform(gs->player_program, "pos", 0); pipeline_uniform(gs->player_program, "tex", 1); pipeline_uniform(gs->player_program, "dir", 2); // Load audio stuff gs->bounce_sound = sound_load("sound/bounce.ogg"); gs->ouch_sound = sound_load("sound/ouch.ogg"); alGenSources(1, &gs->player_source); // Entity stuff gs->num_entities = 1; gs->ent[0].vbo = gs->player_vbo; gs->ent[0].spritesheet = gs->player_spritesheet; gs->ent[0].frame = 0; gs->ent[0].vx = gs->ent[0].vy = 8; gs->ent[0].x = gs->ent[0].y = 8; gs->ent[0].program = gs->player_program; }
struct render* render_new() { struct render* r = STRUCT_NEW(render); r->cur_program = 0; r->cur_tex_id = 0; r->vertex_buffer = vertex_buffer_new(); r->render_state = 0; r->shader = shader_new(); r->scissors.x = 0; r->scissors.y = 0; r->scissors.width = GAME->config.window_width; r->scissors.width = GAME->config.window_height; r->drawcall = 0; return r; }
int main(int argc, char* argv[]) { int cw = 750; int ch = 750; cg_init(cw, ch, NULL); glClearColor(0,0,1,1); // Actualizar la pantalla: glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glViewport(0,0,cw, ch); glFrustum(-1,1,-1,1,1,1000); glEnable(GL_LIGHTING); // glEnable(GL_NORMALIZE); float l0[] = {1.0f,1.0f,1.0f,1.0f}; float la[] = {0.10f,0.10f,0.10f,1.0f}; float l0p[]= {1.0f,1.0f,1.0f,1.0f}; float ls[] = {1.0f,1.0f,1.0f,1.0f}; glLightfv(GL_LIGHT0, GL_AMBIENT, la); glLightfv(GL_LIGHT0, GL_DIFFUSE, l0); glLightfv(GL_LIGHT0, GL_POSITION, l0p); glLightfv(GL_LIGHT0, GL_SPECULAR, ls); glEnable(GL_LIGHT0); float cyan[] = {1.0f, 1.0f, 1.0f, 1.f}; glMaterialfv(GL_FRONT, GL_DIFFUSE, cyan); glMaterialfv(GL_FRONT, GL_SPECULAR, ls); glMateriali(GL_FRONT, GL_SHININESS, 16); float ang = 0.0f; float pitch = 0.0f; float ang_vel = 1.0f; char done = 0; char wireframe = 0; char bfc = 0; glEnable(GL_DEPTH_TEST); char zbuff = 1; unsigned char key_pressed[1024]; memset(key_pressed, 0, 1024); char use_shader = 0; char specular = 0; Shader gouraud = shader_new("shaders/gouraud_vp.glsl", "shaders/gouraud_fp.glsl"); GLint uniform_especular = shader_get_unif_loc(gouraud, "especular"); GLint uniform_tex = shader_get_unif_loc(gouraud, "tex"); Obj* objPtr ; int example = atoi(argv[1]); if (example==1 || example==3) objPtr = obj_load("../Models/knight_texturas.obj"); else if (example==2) objPtr = obj_load("../Models/box_texturas.obj"); //Cargo la imagen de disco usando SDL_image SDL_Surface* surface; // = IMG_Load("../Models/knight.png"); if (example==1 ) surface = IMG_Load("../Models/knight.png"); else if (example==2) surface = IMG_Load("../Models/box.jpg"); else if (example==3) surface = IMG_Load("../Models/knight_good.png"); // Obj* objPtr = obj_load("../Models/knight_texturas.obj"); // Obj* objPtr = obj_load("../Models/box_texturas.obj"); //Cargo la imagen de disco usando SDL_image // SDL_Surface* surface = IMG_Load("../Models/knight.png"); // SDL_Surface* surface = IMG_Load("../Models/knight_good.png"); // SDL_Surface* surface = IMG_Load("../Models/box.jpg"); if (surface==NULL) { //Si falla la carga de la imagen, despliego el mensaje de error correspondiente y termino el programa. printf("Error: \"%s\"\n", SDL_GetError()); return 1; } GLuint texture; //Creo un espacio para alojar una textura en memoria de video glGenTextures(1,&texture); //Activo la textura nro 0 glActiveTexture(GL_TEXTURE0); //Habilito la carga para la textura recien creada glBindTexture(GL_TEXTURE_2D,texture); //Cargo los datos de la imagen en la textura. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGB,GL_UNSIGNED_BYTE, surface->pixels); //Luego de copiada la imagen a memoria de video, puedo liberarla sin problemas SDL_FreeSurface(surface); //Seteo el filtro a usar cuando se mapea la textura a una superficie mas chica (GL_LINEAR = filtro bilineal) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //Seteo el filtro a usar cuando se mapea la textura a una superficie mas grande (GL_LINEAR = filtro bilineal) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //Seteo el comportamiento cuando encuentro coordenadas de textura fuera del rango [0,1] //GL_REPEAT es el comportamiento por defecto. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); while (!done) { SDL_Event event; while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: key_pressed[event.key.keysym.sym] = 1; if (event.key.keysym.sym == SDLK_p) { use_shader = !use_shader; break; } else if (event.key.keysym.sym == SDLK_s) { specular = !specular; break; } else if (event.key.keysym.sym == SDLK_z) { zbuff = !zbuff; if(zbuff) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); break; } else if (event.key.keysym.sym == SDLK_m) { wireframe = !wireframe; if(wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break; } else if (event.key.keysym.sym == SDLK_b) { bfc = !bfc; if(bfc) { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CW); } else glDisable(GL_CULL_FACE); break; } else if (event.key.keysym.sym != SDLK_ESCAPE) break; case SDL_QUIT : done = 1; break; case SDL_KEYUP: key_pressed[event.key.keysym.sym] = 0; } } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (example==1 || example==3) glTranslatef(0.0f, 0.0f, -50.0f); else if (example==2) glTranslatef(0.0f, 0.0f, -2.0f); // glTranslatef(0.0f, 0.0f, -50.0f); // glTranslatef(0.0f, 0.0f, -2.0f); glRotatef(pitch, 1.0f, 0.0f, 0.0f); glRotatef(ang, 0.0f, 1.0f, 0.0f); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); if(key_pressed[SDLK_RIGHT]) ang += ang_vel; if(key_pressed[SDLK_LEFT]) ang -= ang_vel; if(key_pressed[SDLK_UP]) pitch += ang_vel; if(key_pressed[SDLK_DOWN]) pitch -= ang_vel; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //Informo a OpenGL que para todas las operaciones a continuaci�n utilice las texturas 2D cargadas glEnable(GL_TEXTURE_2D); if(use_shader) { shader_use(gouraud); glUniform1i(uniform_especular, specular); //Le digo al shader que el sampler2D de nombre "tex" se corresponde con GL_TEXTURE0 //que es donde cargu� mi textura. glUniform1i(uniform_tex, 0); //Luego asocio la textura con el id "texture" glBindTexture(GL_TEXTURE_2D,texture); obj_render2(objPtr); shader_stop(gouraud); } else { glBindTexture(GL_TEXTURE_2D,texture); obj_render2(objPtr); } cg_repaint(); } // while // Liberar recursos: obj_free(objPtr); shader_free(gouraud); glDeleteTextures(1,&texture); cg_close(); return 0; }
void boot_init(int* argc, char** argv) { int error; fail_if(glfwInit() == false); // OpenGL version 3 glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 0); // No window resize glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, true); // 400% gameboy scale, 5 bit rgb with 1 bit alpha, 8 bit z buffer fail_if(glfwOpenWindow(160 * 4, 144 * 4, 5, 5, 5, 1, 8, 0, GLFW_WINDOW) == false); glfwSetWindowTitle(""); glfwEnable(GLFW_AUTO_POLL_EVENTS); // Automatically poll input on swap glfwSwapInterval(1); // 0: vsync off, 1: vsync on printf("Renderer: %s\n", glGetString(GL_RENDERER)); printf("GL Version: %s\n", glGetString(GL_VERSION)); printf("Using GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); error = glewInit(); if (error != GLEW_OK) { fprintf(stderr, "GLEW error: %s\n", glewGetErrorString(error)); } printf("GL Extension Wrangler: %s\n", glewGetString(GLEW_VERSION)); // Load audio fail_if(alutInit(argc, argv) == false); glClearColor(206.0/255.0, 230.0/255.0, 165.0/255.0, 1.0f); glEnable(GL_SCISSOR_TEST); // For geom culling // transparency glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // z-buffer glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // Set up perspective glOrtho(0, 160, 144, 0, -1.0, 1.0); glDepthRange(-1.0f, 1.0f); glViewport(0, 0, 160 * 4, 144 * 4); // This is where Ill put the logo thing unsigned logo = bitmap_load("bmp/logo.bmp"); unsigned logo_vbo; float t0, t1, dt; float logo_x = 16, logo_y = -80; float logo_v[] = { 0, 0, 0, 1.0 - 0, 0, 128, 0, 1.0 - 1, 128, 128, 1, 1.0 - 1, 128, 0, 1, 1.0 - 0, }; glGenBuffers(1, &logo_vbo); glBindBuffer(GL_ARRAY_BUFFER, logo_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(logo_v)*sizeof(float), logo_v, GL_STATIC_DRAW); Pipeline* logo_program = pipeline_new( shader_new(SHADER_VERTEX, "shader/logo.vert"), shader_new(SHADER_FRAGMENT, "shader/logo.frag")); pipeline_attribute(logo_program, "coord", 0); pipeline_attribute(logo_program, "st", 1); pipeline_uniform(logo_program, "pos", 0); pipeline_uniform(logo_program, "tex", 1); glUseProgram(logo_program->id); // Bind the logo to texture 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, logo); glUniform1i(logo_program->uniform[1], 0); // Bind logo vbo glBindBuffer(GL_ARRAY_BUFFER, logo_vbo); glEnableVertexAttribArray(logo_program->attribute[0]); glVertexAttribPointer(logo_program->attribute[0], 2, GL_FLOAT, false, 4*sizeof(float), (void*)0); glEnableVertexAttribArray(logo_program->attribute[1]); glVertexAttribPointer(logo_program->attribute[1], 2, GL_FLOAT, false, 4*sizeof(float), (void*)(2 * sizeof(float))); // load sound unsigned sound_source; alGenSources(1, &sound_source); Sound* ding = sound_load("sound/ding.ogg"); alSourcei(sound_source, AL_BUFFER, ding->buffer); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glfwSwapBuffers(); sleep(1); t0 = glfwGetTime(); while (logo_y < 8) { t1 = glfwGetTime(); dt = t1 - t0; t0 = t1; logo_y += 50 * dt; glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glUniform2f(logo_program->uniform[0], roundf(logo_x), roundf(logo_y)); // Render logo glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glfwSwapBuffers(); } alSourcePlay(sound_source); glDisableVertexAttribArray(logo_program->attribute[0]); glDisableVertexAttribArray(logo_program->attribute[1]); sleep(1); }
// The MAIN function, from here we start the application and run the game loop int main() { // Init GLFW glfwInit(); // Set all the required options for GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Create a GLFWwindow object that we can use for GLFW's functions GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", NULL, NULL); glfwMakeContextCurrent(window); // Set the required callback functions glfwSetKeyCallback(window, key_callback); // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions glewExperimental = GL_TRUE; // Initialize GLEW to setup the OpenGL Function pointers glewInit(); // Define the viewport dimensions glViewport(0, 0, WIDTH, HEIGHT); // Setup OpenGL options glEnable(GL_DEPTH_TEST); // Build and compile our shader program shader our_shader = shader_new("shader.vs", "shader.frag"); // Set up vertex data (and buffer(s)) and attribute pointers GLfloat vertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; // World space positions of our cubes graphene_point3d_t cubePositions[] = { GRAPHENE_POINT3D_INIT(0.0f, 0.0f, 0.0f), GRAPHENE_POINT3D_INIT( 2.0f, 5.0f, -15.0f), GRAPHENE_POINT3D_INIT(-1.5f, -2.2f, -2.5f), GRAPHENE_POINT3D_INIT(-3.8f, -2.0f, -12.3f), GRAPHENE_POINT3D_INIT( 2.4f, -0.4f, -3.5f), GRAPHENE_POINT3D_INIT(-1.7f, 3.0f, -7.5f), GRAPHENE_POINT3D_INIT( 1.3f, -2.0f, -2.5f), GRAPHENE_POINT3D_INIT( 1.5f, 2.0f, -2.5f), GRAPHENE_POINT3D_INIT( 1.5f, 0.2f, -1.5f), GRAPHENE_POINT3D_INIT(-1.3f, 1.0f, -1.5f) }; GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // TexCoord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glBindVertexArray(0); // Unbind VAO // Load and create a texture GLuint texture1; GLuint texture2; // ==================== // Texture 1 // ==================== glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); // All upcoming GL_TEXTURE_2D operations now have effect on our texture object // Set our texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture wrapping to GL_REPEAT glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Load, create texture and generate mipmaps int width, height; unsigned char* image = SOIL_load_image("container.jpg", &width, &height, 0, SOIL_LOAD_RGB); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glGenerateMipmap(GL_TEXTURE_2D); SOIL_free_image_data(image); glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture when done, so we won't accidentily mess up our texture. // =================== // Texture 2 // =================== glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); // Set our texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Load, create texture and generate mipmaps image = SOIL_load_image("awesomeface.png", &width, &height, 0, SOIL_LOAD_RGB); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glGenerateMipmap(GL_TEXTURE_2D); SOIL_free_image_data(image); glBindTexture(GL_TEXTURE_2D, 0); // Game loop while (!glfwWindowShouldClose(window)) { // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions glfwPollEvents(); // Render // Clear the colorbuffer glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Bind Textures using texture units glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture1); glUniform1i(glGetUniformLocation(our_shader.program, "ourTexture1"), 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture2); glUniform1i(glGetUniformLocation(our_shader.program, "ourTexture2"), 1); // Activate shader shader_use(&our_shader); // Create transformations graphene_matrix_t view; graphene_point3d_t view_point; graphene_matrix_init_translate(&view, graphene_point3d_init(&view_point, 0.0f, 0.0f, -3.0f)); graphene_matrix_t projection; graphene_matrix_init_perspective(&projection, 45.0f, (GLfloat) WIDTH / (GLfloat) HEIGHT, 0.1f, 100.0f); // Get their uniform location GLint modelLoc = glGetUniformLocation(our_shader.program, "model"); GLint viewLoc = glGetUniformLocation(our_shader.program, "view"); GLint projLoc = glGetUniformLocation(our_shader.program, "projection"); // Pass the matrices to the shader GLfloat view_f[16] = {}; graphene_matrix_to_float(&view, view_f); GLfloat proj_f[16] = {}; graphene_matrix_to_float(&projection, proj_f); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, view_f); // Note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once. glUniformMatrix4fv(projLoc, 1, GL_FALSE, proj_f); glBindVertexArray(VAO); for (GLuint i = 0; i < 10; i++) { // Calculate the model matrix for each object and pass it to shader before drawing graphene_matrix_t model; graphene_matrix_init_translate(&model, &cubePositions[i]); GLfloat angle = 5.0f * i; graphene_vec3_t axis; graphene_vec3_init(&axis, -1.3f, 1.0f, -1.5f); graphene_matrix_rotate(&model, angle, &axis); GLfloat model_f[16] = {}; graphene_matrix_to_float(&model, model_f); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, model_f); glDrawArrays(GL_TRIANGLES, 0, 36); } glBindVertexArray(0); // Swap the screen buffers glfwSwapBuffers(window); } // Properly de-allocate all resources once they've outlived their purpose glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // Terminate GLFW, clearing any resources allocated by GLFW. glfwTerminate(); return 0; }