diff --git a/src/engine/renderer/Material.cpp b/src/engine/renderer/Material.cpp index 5d65f7dad..1df69013a 100644 --- a/src/engine/renderer/Material.cpp +++ b/src/engine/renderer/Material.cpp @@ -519,9 +519,9 @@ void UpdateSurfaceDataReflection( uint32_t* materials, Material& material, drawS // bind u_ColorMap if ( backEnd.currentEntity && ( backEnd.currentEntity != &tr.worldEntity ) ) { - GL_BindNearestCubeMap( gl_reflectionShaderMaterial->GetUniformLocation_ColorMap(), backEnd.currentEntity->e.origin ); + GL_BindNearestCubeMap( gl_reflectionShaderMaterial->GetUniformLocation_ColorMapCube(), backEnd.currentEntity->e.origin ); } else { - GL_BindNearestCubeMap( gl_reflectionShaderMaterial->GetUniformLocation_ColorMap(), backEnd.viewParms.orientation.origin ); + GL_BindNearestCubeMap( gl_reflectionShaderMaterial->GetUniformLocation_ColorMapCube(), backEnd.viewParms.orientation.origin ); } if ( pStage->enableNormalMapping ) { diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 6fd4b05e6..b1f67e328 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -707,11 +707,20 @@ static std::string GenEngineConstants() { { AddDefine( str, "r_showDeluxeMaps", 1 ); } + else if ( r_showReflectionMaps.Get() ) + { + AddDefine( str, "r_showReflectionMaps", 1 ); + } else if ( r_showVertexColors.Get() ) { AddDefine( str, "r_showVertexColors", 1 ); } + if( r_showCubeProbes.Get() ) + { + AddDefine( str, "r_showCubeProbes", 1 ); + } + if ( glConfig2.vboVertexSkinningAvailable ) { AddDefine( str, "r_vertexSkinning", 1 ); @@ -2423,7 +2432,7 @@ void GLShader_shadowFill::SetShaderProgramUniforms( shaderProgram_t *shaderProgr GLShader_reflection::GLShader_reflection( GLShaderManager *manager ): GLShader("reflection", "reflection_CB", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager ), - u_ColorMap( this ), + u_ColorMapCube( this ), u_NormalMap( this ), u_HeightMap( this ), u_TextureMatrix( this ), @@ -2435,6 +2444,8 @@ GLShader_reflection::GLShader_reflection( GLShaderManager *manager ): u_ReliefOffsetBias( this ), u_NormalScale( this ), u_VertexInterpolation( this ), + u_CameraPosition( this ), + u_InverseLightFactor( this ), GLDeformStage( this ), GLCompileMacro_USE_VERTEX_SKINNING( this ), GLCompileMacro_USE_VERTEX_ANIMATION( this ), @@ -2452,7 +2463,7 @@ void GLShader_reflection::SetShaderProgramUniforms( shaderProgram_t *shaderProgr GLShader_reflectionMaterial::GLShader_reflectionMaterial( GLShaderManager* manager ) : GLShader( "reflectionMaterial", "reflection_CB", true, ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT, manager ), - u_ColorMap( this ), + u_ColorMapCube( this ), u_NormalMap( this ), u_HeightMap( this ), u_TextureMatrix( this ), @@ -2464,6 +2475,8 @@ GLShader_reflectionMaterial::GLShader_reflectionMaterial( GLShaderManager* manag u_ReliefOffsetBias( this ), u_NormalScale( this ), u_VertexInterpolation( this ), + u_CameraPosition( this ), + u_InverseLightFactor( this ), GLDeformStage( this ), // GLCompileMacro_USE_VERTEX_SKINNING( this ), GLCompileMacro_USE_VERTEX_ANIMATION( this ), diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index ae168f356..694acb3e2 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -4253,7 +4253,7 @@ class GLShader_shadowFill : class GLShader_reflection : public GLShader, - public u_ColorMap, + public u_ColorMapCube, public u_NormalMap, public u_HeightMap, public u_TextureMatrix, @@ -4265,6 +4265,8 @@ class GLShader_reflection : public u_ReliefOffsetBias, public u_NormalScale, public u_VertexInterpolation, + public u_CameraPosition, + public u_InverseLightFactor, public GLDeformStage, public GLCompileMacro_USE_VERTEX_SKINNING, public GLCompileMacro_USE_VERTEX_ANIMATION, @@ -4278,7 +4280,7 @@ class GLShader_reflection : class GLShader_reflectionMaterial : public GLShader, - public u_ColorMap, + public u_ColorMapCube, public u_NormalMap, public u_HeightMap, public u_TextureMatrix, @@ -4290,6 +4292,8 @@ class GLShader_reflectionMaterial : public u_ReliefOffsetBias, public u_NormalScale, public u_VertexInterpolation, + public u_CameraPosition, + public u_InverseLightFactor, public GLDeformStage, // public GLCompileMacro_USE_VERTEX_SKINNING, public GLCompileMacro_USE_VERTEX_ANIMATION, diff --git a/src/engine/renderer/glsl_source/lightMapping_fp.glsl b/src/engine/renderer/glsl_source/lightMapping_fp.glsl index 564086162..eb7908a4b 100644 --- a/src/engine/renderer/glsl_source/lightMapping_fp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_fp.glsl @@ -237,6 +237,18 @@ void main() outputColor = texture2D(u_LightMap, var_TexLight); #elif defined(r_showDeluxeMaps) && defined(USE_DELUXE_MAPPING) outputColor = texture2D(u_DeluxeMap, var_TexLight); + #elif defined(USE_REFLECTIVE_SPECULAR) && defined(r_showReflectionMaps) + vec4 envColor0 = textureCube(u_EnvironmentMap0, reflect(-viewDir, normal)); + vec4 envColor1 = textureCube(u_EnvironmentMap1, reflect(-viewDir, normal)); + + outputColor = vec4( mix(envColor0, envColor1, u_EnvironmentInterpolation).rgb, 1.0 ); + + /* HACK: use sign to know if there is a light or not, and + then if it will receive overbright multiplication or not. */ + if ( u_InverseLightFactor < 0 ) + { + outputColor *= - u_InverseLightFactor; + } #elif defined(r_showVertexColors) /* We need to keep the texture alpha channel so impact marks like creep don't fully overwrite the world texture. */ diff --git a/src/engine/renderer/glsl_source/material_fp.glsl b/src/engine/renderer/glsl_source/material_fp.glsl index bf72a5cf6..6f4ac7107 100644 --- a/src/engine/renderer/glsl_source/material_fp.glsl +++ b/src/engine/renderer/glsl_source/material_fp.glsl @@ -94,7 +94,7 @@ sampler3D u_LightGrid2 = sampler3D( u_LightGrid2_initial ); #endif // !LIQUID_GLSL #if defined(REFLECTION_CB_GLSL) -samplerCube u_ColorMap = samplerCube( u_ColorMap_initial ); +samplerCube u_ColorMapCube = samplerCube( u_ColorMapCube_initial ); #endif // !REFLECTION_CB_GLSL #if defined(RELIEFMAPPING_GLSL) diff --git a/src/engine/renderer/glsl_source/reflection_CB_fp.glsl b/src/engine/renderer/glsl_source/reflection_CB_fp.glsl index 65904b27e..194318588 100644 --- a/src/engine/renderer/glsl_source/reflection_CB_fp.glsl +++ b/src/engine/renderer/glsl_source/reflection_CB_fp.glsl @@ -26,10 +26,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define REFLECTION_CB_GLSL -uniform samplerCube u_ColorMap; +uniform samplerCube u_ColorMapCube; uniform vec3 u_ViewOrigin; uniform mat4 u_ModelMatrix; +uniform float u_InverseLightFactor; + IN(smooth) vec3 var_Position; IN(smooth) vec2 var_TexCoords; IN(smooth) vec4 var_Tangent; @@ -66,6 +68,13 @@ void main() // compute reflection ray vec3 reflectionRay = reflect(viewDir, normal); - outputColor = textureCube(u_ColorMap, reflectionRay).rgba; + outputColor = textureCube(u_ColorMapCube, reflectionRay).rgba; + + #if defined(r_showCubeProbes) + viewDir = normalize(var_Position); + outputColor = textureCube(u_ColorMapCube, viewDir); + + outputColor.rgb *= u_InverseLightFactor; + #endif // outputColor = vec4(1.0, 0.0, 0.0, 1.0); } diff --git a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl index ed667acbc..240f02093 100644 --- a/src/engine/renderer/glsl_source/reflection_CB_vp.glsl +++ b/src/engine/renderer/glsl_source/reflection_CB_vp.glsl @@ -32,6 +32,10 @@ uniform mat4 u_ModelViewProjectionMatrix; uniform float u_Time; +#if defined(r_showCubeProbes) + uniform vec3 u_CameraPosition; +#endif + OUT(smooth) vec3 var_Position; OUT(smooth) vec2 var_TexCoords; OUT(smooth) vec4 var_Tangent; @@ -65,7 +69,13 @@ void main() gl_Position = u_ModelViewProjectionMatrix * position; // transform position into world space - var_Position = (u_ModelMatrix * position).xyz; + #if defined(r_showCubeProbes) + /* Hack: This is used for debug purposes only, + but it will break ST_REFLECTIONMAP and ST_COLLAPSE_REFLECTIONMAP stages */ + var_Position = (u_ModelMatrix * ( position - vec4( u_CameraPosition, 0.0 ) )).xyz; + #else + var_Position = (u_ModelMatrix * position).xyz; + #endif var_Tangent.xyz = (u_ModelMatrix * vec4(LB.tangent, 0.0)).xyz; var_Binormal.xyz = (u_ModelMatrix * vec4(LB.binormal, 0.0)).xyz; diff --git a/src/engine/renderer/glsl_source/refraction_C_fp.glsl b/src/engine/renderer/glsl_source/refraction_C_fp.glsl index 520335024..8d451ef69 100644 --- a/src/engine/renderer/glsl_source/refraction_C_fp.glsl +++ b/src/engine/renderer/glsl_source/refraction_C_fp.glsl @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* refraction_C_fp.glsl */ -uniform samplerCube u_ColorMap; +uniform samplerCube u_ColorMapCube; uniform vec3 u_ViewOrigin; uniform float u_RefractionIndex; uniform float u_FresnelPower; @@ -51,8 +51,8 @@ void main() // compute fresnel term float fresnel = u_FresnelBias + pow(1.0 - dot(incidentRay, normal), u_FresnelPower) * u_FresnelScale; - vec3 reflectColor = textureCube(u_ColorMap, reflectionRay).rgb; - vec3 refractColor = textureCube(u_ColorMap, T).rgb; + vec3 reflectColor = textureCube(u_ColorMapCube, reflectionRay).rgb; + vec3 refractColor = textureCube(u_ColorMapCube, T).rgb; // compute final color vec4 color; diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 34c1784e7..a5de777d1 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -4040,12 +4040,15 @@ static void RB_RenderDebugUtils() } // GLSL shader isn't built when reflection mapping is disabled. - if ( r_showCubeProbes->integer && tr.cubeHashTable && r_reflectionMapping->integer && + if ( r_showCubeProbes.Get() && tr.cubeHashTable && r_reflectionMapping->integer && !( backEnd.refdef.rdflags & ( RDF_NOWORLDMODEL | RDF_NOCUBEMAP ) ) ) { static const vec3_t mins = { -8, -8, -8 }; static const vec3_t maxs = { 8, 8, 8 }; + static const vec3_t outlineMins = { -9, -9, -9 }; + static const vec3_t outlineMaxs = { 9, 9, 9 }; + // choose right shader program ---------------------------------- gl_reflectionShader->SetVertexSkinning( false ); gl_reflectionShader->SetVertexAnimation( false ); @@ -4066,7 +4069,7 @@ static void RB_RenderDebugUtils() gl_reflectionShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); gl_reflectionShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); + gl_reflectionShader->SetUniform_InverseLightFactor( tr.mapInverseLightFactor ); for ( cubemapProbe_t *cubeProbe : tr.cubeProbes ) { @@ -4077,15 +4080,20 @@ static void RB_RenderDebugUtils() continue; } + Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); + + gl_reflectionShader->SetUniform_CameraPosition( cubeProbe->origin ); + // bind u_ColorMap - gl_reflectionShader->SetUniform_ColorMapBindless( - GL_BindToTMU( 0, cubeProbe->cubemap ) + gl_reflectionShader->SetUniform_ColorMapCubeBindless( + GL_BindToTMU( 0, cubeProbe->cubemap ) ); Tess_AddCubeWithNormals( cubeProbe->origin, mins, maxs, Color::White ); + + Tess_End(); } - Tess_End(); { cubemapProbe_t *cubeProbeNearest; @@ -4121,6 +4129,8 @@ static void RB_RenderDebugUtils() ); gl_genericShader->SetUniform_TextureMatrix( matrixIdentity ); + GL_State( GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS ); + GL_CheckErrors(); R_FindTwoNearestCubeMaps( backEnd.viewParms.orientation.origin, &cubeProbeNearest, &cubeProbeSecondNearest ); @@ -4133,12 +4143,12 @@ static void RB_RenderDebugUtils() } else if ( cubeProbeSecondNearest == nullptr ) { - Tess_AddCubeWithNormals( cubeProbeNearest->origin, mins, maxs, Color::Yellow ); + Tess_AddCubeWithNormals( cubeProbeNearest->origin, outlineMins, outlineMaxs, Color::Yellow ); } else { - Tess_AddCubeWithNormals( cubeProbeNearest->origin, mins, maxs, Color::Green ); - Tess_AddCubeWithNormals( cubeProbeSecondNearest->origin, mins, maxs, Color::Red ); + Tess_AddCubeWithNormals( cubeProbeNearest->origin, outlineMins, outlineMaxs, Color::Green ); + Tess_AddCubeWithNormals( cubeProbeSecondNearest->origin, outlineMins, outlineMaxs, Color::Red ); } Tess_End(); @@ -4814,23 +4824,16 @@ static void RB_RenderPostProcess() RB_FXAA(); - // render chromatric aberration + // render chromatic aberration RB_CameraPostFX(); // copy to given byte buffer that is NOT a FBO - if (tr.refdef.pixelTarget != nullptr) - { - int i; - - // need to convert Y axis - // Bugfix: drivers absolutely hate running in high res and using glReadPixels near the top or bottom edge. - // Sooo... let's do it in the middle. - glReadPixels(glConfig.vidWidth / 2, glConfig.vidHeight / 2, tr.refdef.pixelTargetWidth, tr.refdef.pixelTargetHeight, GL_RGBA, - GL_UNSIGNED_BYTE, tr.refdef.pixelTarget); + if ( tr.refdef.pixelTarget != nullptr ) { + glReadPixels( 0, 0, tr.refdef.pixelTargetWidth, tr.refdef.pixelTargetHeight, GL_RGBA, + GL_UNSIGNED_BYTE, tr.refdef.pixelTarget ); - for (i = 0; i < tr.refdef.pixelTargetWidth * tr.refdef.pixelTargetHeight; i++) - { - tr.refdef.pixelTarget[(i * 4) + 3] = 255; //set the alpha pure white + for ( int i = 0; i < tr.refdef.pixelTargetWidth * tr.refdef.pixelTargetHeight; i++ ) { + tr.refdef.pixelTarget[( i * 4 ) + 3] = 255; // Set the alpha to 1.0 } } diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index 1240ee761..3f6d39e53 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -6279,7 +6279,7 @@ static const int HASHTABLE_SIZE = 7919; // 32749 // 2039 /* prime, use % */ #define HASH_USE_EPSILON #ifdef HASH_USE_EPSILON -#define HASH_XYZ_EPSILON 100.0f +#define HASH_XYZ_EPSILON 256.0f #define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON #endif @@ -6501,19 +6501,6 @@ void R_FindTwoNearestCubeMaps( const vec3_t position, cubemapProbe_t **cubeProbe void R_BuildCubeMaps() { - int i; - int ii, jj; - bool flipx; - bool flipy; - int x, y, xy, xy2; - - byte temp[ REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4 ]; - byte *dest; - - int startTime, endTime; - size_t tics = 0; - size_t nextTicCount = 0; - // Early abort if a BSP is not loaded yet since // the buildcubemaps command can be called from // everywhere including the main menu. @@ -6522,13 +6509,19 @@ void R_BuildCubeMaps() return; } - startTime = ri.Milliseconds(); + const int cubeMapSize = r_cubeProbeSize.Get(); + if ( cubeMapSize > glConfig2.maxCubeMapTextureSize ) { + Log::Warn( "Cube probe size exceeds max cubemap texture size (%i/%i)", cubeMapSize, glConfig2.maxCubeMapTextureSize ); + return; + } + + const int startTime = ri.Milliseconds(); refdef_t rf{}; - for ( i = 0; i < 6; i++ ) + for ( int i = 0; i < 6; i++ ) { - tr.cubeTemp[ i ] = (byte*) Z_Malloc( REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4 ); + tr.cubeTemp[ i ] = (byte*) Z_Malloc( ( size_t ) cubeMapSize * cubeMapSize * 4 ); } // calculate origins for our probes @@ -6538,7 +6531,7 @@ void R_BuildCubeMaps() { bspNode_t *node; - for ( i = 0; i < tr.world->numnodes; i++ ) + for ( int i = 0; i < tr.world->numnodes; i++ ) { node = &tr.world->nodes[ i ]; @@ -6554,13 +6547,38 @@ void R_BuildCubeMaps() continue; } + // This eliminates most of the void nodes, however some may still be left around patch meshes + if ( !node->numMarkSurfaces ) { + continue; + } + + // There might be leafs with only invisible surfaces + bool hasVisibleSurfaces = false; + int surfaceCount = node->numMarkSurfaces; + bspSurface_t** view = tr.world->viewSurfaces + node->firstMarkSurface; + while ( surfaceCount-- ) { + bspSurface_t* surface = *view; + + view++; + + if ( *(surface->data) == surfaceType_t::SF_FACE || *(surface->data) == surfaceType_t::SF_TRIANGLES + || *(surface->data) == surfaceType_t::SF_VBO_MESH || *(surface->data) == surfaceType_t::SF_GRID ) { + hasVisibleSurfaces = true; + break; + } + } + + if ( !hasVisibleSurfaces ) { + continue; + } + vec3_t origin; VectorAdd( node->maxs, node->mins, origin ); VectorScale( origin, 0.5, origin ); if ( FindVertexInHashTable( tr.cubeHashTable, origin, 256 ) == nullptr ) { - auto *cubeProbe = (cubemapProbe_t*) ri.Hunk_Alloc( sizeof( cubemapProbe_t ), ha_pref::h_high ); + cubemapProbe_t* cubeProbe = (cubemapProbe_t*) ri.Hunk_Alloc( sizeof( cubemapProbe_t ), ha_pref::h_high ); tr.cubeProbes.push_back( cubeProbe ); VectorCopy( origin, cubeProbe->origin ); @@ -6579,40 +6597,14 @@ void R_BuildCubeMaps() VectorClear( cubeProbe->origin ); } - Log::Notice("...pre-rendering %d cubemaps", tr.cubeProbes.size() ); - Log::Notice("0%% 10 20 30 40 50 60 70 80 90 100%%" ); - Log::Notice("|----|----|----|----|----|----|----|----|----|----|" ); - - for ( size_t j = 0; j < tr.cubeProbes.size(); j++ ) - { - cubemapProbe_t *cubeProbe = tr.cubeProbes[ j ]; - - //Log::Notice("rendering cubemap at (%i %i %i)", (int)cubeProbe->origin[0], (int)cubeProbe->origin[1], - // (int)cubeProbe->origin[2]); - - if ( ( j + 1 ) >= nextTicCount ) - { - size_t ticsNeeded = ( size_t )( ( ( double )( j + 1 ) / tr.cubeProbes.size() ) * 50.0 ); - - do - { - Log::Notice("*"); - Cmd::ExecuteCommand("updatescreen"); - } - while ( ++tics < ticsNeeded ); - - nextTicCount = ( size_t )( ( tics / 50.0 ) * tr.cubeProbes.size() ); + Log::Notice( "...pre-rendering %d cubemaps", tr.cubeProbes.size() ); - if ( ( j + 1 ) == tr.cubeProbes.size() ) - { - if ( tics < 51 ) - { - Log::Notice("*"); - } + const bool gpuOcclusionCulling = r_gpuOcclusionCulling.Get(); + r_gpuOcclusionCulling.Set( false ); - Log::Notice(""); - } - } + for ( size_t i = 0; i < tr.cubeProbes.size(); i++ ) + { + cubemapProbe_t *cubeProbe = tr.cubeProbes[ i ]; VectorCopy( cubeProbe->origin, rf.vieworg ); @@ -6622,18 +6614,21 @@ void R_BuildCubeMaps() rf.fov_y = 90; rf.x = 0; rf.y = 0; - rf.width = REF_CUBEMAP_SIZE; - rf.height = REF_CUBEMAP_SIZE; + rf.width = cubeMapSize; + rf.height = cubeMapSize; rf.time = 0; + rf.gradingWeights[0] = 0.0; + rf.gradingWeights[1] = 0.0; + rf.gradingWeights[2] = 0.0; + rf.gradingWeights[3] = 1.0; + rf.rdflags = RDF_NOCUBEMAP | RDF_NOBLOOM; - for ( i = 0; i < 6; i++ ) + for ( int j = 0; j < 6; j++ ) { - flipx = false; - flipy = false; - switch ( i ) + switch ( j ) { case 0: { @@ -6647,7 +6642,6 @@ void R_BuildCubeMaps() rf.viewaxis[ 1 ][ 2 ] = 1; CrossProduct( rf.viewaxis[ 0 ], rf.viewaxis[ 1 ], rf.viewaxis[ 2 ] ); - //flipx=true; break; } @@ -6663,7 +6657,6 @@ void R_BuildCubeMaps() rf.viewaxis[ 1 ][ 2 ] = -1; CrossProduct( rf.viewaxis[ 0 ], rf.viewaxis[ 1 ], rf.viewaxis[ 2 ] ); - //flipx=true; break; } @@ -6679,7 +6672,6 @@ void R_BuildCubeMaps() rf.viewaxis[ 1 ][ 2 ] = 0; CrossProduct( rf.viewaxis[ 0 ], rf.viewaxis[ 1 ], rf.viewaxis[ 2 ] ); - //flipx=true; break; } @@ -6690,12 +6682,11 @@ void R_BuildCubeMaps() rf.viewaxis[ 0 ][ 1 ] = -1; rf.viewaxis[ 0 ][ 2 ] = 0; - rf.viewaxis[ 1 ][ 0 ] = -1; //-1 + rf.viewaxis[ 1 ][ 0 ] = -1; rf.viewaxis[ 1 ][ 1 ] = 0; rf.viewaxis[ 1 ][ 2 ] = 0; CrossProduct( rf.viewaxis[ 0 ], rf.viewaxis[ 1 ], rf.viewaxis[ 2 ] ); - //flipx=true; break; } @@ -6711,7 +6702,6 @@ void R_BuildCubeMaps() rf.viewaxis[ 1 ][ 2 ] = 0; CrossProduct( rf.viewaxis[ 0 ], rf.viewaxis[ 1 ], rf.viewaxis[ 2 ] ); - // flipx=true; break; } @@ -6727,72 +6717,46 @@ void R_BuildCubeMaps() rf.viewaxis[ 1 ][ 2 ] = 0; CrossProduct( rf.viewaxis[ 0 ], rf.viewaxis[ 1 ], rf.viewaxis[ 2 ] ); - //flipx=true; break; } } - tr.refdef.pixelTarget = tr.cubeTemp[ i ]; - memset( tr.cubeTemp[ i ], 255, REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4 ); - tr.refdef.pixelTargetWidth = REF_CUBEMAP_SIZE; - tr.refdef.pixelTargetHeight = REF_CUBEMAP_SIZE; + tr.refdef.pixelTarget = tr.cubeTemp[ j ]; + memset( tr.cubeTemp[ j ], 255, ( size_t ) cubeMapSize * cubeMapSize * 4 ); + tr.refdef.pixelTargetWidth = cubeMapSize; + tr.refdef.pixelTargetHeight = cubeMapSize; - RE_BeginFrame(); - RE_RenderScene( &rf ); - RE_EndFrame( &ii, &jj ); + int msecUnused1; + int msecUnused2; + // Material system writes culled surfaces for the next frame, so we need to render twice with it to cull correctly + if ( glConfig2.materialSystemAvailable ) { + tr.refdef.pixelTarget = nullptr; - if ( flipx ) - { - dest = tr.cubeTemp[ i ]; - memcpy( temp, dest, REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4 ); + RE_BeginFrame(); + RE_RenderScene( &rf ); + RE_EndFrame( &msecUnused1, &msecUnused2 ); - for ( y = 0; y < REF_CUBEMAP_SIZE; y++ ) - { - for ( x = 0; x < REF_CUBEMAP_SIZE; x++ ) - { - xy = ( ( y * REF_CUBEMAP_SIZE ) + x ) * 4; - xy2 = ( ( y * REF_CUBEMAP_SIZE ) + ( ( REF_CUBEMAP_SIZE - 1 ) - x ) ) * 4; - dest[ xy2 + 0 ] = temp[ xy + 0 ]; - dest[ xy2 + 1 ] = temp[ xy + 1 ]; - dest[ xy2 + 2 ] = temp[ xy + 2 ]; - dest[ xy2 + 3 ] = temp[ xy + 3 ]; - } - } + tr.refdef.pixelTarget = tr.cubeTemp[j]; } - if ( flipy ) - { - dest = tr.cubeTemp[ i ]; - memcpy( temp, dest, REF_CUBEMAP_SIZE * REF_CUBEMAP_SIZE * 4 ); - - for ( y = 0; y < REF_CUBEMAP_SIZE; y++ ) - { - for ( x = 0; x < REF_CUBEMAP_SIZE; x++ ) - { - xy = ( ( y * REF_CUBEMAP_SIZE ) + x ) * 4; - xy2 = ( ( ( ( REF_CUBEMAP_SIZE - 1 ) - y ) * REF_CUBEMAP_SIZE ) + x ) * 4; - dest[ xy2 + 0 ] = temp[ xy + 0 ]; - dest[ xy2 + 1 ] = temp[ xy + 1 ]; - dest[ xy2 + 2 ] = temp[ xy + 2 ]; - dest[ xy2 + 3 ] = temp[ xy + 3 ]; - } - } - } + RE_BeginFrame(); + RE_RenderScene( &rf ); + RE_EndFrame( &msecUnused1, &msecUnused2 ); // encode the pixel intensity into the alpha channel, saves work in the shader - byte r, g, b, best; + byte best; - dest = tr.cubeTemp[ i ]; + byte* dest = tr.cubeTemp[ j ]; - for ( y = 0; y < REF_CUBEMAP_SIZE; y++ ) + for ( int y = 0; y < cubeMapSize; y++ ) { - for ( x = 0; x < REF_CUBEMAP_SIZE; x++ ) + for ( int x = 0; x < cubeMapSize; x++ ) { - xy = ( ( y * REF_CUBEMAP_SIZE ) + x ) * 4; + int xy = ( ( y * cubeMapSize ) + x ) * 4; - r = dest[ xy + 0 ]; - g = dest[ xy + 1 ]; - b = dest[ xy + 2 ]; + const byte r = dest[ xy + 0 ]; + const byte g = dest[ xy + 1 ]; + const byte b = dest[ xy + 2 ]; if ( ( r > g ) && ( r > b ) ) { @@ -6813,7 +6777,7 @@ void R_BuildCubeMaps() } // build the cubemap - cubeProbe->cubemap = R_AllocImage( Str::Format( "_autoCube%d", j ).c_str(), false); + cubeProbe->cubemap = R_AllocImage( Str::Format( "_autoCube%d", i ).c_str(), false ); if ( !cubeProbe->cubemap ) { @@ -6822,8 +6786,8 @@ void R_BuildCubeMaps() cubeProbe->cubemap->type = GL_TEXTURE_CUBE_MAP; - cubeProbe->cubemap->width = REF_CUBEMAP_SIZE; - cubeProbe->cubemap->height = REF_CUBEMAP_SIZE; + cubeProbe->cubemap->width = cubeMapSize; + cubeProbe->cubemap->height = cubeMapSize; cubeProbe->cubemap->bits = IF_NOPICMIP; cubeProbe->cubemap->filterType = filterType_t::FT_LINEAR; @@ -6834,14 +6798,16 @@ void R_BuildCubeMaps() R_UploadImage( ( const byte ** ) tr.cubeTemp, 6, 1, cubeProbe->cubemap, imageParams ); } - Log::Notice(""); + r_gpuOcclusionCulling.Set( gpuOcclusionCulling ); + + Log::Notice( "" ); // turn pixel targets off tr.refdef.pixelTarget = nullptr; // assign the surfs a cubemap - endTime = ri.Milliseconds(); - Log::Notice("cubemap probes pre-rendering time of %i cubes = %5.2f seconds", tr.cubeProbes.size(), + const int endTime = ri.Milliseconds(); + Log::Notice( "Cubemap probes pre-rendering time of %d cubes = %5.2f seconds", tr.cubeProbes.size(), ( endTime - startTime ) / 1000.0 ); } diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 0df855c1a..2c2f202e3 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -162,6 +162,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_reliefMapping; cvar_t *r_glowMapping; cvar_t *r_reflectionMapping; + Cvar::Range> r_cubeProbeSize( "r_cubeProbeSize", "Size of the static reflections cubemaps", Cvar::NONE, + 32, 1, 32768 ); cvar_t *r_halfLambertLighting; cvar_t *r_rimLighting; @@ -218,7 +220,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_showDeluxeMaps; cvar_t *r_showNormalMaps; cvar_t *r_showMaterialMaps; - cvar_t *r_showCubeProbes; + Cvar::Cvar r_showReflectionMaps( "r_showReflectionMaps", "Show only the static reflections on surfaces", Cvar::NONE, false ); + Cvar::Cvar r_showCubeProbes( "r_showCubeProbes", "Show static reflections cubemap placement", Cvar::NONE, false ); + Cvar::Cvar r_showCubeProbeFace( "r_showCubeProbeFace", "Render from the perspective of a selected static reflection " + "cubemap face, -1 to disable", Cvar::NONE, -1 ); cvar_t *r_showBspNodes; cvar_t *r_showParallelShadowSplits; @@ -1217,6 +1222,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_reliefMapping = Cvar_Get( "r_reliefMapping", "0", CVAR_LATCH | CVAR_ARCHIVE ); r_glowMapping = Cvar_Get( "r_glowMapping", "1", CVAR_LATCH ); r_reflectionMapping = Cvar_Get( "r_reflectionMapping", "0", CVAR_LATCH | CVAR_ARCHIVE ); + Cvar::Latch( r_cubeProbeSize ); r_halfLambertLighting = Cvar_Get( "r_halfLambertLighting", "1", CVAR_LATCH | CVAR_ARCHIVE ); r_rimLighting = Cvar_Get( "r_rimLighting", "0", CVAR_LATCH | CVAR_ARCHIVE ); @@ -1310,7 +1316,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_showDeluxeMaps = Cvar_Get( "r_showDeluxeMaps", "0", CVAR_CHEAT | CVAR_LATCH ); r_showNormalMaps = Cvar_Get( "r_showNormalMaps", "0", CVAR_CHEAT | CVAR_LATCH ); r_showMaterialMaps = Cvar_Get( "r_showMaterialMaps", "0", CVAR_CHEAT | CVAR_LATCH ); - r_showCubeProbes = Cvar_Get( "r_showCubeProbes", "0", CVAR_CHEAT ); + Cvar::Latch( r_showReflectionMaps ); r_showBspNodes = Cvar_Get( "r_showBspNodes", "0", CVAR_CHEAT ); r_showParallelShadowSplits = Cvar_Get( "r_showParallelShadowSplits", "0", CVAR_CHEAT | CVAR_LATCH ); diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index f1685cde4..47405fa1e 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -322,9 +322,8 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; GLDEBUG_ALL }; -#define REF_CUBEMAP_SIZE 32 +#define REF_CUBEMAP_SIZE 32 #define REF_CUBEMAP_STORE_SIZE 1024 -#define REF_CUBEMAP_STORE_SIDE ( REF_CUBEMAP_STORE_SIZE / REF_CUBEMAP_SIZE ) #define REF_COLORGRADE_SLOTS 4 #define REF_COLORGRADEMAP_SIZE 16 @@ -2888,6 +2887,7 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; extern cvar_t *r_reliefMapping; extern cvar_t *r_glowMapping; extern cvar_t *r_reflectionMapping; + extern Cvar::Range> r_cubeProbeSize; extern cvar_t *r_halfLambertLighting; extern cvar_t *r_rimLighting; @@ -2968,7 +2968,9 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; extern cvar_t *r_showDeluxeMaps; extern cvar_t *r_showNormalMaps; extern cvar_t *r_showMaterialMaps; - extern cvar_t *r_showCubeProbes; + extern Cvar::Cvar r_showReflectionMaps; + extern Cvar::Cvar r_showCubeProbes; + extern Cvar::Cvar r_showCubeProbeFace; extern cvar_t *r_showBspNodes; extern cvar_t *r_showParallelShadowSplits; diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index f000efbac..659e19554 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -459,6 +459,135 @@ void RE_AddDynamicLightToSceneQ3A( const vec3_t org, float radius, float r, floa RE_AddDynamicLightToSceneET( org, radius, r_lightScale->value, r, g, b, 0, 0 ); } +static void RE_RenderCubeProbeFace( const refdef_t* originalRefdef ) { + const size_t globalID = r_showCubeProbeFace.Get(); + const size_t probeID = globalID / 6; + + if ( probeID >= tr.cubeProbes.size() ) { + Log::Warn( "Cube probe face out of range! (%i/%i)", probeID, tr.cubeProbes.size() ); + return; + } + + refdef_t refdef{}; + const int faceID = globalID % 6; + + const int cubeMapSize = r_cubeProbeSize.Get(); + + VectorCopy( tr.cubeProbes[probeID]->origin, refdef.vieworg ); + + refdef.fov_x = 90; + refdef.fov_y = 90; + refdef.x = 0; + refdef.y = 0; + refdef.width = cubeMapSize; + refdef.height = cubeMapSize; + refdef.time = originalRefdef->time; + VectorCopy( originalRefdef->gradingWeights, refdef.gradingWeights ); + + refdef.rdflags = RDF_NOCUBEMAP | RDF_NOBLOOM; + + switch ( faceID ) { + case 0: + { + //X+ + refdef.viewaxis[0][0] = 1; + refdef.viewaxis[0][1] = 0; + refdef.viewaxis[0][2] = 0; + + refdef.viewaxis[1][0] = 0; + refdef.viewaxis[1][1] = 0; + refdef.viewaxis[1][2] = 1; + + CrossProduct( refdef.viewaxis[0], refdef.viewaxis[1], refdef.viewaxis[2] ); + break; + } + + case 1: + { + //X- + refdef.viewaxis[0][0] = -1; + refdef.viewaxis[0][1] = 0; + refdef.viewaxis[0][2] = 0; + + refdef.viewaxis[1][0] = 0; + refdef.viewaxis[1][1] = 0; + refdef.viewaxis[1][2] = -1; + + CrossProduct( refdef.viewaxis[0], refdef.viewaxis[1], refdef.viewaxis[2] ); + break; + } + + case 2: + { + //Y+ + refdef.viewaxis[0][0] = 0; + refdef.viewaxis[0][1] = 1; + refdef.viewaxis[0][2] = 0; + + refdef.viewaxis[1][0] = -1; + refdef.viewaxis[1][1] = 0; + refdef.viewaxis[1][2] = 0; + + CrossProduct( refdef.viewaxis[0], refdef.viewaxis[1], refdef.viewaxis[2] ); + break; + } + + case 3: + { + //Y- + refdef.viewaxis[0][0] = 0; + refdef.viewaxis[0][1] = -1; + refdef.viewaxis[0][2] = 0; + + refdef.viewaxis[1][0] = -1; //-1 + refdef.viewaxis[1][1] = 0; + refdef.viewaxis[1][2] = 0; + + CrossProduct( refdef.viewaxis[0], refdef.viewaxis[1], refdef.viewaxis[2] ); + break; + } + + case 4: + { + //Z+ + refdef.viewaxis[0][0] = 0; + refdef.viewaxis[0][1] = 0; + refdef.viewaxis[0][2] = 1; + + refdef.viewaxis[1][0] = -1; + refdef.viewaxis[1][1] = 0; + refdef.viewaxis[1][2] = 0; + + CrossProduct( refdef.viewaxis[0], refdef.viewaxis[1], refdef.viewaxis[2] ); + break; + } + + case 5: + { + //Z- + refdef.viewaxis[0][0] = 0; + refdef.viewaxis[0][1] = 0; + refdef.viewaxis[0][2] = -1; + + refdef.viewaxis[1][0] = 1; + refdef.viewaxis[1][1] = 0; + refdef.viewaxis[1][2] = 0; + + CrossProduct( refdef.viewaxis[0], refdef.viewaxis[1], refdef.viewaxis[2] ); + break; + } + } + + if ( glConfig2.materialSystemAvailable ) { + // Material system writes culled surfaces for the next frame, so we need to render twice with it to cull correctly + R_SyncRenderThread(); + RE_RenderScene( &refdef ); + } + R_SyncRenderThread(); + RE_RenderScene( &refdef ); + +} + /* @@@@@@@@@@@@@@@@@@@@@ RE_RenderScene @@ -581,15 +710,16 @@ void RE_RenderScene( const refdef_t *fd ) if ( tr.refdef.pixelTarget == nullptr ) { parms.viewportX = tr.refdef.x; - parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height ); + if( fd->rdflags & RDF_NOCUBEMAP ) { + parms.viewportY = tr.refdef.height - ( tr.refdef.y + tr.refdef.height ); + } else { + parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height ); + } } else { - //Driver bug, if we try and do pixel target work along the top edge of a window - //we can end up capturing part of the status bar. (see screenshot corruption..) - //Soooo.. use the middle. - parms.viewportX = glConfig.vidWidth / 2; - parms.viewportY = glConfig.vidHeight / 2; + parms.viewportX = tr.refdef.x; + parms.viewportY = tr.refdef.height - ( tr.refdef.y + tr.refdef.height ); } parms.viewportWidth = tr.refdef.width; @@ -642,6 +772,11 @@ void RE_RenderScene( const refdef_t *fd ) r_firstSceneVisTest = r_numVisTests; tr.frontEndMsec += ri.Milliseconds() - startTime; + + if ( ( r_showCubeProbeFace.Get() >= 0 ) && tr.cubeHashTable && r_reflectionMapping->integer + && !( fd->rdflags & RDF_NOCUBEMAP ) ) { + RE_RenderCubeProbeFace( fd ); + } } /* diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 8b5a5387d..dd4b4341b 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -994,7 +994,8 @@ void Render_lightMapping( shaderStage_t *pStage ) // Not implemented yet in PBR code. bool enableReflectiveSpecular = - pStage->enableSpecularMapping && tr.cubeHashTable != nullptr && r_reflectionMapping->integer; + pStage->enableSpecularMapping && tr.cubeHashTable != nullptr && r_reflectionMapping->integer + && !( tr.refdef.rdflags & RDF_NOCUBEMAP ); GL_State( stateBits );