From ed3198b65f1941e4bd918d06a84f0f8acf3fdaa1 Mon Sep 17 00:00:00 2001 From: plagman Date: Thu, 26 Mar 2009 16:32:00 +0000 Subject: [PATCH] Shadows. git-svn-id: https://svn.eduke32.com/eduke32@1268 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/include/polymer.h | 8 ++ polymer/eduke32/build/src/polymer.c | 179 ++++++++++++++++++++---- 2 files changed, 157 insertions(+), 30 deletions(-) diff --git a/polymer/eduke32/build/include/polymer.h b/polymer/eduke32/build/include/polymer.h index 8b294bf23..5a3bdb2dd 100644 --- a/polymer/eduke32/build/include/polymer.h +++ b/polymer/eduke32/build/include/polymer.h @@ -54,6 +54,7 @@ typedef enum { PR_BIT_DIFFUSE_MODULATION, PR_BIT_DIFFUSE_MIRROR_MAP, PR_BIT_DIFFUSE_GLOW_MAP, + PR_BIT_SHADOW_MAP, PR_BIT_SPOT_LIGHT, PR_BIT_POINT_LIGHT, PR_BIT_FOOTER, // must be just before last @@ -102,6 +103,9 @@ typedef struct s_prrograminfo { GLint uniform_mirrorMap; // PR_BIT_DIFFUSE_GLOW_MAP GLint uniform_glowMap; + // PR_BIT_SHADOW_MAP + GLint uniform_shadowMap; + GLint uniform_shadowProjMatrix; // PR_BIT_SPOT_LIGHT GLint uniform_spotDir; GLint uniform_spotRadius; @@ -132,13 +136,16 @@ typedef struct s_prlight { GLfloat proj[16]; GLfloat transform[16]; float frustum[5 * 4]; + int32_t rtindex; } _prlight; // RENDER TARGETS typedef struct s_prrt { + GLenum target; GLuint color; GLuint z; GLuint fbo; + int32_t xdim, ydim; } _prrt; // BUILD DATA @@ -286,6 +293,7 @@ static void polymer_compileprogram(int32_t programbits); // LIGHTS static int32_t polymer_planeinlight(_prplane* plane, _prlight* light); static void polymer_culllight(char lightindex); +static void polymer_prepareshadows(void); // RENDER TARGETS static void polymer_initrendertargets(int32_t count); diff --git a/polymer/eduke32/build/src/polymer.c b/polymer/eduke32/build/src/polymer.c index 0637f652a..80c8252fe 100644 --- a/polymer/eduke32/build/src/polymer.c +++ b/polymer/eduke32/build/src/polymer.c @@ -124,6 +124,15 @@ _prlight prlights[PR_MAXLIGHTS]; int32_t lightcount; int32_t curlight; +GLfloat shadowBias[] = +{ + 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 +}; + + // MATERIALS _prprogrambit prprogrambits[PR_BIT_COUNT] = { { @@ -288,6 +297,21 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = { " result = vec4((result.rgb * (1.0 - glowTexel.a)) + (glowTexel.rgb * glowTexel.a), result.a);\n" "\n", }, + { + 1 << PR_BIT_SHADOW_MAP, + // vert_def + "uniform mat4 shadowProjMatrix;\n" + "\n", + // vert_prog + " gl_TexCoord[texCoord++] = shadowProjMatrix * curVertex;\n" + "\n", + // frag_def + "uniform sampler2DShadow shadowMap;\n" + "\n", + // frag_prog + " shadowResult = shadow2DProj(shadowMap, gl_TexCoord[texCoord++]).a;\n" + "\n", + }, { 1 << PR_BIT_SPOT_LIGHT, // vert_def @@ -367,7 +391,7 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = { " E = normalize(eyeVector);\n" " R = reflect(-L, N);\n" "\n" - " lightDiffuse = diffuseTexel.a * gl_Color.a * diffuseTexel.rgb *\n" + " lightDiffuse = diffuseTexel.a * gl_Color.a * diffuseTexel.rgb * shadowResult *\n" " gl_LightSource[0].diffuse.rgb * lightAttenuation * spotAttenuation;\n" " result += vec4(lightDiffuse * NdotL, 0.0);\n" "\n" @@ -402,6 +426,7 @@ _prprogrambit prprogrambits[PR_BIT_COUNT] = { " int isSpotLight = 0;\n" " vec3 spotVector;\n" " vec2 spotCosRadius;\n" + " float shadowResult = 1;\n" "\n", // frag_prog " gl_FragColor = result;\n" @@ -581,6 +606,9 @@ void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t da pos[1] = -(float)(daposz) / 16.0f; pos[2] = -daposx; + depth = 0; + polymer_prepareshadows(); + bglMatrixMode(GL_MODELVIEW); bglLoadIdentity(); @@ -648,7 +676,6 @@ void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t da rootsectnum = dacursectnum; // GO! - depth = 0; polymer_displayrooms(dacursectnum); curmodelviewmatrix = rootmodelviewmatrix; @@ -962,6 +989,8 @@ void polymer_addlight(_prlight light) bglPopMatrix(); polymer_extractfrustum(prlights[lightcount].transform, prlights[lightcount].proj, prlights[lightcount].frustum); + + prlights[lightcount].rtindex = -1; } polymer_culllight(lightcount); @@ -984,6 +1013,7 @@ static void polymer_displayrooms(int16_t dacursectnum) GLuint queryid[MAXWALLS]; int16_t drawingstate[MAXSECTORS]; GLfloat localmodelviewmatrix[16]; + GLfloat localprojectionmatrix[16]; float frustum[5 * 4]; int32_t localspritesortcnt; spritetype localtsprite[MAXSPRITESONSCREEN]; @@ -994,15 +1024,11 @@ static void polymer_displayrooms(int16_t dacursectnum) GLdouble plane[4]; float coeff; - if (depth) - { - curmodelviewmatrix = localmodelviewmatrix; - bglGetFloatv(GL_MODELVIEW_MATRIX, localmodelviewmatrix); - } - else - curmodelviewmatrix = rootmodelviewmatrix; + curmodelviewmatrix = localmodelviewmatrix; + bglGetFloatv(GL_MODELVIEW_MATRIX, localmodelviewmatrix); + bglGetFloatv(GL_PROJECTION_MATRIX, localprojectionmatrix); - polymer_extractfrustum(curmodelviewmatrix, projectionmatrix, frustum); + polymer_extractfrustum(localmodelviewmatrix, localprojectionmatrix, frustum); memset(querydelay, 0, sizeof(int16_t) * MAXSECTORS); memset(queryid, 0, sizeof(GLuint) * MAXWALLS); @@ -3106,8 +3132,12 @@ static int32_t polymer_bindmaterial(_prmaterial material, char* lights, int if (lightcount) { programbits |= prprogrambits[PR_BIT_POINT_LIGHT].bit; // PR_BIT_SPOT_LIGHT - if (prlights[lights[curlight]].radius) + if (prlights[lights[curlight]].radius) { programbits |= prprogrambits[PR_BIT_SPOT_LIGHT].bit; + // PR_BIT_SHADOW_MAP + if (prlights[lights[curlight]].rtindex != -1) + programbits |= prprogrambits[PR_BIT_SHADOW_MAP].bit; + } } // material override @@ -3256,6 +3286,28 @@ static int32_t polymer_bindmaterial(_prmaterial material, char* lights, int bglUniform3fvARB(prprograms[programbits].uniform_spotDir, 1, dir); bglUniform2fvARB(prprograms[programbits].uniform_spotRadius, 1, indir); + + // PR_BIT_SHADOW_MAP + if (programbits & prprogrambits[PR_BIT_SHADOW_MAP].bit) + { + GLfloat matrix[16]; + + bglMatrixMode(GL_TEXTURE); + bglLoadMatrixf(shadowBias); + bglMultMatrixf(prlights[lights[curlight]].proj); + bglMultMatrixf(prlights[lights[curlight]].transform); + bglGetFloatv(GL_TEXTURE_MATRIX, matrix); + bglLoadIdentity(); + bglMatrixMode(GL_MODELVIEW); + + bglActiveTextureARB(texunit + GL_TEXTURE0_ARB); + bglBindTexture(prrts[prlights[lights[curlight]].rtindex].target, prrts[prlights[lights[curlight]].rtindex].z); + + bglUniform1iARB(prprograms[programbits].uniform_shadowMap, texunit); + bglUniformMatrix4fvARB(prprograms[programbits].uniform_shadowProjMatrix, 1, GL_FALSE, matrix); + + texunit++; + } } range[0] = prlights[lights[curlight]].range / 1000.0f; @@ -3414,6 +3466,13 @@ static void polymer_compileprogram(int32_t programbits) prprograms[programbits].uniform_glowMap = bglGetUniformLocationARB(program, "glowMap"); } + // PR_BIT_SHADOW_MAP + if (programbits & prprogrambits[PR_BIT_SHADOW_MAP].bit) + { + prprograms[programbits].uniform_shadowMap = bglGetUniformLocationARB(program, "shadowMap"); + prprograms[programbits].uniform_shadowProjMatrix = bglGetUniformLocationARB(program, "shadowProjMatrix"); + } + // PR_BIT_SPOT_LIGHT if (programbits & prprogrambits[PR_BIT_SPOT_LIGHT].bit) { @@ -3529,6 +3588,49 @@ static void polymer_culllight(char lightindex) } } +static void polymer_prepareshadows(void) +{ + int32_t i, j; + + i = j = 0; + + while ((i < lightcount) && (j < 1)) + { + if (prlights[i].radius) + { + prlights[i].rtindex = j + 1; + + bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prrts[prlights[i].rtindex].fbo); + bglPushAttrib(GL_VIEWPORT_BIT); + bglViewport(0, 0, prrts[prlights[i].rtindex].xdim, prrts[prlights[i].rtindex].ydim); + + bglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + bglMatrixMode(GL_PROJECTION); + bglPushMatrix(); + bglLoadMatrixf(prlights[i].proj); + bglMatrixMode(GL_MODELVIEW); + bglLoadMatrixf(prlights[i].transform); + + bglEnable(GL_POLYGON_OFFSET_FILL); + bglPolygonOffset(15, 15); + + polymer_displayrooms(prlights[i].sector); + + bglDisable(GL_POLYGON_OFFSET_FILL); + + bglMatrixMode(GL_PROJECTION); + bglPopMatrix(); + + bglPopAttrib(); + bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + j++; + } + i++; + } +} + // RENDER TARGETS static void polymer_initrendertargets(int32_t count) { @@ -3539,39 +3641,56 @@ static void polymer_initrendertargets(int32_t count) i = 0; while (i < count) { - bglGenTextures(1, &prrts[i].color); - bglBindTexture(GL_TEXTURE_RECTANGLE, prrts[i].color); + if (!i) { + prrts[i].target = GL_TEXTURE_RECTANGLE; + prrts[i].xdim = xdim; + prrts[i].ydim = ydim; - bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, xdim, ydim, 0); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP); + bglGenTextures(1, &prrts[i].color); + bglBindTexture(prrts[i].target, prrts[i].color); + + bglCopyTexImage2D(prrts[i].target, 0, GL_RGBA, 0, 0, prrts[i].xdim, prrts[i].ydim, 0); + bglTexParameteri(prrts[i].target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + bglTexParameteri(prrts[i].target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + bglTexParameteri(prrts[i].target, GL_TEXTURE_WRAP_S, GL_CLAMP); + bglTexParameteri(prrts[i].target, GL_TEXTURE_WRAP_T, GL_CLAMP); + } else { + prrts[i].target = GL_TEXTURE_2D; + prrts[i].xdim = 512; + prrts[i].ydim = 512; + prrts[i].color = 0; + } bglGenTextures(1, &prrts[i].z); - bglBindTexture(GL_TEXTURE_RECTANGLE, prrts[i].z); + bglBindTexture(prrts[i].target, prrts[i].z); - bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER); - bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + bglCopyTexImage2D(prrts[i].target, 0, GL_DEPTH_COMPONENT, 0, 0, prrts[i].xdim, prrts[i].ydim, 0); + bglTexParameteri(prrts[i].target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + bglTexParameteri(prrts[i].target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + bglTexParameteri(prrts[i].target, GL_TEXTURE_WRAP_S, GL_CLAMP); + bglTexParameteri(prrts[i].target, GL_TEXTURE_WRAP_T, GL_CLAMP); + bglTexParameteri(prrts[i].target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + bglTexParameteri(prrts[i].target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + bglTexParameteri(prrts[i].target, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); bglGenFramebuffersEXT(1, &prrts[i].fbo); bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prrts[i].fbo); - bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE, prrts[i].color, 0); - bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, prrts[i].z, 0); + if (prrts[i].color) + bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + prrts[i].target, prrts[i].color, 0); + else { + bglDrawBuffer(GL_NONE); + bglReadBuffer(GL_NONE); + } + bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, prrts[i].target, prrts[i].z, 0); if (bglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { OSD_Printf("FBO #%d initialization failed.\n", i); } - bglBindTexture(GL_TEXTURE_RECTANGLE, 0); + bglBindTexture(prrts[i].target, 0); bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); i++;