diff options
author | Tim Angus <tim@ngus.net> | 2016-04-09 17:57:28 +0100 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2016-04-09 17:57:28 +0100 |
commit | f45fbef604e05144057dec8d1dbfc5d4f5a2a822 (patch) | |
tree | 152d2a428b078f7a89756ea9e156695fc69f1686 /src/renderergl2/tr_backend.c | |
parent | 7f9e97d611b4b267d9dd913144cb9632f96c90c2 (diff) | |
parent | 87abdd914988724e164ffb16380ad26be8420b84 (diff) |
Merge branch 'master' into gpp
Diffstat (limited to 'src/renderergl2/tr_backend.c')
-rw-r--r-- | src/renderergl2/tr_backend.c | 439 |
1 files changed, 236 insertions, 203 deletions
diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 6c03db3c..0e331752 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -21,6 +21,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "tr_local.h" +#include "tr_fbo.h" +#include "tr_dsa.h" backEndData_t *backEndData; backEndState_t backEnd; @@ -37,80 +39,27 @@ static float s_flipMatrix[16] = { /* -** GL_Bind -*/ -void GL_Bind( image_t *image ) { - int texnum; - - if ( !image ) { - ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" ); - texnum = tr.defaultImage->texnum; - } else { - texnum = image->texnum; - } - - if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option - texnum = tr.dlightImage->texnum; - } - - if ( glState.currenttextures[glState.currenttmu] != texnum ) { - if ( image ) { - image->frameUsed = tr.frameCount; - } - glState.currenttextures[glState.currenttmu] = texnum; - if (image && image->flags & IMGFLAG_CUBEMAP) - qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum ); - else - qglBindTexture( GL_TEXTURE_2D, texnum ); - } -} - -/* -** GL_SelectTexture -*/ -void GL_SelectTexture( int unit ) -{ - if ( glState.currenttmu == unit ) - { - return; - } - - if (!(unit >= 0 && unit <= 31)) - ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit ); - - if (!qglActiveTextureARB) - ri.Error( ERR_DROP, "GL_SelectTexture: multitexture disabled" ); - - qglActiveTextureARB( GL_TEXTURE0_ARB + unit ); - - glState.currenttmu = unit; -} - -/* ** GL_BindToTMU */ void GL_BindToTMU( image_t *image, int tmu ) { - int texnum; - int oldtmu = glState.currenttmu; + GLuint texture = (tmu == TB_COLORMAP) ? tr.defaultImage->texnum : 0; + GLenum target = GL_TEXTURE_2D; - if (!image) - texnum = 0; - else - texnum = image->texnum; - - if ( glState.currenttextures[tmu] != texnum ) { - GL_SelectTexture( tmu ); - if (image) - image->frameUsed = tr.frameCount; - glState.currenttextures[tmu] = texnum; + if (image) + { + if (image->flags & IMGFLAG_CUBEMAP) + target = GL_TEXTURE_CUBE_MAP; - if (image && (image->flags & IMGFLAG_CUBEMAP)) - qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum ); - else - qglBindTexture( GL_TEXTURE_2D, texnum ); - GL_SelectTexture( oldtmu ); + image->frameUsed = tr.frameCount; + texture = image->texnum; + } + else + { + ri.Printf(PRINT_WARNING, "GL_BindToTMU: NULL image\n"); } + + GL_BindMultiTexture(GL_TEXTURE0_ARB + tmu, target, texture); } @@ -143,39 +92,6 @@ void GL_Cull( int cullType ) { } /* -** GL_TexEnv -*/ -void GL_TexEnv( int env ) -{ - if ( env == glState.texEnv[glState.currenttmu] ) - { - return; - } - - glState.texEnv[glState.currenttmu] = env; - - - switch ( env ) - { - case GL_MODULATE: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - break; - case GL_REPLACE: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - break; - case GL_DECAL: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); - break; - case GL_ADD: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); - break; - default: - ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env ); - break; - } -} - -/* ** GL_State ** ** This routine is responsible for setting the most commonly changed state @@ -463,30 +379,20 @@ void RB_BeginDrawingView (void) { if (glRefConfig.framebufferObject) { + FBO_t *fbo = backEnd.viewParms.targetFbo; + // FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world // drawing more world check is in case of double renders, such as skyportals - if (backEnd.viewParms.targetFbo == NULL) + if (fbo == NULL && !(backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) + fbo = tr.renderFbo; + + if (tr.renderCubeFbo && fbo == tr.renderCubeFbo) { - if (!tr.renderFbo || (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } + cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; + FBO_AttachImage(fbo, cubemap->image, GL_COLOR_ATTACHMENT0_EXT, backEnd.viewParms.targetFboLayer); } - else - { - FBO_Bind(backEnd.viewParms.targetFbo); - // FIXME: hack for cubemap testing - if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) - { - //qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, backEnd.viewParms.targetFbo->colorImage[0]->texnum, 0); - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]->texnum, 0); - } - } + FBO_Bind(fbo); } // @@ -550,8 +456,6 @@ void RB_BeginDrawingView (void) { } -#define MAC_EVENT_PUMP_MSEC 5 - /* ================== RB_RenderDrawSurfList @@ -857,6 +761,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * } RE_UploadCinematic (w, h, cols, rows, data, client, dirty); + GL_BindToTMU(tr.scratchImage[client], TB_COLORMAP); if ( r_speeds->integer ) { end = ri.Milliseconds(); @@ -866,14 +771,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * // FIXME: HUGE hack if (glRefConfig.framebufferObject) { - if (!tr.renderFbo || backEnd.framePostProcessed) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } + FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); } RB_SetGL2D(); @@ -897,23 +795,30 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * } void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { + GLuint texture; + + if (!tr.scratchImage[client]) + { + ri.Printf(PRINT_WARNING, "RE_UploadCinematic: scratch images not initialized\n"); + return; + } - GL_Bind( tr.scratchImage[client] ); + texture = tr.scratchImage[client]->texnum; // if the scratchImage isn't in the format we want, specify it as a new texture if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) { tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; - qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + qglTextureImage2D(texture, GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else { if (dirty) { // otherwise, just subimage upload it so that drivers can tell we are going to be changing // it and don't try and do a texture compression - qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); + qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data); } } } @@ -952,16 +857,7 @@ const void *RB_StretchPic ( const void *data ) { // FIXME: HUGE hack if (glRefConfig.framebufferObject) - { - if (!tr.renderFbo || backEnd.framePostProcessed) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } - } + FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); RB_SetGL2D(); @@ -1061,6 +957,9 @@ const void *RB_DrawSurfs( const void *data ) { if (glRefConfig.framebufferObject && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && (r_depthPrepass->integer || (backEnd.viewParms.flags & VPF_DEPTHSHADOW))) { FBO_t *oldFbo = glState.currentFBO; + vec4_t viewInfo; + + VectorSet4(viewInfo, backEnd.viewParms.zFar / r_znear->value, backEnd.viewParms.zFar, 0.0, 0.0); backEnd.depthFill = qtrue; qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -1073,17 +972,20 @@ const void *RB_DrawSurfs( const void *data ) { // If we're using multisampling, resolve the depth first FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST); } - else if (tr.renderFbo == NULL) + else if (tr.renderFbo == NULL && tr.renderDepthImage) { // If we're rendering directly to the screen, copy the depth to a texture - GL_BindToTMU(tr.renderDepthImage, 0); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0); + qglCopyTextureImage2D(tr.renderDepthImage->texnum, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0); } - if (r_ssao->integer) + if (tr.hdrDepthFbo) { // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image - FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); + vec4_t srcTexCoords; + + VectorSet4(srcTexCoords, 0.0f, 0.0f, 1.0f, 1.0f); + + FBO_BlitFromTexture(tr.renderDepthImage, srcTexCoords, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); } if (r_sunlightMode->integer && backEnd.viewParms.flags & VPF_USESUNLIGHT) @@ -1148,15 +1050,12 @@ const void *RB_DrawSurfs( const void *data ) { GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg); { - vec4_t viewInfo; vec3_t viewVector; float zmax = backEnd.viewParms.zFar; float ymax = zmax * tan(backEnd.viewParms.fovY * M_PI / 360.0f); float xmax = zmax * tan(backEnd.viewParms.fovX * M_PI / 360.0f); - float zmin = r_znear->value; - VectorScale(backEnd.refdef.viewaxis[0], zmax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWFORWARD, viewVector); VectorScale(backEnd.refdef.viewaxis[1], xmax, viewVector); @@ -1164,13 +1063,38 @@ const void *RB_DrawSurfs( const void *data ) { VectorScale(backEnd.refdef.viewaxis[2], ymax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWUP, viewVector); - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - GLSL_SetUniformVec4(&tr.shadowmaskShader, UNIFORM_VIEWINFO, viewInfo); } - RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); + + if (r_shadowBlur->integer) + { + viewInfo[2] = 1.0f / (float)(tr.screenScratchFbo->width); + viewInfo[3] = 1.0f / (float)(tr.screenScratchFbo->height); + + FBO_Bind(tr.screenScratchFbo); + + GLSL_BindProgram(&tr.depthBlurShader[0]); + + GL_BindToTMU(tr.screenShadowImage, TB_COLORMAP); + GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); + + GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); + + RB_InstantQuad2(quadVerts, texCoords); + + FBO_Bind(tr.screenShadowFbo); + + GLSL_BindProgram(&tr.depthBlurShader[1]); + + GL_BindToTMU(tr.screenScratchImage, TB_COLORMAP); + GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); + + GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); + + RB_InstantQuad2(quadVerts, texCoords); + } } if (r_ssao->integer) @@ -1178,6 +1102,10 @@ const void *RB_DrawSurfs( const void *data ) { vec4_t quadVerts[4]; vec2_t texCoords[4]; + viewInfo[2] = 1.0f / ((float)(tr.quarterImage[0]->width) * tan(backEnd.viewParms.fovX * M_PI / 360.0f) * 2.0f); + viewInfo[3] = 1.0f / ((float)(tr.quarterImage[0]->height) * tan(backEnd.viewParms.fovY * M_PI / 360.0f) * 2.0f); + viewInfo[3] *= (float)backEnd.viewParms.viewportHeight / (float)backEnd.viewParms.viewportWidth; + FBO_Bind(tr.quarterFbo[0]); qglViewport(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); @@ -1199,20 +1127,14 @@ const void *RB_DrawSurfs( const void *data ) { GL_BindToTMU(tr.hdrDepthImage, TB_COLORMAP); - { - vec4_t viewInfo; - - float zmax = backEnd.viewParms.zFar; - float zmin = r_znear->value; - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.ssaoShader, UNIFORM_VIEWINFO, viewInfo); - } + GLSL_SetUniformVec4(&tr.ssaoShader, UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); + viewInfo[2] = 1.0f / (float)(tr.quarterImage[0]->width); + viewInfo[3] = 1.0f / (float)(tr.quarterImage[0]->height); + FBO_Bind(tr.quarterFbo[1]); qglViewport(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); @@ -1223,16 +1145,7 @@ const void *RB_DrawSurfs( const void *data ) { GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP); GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); - { - vec4_t viewInfo; - - float zmax = backEnd.viewParms.zFar; - float zmin = r_znear->value; - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); - } + GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); @@ -1247,16 +1160,7 @@ const void *RB_DrawSurfs( const void *data ) { GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP); GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); - { - vec4_t viewInfo; - - float zmax = backEnd.viewParms.zFar; - float zmin = r_znear->value; - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); - } + GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); @@ -1314,11 +1218,11 @@ const void *RB_DrawSurfs( const void *data ) { if (glRefConfig.framebufferObject && tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) { + cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; + FBO_Bind(NULL); - GL_SelectTexture(TB_CUBEMAP); - GL_BindToTMU(tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex], TB_CUBEMAP); - qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP); - GL_SelectTexture(0); + if (cubemap && cubemap->image) + qglGenerateTextureMipmap(cubemap->image->texnum, GL_TEXTURE_CUBE_MAP); } return (const void *)(cmd + 1); @@ -1395,7 +1299,7 @@ void RB_ShowImages( void ) { { vec4_t quadVerts[4]; - GL_Bind(image); + GL_BindToTMU(image, TB_COLORMAP); VectorSet4(quadVerts[0], x, y, 0, 1); VectorSet4(quadVerts[1], x + w, y, 0, 1); @@ -1571,21 +1475,18 @@ const void *RB_CapShadowMap(const void *data) if (cmd->map != -1) { - GL_SelectTexture(0); if (cmd->cubeSide != -1) { if (tr.shadowCubemaps[cmd->map]) { - GL_Bind(tr.shadowCubemaps[cmd->map]); - qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); + qglCopyTextureImage2D(tr.shadowCubemaps[cmd->map]->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); } } else { if (tr.pshadowMaps[cmd->map]) { - GL_Bind(tr.pshadowMaps[cmd->map]); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); + qglCopyTextureImage2D(tr.pshadowMaps[cmd->map]->texnum, GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - (backEnd.refdef.y + PSHADOW_MAP_SIZE), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); } } } @@ -1644,10 +1545,6 @@ const void *RB_PostProcess(const void *data) srcBox[2] = backEnd.viewParms.viewportWidth * tr.screenSsaoImage->width / (float)glConfig.vidWidth; srcBox[3] = backEnd.viewParms.viewportHeight * tr.screenSsaoImage->height / (float)glConfig.vidHeight; - //FBO_BlitFromTexture(tr.screenSsaoImage, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); - srcBox[1] = tr.screenSsaoImage->height - srcBox[1]; - srcBox[3] = -srcBox[3]; - FBO_Blit(tr.screenSsaoFbo, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); } @@ -1658,7 +1555,7 @@ const void *RB_PostProcess(const void *data) if (srcFbo) { - if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer) && qglActiveTextureARB) + if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer)) { autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer; RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure); @@ -1688,6 +1585,71 @@ const void *RB_PostProcess(const void *data) else RB_GaussianBlur(backEnd.refdef.blurFactor); +#if 0 + if (0) + { + vec4_t quadVerts[4]; + vec2_t texCoords[4]; + ivec4_t iQtrBox; + vec4_t box; + vec4_t viewInfo; + static float scale = 5.0f; + + scale -= 0.005f; + if (scale < 0.01f) + scale = 5.0f; + + FBO_FastBlit(NULL, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + iQtrBox[0] = backEnd.viewParms.viewportX * tr.quarterImage[0]->width / (float)glConfig.vidWidth; + iQtrBox[1] = backEnd.viewParms.viewportY * tr.quarterImage[0]->height / (float)glConfig.vidHeight; + iQtrBox[2] = backEnd.viewParms.viewportWidth * tr.quarterImage[0]->width / (float)glConfig.vidWidth; + iQtrBox[3] = backEnd.viewParms.viewportHeight * tr.quarterImage[0]->height / (float)glConfig.vidHeight; + + qglViewport(iQtrBox[0], iQtrBox[1], iQtrBox[2], iQtrBox[3]); + qglScissor(iQtrBox[0], iQtrBox[1], iQtrBox[2], iQtrBox[3]); + + VectorSet4(box, 0.0f, 0.0f, 1.0f, 1.0f); + + texCoords[0][0] = box[0]; texCoords[0][1] = box[3]; + texCoords[1][0] = box[2]; texCoords[1][1] = box[3]; + texCoords[2][0] = box[2]; texCoords[2][1] = box[1]; + texCoords[3][0] = box[0]; texCoords[3][1] = box[1]; + + VectorSet4(box, -1.0f, -1.0f, 1.0f, 1.0f); + + VectorSet4(quadVerts[0], box[0], box[3], 0, 1); + VectorSet4(quadVerts[1], box[2], box[3], 0, 1); + VectorSet4(quadVerts[2], box[2], box[1], 0, 1); + VectorSet4(quadVerts[3], box[0], box[1], 0, 1); + + GL_State(GLS_DEPTHTEST_DISABLE); + + + VectorSet4(viewInfo, backEnd.viewParms.zFar / r_znear->value, backEnd.viewParms.zFar, 0.0, 0.0); + + viewInfo[2] = scale / (float)(tr.quarterImage[0]->width); + viewInfo[3] = scale / (float)(tr.quarterImage[0]->height); + + FBO_Bind(tr.quarterFbo[1]); + GLSL_BindProgram(&tr.depthBlurShader[2]); + GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP); + GLSL_SetUniformVec4(&tr.depthBlurShader[2], UNIFORM_VIEWINFO, viewInfo); + RB_InstantQuad2(quadVerts, texCoords); + + FBO_Bind(tr.quarterFbo[0]); + GLSL_BindProgram(&tr.depthBlurShader[3]); + GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP); + GLSL_SetUniformVec4(&tr.depthBlurShader[3], UNIFORM_VIEWINFO, viewInfo); + RB_InstantQuad2(quadVerts, texCoords); + + SetViewportAndScissor(); + + FBO_FastBlit(tr.quarterFbo[1], NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + FBO_Bind(NULL); + } +#endif + if (0 && r_sunlightMode->integer) { ivec4_t dstBox; @@ -1727,7 +1689,7 @@ const void *RB_PostProcess(const void *data) { VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256); //FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); - FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1], NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); + FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1].image, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); } } #endif @@ -1737,6 +1699,74 @@ const void *RB_PostProcess(const void *data) return (const void *)(cmd + 1); } +// FIXME: put this function declaration elsewhere +void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth); + +/* +============= +RB_ExportCubemaps + +============= +*/ +const void *RB_ExportCubemaps(const void *data) +{ + const exportCubemapsCommand_t *cmd = data; + + // finish any 2D drawing if needed + if (tess.numIndexes) + RB_EndSurface(); + + if (!glRefConfig.framebufferObject || !tr.world || tr.numCubemaps == 0) + { + // do nothing + ri.Printf(PRINT_ALL, "Nothing to export!\n"); + return (const void *)(cmd + 1); + } + + if (cmd) + { + FBO_t *oldFbo = glState.currentFBO; + int sideSize = r_cubemapSize->integer * r_cubemapSize->integer * 4; + byte *cubemapPixels = ri.Malloc(sideSize * 6); + int i, j; + + FBO_Bind(tr.renderCubeFbo); + + for (i = 0; i < tr.numCubemaps; i++) + { + char filename[MAX_QPATH]; + cubemap_t *cubemap = &tr.cubemaps[i]; + byte *p = cubemapPixels; + + for (j = 0; j < 6; j++) + { + FBO_AttachImage(tr.renderCubeFbo, cubemap->image, GL_COLOR_ATTACHMENT0_EXT, j); + qglReadPixels(0, 0, r_cubemapSize->integer, r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p); + p += sideSize; + } + + if (cubemap->name[0]) + { + COM_StripExtension(cubemap->name, filename, MAX_QPATH); + Q_strcat(filename, MAX_QPATH, ".dds"); + } + else + { + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i); + } + + R_SaveDDS(filename, cubemapPixels, r_cubemapSize->integer, r_cubemapSize->integer, 6); + ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename); + } + + FBO_Bind(oldFbo); + + ri.Free(cubemapPixels); + } + + return (const void *)(cmd + 1); +} + /* ==================== @@ -1785,6 +1815,9 @@ void RB_ExecuteRenderCommands( const void *data ) { case RC_POSTPROCESS: data = RB_PostProcess(data); break; + case RC_EXPORT_CUBEMAPS: + data = RB_ExportCubemaps(data); + break; case RC_END_OF_LIST: default: // finish any 2D drawing if needed |