コード例 #1
0
ファイル: game.c プロジェクト: jsutlovic/YALS2
static inline void _setup_camera(game *g) {
    if (g->d.ortho) {
        mat4x4_ortho(g->d.proj, -g->aspect, g->aspect, -1, 1, 0.001, 1000);
    } else {
        mat4x4_perspective(g->d.proj, 45.0, g->aspect, 0.001, 1000.0);
    }

    vec3_sub(g->d.view_f, g->d.center, g->d.eye);
    vec3_norm(g->d.view_f, g->d.view_f);

    vec3_mul_cross(g->d.view_r, g->d.view_f, g->d.up);
    vec3_norm(g->d.view_r, g->d.view_r);

    vec3_mul_cross(g->d.view_u, g->d.view_r, g->d.view_f);

    _calc_zoom(g, 0); // Update zoom for this view type
}
コード例 #2
0
ファイル: camera.c プロジェクト: eivindlysne/3Dstuff
Camera* Camera_init(
    vec3 const position,
    float fov,
    float aspect,
    float zNear,
    float zFar
) {
    Camera* camera = malloc(sizeof(Camera));

    camera->transform = Transform_init_default();
    camera->transform.position[0] = position[0];
    camera->transform.position[1] = position[1];
    camera->transform.position[2] = position[2];

    mat4x4_perspective(camera->projection, toRadians(fov), aspect, zNear, zFar);

    return camera;
}
コード例 #3
0
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    float ratio = 1.f;
    mat4x4 projection;

    if (height > 0)
        ratio = (float) width / (float) height;

    // Setup viewport
    glViewport(0, 0, width, height);

    // Change to the projection matrix and set our viewing volume
    glMatrixMode(GL_PROJECTION);
    mat4x4_perspective(projection,
                       60.f * (float) M_PI / 180.f,
                       ratio,
                       1.f, 1024.f);
    glLoadMatrixf((const GLfloat*) projection);
}
コード例 #4
0
ファイル: boing.c プロジェクト: GarrPeter/glfw
/*****************************************************************************
 * reshape()
 *****************************************************************************/
void reshape( GLFWwindow* window, int w, int h )
{
   mat4x4 projection, view;

   glViewport( 0, 0, (GLsizei)w, (GLsizei)h );

   glMatrixMode( GL_PROJECTION );
   mat4x4_perspective( projection,
                       2.f * (float) atan2( RADIUS, 200.f ),
                       (float)w / (float)h,
                       1.f, VIEW_SCENE_DIST );
   glLoadMatrixf((const GLfloat*) projection);

   glMatrixMode( GL_MODELVIEW );
   {
      vec3 eye = { 0.f, 0.f, VIEW_SCENE_DIST };
      vec3 center = { 0.f, 0.f, 0.f };
      vec3 up = { 0.f, -1.f, 0.f };
      mat4x4_look_at( view, eye, center, up );
   }
   glLoadMatrixf((const GLfloat*) view);
}
コード例 #5
0
ファイル: wolf.c プロジェクト: Clever-Boy/wolf
static void wolf_frame(struct point2 *position, struct vector2 *direction, float angle)
{
	glClearColor(0,0,0,0); 
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 

	mat4x4 project;
	mat4x4_identity(project);
	mat4x4_perspective(project, degrees_to_radians(FOV), 640.0/480.0, 0.1f, 64.0f);

	mat4x4_identity(model_view);
	vec3 eye;
	eye[0] = position->x;
	eye[1] = 0.3;
	eye[2] = position->y;
	vec3 center;
	center[0] = position->x+direction->x;
	center[1] = 0.3;
	center[2] = position->y+direction->y;
	vec3 up;
	up[0] = 0.0;
	up[1] = 1.0;
	up[2] = 0.0;
	mat4x4_look_at(model_view, eye, center, up);

	glMatrixMode(GL_PROJECTION);
	glLoadMatrixf((const GLfloat*) project);

	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixf((const GLfloat*) model_view);

	glEnable(GL_DEPTH_TEST);

	wolf_draw_floor();

	wolf_raycast(position, angle, wolf_draw_wall);
}
コード例 #6
0
ファイル: particles.cpp プロジェクト: dw7017/glfw
static void draw_scene(GLFWwindow* window, double t)
{
    double xpos, ypos, zpos, angle_x, angle_y, angle_z;
    static double t_old = 0.0;
    float dt;
    mat4x4 projection;

    // Calculate frame-to-frame delta time
    dt = (float) (t - t_old);
    t_old = t;

    mat4x4_perspective(projection,
                       65.f * (float) M_PI / 180.f,
                       aspect_ratio,
                       1.0, 60.0);

    glClearColor(0.1f, 0.1f, 0.1f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf((const GLfloat*) projection);

    // Setup camera
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // Rotate camera
    angle_x = 90.0 - 10.0;
    angle_y = 10.0 * sin(0.3 * t);
    angle_z = 10.0 * t;
    glRotated(-angle_x, 1.0, 0.0, 0.0);
    glRotated(-angle_y, 0.0, 1.0, 0.0);
    glRotated(-angle_z, 0.0, 0.0, 1.0);

    // Translate camera
    xpos =  15.0 * sin((M_PI / 180.0) * angle_z) +
             2.0 * sin((M_PI / 180.0) * 3.1 * t);
    ypos = -15.0 * cos((M_PI / 180.0) * angle_z) +
             2.0 * cos((M_PI / 180.0) * 2.9 * t);
    zpos = 4.0 + 2.0 * cos((M_PI / 180.0) * 4.9 * t);
    glTranslated(-xpos, -ypos, -zpos);

    glFrontFace(GL_CCW);
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);

    setup_lights();
    glEnable(GL_LIGHTING);

    glEnable(GL_FOG);
    glFogi(GL_FOG_MODE, GL_EXP);
    glFogf(GL_FOG_DENSITY, 0.05f);
    glFogfv(GL_FOG_COLOR, fog_color);

    draw_floor();

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glDepthMask(GL_TRUE);

    draw_fountain();

    glDisable(GL_LIGHTING);
    glDisable(GL_FOG);

    // Particles must be drawn after all solid objects have been drawn
    draw_particles(window, t, dt);

    // Z-buffer not needed anymore
    glDisable(GL_DEPTH_TEST);
}
コード例 #7
0
ファイル: main.c プロジェクト: samnm/dream
int main(void)
{
  Primative *edits[] = {
    primative_create(CUBE, ADDITIVE),
    primative_create(SPHERE, ADDITIVE),
    primative_create(SPHERE, SUBTRACTIVE),
    primative_create(SPHERE, ADDITIVE)
  };

  primative_scale(edits[0], 0.4, 1.0, 1.5);
  primative_translate(edits[1], 0.2, 0, 0);
  primative_translate(edits[2], -0.3, 0, 0);
  primative_translate(edits[3], -0.5, 0, 0);
  primative_scale(edits[3], 0.5, 0.5, 0.5);
  edits[1]->blend = 0.2;

  sdf_args.edits = edits;
  sdf_args.num_edits = 4;

  vec3 origin = {0, 0, 0};
  vec3 halfDim = {1, 1, 1};
  OctTree *tree = octTree_create(origin, halfDim);

  octTree_populate(tree, distance);

  int num_verticies = octTree_count(tree);
  size_t vert_size = sizeof(Point);
  fprintf(stdout, "num verts %d\n", num_verticies);

  int vi = 0;
  Point *verticies = malloc(num_verticies * vert_size);
  octTree_get_points(tree, verticies, &vi);

  GLFWwindow* window;

  mat4x4 ident;
  mat4x4_identity(ident);

  glfwSetErrorCallback(error_callback);

  if (!glfwInit())
    exit(EXIT_FAILURE);

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

  window = glfwCreateWindow(640, 480, "speed dream", NULL, NULL);
  if (!window)
  {
    glfwTerminate();
    exit(EXIT_FAILURE);
  }

  glfwMakeContextCurrent(window);
  glfwSwapInterval(1);

  glEnable(GL_PROGRAM_POINT_SIZE);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);

  glfwSetKeyCallback(window, key_callback);

  mat4x4 proj;
  mat4x4 view;
  mat4x4 matrix;

  mat4x4_identity(view);
  mat4x4_identity(matrix);

  vec3_set(camera.pos, 0.0f, 0.0f, 0.0f);

  // Create Vertex Array Object
  GLuint vao;
  glGenVertexArrays(1, &vao);
  glBindVertexArray(vao);

  // Create a Vertex Buffer Object and copy the vertex data to it
  GLuint vbo;
  glGenBuffers(1, &vbo);

  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, num_verticies * vert_size, verticies, GL_STATIC_DRAW);

  // Create and compile the shaders
  GLuint vertexShader = loadShader(GL_VERTEX_SHADER, DREAM_VERT);
  GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, DREAM_FRAG);

  // Link the vertex and fragment shader into a shader program
  GLuint shaderProgram = glCreateProgram();
  glAttachShader(shaderProgram, vertexShader);
  glAttachShader(shaderProgram, fragmentShader);
  glBindFragDataLocation(shaderProgram, 0, "outColor");
  glLinkProgram(shaderProgram);
  glUseProgram(shaderProgram);

  // Specify the layout of the vertex data
  GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
  glEnableVertexAttribArray(posAttrib);
  glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, vert_size, 0);

  GLint normAttrib = glGetAttribLocation(shaderProgram, "normal");
  glEnableVertexAttribArray(normAttrib);
  glVertexAttribPointer(normAttrib, 3, GL_FLOAT, GL_FALSE, vert_size, (void*)(3 * sizeof(GLfloat)));

  GLint colorAttrib = glGetAttribLocation(shaderProgram, "color");
  glEnableVertexAttribArray(colorAttrib);
  glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, vert_size, (void*)(6 * sizeof(GLfloat)));

  GLint uniModel = glGetUniformLocation(shaderProgram, "model");
  GLint uniView = glGetUniformLocation(shaderProgram, "view");
  GLint uniProj = glGetUniformLocation(shaderProgram, "proj");

  vec3 lightPos = {3.f, 0.f, 3.f};
  GLint uniLightPos = glGetUniformLocation(shaderProgram, "lightPos");
  glUniform3fv(uniLightPos, 1, (const GLfloat *)&lightPos);

  while (!glfwWindowShouldClose(window))
  {
    float ratio;
    int width, height;

    glfwGetFramebufferSize(window, &width, &height);
    ratio = width / (float) height;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    vec4 movement = {0, 0, 0, 1};
    if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
      movement[0] -= 0.1;
    if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
      movement[0] += 0.1;
    if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
      movement[2] += 0.1;
    if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
      movement[2] -= 0.1;

    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
      camera.pitch -= 0.05;
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
      camera.pitch += 0.05;
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
      camera.yaw += 0.05;
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
      camera.yaw -= 0.05;

    mat4x4 pitch_mat;
    mat4x4_identity(pitch_mat);
    mat4x4_rotate_X(pitch_mat, pitch_mat, camera.pitch);

    mat4x4 yaw_mat;
    mat4x4_identity(yaw_mat);
    mat4x4_rotate_Y(yaw_mat, yaw_mat, camera.yaw);

    mat4x4 inv_yaw_mat;
    mat4x4_invert(inv_yaw_mat, yaw_mat);

    vec4 rotated_movement;
    mat4x4_mul_vec4(rotated_movement, inv_yaw_mat, movement);
    camera.pos[0] += rotated_movement[0];
    camera.pos[1] += rotated_movement[1];
    camera.pos[2] += rotated_movement[2];

    mat4x4 translation_mat;
    mat4x4_translate(translation_mat, camera.pos[0], camera.pos[1], camera.pos[2]);

    mat4x4_mul(view, pitch_mat, yaw_mat);
    mat4x4_mul(view, view, translation_mat);
    glUniformMatrix4fv(uniView, 1, GL_FALSE, (const GLfloat *)&view);

    mat4x4_perspective(proj, 60 * M_PI / 180, ratio, 0.1f, 10.0f);
    glUniformMatrix4fv(uniProj, 1, GL_FALSE, (const GLfloat *)&proj);

    glUniformMatrix4fv(uniModel, 1, GL_FALSE, (const GLfloat *)&matrix);

    glDrawArrays(GL_POINTS, 0, num_verticies);

    glfwSwapBuffers(window);
    glfwPollEvents();
  }

  glDeleteProgram(shaderProgram);
  glDeleteShader(fragmentShader);
  glDeleteShader(vertexShader);

  glDeleteBuffers(1, &vbo);
  glDeleteVertexArrays(1, &vao);

  glfwDestroyWindow(window);

  free(verticies);

  glfwTerminate();
  exit(EXIT_SUCCESS);
}
コード例 #8
0
ファイル: main.c プロジェクト: larso0/PTGame
int main(int argc, char** argv)
{
    Settings settings;
    ConstructSettings(&settings);
    LoadSettingsFile(&settings, "settings.ini");
    if(Init(&settings) < 0) return -1;

    GLuint program;
    if(SetupProgram(&program) < 0) return -2;

    GLuint grid_vbuf = CreateGridVertexBuffer(settings.graphics.viewdistance);
    int grid_icount;
    GLuint grid_ibuf = CreateGridIndexBuffer(&grid_icount,
                                             settings.graphics.viewdistance);

    glUseProgram(program);
    GLint grid_pos_loc = glGetAttribLocation(program, "grid_pos");
    GLint grid_world_mat_loc = glGetUniformLocation(program, "world_mat");
    GLint grid_view_mat_loc = glGetUniformLocation(program, "view_mat");
    GLint grid_proj_mat_loc = glGetUniformLocation(program, "proj_mat");
    GLint grid_color_loc = glGetUniformLocation(program, "color");
    GLint grid_viewdistance_loc = glGetUniformLocation(program, "viewdistance");

    glUniform3f(grid_color_loc, 0.f, 0.6f, 0.f);
    glUniform1f(grid_viewdistance_loc, settings.graphics.viewdistance);

    GLuint grid_vao;
    glGenVertexArrays(1, &grid_vao);
    glBindVertexArray(grid_vao);
    glBindBuffer(GL_ARRAY_BUFFER, grid_vbuf);
    glEnableVertexAttribArray(grid_pos_loc);
    glVertexAttribPointer(grid_pos_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid_ibuf);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glClearColor(0.5f, 0.5f, 0.5f, 1.f);
    glViewport(0, 0, settings.video.width, settings.video.height);

    Node grid_node;
    ConstructNode(&grid_node);
    Camera camera;
    ConstructCamera(&camera);
    mat4x4 projection_matrix;
    mat4x4_perspective(projection_matrix,
                       settings.video.pfov,
                       settings.video.width/(float)settings.video.height,
                       settings.video.pnear,
                       settings.video.pfar);
    glUniformMatrix4fv(grid_proj_mat_loc, 1, GL_FALSE,
                       (const float*)projection_matrix);

    float speed = 10.f;
    Uint32 ticks = SDL_GetTicks();
    State state = STATE_RUNNING | (settings.video.fullscreen ? STATE_FULLSCREEN : 0);
    while(state & STATE_RUNNING)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glUseProgram(program);
        glUniformMatrix4fv(grid_world_mat_loc, 1, GL_FALSE,
                           (const float*)grid_node.world_matrix);
        glUniformMatrix4fv(grid_view_mat_loc, 1, GL_FALSE,
                           (const float*)camera.view_matrix);
        glBindVertexArray(grid_vao);
        glDrawElements(GL_TRIANGLE_STRIP, grid_icount, GL_UNSIGNED_INT, NULL);
        SDL_GL_SwapWindow(window);

        SDL_Event event;
        while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
            case SDL_QUIT:
                state &= ~STATE_RUNNING;
                break;
            case SDL_KEYUP:
                switch(event.key.keysym.scancode)
                {
                case SDL_SCANCODE_F11:
                    state ^= STATE_FULLSCREEN;
                    SDL_SetWindowFullscreen
                    (
                        window,
                        state & STATE_FULLSCREEN ?
                        SDL_WINDOW_FULLSCREEN_DESKTOP : 0
                    );
                    break;
                case SDL_SCANCODE_ESCAPE:
                    state ^= STATE_MOUSE_GRABBED;
                    SDL_SetRelativeMouseMode(state & STATE_MOUSE_GRABBED);
                    break;
                case SDL_SCANCODE_LSHIFT:
                    speed = settings.controls.speed1;
                    break;
                default:
                    break;
                }
                break;
            case SDL_KEYDOWN:
                switch(event.key.keysym.scancode)
                {
                case SDL_SCANCODE_LSHIFT:
                    speed = settings.controls.speed2;
                    break;
                default:
                    break;
                }
                break;
            case SDL_WINDOWEVENT:
                if(event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
                {
                    int w = event.window.data1;
                    int h = event.window.data2;
                    glViewport(0, 0, w, h);
                    mat4x4_perspective(projection_matrix,
                                       settings.video.pfov,
                                       w/(float)h,
                                       settings.video.pnear,
                                       settings.video.pfar);
                    glUniformMatrix4fv(grid_proj_mat_loc, 1, GL_FALSE,
                                       (const float*)projection_matrix);
                }
                break;
            case SDL_MOUSEMOTION:
                if(state & STATE_MOUSE_GRABBED)
                {
                    camera.yaw -= settings.controls.xsensitivity *
                                  event.motion.xrel;
                    camera.pitch -= settings.controls.xsensitivity *
                                    event.motion.yrel;
                }
                break;
            default:
                break;
            }
        }
        Uint32 nticks = SDL_GetTicks();
        float delta = (nticks - ticks)/1000.f;
        ticks = nticks;

        const Uint8* keys = SDL_GetKeyboardState(NULL);
        vec3 movement;
        int i;
        for(i = 0; i < 3; i++) movement[i] = 0.f;
        SDL_bool moved = SDL_FALSE;
        if(keys[SDL_SCANCODE_W] && !keys[SDL_SCANCODE_S])
        {
            vec3_add(movement, movement, camera.direction);
            moved = SDL_TRUE;
        }
        else if(keys[SDL_SCANCODE_S] && !keys[SDL_SCANCODE_W])
        {
            vec3_sub(movement, movement, camera.direction);
            moved = SDL_TRUE;
        }
        if(keys[SDL_SCANCODE_A] && !keys[SDL_SCANCODE_D])
        {
            vec3_sub(movement, movement, camera.right);
            moved = SDL_TRUE;
        }
        else if(keys[SDL_SCANCODE_D] && !keys[SDL_SCANCODE_A])
        {
            vec3_add(movement, movement, camera.right);
            moved = SDL_TRUE;
        }
        if(keys[SDL_SCANCODE_Q] && !keys[SDL_SCANCODE_E])
        {
            vec3_sub(movement, movement, camera.up);
            moved = SDL_TRUE;
        }
        else if(keys[SDL_SCANCODE_E] && !keys[SDL_SCANCODE_Q])
        {
            vec3_add(movement, movement, camera.up);
            moved = SDL_TRUE;
        }

        if(moved)
        {
            vec3_norm(movement, movement);
            vec3_scale(movement, movement, delta * speed);
            vec3_add(camera.node.translation, camera.node.translation,
                     movement);
        }

        UpdateCamera(&camera);

        if(moved)
        {
            vec2 tmp1;
            tmp1[0] = camera.node.position[0];
            tmp1[1] = camera.node.position[2];
            vec2 tmp2;
            tmp2[0] = grid_node.position[0];
            tmp2[1] = grid_node.position[2];
            vec2_sub(tmp1, tmp1, tmp2);
            tmp1[0] = floor(tmp1[0]);
            tmp1[1] = floor(tmp1[1]);
            grid_node.translation[0] += tmp1[0];
            grid_node.translation[2] += tmp1[1];
            UpdateNode(&grid_node);
        }
    }

    glDeleteVertexArrays(1, &grid_vao);
    glDeleteBuffers(1, &grid_vbuf);
    glDeleteBuffers(1, &grid_ibuf);
    glDeleteProgram(program);

    return 0;
}
コード例 #9
0
ファイル: cube.c プロジェクト: hialin/hialin
int main(void)
{
    glfwSetErrorCallback(error_callback);

    if (!glfwInit())
        exit(EXIT_FAILURE);

    GLFWmonitor *monitor = glfwGetPrimaryMonitor();
    const GLFWvidmode *mode = glfwGetVideoMode(monitor);
    printf("monitor mode: %d, %d\n", mode->width, mode->height);

    // if DEBUG {
    //     glfw.WindowHint(glfw.OpenGLDebugContext, gl.TRUE)
    // }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 1);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow *window = glfwCreateWindow(mode->width, mode->height, "Hialin", NULL, NULL);
    if (!window) {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }

    glfwSetKeyCallback(window, key_callback);

    glfwMakeContextCurrent(window);
    glfwSwapInterval(0);

    p_glBindFragDataLocation = (glBindFragDataLocation_t)glfwGetProcAddress("glBindFragDataLocation");
    if (!p_glBindFragDataLocation) {
        printf("\n failed glBindFragDataLocation");
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    p_glGenVertexArrays = (glGenVertexArrays_t)glfwGetProcAddress("glGenVertexArrays");
    if (!p_glGenVertexArrays) {
        printf("\n failed glGenVertexArrays");
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    p_glBindVertexArray = (glBindVertexArray_t)glfwGetProcAddress("glBindVertexArray");
    if (!p_glBindVertexArray) {
        printf("\n failed glBindVertexArray");
        glfwTerminate();
        exit(EXIT_FAILURE);
    }


    GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
    {
        glShaderSource(vsh, 1, &vertex_shader_text, NULL);
        glCompileShader(vsh);
        int result;
        glGetShaderiv(vsh, GL_COMPILE_STATUS, &result );
        if (result == GL_FALSE) {
            int logLength;
            glGetShaderiv(vsh, GL_INFO_LOG_LENGTH, &logLength);
            char log[10*1024] = {0};
            glGetShaderInfoLog(vsh, logLength, NULL, log);
            printf("\nvertex shader compile: %s", log);
            glfwTerminate();
            exit(EXIT_FAILURE);
        }
    }
    glCheck();

    GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
    {
        glShaderSource(fsh, 1, &fragment_shader_text, NULL);
        glCompileShader(fsh);
        int result;
        glGetShaderiv(fsh, GL_COMPILE_STATUS, &result);
        if (result == GL_FALSE) {
            int logLength;
            glGetShaderiv(fsh, GL_INFO_LOG_LENGTH, &logLength);
            char log[10*1024] = {0};
            glGetShaderInfoLog(fsh, logLength, NULL, log);
            printf("\nfragment shader compile: %s", log);
            glfwTerminate();
            exit(EXIT_FAILURE);
        }
    }
    glCheck();

    GLuint program = glCreateProgram();
    {
        glAttachShader(program, vsh);
        glAttachShader(program, fsh);
        glLinkProgram(program);
        int result;
        glGetProgramiv(program, GL_LINK_STATUS, &result);
        if (result == GL_FALSE) {
            int logLength;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
            char log[10*1024] = {0};
            glGetProgramInfoLog(program, logLength, NULL, log);
            printf("\nprogram link: \n%s", log);
            glfwTerminate();
            exit(EXIT_FAILURE);
        }
    }
    glCheck();
    glUseProgram(program);
    glCheck();

    GLint projectionU = glGetUniformLocation(program, "projection");

    mat4x4 camera;
    vec3 eye = {3, 3, 3}, center = {0, 0, 0}, up = {0, 1, 0};
    mat4x4_look_at(camera, eye, center, up);
    GLint cameraU = glGetUniformLocation(program, "camera");
    glUniformMatrix4fv(cameraU, 1, GL_FALSE, (const float*)camera);
    glCheck();

    mat4x4 model;
    mat4x4_identity(model);
    GLint modelU = glGetUniformLocation(program, "model");
    glUniformMatrix4fv(modelU, 1, GL_FALSE, (const float*)model);
    glCheck();

    GLint texU = glGetUniformLocation(program, "tex");
    glUniform1i(texU, 0);
    p_glBindFragDataLocation(program, 0, "outputColor");
    glCheck();

    // Load the texture
    // char *texturePath = "./Resources/code.png"
    // GLuint texture = MakeTexture(0, texturePath);
    GLuint texture = MakeTexture(0);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glCheck();

    // Configure the vertex data
    GLuint vao;
    p_glGenVertexArrays(1, &vao);
    p_glBindVertexArray(vao);
    glCheck();

    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
    glCheck();

    GLuint val = glGetAttribLocation(program, "vert");
    glEnableVertexAttribArray(val);
    glVertexAttribPointer(val, 3, GL_FLOAT, GL_FALSE, 5*4, (const void *)(0*4));
    glCheck();

    GLuint valTC = glGetAttribLocation(program, "vertTexCoord");
    glEnableVertexAttribArray(valTC);
    glVertexAttribPointer(valTC, 2, GL_FLOAT, GL_FALSE, 5*4, (const void *)(3*4));
    glCheck();

    // Configure global settings
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glCheck();

    long time0 = tick();

    float angle = 0.01;

    int width = 0, height = 0;
    int i = 0;
    while (!glfwWindowShouldClose(window))
    {
        int w, h;
        glfwGetFramebufferSize(window, &w, &h);
        if (w != width || h != height) {
            width = w;
            height = h;
            glViewport(0, 0, width, height);
            printf("buffer size: %d %d\n", w, h);
        }
        float ratio = width/(float)height;

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        mat4x4_rotate_Y(model, model, angle);

        mat4x4 projection;
        mat4x4_perspective(projection, 0.785, ratio, 0.1, 10.0); // 45 degrees == 0.785 radians

        glUniformMatrix4fv(projectionU, 1, GL_FALSE, (const float*)projection);
        glUniformMatrix4fv(modelU, 1, GL_FALSE, (const float*)model);

        for (int i = 0; i < 1*1000; i++) {
            glDrawArrays(GL_TRIANGLES, 0, 6*2*3); // 12 triangles
        }

        i++;
        if (i == 100) {
            printf("time for 100 frames: %ld\n", tick()-time0);
        } else if (i == 1000) {
            printf("time for 1000 frames: %ld\n", tick()-time0);
            break;
        }

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();
    exit(EXIT_SUCCESS);
}