nuclear@0: #include nuclear@18: #include nuclear@16: #include "opengl.h" nuclear@0: #include "game.h" nuclear@1: #include "board.h" nuclear@14: #include "scenery.h" nuclear@15: #include "sdr.h" nuclear@18: #include "shadow.h" nuclear@18: #include "opt.h" nuclear@0: nuclear@18: static void draw_scene(); nuclear@0: static void draw_backdrop(); nuclear@0: nuclear@0: int win_width, win_height; nuclear@17: unsigned long cur_time; nuclear@15: unsigned int sdr_phong, sdr_phong_notex; nuclear@18: unsigned int sdr_shadow, sdr_shadow_notex; nuclear@19: unsigned int sdr_unlit; nuclear@14: bool wireframe; nuclear@0: nuclear@1: static Board board; nuclear@1: nuclear@8: static float cam_theta, cam_phi = 45, cam_dist = 3; nuclear@0: static bool bnstate[8]; nuclear@0: static int prev_x, prev_y; nuclear@0: nuclear@19: static bool dbg_busyloop, dbg_show_shadowmap; nuclear@0: nuclear@0: bool game_init() nuclear@0: { nuclear@16: if(init_opengl() == -1) { nuclear@16: return false; nuclear@16: } nuclear@16: nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_CULL_FACE); nuclear@11: glEnable(GL_NORMALIZE); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_LIGHT0); nuclear@0: nuclear@19: float amb[] = {0.3, 0.3, 0.3, 1.0}; nuclear@19: glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); nuclear@19: nuclear@16: if(glcaps.sep_spec) { nuclear@16: glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); nuclear@16: } nuclear@16: nuclear@16: if(glcaps.fsaa) { nuclear@5: glEnable(GL_MULTISAMPLE); nuclear@5: } nuclear@5: nuclear@16: if(glcaps.shaders) { nuclear@16: Mesh::use_custom_sdr_attr = false; nuclear@16: if(!(sdr_phong = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl"))) { nuclear@16: return false; nuclear@16: } nuclear@16: if(!(sdr_phong_notex = create_program_load("sdr/phong.v.glsl", "sdr/phong-notex.p.glsl"))) { nuclear@16: return false; nuclear@16: } nuclear@18: nuclear@18: if(glcaps.fbo) { nuclear@19: init_shadow(2048); nuclear@18: nuclear@18: if(!(sdr_shadow = create_program_load("sdr/shadow.v.glsl", "sdr/shadow.p.glsl"))) { nuclear@18: return false; nuclear@18: } nuclear@18: set_uniform_int(sdr_shadow, "tex", 0); nuclear@18: set_uniform_int(sdr_shadow, "shadowmap", 1); nuclear@18: nuclear@18: if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) { nuclear@18: return false; nuclear@18: } nuclear@19: set_uniform_int(sdr_shadow_notex, "shadowmap", 1); nuclear@18: } nuclear@15: } nuclear@15: nuclear@1: if(!board.init()) { nuclear@1: return false; nuclear@1: } nuclear@17: board.setup(); nuclear@1: nuclear@14: if(!init_scenery()) { nuclear@14: return false; nuclear@14: } nuclear@14: nuclear@18: assert(glGetError() == GL_NO_ERROR); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: void game_cleanup() nuclear@0: { nuclear@1: board.destroy(); nuclear@14: destroy_scenery(); nuclear@18: destroy_shadow(); nuclear@0: } nuclear@0: nuclear@0: void game_update(unsigned long time_msec) nuclear@0: { nuclear@17: cur_time = time_msec; nuclear@0: } nuclear@0: nuclear@0: void game_display() nuclear@0: { nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@20: glTranslatef(0, 0.1, -cam_dist); nuclear@0: glRotatef(cam_phi, 1, 0, 0); nuclear@0: glRotatef(cam_theta, 0, 1, 0); nuclear@0: nuclear@19: float lpos[] = {-10, 20, 10, 1}; nuclear@19: glLightfv(GL_LIGHT0, GL_POSITION, lpos); nuclear@6: nuclear@18: if(opt.shadows && sdr_shadow) { nuclear@19: begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 4.5); nuclear@18: draw_scene(); nuclear@18: end_shadow_pass(); nuclear@18: nuclear@18: glActiveTexture(GL_TEXTURE1); nuclear@18: glBindTexture(GL_TEXTURE_2D, get_shadow_tex()); nuclear@18: nuclear@18: glMatrixMode(GL_TEXTURE); nuclear@18: Matrix4x4 shadow_matrix = get_shadow_matrix(); nuclear@19: glLoadTransposeMatrixf(shadow_matrix[0]); nuclear@18: nuclear@18: glActiveTexture(GL_TEXTURE0); nuclear@18: glMatrixMode(GL_MODELVIEW); nuclear@18: nuclear@18: draw_scene(); nuclear@18: nuclear@18: glActiveTexture(GL_TEXTURE1); nuclear@18: glBindTexture(GL_TEXTURE_2D, 0); nuclear@18: glActiveTexture(GL_TEXTURE0); nuclear@19: glBindTexture(GL_TEXTURE_2D, 0); nuclear@18: } else { nuclear@18: draw_scene(); nuclear@18: } nuclear@15: nuclear@19: if(dbg_show_shadowmap) { nuclear@19: glMatrixMode(GL_PROJECTION); nuclear@19: glPushMatrix(); nuclear@19: glLoadIdentity(); nuclear@19: glMatrixMode(GL_MODELVIEW); nuclear@19: glPushMatrix(); nuclear@19: glLoadIdentity(); nuclear@19: glMatrixMode(GL_TEXTURE); nuclear@19: glLoadIdentity(); nuclear@19: nuclear@19: glPushAttrib(GL_ENABLE_BIT); nuclear@19: glUseProgram(0); nuclear@19: glBindTexture(GL_TEXTURE_2D, get_shadow_tex()); nuclear@19: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); nuclear@19: glEnable(GL_TEXTURE_2D); nuclear@19: glDisable(GL_DEPTH_TEST); nuclear@19: glDisable(GL_LIGHTING); nuclear@19: glDisable(GL_BLEND); nuclear@19: nuclear@19: glBegin(GL_QUADS); nuclear@19: glColor4f(1, 1, 1, 1); nuclear@19: glTexCoord2f(0, 0); glVertex2f(-1, -1); nuclear@19: glTexCoord2f(1, 0); glVertex2f(1, -1); nuclear@19: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@19: glTexCoord2f(0, 1); glVertex2f(-1, 1); nuclear@19: glEnd(); nuclear@19: nuclear@19: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); nuclear@19: glBindTexture(GL_TEXTURE_2D, 0); nuclear@19: nuclear@19: glPopAttrib(); nuclear@19: nuclear@19: glMatrixMode(GL_PROJECTION); nuclear@19: glPopMatrix(); nuclear@19: glMatrixMode(GL_MODELVIEW); nuclear@19: glPopMatrix(); nuclear@19: } nuclear@19: nuclear@15: if(dbg_busyloop) { nuclear@15: redisplay(); nuclear@15: } nuclear@0: } nuclear@0: nuclear@18: static void draw_scene() nuclear@18: { nuclear@18: draw_backdrop(); nuclear@18: draw_scenery(); nuclear@18: board.draw(); nuclear@18: } nuclear@18: nuclear@0: static void draw_backdrop() nuclear@0: { nuclear@0: glPushAttrib(GL_ENABLE_BIT); nuclear@0: glDisable(GL_LIGHTING); nuclear@0: glDisable(GL_DEPTH_TEST); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glPushMatrix(); nuclear@0: glLoadIdentity(); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glPushMatrix(); nuclear@0: glLoadIdentity(); nuclear@0: nuclear@0: glBegin(GL_QUADS); nuclear@0: glColor3f(0.9, 0.8, 0.6); nuclear@0: glVertex2f(-1, -1); nuclear@0: glVertex2f(1, -1); nuclear@0: glColor3f(0.4, 0.5, 0.8); nuclear@0: glVertex2f(1, 1); nuclear@0: glVertex2f(-1, 1); nuclear@0: glEnd(); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glPopMatrix(); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glPopMatrix(); nuclear@0: nuclear@0: glPopAttrib(); nuclear@0: } nuclear@0: nuclear@0: void game_reshape(int x, int y) nuclear@0: { nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@5: gluPerspective(45, (float)x / (float)y, 0.2, 200.0); nuclear@0: nuclear@0: glViewport(0, 0, x, y); nuclear@0: } nuclear@0: nuclear@0: void game_keyboard(int bn, bool press) nuclear@0: { nuclear@0: if(press) { nuclear@0: switch(bn) { nuclear@0: case 27: nuclear@0: quit(); nuclear@14: nuclear@14: case 'w': nuclear@14: wireframe = !wireframe; nuclear@14: redisplay(); nuclear@14: break; nuclear@15: nuclear@15: case 'd': nuclear@15: dbg_busyloop = !dbg_busyloop; nuclear@15: redisplay(); nuclear@15: break; nuclear@18: nuclear@19: case 'D': nuclear@19: dbg_show_shadowmap = !dbg_show_shadowmap; nuclear@19: redisplay(); nuclear@19: break; nuclear@19: nuclear@18: case 's': nuclear@18: opt.shadows = !opt.shadows; nuclear@18: redisplay(); nuclear@18: break; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void game_mbutton(int bn, bool press, int x, int y) nuclear@0: { nuclear@0: bnstate[bn] = press; nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: } nuclear@0: nuclear@0: void game_mmotion(int x, int y) nuclear@0: { nuclear@0: int dx = x - prev_x; nuclear@0: int dy = y - prev_y; nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: nuclear@0: if(bnstate[0]) { nuclear@0: cam_theta += dx * 0.5; nuclear@0: cam_phi += dy * 0.5; nuclear@0: nuclear@0: if(cam_phi < -90) cam_phi = -90; nuclear@0: if(cam_phi > 90) cam_phi = 90; nuclear@0: nuclear@0: redisplay(); nuclear@0: } nuclear@0: if(bnstate[2]) { nuclear@0: cam_dist += dy * 0.1; nuclear@0: if(cam_dist < 0.0) cam_dist = 0.0; nuclear@0: nuclear@0: redisplay(); nuclear@0: } nuclear@0: }