nuclear@0: #include nuclear@0: #include nuclear@0: #include "opengl.h" nuclear@0: #include "game.h" nuclear@0: #include "sdr.h" nuclear@0: #include "shader.h" nuclear@0: #include "shadow.h" nuclear@0: #include "opt.h" nuclear@0: nuclear@2: #include "room.h" nuclear@2: nuclear@0: static void draw_scene(); nuclear@0: nuclear@0: int win_width, win_height; nuclear@0: unsigned long cur_time; nuclear@0: bool dbg_wireframe; nuclear@0: int dbg_int; nuclear@0: nuclear@0: unsigned int sdr_shadow, sdr_shadow_notex; nuclear@0: nuclear@0: static float cam_theta, cam_phi = 25, cam_dist = 8; nuclear@0: static bool bnstate[8]; nuclear@0: static int prev_x, prev_y; nuclear@0: nuclear@0: static unsigned int modkeys; nuclear@0: nuclear@0: nuclear@0: bool game_init() nuclear@0: { nuclear@0: if(init_opengl() == -1) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: glEnable(GL_NORMALIZE); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_LIGHT0); nuclear@0: nuclear@2: float amb[] = {0.1, 0.1, 0.1, 1.0}; nuclear@0: glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); nuclear@0: nuclear@0: if(glcaps.sep_spec) { nuclear@0: glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); nuclear@0: } nuclear@0: glEnable(GL_MULTISAMPLE); nuclear@0: nuclear@0: if(!init_shadow(4096)) { nuclear@0: fprintf(stderr, "failed to initialize shadowmaps\n"); nuclear@0: return false; nuclear@0: } nuclear@0: if(!(sdr_shadow = create_program_load("sdr/shadow.v.glsl", "sdr/shadow.p.glsl"))) { nuclear@0: return false; nuclear@0: } nuclear@0: set_uniform_int(sdr_shadow, "tex", 0); nuclear@0: set_uniform_int(sdr_shadow, "shadowmap", 1); nuclear@0: nuclear@0: if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) { nuclear@0: return false; nuclear@0: } nuclear@0: set_uniform_int(sdr_shadow_notex, "shadowmap", 1); nuclear@0: nuclear@2: if(!init_room()) { nuclear@2: return false; nuclear@2: } nuclear@0: nuclear@0: assert(glGetError() == GL_NO_ERROR); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: void game_cleanup() nuclear@0: { nuclear@2: cleanup_room(); nuclear@0: } nuclear@0: nuclear@0: void game_update(unsigned long time_msec) nuclear@0: { nuclear@0: 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@0: 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@2: float lpos[] = {-0, 0, 0, 1}; nuclear@0: glLightfv(GL_LIGHT0, GL_POSITION, lpos); nuclear@0: nuclear@2: opt.shadows = false; nuclear@0: if(opt.shadows && sdr_shadow) { nuclear@0: begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 5); nuclear@0: draw_scene(); nuclear@0: end_shadow_pass(); nuclear@0: nuclear@0: glActiveTexture(GL_TEXTURE1); nuclear@0: glBindTexture(GL_TEXTURE_2D, get_shadow_tex()); nuclear@0: nuclear@0: glMatrixMode(GL_TEXTURE); nuclear@0: Matrix4x4 shadow_matrix = get_shadow_matrix(); nuclear@0: glLoadTransposeMatrixf(shadow_matrix[0]); nuclear@0: nuclear@0: glActiveTexture(GL_TEXTURE0); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: nuclear@2: override_shader(sdr_shadow_notex); nuclear@0: nuclear@0: draw_scene(); nuclear@0: nuclear@0: glActiveTexture(GL_TEXTURE1); nuclear@0: glBindTexture(GL_TEXTURE_2D, 0); nuclear@0: glActiveTexture(GL_TEXTURE0); nuclear@0: glBindTexture(GL_TEXTURE_2D, 0); nuclear@0: } else { nuclear@2: override_shader(sdr_shadow_notex); nuclear@0: draw_scene(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void glmaterial(float r, float g, float b, float spec, float shin) nuclear@0: { nuclear@0: float color[] = {r, g, b, 1}; nuclear@0: float scolor[] = {spec, spec, spec, 1}; nuclear@0: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); nuclear@0: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scolor); nuclear@0: glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin); nuclear@0: } nuclear@0: nuclear@0: static void draw_scene() nuclear@0: { nuclear@2: draw_room(); nuclear@2: nuclear@0: glPushMatrix(); nuclear@2: glTranslatef(0, 0.75, 0); nuclear@0: nuclear@0: glmaterial(0.2, 0.3, 1.0, 0.8, 60.0); nuclear@0: draw_teapot(); nuclear@2: nuclear@2: glPopMatrix(); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void game_reshape(int x, int y) nuclear@0: { nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: 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@0: nuclear@0: case 'w': nuclear@0: dbg_wireframe = !dbg_wireframe; nuclear@0: redisplay(); nuclear@0: break; nuclear@0: nuclear@0: case 's': nuclear@0: opt.shadows = !opt.shadows; nuclear@0: redisplay(); nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void game_modifier_key(int key, bool press) nuclear@0: { nuclear@0: if(press) { nuclear@0: modkeys |= (1 << key); nuclear@0: } else { nuclear@0: modkeys &= ~(1 << key); 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: if(modkeys) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: if(bn == 0) { nuclear@0: } 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(modkeys) { 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: 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: } nuclear@0: }