# HG changeset patch # User John Tsiombikas # Date 1435530576 -10800 # Node ID 986c0b76513f0c7418eeb7dd9734aba33516f163 # Parent 16a420432aa34ff2368f1ecffe54df331ad6cb0e shadows, not completed diff -r 16a420432aa3 -r 986c0b76513f sdr/shadow-notex.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/shadow-notex.p.glsl Mon Jun 29 01:29:36 2015 +0300 @@ -0,0 +1,29 @@ +/* vi: set ft=glsl */ +uniform sampler2DShadow shadowmap; + +varying vec3 vdir, ldir, normal; +varying vec4 shadow_tc; + +#define KD gl_FrontMaterial.diffuse.rgb +#define KS gl_FrontMaterial.specular.rgb +#define SPOW gl_FrontMaterial.shininess + +void main() +{ + float shadow = shadow2DProj(shadowmap, shadow_tc).x; + + vec3 n = normalize(normal); + vec3 v = normalize(vdir); + vec3 l = normalize(ldir); + vec3 h = normalize(l + v); + + float ndotl = max(dot(n, l), 0.0); + float ndoth = max(dot(n, h), 0.0); + + vec3 diffuse = KD * gl_LightSource[0].diffuse.rgb * ndotl; + vec3 specular = KS * gl_LightSource[0].specular.rgb * pow(ndoth, SPOW); + + vec3 ambient = gl_LightModel.ambient.rgb * KD; + gl_FragColor.rgb = ambient + (diffuse + specular) * shadow; + gl_FragColor.a = gl_FrontMaterial.diffuse.a; +} diff -r 16a420432aa3 -r 986c0b76513f sdr/shadow.p.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/shadow.p.glsl Mon Jun 29 01:29:36 2015 +0300 @@ -0,0 +1,32 @@ +/* vi: set ft=glsl */ +uniform sampler2D tex; +uniform sampler2DShadow shadowmap; + +varying vec3 vdir, ldir, normal; +varying vec4 shadow_tc; + +#define KD gl_FrontMaterial.diffuse.rgb +#define KS gl_FrontMaterial.specular.rgb +#define SPOW gl_FrontMaterial.shininess + +void main() +{ + float shadow = shadow2DProj(shadowmap, shadow_tc).x; + vec4 texel = texture2D(tex, gl_TexCoord[0].st); + + vec3 n = normalize(normal); + vec3 v = normalize(vdir); + vec3 l = normalize(ldir); + vec3 h = normalize(l + v); + + float ndotl = max(dot(n, l), 0.0); + float ndoth = max(dot(n, h), 0.0); + + vec3 albedo = KD * texel.rgb; + vec3 diffuse = albedo * gl_LightSource[0].diffuse.rgb * ndotl; + vec3 specular = KS * gl_LightSource[0].specular.rgb * pow(ndoth, SPOW); + + vec3 ambient = gl_LightModel.ambient.rgb * albedo; + gl_FragColor.rgb = ambient + (diffuse + specular) * shadow; + gl_FragColor.a = gl_FrontMaterial.diffuse.a * texel.a; +} diff -r 16a420432aa3 -r 986c0b76513f sdr/shadow.v.glsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sdr/shadow.v.glsl Mon Jun 29 01:29:36 2015 +0300 @@ -0,0 +1,22 @@ +varying vec3 vdir, ldir, normal; +varying vec4 shadow_tc; + +void main() +{ + gl_Position = ftransform(); + + vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz; + normal = gl_NormalMatrix * gl_Normal; + vdir = -vpos; + ldir = gl_LightSource[0].position.xyz - vpos; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 offmat = mat4(0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0); + mat4 tex_matrix = offmat * gl_TextureMatrix[1]; + + shadow_tc = tex_matrix * gl_Vertex; + shadow_tc = shadow_tc / shadow_tc.w; +} diff -r 16a420432aa3 -r 986c0b76513f src/board.cc --- a/src/board.cc Sun Jun 28 23:04:37 2015 +0300 +++ b/src/board.cc Mon Jun 29 01:29:36 2015 +0300 @@ -21,6 +21,28 @@ #define PIECES_PER_LAYER 5 +static const vec2_t piece_cp[] = { + {0, 0.25}, + {1, 0.25}, // mid0 + {2, 0.5}, + {2.5, 0.5}, // mid1 + {3, 0.5}, + {4, 0.5}, // mid2 + {4, 0}, + {4, -0.5}, // mid3 + {3, -0.5}, + {2.5, -0.5}, // mid4 + {0, -0.5} +}; +static const BezCurve piece_curve = { + sizeof piece_cp / sizeof *piece_cp, + (vec2_t*)piece_cp, + 0.25 * PIECE_RAD +}; + +#define PIECE_HEIGHT (0.25 * PIECE_RAD) + + Piece::Piece() { owner = 0; @@ -138,7 +160,7 @@ int layer = level / PIECES_PER_LAYER; int layer_level = level % PIECES_PER_LAYER; - pos.y = (layer + 1) * 0.25 * PIECE_RAD; + pos.y = (layer + 0.5) * PIECE_HEIGHT; pos.z = (-VSIZE * 0.5 + PIECE_RAD + PIECE_RAD * 2.0 * layer_level); if(top_side) { @@ -168,28 +190,13 @@ } -static const vec2_t piece_cp[] = { - {0, 0.25}, - {1, 0.25}, // mid0 - {2, 0.5}, - {2.5, 0.5}, // mid1 - {3, 0.5}, - {4, 0.5}, // mid2 - {4, 0}, - {4, -0.5}, // mid3 - {3, -0.5}, - {2.5, -0.5}, // mid4 - {0, -0.5} -}; -static const BezCurve piece_curve = { - sizeof piece_cp / sizeof *piece_cp, - (vec2_t*)piece_cp, - 0.25 * PIECE_RAD -}; - - bool Board::generate() { + static const float board_spec = 0.4; + bool use_shadows = opt.shadows && sdr_shadow; + unsigned int board_sdr = use_shadows ? sdr_shadow : sdr_phong; + unsigned int piece_sdr = use_shadows ? sdr_shadow_notex : sdr_phong_notex; + Mesh tmp; Matrix4x4 xform; @@ -208,6 +215,8 @@ obottom->set_mesh(bottom); obottom->xform().set_translation(Vector3(sign * BOARD_OFFSET, 0, 0)); obottom->set_texture(img_field.texture()); + obottom->set_shader(board_sdr); + obottom->mtl.specular = Vector3(board_spec, board_spec, board_spec); obj.push_back(obottom); @@ -248,6 +257,8 @@ osides->set_texture(img_wood.texture()); osides->tex_xform().set_scaling(Vector3(2, 2, 2)); osides->tex_xform().rotate(-Vector3(1, 0, 0.5), M_PI / 4.0); + osides->mtl.specular = Vector3(board_spec, board_spec, board_spec); + osides->set_shader(board_sdr); obj.push_back(osides); } @@ -321,7 +332,7 @@ opiece->mtl.diffuse = Vector3(0.6, 0.6, 0.6); opiece->mtl.specular = Vector3(0.8, 0.8, 0.8); opiece->xform().set_translation(Vector3(0, 0.2, 0)); - opiece->set_shader(sdr_phong_notex); + opiece->set_shader(piece_sdr); //obj.push_back(opiece); piece_obj = opiece; diff -r 16a420432aa3 -r 986c0b76513f src/game.cc --- a/src/game.cc Sun Jun 28 23:04:37 2015 +0300 +++ b/src/game.cc Mon Jun 29 01:29:36 2015 +0300 @@ -1,15 +1,20 @@ #include +#include #include "opengl.h" #include "game.h" #include "board.h" #include "scenery.h" #include "sdr.h" +#include "shadow.h" +#include "opt.h" +static void draw_scene(); static void draw_backdrop(); int win_width, win_height; unsigned long cur_time; unsigned int sdr_phong, sdr_phong_notex; +unsigned int sdr_shadow, sdr_shadow_notex; bool wireframe; static Board board; @@ -48,6 +53,20 @@ if(!(sdr_phong_notex = create_program_load("sdr/phong.v.glsl", "sdr/phong-notex.p.glsl"))) { return false; } + + if(glcaps.fbo) { + init_shadow(512); + + if(!(sdr_shadow = create_program_load("sdr/shadow.v.glsl", "sdr/shadow.p.glsl"))) { + return false; + } + set_uniform_int(sdr_shadow, "tex", 0); + set_uniform_int(sdr_shadow, "shadowmap", 1); + + if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) { + return false; + } + } } if(!board.init()) { @@ -59,6 +78,7 @@ return false; } + assert(glGetError() == GL_NO_ERROR); return true; } @@ -66,6 +86,7 @@ { board.destroy(); destroy_scenery(); + destroy_shadow(); } void game_update(unsigned long time_msec) @@ -86,15 +107,44 @@ float ldir[] = {-10, 20, 10, 1}; glLightfv(GL_LIGHT0, GL_POSITION, ldir); - draw_backdrop(); - draw_scenery(); - board.draw(); + if(opt.shadows && sdr_shadow) { + printf("shadow pass\n"); + + begin_shadow_pass(Vector3(-10, 20, 10), Vector3(0, 0, 0), 25); + draw_scene(); + end_shadow_pass(); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, get_shadow_tex()); + + glMatrixMode(GL_TEXTURE); + Matrix4x4 shadow_matrix = get_shadow_matrix(); + glLoadMatrixf(shadow_matrix[0]); + + glActiveTexture(GL_TEXTURE0); + glMatrixMode(GL_MODELVIEW); + + draw_scene(); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + } else { + draw_scene(); + } if(dbg_busyloop) { redisplay(); } } +static void draw_scene() +{ + draw_backdrop(); + draw_scenery(); + board.draw(); +} + static void draw_backdrop() { glPushAttrib(GL_ENABLE_BIT); @@ -150,6 +200,11 @@ dbg_busyloop = !dbg_busyloop; redisplay(); break; + + case 's': + opt.shadows = !opt.shadows; + redisplay(); + break; } } } diff -r 16a420432aa3 -r 986c0b76513f src/game.h --- a/src/game.h Sun Jun 28 23:04:37 2015 +0300 +++ b/src/game.h Mon Jun 29 01:29:36 2015 +0300 @@ -3,6 +3,7 @@ extern int win_width, win_height; extern unsigned int sdr_phong, sdr_phong_notex; +extern unsigned int sdr_shadow, sdr_shadow_notex; extern unsigned long cur_time; extern bool wireframe; diff -r 16a420432aa3 -r 986c0b76513f src/opengl.c --- a/src/opengl.c Sun Jun 28 23:04:37 2015 +0300 +++ b/src/opengl.c Mon Jun 29 01:29:36 2015 +0300 @@ -9,6 +9,7 @@ glcaps.shaders = GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader; glcaps.fsaa = GLEW_ARB_multisample; glcaps.sep_spec = GLEW_EXT_separate_specular_color; + glcaps.fbo = GLEW_ARB_framebuffer_object; return 0; } diff -r 16a420432aa3 -r 986c0b76513f src/opengl.h --- a/src/opengl.h Sun Jun 28 23:04:37 2015 +0300 +++ b/src/opengl.h Mon Jun 29 01:29:36 2015 +0300 @@ -7,6 +7,7 @@ int shaders; int fsaa; int sep_spec; + int fbo; }; extern struct GLCaps glcaps; diff -r 16a420432aa3 -r 986c0b76513f src/opt.cc --- a/src/opt.cc Sun Jun 28 23:04:37 2015 +0300 +++ b/src/opt.cc Mon Jun 29 01:29:36 2015 +0300 @@ -10,6 +10,8 @@ opt.xres = 1280; opt.yres = 800; opt.fullscreen = false; + opt.shadows = false; opt.reflections = true; + opt.def_username = opt.saved_passwd = 0; opt.piece_color[0] = v3_cons(0.3, 0.35, 0.6); diff -r 16a420432aa3 -r 986c0b76513f src/opt.h --- a/src/opt.h Sun Jun 28 23:04:37 2015 +0300 +++ b/src/opt.h Mon Jun 29 01:29:36 2015 +0300 @@ -6,6 +6,7 @@ struct Options { int xres, yres; bool fullscreen; + bool shadows, reflections; char *def_username, *saved_passwd; diff -r 16a420432aa3 -r 986c0b76513f src/scenery.cc --- a/src/scenery.cc Sun Jun 28 23:04:37 2015 +0300 +++ b/src/scenery.cc Mon Jun 29 01:29:36 2015 +0300 @@ -8,6 +8,7 @@ #include "revol.h" #include "image.h" #include "sdr.h" +#include "opt.h" static bool gen_textures(); @@ -33,6 +34,7 @@ bool init_scenery() { + unsigned int sdr = opt.shadows && sdr_shadow ? sdr_shadow : sdr_phong; if(!gen_textures()) { return false; } @@ -56,7 +58,7 @@ otable->mtl.specular = Vector3(0.7, 0.7, 0.7); otable->xform().set_translation(Vector3(0, -0.025, 0)); otable->set_texture(img_marble.texture()); - otable->set_shader(sdr_phong); + otable->set_shader(sdr); obj.push_back(otable); diff -r 16a420432aa3 -r 986c0b76513f src/shadow.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shadow.cc Mon Jun 29 01:29:36 2015 +0300 @@ -0,0 +1,108 @@ +#include +#include "opengl.h" +#include "shadow.h" +#include "vmath/vmath.h" + +static int tex_sz, prev_vp[4]; +static unsigned int fbo, depth_tex, rb_color; +static Matrix4x4 shadow_mat; + +bool init_shadow(int sz) +{ + if(!glcaps.fbo) { + return true; + } + + tex_sz = sz; + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glGenTextures(1, &depth_tex); + glBindTexture(GL_TEXTURE_2D, depth_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex_sz, tex_sz, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_tex, 0); + + assert(glGetError() == GL_NO_ERROR); + + glDrawBuffer(GL_FALSE); + glReadBuffer(GL_FALSE); + + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + fprintf(stderr, "incomplete framebuffer\n"); + return false; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDrawBuffer(GL_BACK); + glReadBuffer(GL_BACK); + assert(glGetError() == GL_NO_ERROR); + + return true; +} + +void destroy_shadow() +{ + glDeleteTextures(1, &depth_tex); + glDeleteRenderbuffers(1, &rb_color); + glDeleteFramebuffers(1, &fbo); +} + +void begin_shadow_pass(const Vector3 &lpos, const Vector3 <arg, float lfov) +{ + Matrix4x4 viewmat, projmat; + + glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); + glDisable(GL_LIGHTING); + glColorMask(0, 0, 0, 0); + glDepthMask(1); + + projmat.set_perspective(DEG_TO_RAD(lfov) * 2.0, 1.0, 0.5, 500.0); + viewmat.set_lookat(lpos, ltarg, Vector3(0, 1, 0)); + shadow_mat = viewmat * projmat; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadTransposeMatrixf(projmat[0]); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadTransposeMatrixf(viewmat[0]); + + glGetIntegerv(GL_VIEWPORT, prev_vp); + glViewport(0, 0, tex_sz, tex_sz); + + glCullFace(GL_FRONT); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); +} + + +void end_shadow_pass() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glCullFace(GL_BACK); + + glViewport(prev_vp[0], prev_vp[1], prev_vp[2], prev_vp[3]); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glPopAttrib(); +} + +Matrix4x4 get_shadow_matrix() +{ + return shadow_mat; +} + +unsigned int get_shadow_tex() +{ + return depth_tex; +} diff -r 16a420432aa3 -r 986c0b76513f src/shadow.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shadow.h Mon Jun 29 01:29:36 2015 +0300 @@ -0,0 +1,15 @@ +#ifndef SHADOW_H_ +#define SHADOW_H_ + +#include "vmath/vmath.h" + +bool init_shadow(int sz); +void destroy_shadow(); + +void begin_shadow_pass(const Vector3 &lpos, const Vector3 <arg, float lfov); +void end_shadow_pass(); + +Matrix4x4 get_shadow_matrix(); +unsigned int get_shadow_tex(); + +#endif // SHADOW_H_