diff --git a/engine/include/GearBox/Math.h b/engine/include/GearBox/Math.h index 8c6af6d..ef51ea0 100644 --- a/engine/include/GearBox/Math.h +++ b/engine/include/GearBox/Math.h @@ -16,6 +16,7 @@ GBDECL void GBMathSubtract3(GBVector3 r, GBVector3 v0, GBVector3 v1); GBDECL void GBMathAdd3(GBVector3 r, GBVector3 v0, GBVector3 v1); GBDECL void GBMathNormal3x3(GBVector3 r, GBVector3 v0, GBVector3 v1, GBVector3 v2); GBDECL void GBMathNormal3x4(GBVector3 r, GBVector3 v0, GBVector3 v1, GBVector3 v2, GBVector3 v3); +GBDECL void GBMathInvert4x4(GBMatrix4x4 out, GBMatrix4x4 in); GBDECL double GBMathCot(double x); #ifdef __cplusplus diff --git a/engine/include/GearBox/TypeDefs.h b/engine/include/GearBox/TypeDefs.h index d91000d..7f8d210 100644 --- a/engine/include/GearBox/TypeDefs.h +++ b/engine/include/GearBox/TypeDefs.h @@ -57,6 +57,7 @@ typedef void* GBGL; #endif typedef double GBVector3[3]; typedef double GBVector4[4]; +typedef double GBMatrix4x4[16]; typedef void (*GBGLSwapBufferCallback)(void); typedef void (*GBReadyCallback)(int width, int height); @@ -78,6 +79,7 @@ struct _GBGL { GLuint shadow_texture; GLuint shadow_shader; GLdouble shadow_modelview[16]; + GLdouble shadow_projection[16]; GLdouble shadow_old_projection[16]; GLdouble shadow_old_modelview[16]; }; diff --git a/engine/resource/shader/shadow.fs b/engine/resource/shader/shadow.fs index 215c7fe..6d3a3d8 100644 --- a/engine/resource/shader/shadow.fs +++ b/engine/resource/shader/shadow.fs @@ -1,20 +1,52 @@ #version 110 -uniform sampler2DShadow depth_texture; -varying vec4 shadow; -varying vec4 color; -uniform float solid_color; +varying vec4 vPos; +varying vec3 vNrm; +varying vec4 vShadowCoord; + +uniform sampler2D depth_texture; uniform sampler2D current_texture; -void main (void){ - vec4 c; +vec4 PhongShading(void) +{ + vec3 N = normalize(vNrm); + vec3 L = normalize(gl_LightSource[0].position.xyz-vPos.xyz); - if(solid_color > 0.5){ - c = color; - }else{ - c = texture2D(current_texture, gl_TexCoord[0].st); - } - c = color; + vec4 ambient = gl_FrontLightProduct[0].ambient; - gl_FragColor = (shadow + (gl_Color - shadow) * shadow2DProj(depth_texture, gl_TexCoord[1])) * c; + float dcoef = max(dot(L, N), 0.0); + vec4 diffuse = gl_FrontLightProduct[0].diffuse*dcoef; + + vec4 specular = vec4(0.0); + if(dcoef > 0.0){ + vec3 V = normalize(-vPos.xyz); + + vec3 R = reflect(-L, N); + float specularLight = pow(max(dot(R, V), 0.0), gl_FrontMaterial.shininess); + + specular = gl_FrontLightProduct[0].specular*specularLight; + } + return ambient+diffuse+specular; +} + +float ShadowCoef(void){ + vec4 shadow_coord = vShadowCoord / vShadowCoord.w; + float view = shadow_coord.z; + float light = texture2D(depth_texture, shadow_coord.xy).z; + float shadow_coef = 1.0; + + if(vShadowCoord.w > 0.0){ + shadow_coef = light < view ? 0.0 : 1.0; + } + + return shadow_coef; +} + +void main(void){ + vec4 c = gl_Color; + vec4 ambient = gl_LightSource[0].ambient; + float shadow_coef = ShadowCoef(); + + gl_FragColor = ambient * shadow_coef * c + (1.0 - ambient) * c; + gl_FragColor.a = 1.0; } diff --git a/engine/resource/shader/shadow.vs b/engine/resource/shader/shadow.vs index c1beaaf..ffeafdb 100644 --- a/engine/resource/shader/shadow.vs +++ b/engine/resource/shader/shadow.vs @@ -1,28 +1,15 @@ #version 110 -varying vec4 shadow; -varying vec4 color; +varying vec4 vPos; +varying vec3 vNrm; +varying vec4 vShadowCoord; void main(void){ - vec3 position = vec3(gl_ModelViewMatrix * gl_Vertex); - vec3 normal = normalize(gl_NormalMatrix * gl_Normal); - vec3 light = normalize(gl_LightSource[0].position.xyz - position); - float diffuse = dot(light, normal); + vPos = gl_ModelViewMatrix * gl_Vertex; + vNrm = normalize(gl_NormalMatrix * gl_Normal); + vShadowCoord = gl_TextureMatrix[7] * gl_ModelViewMatrix * gl_Vertex; - color = gl_Color; - - gl_FrontColor = gl_LightSource[0].ambient; - shadow = gl_FrontColor; - if (diffuse > 0.0){ - vec3 view = normalize(position); - vec3 halfway = normalize(light - view); - float specular = pow(max(dot(normal, halfway), 0.0), gl_FrontMaterial.shininess); - vec4 temp = gl_LightSource[0].diffuse * diffuse; - shadow += temp * 0.2; - gl_FrontColor += temp + gl_FrontLightProduct[0].specular * specular; - } - - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - gl_TexCoord[1] = gl_TextureMatrix[1] * gl_ModelViewMatrix * gl_Vertex; - gl_Position = ftransform(); + gl_Position = gl_ProjectionMatrix * vPos; + gl_FrontColor = gl_Color; + gl_TexCoord[0] * gl_MultiTexCoord0; } diff --git a/engine/src/client.c b/engine/src/client.c index 1385858..e4e530d 100644 --- a/engine/src/client.c +++ b/engine/src/client.c @@ -18,10 +18,10 @@ GBClient GBClientCreate(GBEngine engine) { client->look_at[1] = 0; client->look_at[2] = 0; - client->light0[0] = 0; - client->light0[1] = 1; - client->light0[2] = -5; - client->light0[3] = 1; + client->light0[0] = 5; + client->light0[1] = 5; + client->light0[2] = 5; + client->light0[3] = 0; client->gl = GBGLCreate(client); @@ -56,13 +56,44 @@ static void scene(void) { glRotatef(180 * i, 0, 1, 0); glBegin(GL_QUADS); glNormal3f(-1, 0, 0); - glVertex3f(-1, 0.5, 0); - glVertex3f(-1, 0, 0); - glVertex3f(1, 0, 0); - glVertex3f(1, 0.5, 0); + glVertex3f(-1, 0.5, 0.25); + glVertex3f(-1, 0, 0.25); + glVertex3f(1, 0, 0.25); + glVertex3f(1, 0.5, 0.25); glEnd(); glPopMatrix(); } + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(-1, 0.5, -0.25); + glVertex3f(-1, 0.5, 0.25); + glVertex3f(1, 0.5, 0.25); + glVertex3f(1, 0.5, -0.25); + glEnd(); + + glBegin(GL_QUADS); + glNormal3f(0, 1, 0); + glVertex3f(-1, -0.5, 0.25); + glVertex3f(-1, -0.5, -0.25); + glVertex3f(1, -0.5, -0.25); + glVertex3f(1, -0.5, 0.25); + glEnd(); + + glBegin(GL_QUADS); + glNormal3f(-1, 0, 0); + glVertex3f(-1, 0.5, 0.25); + glVertex3f(-1, 0.5, -0.25); + glVertex3f(-1, 0, -0.25); + glVertex3f(-1, 0, 0.25); + glEnd(); + + glBegin(GL_QUADS); + glNormal3f(1, 0, 0); + glVertex3f(1, 0.5, -0.25); + glVertex3f(1, 0.5, 0.25); + glVertex3f(1, 0, 0.25); + glVertex3f(1, 0, -0.25); + glEnd(); } void GBClientStep(GBClient client) { diff --git a/engine/src/gl_shadow.c b/engine/src/gl_shadow.c index 5e3372a..f8b839e 100644 --- a/engine/src/gl_shadow.c +++ b/engine/src/gl_shadow.c @@ -1,5 +1,7 @@ #include +#include + #define SHADOW_WIDTH 1024 #define SHADOW_HEIGHT 1024 @@ -24,8 +26,9 @@ void GBGLShadowInit(GBGL gl) { if(GBGLShaderPrepare(gl, &gl->shadow_shader, "base:/shader/shadow.vs", "base:/shader/shadow.fs")) { glUseProgram(gl->shadow_shader); - glUniform1i(glGetUniformLocation(gl->shadow_shader, "depth_texture"), 1); + glUniform1i(glGetUniformLocation(gl->shadow_shader, "depth_texture"), 7); glUniform1i(glGetUniformLocation(gl->shadow_shader, "current_texture"), 0); + glUseProgram(0); } } @@ -39,11 +42,13 @@ void GBGLShadowBeforeMapping(GBGL gl) { glMatrixMode(GL_PROJECTION); glGetDoublev(GL_PROJECTION_MATRIX, gl->shadow_old_projection); glLoadIdentity(); + GBGLPerspective(gl, SHADOW_WIDTH, SHADOW_HEIGHT); + + glGetDoublev(GL_PROJECTION_MATRIX, gl->shadow_projection); glMatrixMode(GL_MODELVIEW); glGetDoublev(GL_MODELVIEW_MATRIX, gl->shadow_old_modelview); glLoadIdentity(); - GBGLPerspective(gl, SHADOW_WIDTH, SHADOW_HEIGHT); GBGLLookAt(gl, gl->engine->client->light0, zero); glGetDoublev(GL_MODELVIEW_MATRIX, gl->shadow_modelview); @@ -52,11 +57,24 @@ void GBGLShadowBeforeMapping(GBGL gl) { glDisable(GL_LIGHTING); +#ifdef SHADOW_CULL glCullFace(GL_FRONT); +#else + glDisable(GL_CULL_FACE); +#endif + + glPolygonOffset(1.1f, 4.0f); + glEnable(GL_POLYGON_OFFSET_FILL); } void GBGLShadowAfterMapping(GBGL gl) { - glActiveTexture(GL_TEXTURE1); + GBMatrix4x4 in, out; + GLdouble mat[16]; + int i; + + glDisable(GL_POLYGON_OFFSET_FILL); + + glActiveTexture(GL_TEXTURE7); glBindTexture(GL_TEXTURE_2D, gl->shadow_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindTexture(GL_TEXTURE_2D, 0); @@ -65,7 +83,11 @@ void GBGLShadowAfterMapping(GBGL gl) { glViewport(0, 0, gl->engine->width, gl->engine->height); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glEnable(GL_LIGHTING); +#ifdef SHADOW_CULL glCullFace(GL_BACK); +#else + glEnable(GL_CULL_FACE); +#endif glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -75,33 +97,42 @@ void GBGLShadowAfterMapping(GBGL gl) { glLoadIdentity(); glMultMatrixd(gl->shadow_old_modelview); - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE7); glMatrixMode(GL_TEXTURE); glLoadIdentity(); + for(i = 0; i < 16; i++) in[i] = gl->shadow_old_modelview[i]; + GBMathInvert4x4(out, in); + for(i = 0; i < 16; i++) mat[i] = out[i]; + glTranslated(0.5, 0.5, 0.5); glScaled(0.5, 0.5, 0.5); + glMultMatrixd(gl->shadow_projection); glMultMatrixd(gl->shadow_modelview); - glMultMatrixd(gl->shadow_old_modelview); + glMultMatrixd(mat); glActiveTexture(GL_TEXTURE0); glMatrixMode(GL_MODELVIEW); - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE7); glBindTexture(GL_TEXTURE_2D, gl->shadow_texture); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glUseProgram(gl->shadow_shader); } void GBGLShadowEnd(GBGL gl) { - glActiveTexture(GL_TEXTURE1); + glUseProgram(0); + + glActiveTexture(GL_TEXTURE7); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); - glActiveTexture(GL_TEXTURE1); + glActiveTexture(GL_TEXTURE7); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glActiveTexture(GL_TEXTURE0); diff --git a/engine/src/math.c b/engine/src/math.c index 8d5c628..73f08e9 100644 --- a/engine/src/math.c +++ b/engine/src/math.c @@ -72,3 +72,34 @@ void GBMathNormal3x4(GBVector3 r, GBVector3 v0, GBVector3 v1, GBVector3 v2, GBVe double GBMathCot(double x) { return (double)1 / tan(x); } + +void GBMathInvert4x4(GBMatrix4x4 out, GBMatrix4x4 in) { + double inv[16], det; + int i; + + inv[0] = in[5] * in[10] * in[15] - in[5] * in[11] * in[14] - in[9] * in[6] * in[15] + in[9] * in[7] * in[14] + in[13] * in[6] * in[11] - in[13] * in[7] * in[10]; + inv[4] = -in[4] * in[10] * in[15] + in[4] * in[11] * in[14] + in[8] * in[6] * in[15] - in[8] * in[7] * in[14] - in[12] * in[6] * in[11] + in[12] * in[7] * in[10]; + inv[8] = in[4] * in[9] * in[15] - in[4] * in[11] * in[13] - in[8] * in[5] * in[15] + in[8] * in[7] * in[13] + in[12] * in[5] * in[11] - in[12] * in[7] * in[9]; + inv[12] = -in[4] * in[9] * in[14] + in[4] * in[10] * in[13] + in[8] * in[5] * in[14] - in[8] * in[6] * in[13] - in[12] * in[5] * in[10] + in[12] * in[6] * in[9]; + inv[1] = -in[1] * in[10] * in[15] + in[1] * in[11] * in[14] + in[9] * in[2] * in[15] - in[9] * in[3] * in[14] - in[13] * in[2] * in[11] + in[13] * in[3] * in[10]; + inv[5] = in[0] * in[10] * in[15] - in[0] * in[11] * in[14] - in[8] * in[2] * in[15] + in[8] * in[3] * in[14] + in[12] * in[2] * in[11] - in[12] * in[3] * in[10]; + inv[9] = -in[0] * in[9] * in[15] + in[0] * in[11] * in[13] + in[8] * in[1] * in[15] - in[8] * in[3] * in[13] - in[12] * in[1] * in[11] + in[12] * in[3] * in[9]; + inv[13] = in[0] * in[9] * in[14] - in[0] * in[10] * in[13] - in[8] * in[1] * in[14] + in[8] * in[2] * in[13] + in[12] * in[1] * in[10] - in[12] * in[2] * in[9]; + inv[2] = in[1] * in[6] * in[15] - in[1] * in[7] * in[14] - in[5] * in[2] * in[15] + in[5] * in[3] * in[14] + in[13] * in[2] * in[7] - in[13] * in[3] * in[6]; + inv[6] = -in[0] * in[6] * in[15] + in[0] * in[7] * in[14] + in[4] * in[2] * in[15] - in[4] * in[3] * in[14] - in[12] * in[2] * in[7] + in[12] * in[3] * in[6]; + inv[10] = in[0] * in[5] * in[15] - in[0] * in[7] * in[13] - in[4] * in[1] * in[15] + in[4] * in[3] * in[13] + in[12] * in[1] * in[7] - in[12] * in[3] * in[5]; + inv[14] = -in[0] * in[5] * in[14] + in[0] * in[6] * in[13] + in[4] * in[1] * in[14] - in[4] * in[2] * in[13] - in[12] * in[1] * in[6] + in[12] * in[2] * in[5]; + inv[3] = -in[1] * in[6] * in[11] + in[1] * in[7] * in[10] + in[5] * in[2] * in[11] - in[5] * in[3] * in[10] - in[9] * in[2] * in[7] + in[9] * in[3] * in[6]; + inv[7] = in[0] * in[6] * in[11] - in[0] * in[7] * in[10] - in[4] * in[2] * in[11] + in[4] * in[3] * in[10] + in[8] * in[2] * in[7] - in[8] * in[3] * in[6]; + inv[11] = -in[0] * in[5] * in[11] + in[0] * in[7] * in[9] + in[4] * in[1] * in[11] - in[4] * in[3] * in[9] - in[8] * in[1] * in[7] + in[8] * in[3] * in[5]; + inv[15] = in[0] * in[5] * in[10] - in[0] * in[6] * in[9] - in[4] * in[1] * in[10] + in[4] * in[2] * in[9] + in[8] * in[1] * in[6] - in[8] * in[2] * in[5]; + + det = in[0] * inv[0] + in[1] * inv[4] + in[2] * inv[8] + in[3] * inv[12]; + if(det == 0) + return; + + det = 1.0 / det; + + for(i = 0; i < 16; i++) + out[i] = inv[i] * det; +}