nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "opengl.h" nuclear@0: #include "game.h" nuclear@7: #include "camera.h" nuclear@10: #include "sdr.h" nuclear@7: nuclear@8: static void draw_quad(float hsz, float vsz); nuclear@0: nuclear@0: static int win_width, win_height; nuclear@9: static float win_aspect; nuclear@9: static int video_width, video_height; nuclear@9: static float video_aspect; nuclear@10: static unsigned int sdrprog; nuclear@10: static int aloc_vertex, aloc_texcoord, uloc_texmat, uloc_wmat, uloc_vmat, uloc_pmat; nuclear@10: nuclear@10: static const char *vsdr_source = nuclear@10: "attribute vec4 attr_pos, attr_tex;\n" nuclear@10: "uniform mat4 world_matrix, proj_matrix, tex_matrix;\n" nuclear@10: "varying vec4 tex_coords;\n" nuclear@10: "void main()\n" nuclear@10: "{\n" nuclear@10: "\tmat4 mvp = proj_matrix * world_matrix;\n" nuclear@10: "\tgl_Position = mvp * attr_pos;\n" nuclear@10: "\ttex_coords = tex_matrix * attr_tex;\n" nuclear@10: "}\n"; nuclear@10: nuclear@10: static const char *psdr_source = nuclear@10: "#extension GL_OES_EGL_image_external : require\n" nuclear@10: "precision lowp float;\n" nuclear@10: "uniform samplerExternalOES tex;\n" nuclear@10: "varying vec4 tex_coords;\n" nuclear@10: "void main()\n" nuclear@10: "{\n" nuclear@10: "\tvec4 texel = texture2D(tex, tex_coords.xy);\n" nuclear@10: "\tgl_FragColor = vec4(texel.xyz, 1.0);\n" nuclear@10: "}\n"; nuclear@0: nuclear@0: nuclear@0: int game_init(void) nuclear@0: { nuclear@10: unsigned int vsdr, psdr; nuclear@10: nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: nuclear@0: glClearColor(0.4, 0.4, 0.4, 1); nuclear@8: nuclear@10: if(!(vsdr = create_vertex_shader(vsdr_source))) nuclear@10: return -1; nuclear@10: if(!(psdr = create_pixel_shader(psdr_source))) nuclear@10: return -1; nuclear@10: if(!(sdrprog = create_program_link(vsdr, psdr))) { nuclear@10: fprintf(stderr, "failed to create shader program\n"); nuclear@10: return -1; nuclear@10: } nuclear@10: glUseProgram(sdrprog); nuclear@10: aloc_vertex = glGetAttribLocation(sdrprog, "attr_pos"); nuclear@10: aloc_texcoord = glGetAttribLocation(sdrprog, "attr_tex"); nuclear@10: uloc_texmat = glGetUniformLocation(sdrprog, "tex_matrix"); nuclear@10: uloc_wmat = glGetUniformLocation(sdrprog, "world_matrix"); nuclear@10: uloc_vmat = glGetUniformLocation(sdrprog, "view_matrix"); nuclear@10: uloc_pmat = glGetUniformLocation(sdrprog, "proj_matrix"); nuclear@10: nuclear@8: cam_start_video(); nuclear@9: cam_video_size(&video_width, &video_height); nuclear@9: if(video_height) { nuclear@9: video_aspect = (float)video_width / (float)video_height; nuclear@9: } else { nuclear@9: video_aspect = 1.0; nuclear@9: } nuclear@9: nuclear@9: printf("started video %dx%d (aspect: %g)\n", video_width, video_height, video_aspect); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void game_shutdown(void) nuclear@0: { nuclear@8: cam_shutdown(); nuclear@10: free_program(sdrprog); nuclear@0: } nuclear@0: nuclear@0: void game_display(unsigned long msec) nuclear@0: { nuclear@9: unsigned int tex; nuclear@9: const float *tex_matrix; nuclear@9: float xscale, yscale; nuclear@9: nuclear@8: cam_update(); nuclear@9: tex = cam_texture(); nuclear@9: tex_matrix = cam_texture_matrix(); nuclear@7: nuclear@4: //float tsec = (float)msec / 1000.0f; nuclear@0: nuclear@4: //glClearColor(sin(tsec * 10.0), cos(tsec * 10.0), -sin(tsec * 10.0), 1.0); nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@10: glUseProgram(sdrprog); nuclear@10: glUniformMatrix4fv(uloc_texmat, 1, 0, tex_matrix); nuclear@10: glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); nuclear@7: nuclear@9: if(video_aspect > win_aspect) { nuclear@9: xscale = 1.0; nuclear@9: yscale = 1.0 / video_aspect; nuclear@9: } else { nuclear@9: xscale = video_aspect; nuclear@9: yscale = 1.0; nuclear@9: } nuclear@9: draw_quad(xscale, yscale); nuclear@7: } nuclear@7: nuclear@8: static void draw_quad(float hsz, float vsz) nuclear@7: { nuclear@7: static const float varr[] = {-1, -1, 1, -1, 1, 1, -1, 1}; nuclear@9: static const float tcarr[] = {0, 0, 1, 0, 1, 1, 0, 1}; nuclear@10: float xform[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; nuclear@7: nuclear@10: if(aloc_vertex == -1) { nuclear@10: return; nuclear@10: } nuclear@7: nuclear@10: xform[0] = hsz; nuclear@10: xform[5] = vsz; nuclear@10: glUniformMatrix4fv(uloc_wmat, 1, 0, xform); nuclear@7: nuclear@10: glEnableVertexAttribArray(aloc_vertex); nuclear@10: glVertexAttribPointer(aloc_vertex, 2, GL_FLOAT, 0, 0, varr); nuclear@10: if(aloc_texcoord) { nuclear@10: glEnableVertexAttribArray(aloc_texcoord); nuclear@10: glVertexAttribPointer(aloc_texcoord, 2, GL_FLOAT, 0, 0, tcarr); nuclear@10: } nuclear@7: nuclear@8: glDrawArrays(GL_TRIANGLE_FAN, 0, 4); nuclear@7: nuclear@10: glDisableVertexAttribArray(aloc_vertex); nuclear@10: if(aloc_texcoord) { nuclear@10: glDisableVertexAttribArray(aloc_texcoord); nuclear@10: } nuclear@0: } nuclear@0: nuclear@0: void game_reshape(int x, int y) nuclear@0: { nuclear@0: win_width = x; nuclear@0: win_height = y; nuclear@9: win_aspect = y ? (float)x / (float)y : 1.0; nuclear@0: glViewport(0, 0, x, y); nuclear@0: nuclear@10: /*glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@10: glScalef((float)win_height / (float)win_width, 1.0, 1.0);*/ nuclear@0: } nuclear@0: nuclear@0: void game_keyboard(int key, int pressed) nuclear@0: { nuclear@0: if(!pressed) return; nuclear@0: nuclear@0: switch(key) { nuclear@0: case 27: nuclear@0: exit(0); nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: #define MAX_TOUCH_IDS 16 nuclear@0: static struct { nuclear@0: int bnstate[8]; nuclear@0: int prev_x, prev_y; nuclear@0: } mstate[MAX_TOUCH_IDS]; nuclear@0: nuclear@0: void game_mouse_button(int id, int bn, int pressed, int x, int y) nuclear@0: { nuclear@0: if(id >= MAX_TOUCH_IDS) return; nuclear@0: nuclear@0: mstate[id].prev_x = x; nuclear@0: mstate[id].prev_y = y; nuclear@0: mstate[id].bnstate[bn] = pressed; nuclear@0: } nuclear@0: nuclear@0: void game_mouse_motion(int id, int x, int y) nuclear@0: { nuclear@0: /* nuclear@0: int dx, dy, cx, cy; nuclear@0: nuclear@0: if(id >= MAX_TOUCH_IDS) return; nuclear@0: nuclear@0: cx = win_width / 2; nuclear@0: cy = win_height / 2; nuclear@0: nuclear@0: dx = x - mstate[id].prev_x; nuclear@0: dy = y - mstate[id].prev_y; nuclear@0: mstate[id].prev_x = x; nuclear@0: mstate[id].prev_y = y; nuclear@0: nuclear@0: if(!dx && !dy) return; nuclear@0: nuclear@0: if(mouselook || mstate[id].bnstate[0]) { nuclear@0: player_turn(&player, dx * 0.5, dy * 0.5); nuclear@0: } nuclear@0: if(mstate[id].bnstate[2]) { nuclear@0: dbg_cam_dist += 0.1 * dy; nuclear@0: if(dbg_cam_dist < 0.0) dbg_cam_dist = 0.0; nuclear@0: } nuclear@0: nuclear@0: if(mouselook) { nuclear@0: warping_mouse = 1; nuclear@0: set_mouse_pos(cx, cy); nuclear@0: mstate[id].prev_x = cx; nuclear@0: mstate[id].prev_y = cy; nuclear@0: } nuclear@0: */ nuclear@0: } nuclear@0: