From 5d26aaddb35f38fea185adc217b974fd3a35ba9f Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 9 Apr 2021 22:28:09 +0200 Subject: [PATCH] Added parallax correction for local cubemaps --- .../lighting/ambient_lighting_IBL.ps.hlsl | 90 ++++++++++++++- .../lighting/ambient_lighting_IBL.vs.hlsl | 10 ++ neo/renderer/OpenGL/RenderDebug_GL.cpp | 20 +++- neo/renderer/RenderBackend.cpp | 23 ++++ neo/renderer/RenderCommon.h | 8 +- neo/renderer/RenderProgs.h | 1 + neo/renderer/RenderProgs_embedded.h | 100 ++++++++++++++++- neo/renderer/RenderWorld_defs.cpp | 106 ++++++++---------- neo/renderer/RenderWorld_envprobes.cpp | 65 +---------- neo/renderer/tr_frontend_main.cpp | 3 + 10 files changed, 294 insertions(+), 132 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl index 6a51b701..7a9d27bf 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl @@ -3,7 +3,7 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. -Copyright (C) 2013-2020 Robert Beckebans +Copyright (C) 2013-2021 Robert Beckebans This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). @@ -52,6 +52,7 @@ struct PS_IN half4 texcoord4 : TEXCOORD4_centroid; half4 texcoord5 : TEXCOORD5_centroid; half4 texcoord6 : TEXCOORD6_centroid; + half4 texcoord7 : TEXCOORD7_centroid; half4 color : COLOR0; }; @@ -61,6 +62,61 @@ struct PS_OUT }; // *INDENT-ON* +// RB: TODO OPTIMIZE +// this is a straight port of idBounds::RayIntersection +bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale ) +{ + int i, ax0, ax1, ax2, side, inside; + float f; + float3 hit; + + ax0 = -1; + inside = 0; + for( i = 0; i < 3; i++ ) + { + if( start[i] < b[0][i] ) + { + side = 0; + } + else if( start[i] > b[1][i] ) + { + side = 1; + } + else + { + inside++; + continue; + } + if( dir[i] == 0.0f ) + { + continue; + } + + f = ( start[i] - b[side][i] ); + + if( ax0 < 0 || abs( f ) > abs( scale * dir[i] ) ) + { + scale = - ( f / dir[i] ); + ax0 = i; + } + } + + if( ax0 < 0 ) + { + scale = 0.0f; + + // return true if the start point is inside the bounds + return ( inside == 3 ); + } + + ax1 = ( ax0 + 1 ) % 3; + ax2 = ( ax0 + 2 ) % 3; + hit[ax1] = start[ax1] + scale * dir[ax1]; + hit[ax2] = start[ax2] + scale * dir[ax2]; + + return ( hit[ax1] >= b[0][ax1] && hit[ax1] <= b[1][ax1] && + hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] ); +} void main( PS_IN fragment, out PS_OUT result ) { @@ -86,11 +142,41 @@ void main( PS_IN fragment, out PS_OUT result ) globalNormal.z = dot3( localNormal, fragment.texcoord6 ); globalNormal = normalize( globalNormal ); - float3 globalEye = normalize( fragment.texcoord3.xyz ); + float3 globalPosition = fragment.texcoord7.xyz; + + // RB: rpGlobalLightOrigin is global view origin + float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition ); float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal ); reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye ); +#if 1 + // parallax box correction using portal area bounds + float hitScale; + float3 bounds[2]; + bounds[0].x = rpWobbleSkyX.x; + bounds[0].y = rpWobbleSkyX.y; + bounds[0].z = rpWobbleSkyX.z; + + bounds[1].x = rpWobbleSkyY.x; + bounds[1].y = rpWobbleSkyY.y; + bounds[1].z = rpWobbleSkyY.z; + + // global fragment position + float3 rayStart = fragment.texcoord7.xyz; + + // we can't start inside the box so move this outside and use the reverse path + rayStart += reflectionVector * 10000; + + if( AABBRayIntersection( bounds, rayStart, -reflectionVector, hitScale ) ) + { + float3 hitPoint = rayStart - reflectionVector * hitScale; + + // rpWobbleSkyZ is cubemap center + reflectionVector = hitPoint - rpWobbleSkyZ.xyz; + } +#endif + half vDotN = saturate( dot3( globalEye, globalNormal ) ); #if defined( USE_PBR ) diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.vs.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.vs.hlsl index 7eee66c1..35bd0b7b 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.vs.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.vs.hlsl @@ -53,6 +53,7 @@ struct VS_OUT { float4 texcoord4 : TEXCOORD4; float4 texcoord5 : TEXCOORD5; float4 texcoord6 : TEXCOORD6; + float4 texcoord7 : TEXCOORD7; float4 color : COLOR0; }; // *INDENT-ON* @@ -157,6 +158,8 @@ void main( VS_IN vertex, out VS_OUT result ) result.texcoord2.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT ); //# calculate normalized vector to viewer in R1 + //result.texcoord3 = modelPosition; + float4 toEye = normalize( rpLocalViewOrigin - modelPosition ); result.texcoord3.x = dot3( toEye, rpModelMatrixX ); @@ -175,6 +178,13 @@ void main( VS_IN vertex, out VS_OUT result ) result.texcoord5.z = dot3( normal, rpModelMatrixY ); result.texcoord6.z = dot3( normal, rpModelMatrixZ ); + float4 worldPosition; + worldPosition.x = dot4( modelPosition, rpModelMatrixX ); + worldPosition.y = dot4( modelPosition, rpModelMatrixY ); + worldPosition.z = dot4( modelPosition, rpModelMatrixZ ); + worldPosition.w = dot4( modelPosition, rpModelMatrixW ); + result.texcoord7 = worldPosition; + #if defined( USE_GPU_SKINNING ) // for joint transformation of the tangent space, we use color and // color2 for weighting information, so hopefully there aren't any diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index e13ccd35..d893e379 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1714,13 +1714,13 @@ void idRenderBackend::DBG_ShowViewEnvprobes() GL_State( GLS_DEFAULT | GLS_CULL_TWOSIDED ); - renderProgManager.BindShader_Octahedron(); - int count = 0; for( viewEnvprobe_t* vProbe = viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next ) { count++; + renderProgManager.BindShader_Octahedron(); + GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); GL_Color( 1.0f, 1.0f, 1.0f ); @@ -1768,6 +1768,22 @@ void idRenderBackend::DBG_ShowViewEnvprobes() } DrawElementsWithCounters( &zeroOneSphereSurface ); + + // non-hidden lines +#if 0 + if( r_showViewEnvprobes.GetInteger() >= 3 ) + { + renderProgManager.BindShader_Color(); + + GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_POLYMODE_LINE | GLS_DEPTHMASK ); + GL_Color( 1.0f, 1.0f, 1.0f ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, vProbe->inverseBaseProbeProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + DrawElementsWithCounters( &zeroOneCubeSurface ); + } +#endif } } diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index b0cefddf..26d3ce04 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1325,6 +1325,25 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas // RB begin if( useIBL ) { + idVec4 probeMins, probeMaxs, probeCenter; + + probeMins[0] = viewDef->globalProbeBounds[0][0]; + probeMins[1] = viewDef->globalProbeBounds[0][1]; + probeMins[2] = viewDef->globalProbeBounds[0][2]; + probeMins[3] = viewDef->globalProbeBounds.IsCleared() ? 1.0f : 0.0f; + + probeMaxs[0] = viewDef->globalProbeBounds[1][0]; + probeMaxs[1] = viewDef->globalProbeBounds[1][1]; + probeMaxs[2] = viewDef->globalProbeBounds[1][2]; + probeMaxs[3] = 0.0f; + + idVec3& center = viewDef->globalProbeBounds.GetCenter(); + probeCenter.Set( center.x, center.y, center.z, 1.0f ); + + SetVertexParm( RENDERPARM_WOBBLESKY_X, probeMins.ToFloatPtr() ); + SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() ); + SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); + if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { // PBR path with roughness, metal and AO @@ -2210,6 +2229,10 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() ); + // use rpGlobalLightOrigin for camera center + idVec4 globalViewOrigin( viewDef->renderView.vieworg.x, viewDef->renderView.vieworg.y, viewDef->renderView.vieworg.z, 1.0f ); + SetVertexParm( RENDERPARM_GLOBALLIGHTORIGIN, globalViewOrigin.ToFloatPtr() ); + // setup renderparms assuming we will be drawing trivial surfaces first RB_SetupForFastPathInteractions( diffuseColor, specularColor ); diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 5d5e5bef..31974653 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -271,8 +271,8 @@ public: // derived information //idPlane lightProject[4]; // old style light projection where Z and W are flipped and projected lights lightProject[3] is divided by ( zNear + zFar ) - idRenderMatrix baseLightProject; // global xyz1 to projected light strq - idRenderMatrix inverseBaseLightProject;// transforms the zero-to-one cube to exactly cover the light in world space + //idRenderMatrix baseLightProject; // global xyz1 to projected light strq + idRenderMatrix inverseBaseProbeProject;// transforms the zero-to-one cube to exactly cover the light in world space idBounds globalProbeBounds; @@ -477,8 +477,9 @@ struct viewEnvprobe_t bool removeFromList; idVec3 globalOrigin; // global envprobe origin used by backend + idBounds globalProbeBounds; - idRenderMatrix inverseBaseLightProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the light volume in world space + idRenderMatrix inverseBaseProbeProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the light volume in world space idImage* irradianceImage; // cubemap image used for diffuse IBL by backend idImage* radianceImage; // cubemap image used for specular IBL by backend }; @@ -612,6 +613,7 @@ struct viewDef_t viewEnvprobe_t* viewEnvprobes; // RB: nearest probe for now + idBounds globalProbeBounds; idRenderMatrix inverseBaseEnvProbeProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the environent probe volume in world space idImage* irradianceImage; // cubemap image used for diffuse IBL by backend idImage* radianceImage; // cubemap image used for specular IBL by backend diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index ab20195f..e2f1076e 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -147,6 +147,7 @@ enum renderParm_t // RB begin RENDERPARM_AMBIENT_COLOR, +// RENDERPARM_GLOBALVIEWORIGIN, RENDERPARM_GLOBALLIGHTORIGIN, RENDERPARM_JITTERTEXSCALE, RENDERPARM_JITTERTEXOFFSET, diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index dd2e2cb1..316311e3 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -4491,7 +4491,7 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" "Doom 3 BFG Edition GPL Source Code\n" "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.\n" - "Copyright (C) 2013-2020 Robert Beckebans\n" + "Copyright (C) 2013-2021 Robert Beckebans\n" "\n" "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\").\n" "\n" @@ -4540,6 +4540,7 @@ static const cgShaderDef_t cg_renderprogs[] = " half4 texcoord4 : TEXCOORD4_centroid;\n" " half4 texcoord5 : TEXCOORD5_centroid;\n" " half4 texcoord6 : TEXCOORD6_centroid;\n" + " half4 texcoord7 : TEXCOORD7_centroid;\n" " half4 color : COLOR0;\n" "};\n" "\n" @@ -4549,6 +4550,61 @@ static const cgShaderDef_t cg_renderprogs[] = "};\n" "// *INDENT-ON*\n" "\n" + "// RB: TODO OPTIMIZE\n" + "// this is a straight port of idBounds::RayIntersection\n" + "bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale )\n" + "{\n" + " int i, ax0, ax1, ax2, side, inside;\n" + " float f;\n" + " float3 hit;\n" + "\n" + " ax0 = -1;\n" + " inside = 0;\n" + " for( i = 0; i < 3; i++ )\n" + " {\n" + " if( start[i] < b[0][i] )\n" + " {\n" + " side = 0;\n" + " }\n" + " else if( start[i] > b[1][i] )\n" + " {\n" + " side = 1;\n" + " }\n" + " else\n" + " {\n" + " inside++;\n" + " continue;\n" + " }\n" + " if( dir[i] == 0.0f )\n" + " {\n" + " continue;\n" + " }\n" + "\n" + " f = ( start[i] - b[side][i] );\n" + "\n" + " if( ax0 < 0 || abs( f ) > abs( scale * dir[i] ) )\n" + " {\n" + " scale = - ( f / dir[i] );\n" + " ax0 = i;\n" + " }\n" + " }\n" + "\n" + " if( ax0 < 0 )\n" + " {\n" + " scale = 0.0f;\n" + "\n" + " // return true if the start point is inside the bounds\n" + " return ( inside == 3 );\n" + " }\n" + "\n" + " ax1 = ( ax0 + 1 ) % 3;\n" + " ax2 = ( ax0 + 2 ) % 3;\n" + " hit[ax1] = start[ax1] + scale * dir[ax1];\n" + " hit[ax2] = start[ax2] + scale * dir[ax2];\n" + "\n" + " return ( hit[ax1] >= b[0][ax1] && hit[ax1] <= b[1][ax1] &&\n" + " hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] );\n" + "}\n" "\n" "void main( PS_IN fragment, out PS_OUT result )\n" "{\n" @@ -4574,11 +4630,41 @@ static const cgShaderDef_t cg_renderprogs[] = " globalNormal.z = dot3( localNormal, fragment.texcoord6 );\n" " globalNormal = normalize( globalNormal );\n" "\n" - " float3 globalEye = normalize( fragment.texcoord3.xyz );\n" + " float3 globalPosition = fragment.texcoord7.xyz;\n" + "\n" + " // RB: rpGlobalLightOrigin is global view origin\n" + " float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition );\n" "\n" " float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );\n" " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );\n" "\n" + "#if 1\n" + " // parallax box correction using portal area bounds\n" + " float hitScale;\n" + " float3 bounds[2];\n" + " bounds[0].x = rpWobbleSkyX.x;\n" + " bounds[0].y = rpWobbleSkyX.y;\n" + " bounds[0].z = rpWobbleSkyX.z;\n" + "\n" + " bounds[1].x = rpWobbleSkyY.x;\n" + " bounds[1].y = rpWobbleSkyY.y;\n" + " bounds[1].z = rpWobbleSkyY.z;\n" + "\n" + " // global fragment position\n" + " float3 rayStart = fragment.texcoord7.xyz;\n" + "\n" + " // we can't start inside the box so move this outside and use the reverse path\n" + " rayStart += reflectionVector * 10000;\n" + "\n" + " if( AABBRayIntersection( bounds, rayStart, -reflectionVector, hitScale ) )\n" + " {\n" + " float3 hitPoint = rayStart - reflectionVector * hitScale;\n" + "\n" + " // rpWobbleSkyZ is cubemap center\n" + " reflectionVector = hitPoint - rpWobbleSkyZ.xyz;\n" + " }\n" + "#endif\n" + "\n" " half vDotN = saturate( dot3( globalEye, globalNormal ) );\n" "\n" "#if defined( USE_PBR )\n" @@ -4746,6 +4832,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 texcoord4 : TEXCOORD4;\n" " float4 texcoord5 : TEXCOORD5;\n" " float4 texcoord6 : TEXCOORD6;\n" + " float4 texcoord7 : TEXCOORD7;\n" " float4 color : COLOR0;\n" "};\n" "// *INDENT-ON*\n" @@ -4850,6 +4937,8 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord2.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT );\n" "\n" " //# calculate normalized vector to viewer in R1\n" + " //result.texcoord3 = modelPosition;\n" + "\n" " float4 toEye = normalize( rpLocalViewOrigin - modelPosition );\n" "\n" " result.texcoord3.x = dot3( toEye, rpModelMatrixX );\n" @@ -4868,6 +4957,13 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord5.z = dot3( normal, rpModelMatrixY );\n" " result.texcoord6.z = dot3( normal, rpModelMatrixZ );\n" "\n" + " float4 worldPosition;\n" + " worldPosition.x = dot4( modelPosition, rpModelMatrixX );\n" + " worldPosition.y = dot4( modelPosition, rpModelMatrixY );\n" + " worldPosition.z = dot4( modelPosition, rpModelMatrixZ );\n" + " worldPosition.w = dot4( modelPosition, rpModelMatrixW );\n" + " result.texcoord7 = worldPosition;\n" + "\n" "#if defined( USE_GPU_SKINNING )\n" " // for joint transformation of the tangent space, we use color and\n" " // color2 for weighting information, so hopefully there aren't any\n" diff --git a/neo/renderer/RenderWorld_defs.cpp b/neo/renderer/RenderWorld_defs.cpp index a6b368cb..d48b6f0f 100644 --- a/neo/renderer/RenderWorld_defs.cpp +++ b/neo/renderer/RenderWorld_defs.cpp @@ -775,83 +775,67 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe ) probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); // ------------------------------------ - // compute the light projection matrix + // compute the probe projection matrix // ------------------------------------ - idRenderMatrix localProject; - float zScale = 1.0f; - float radius = 300.0f; // TODO + // determine the areaNum for the envprobe origin, which may let us + // cull the envprobe if it is behind a closed door + int areaNum = probe->world->PointInArea( probe->parms.origin ); - // An environemt probe uses a box projection like a point light. - // This projects into the 0.0 - 1.0 texture range instead of -1.0 to 1.0 clip space range. - localProject.Zero(); - localProject[0][0] = 0.5f / radius; - localProject[1][1] = 0.5f / radius; - localProject[2][2] = 0.5f / radius; - localProject[0][3] = 0.5f; - localProject[1][3] = 0.5f; - localProject[2][3] = 0.5f; - localProject[3][3] = 1.0f; // identity perspective + // HACK: this should be in the gamecode and set by the entity properties + probe->globalProbeBounds = probe->world->AreaBounds( areaNum ); - // set the old style light projection where Z and W are flipped and - // for projected lights lightProject[3] is divided by ( zNear + zFar ) - /* - light->lightProject[0][0] = localProject[0][0]; - light->lightProject[0][1] = localProject[0][1]; - light->lightProject[0][2] = localProject[0][2]; - light->lightProject[0][3] = localProject[0][3]; - - light->lightProject[1][0] = localProject[1][0]; - light->lightProject[1][1] = localProject[1][1]; - light->lightProject[1][2] = localProject[1][2]; - light->lightProject[1][3] = localProject[1][3]; - - light->lightProject[2][0] = localProject[3][0]; - light->lightProject[2][1] = localProject[3][1]; - light->lightProject[2][2] = localProject[3][2]; - light->lightProject[2][3] = localProject[3][3]; - - light->lightProject[3][0] = localProject[2][0] * zScale; - light->lightProject[3][1] = localProject[2][1] * zScale; - light->lightProject[3][2] = localProject[2][2] * zScale; - light->lightProject[3][3] = localProject[2][3] * zScale; - - // transform the lightProject - float lightTransform[16]; - R_AxisToModelMatrix( light->parms.axis, light->parms.origin, lightTransform ); - for( int i = 0; i < 4; i++ ) - { - idPlane temp = light->lightProject[i]; - R_LocalPlaneToGlobal( lightTransform, temp, light->lightProject[i] ); - } - */ - - // Rotate and translate the light projection by the light matrix. - // 99% of lights remain axis aligned in world space. idMat3 axis; axis.Identity(); - idRenderMatrix lightMatrix; - idRenderMatrix::CreateFromOriginAxis( probe->parms.origin, axis, lightMatrix ); + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( vec3_origin, axis, modelRenderMatrix ); - idRenderMatrix inverseLightMatrix; - if( !idRenderMatrix::Inverse( lightMatrix, inverseLightMatrix ) ) + // render from mins to maxs for debug rendering + //idRenderMatrix::CreateFromOriginAxis( probe->globalProbeBounds[0], axis, modelRenderMatrix ); + + idRenderMatrix inverseModelMatrix; + if( !idRenderMatrix::Inverse( modelRenderMatrix, inverseModelMatrix ) ) { idLib::Warning( "lightMatrix invert failed" ); } - // 'baseLightProject' goes from global space -> light local space -> light projective space - idRenderMatrix::Multiply( localProject, inverseLightMatrix, probe->baseLightProject ); + // move local bounds to center + idBounds localBounds; - // Invert the light projection so we can deform zero-to-one cubes into - // the light model and calculate global bounds. - if( !idRenderMatrix::Inverse( probe->baseLightProject, probe->inverseBaseLightProject ) ) +#if 0 + idVec3 corners[8]; + probe->globalProbeBounds.ToPoints( corners ); + + idVec3 corners2[8]; + for( int i = 0; i < 8; i++ ) { - idLib::Warning( "baseLightProject invert failed" ); + idVec4 p( corners[i].x, corners[i].y, corners[i].z, 1.0f ); + idVec4 o; + + inverseModelMatrix.TransformPoint( p, o ); + + corners2[i].Set( o.x, o.y, o.z ); } - // calculate the global light bounds by inverse projecting the zero to one cube with the 'inverseBaseLightProject' - idRenderMatrix::ProjectedBounds( probe->globalProbeBounds, probe->inverseBaseLightProject, bounds_zeroOneCube, false ); + localBounds.FromPoints( corners2, 8 ); +#else + //idVec3 center = probe->globalProbeBounds.GetCenter(); + + // offset it so it sits on 0 0 0 + //center += center; + + localBounds[0] = probe->globalProbeBounds[0] * 2; + localBounds[1] = probe->globalProbeBounds[1] * 2; + + //idRenderMatrix::CreateFromOriginAxis( -probe->globalProbeBounds[0] * 2, axis, modelRenderMatrix ); +#endif + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, localBounds, probe->inverseBaseProbeProject ); + + // calculate the global model bounds by inverse projecting the unit cube with the 'inverseBaseModelProject' + //idRenderMatrix::ProjectedBounds( probe->globalProbeBounds, probe->inverseBaseProbeProject, bounds_unitCube, false ); } void R_CreateEnvprobeRefs( RenderEnvprobeLocal* probe ) diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index 7bc39a07..e3c53460 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -62,7 +62,8 @@ viewEnvprobe_t* R_SetEnvprobeDefViewEnvprobe( RenderEnvprobeLocal* probe ) // copy data used by backend // RB: this would normaly go into R_AddSingleEnvprobe vProbe->globalOrigin = probe->parms.origin; - vProbe->inverseBaseLightProject = probe->inverseBaseLightProject; + vProbe->globalProbeBounds = probe->globalProbeBounds; + vProbe->inverseBaseProbeProject = probe->inverseBaseProbeProject; //if( probe->irradianceImage->IsLoaded() ) { @@ -104,7 +105,7 @@ bool idRenderWorldLocal::CullEnvprobeByPortals( const RenderEnvprobeLocal* probe if( r_useLightPortalCulling.GetInteger() == 1 ) { ALIGNTYPE16 frustumCorners_t corners; - idRenderMatrix::GetFrustumCorners( corners, probe->inverseBaseLightProject, bounds_zeroOneCube ); + idRenderMatrix::GetFrustumCorners( corners, probe->inverseBaseProbeProject, bounds_zeroOneCube ); for( int i = 0; i < ps->numPortalPlanes; i++ ) { if( idRenderMatrix::CullFrustumCornersToPlane( corners, ps->portalPlanes[i] ) == FRUSTUM_CULL_FRONT ) @@ -114,66 +115,6 @@ bool idRenderWorldLocal::CullEnvprobeByPortals( const RenderEnvprobeLocal* probe } } - else if( r_useLightPortalCulling.GetInteger() >= 2 ) - { - - idPlane frustumPlanes[6]; - idRenderMatrix::GetFrustumPlanes( frustumPlanes, probe->baseLightProject, true, true ); - - // exact clip of light faces against all planes - for( int i = 0; i < 6; i++ ) - { - // the light frustum planes face inward, so the planes that have the - // view origin on the positive side will be the "back" faces of the light, - // which must have some fragment inside the the portal stack planes to be visible - if( frustumPlanes[i].Distance( tr.viewDef->renderView.vieworg ) <= 0.0f ) - { - continue; - } - - // calculate a winding for this frustum side - idFixedWinding w; - w.BaseForPlane( frustumPlanes[i] ); - for( int j = 0; j < 6; j++ ) - { - if( j == i ) - { - continue; - } - if( !w.ClipInPlace( frustumPlanes[j], ON_EPSILON ) ) - { - break; - } - } - if( w.GetNumPoints() <= 2 ) - { - continue; - } - - assert( ps->numPortalPlanes <= MAX_PORTAL_PLANES ); - assert( w.GetNumPoints() + ps->numPortalPlanes < MAX_POINTS_ON_WINDING ); - - // now clip the winding against each of the portalStack planes - // skip the last plane which is the last portal itself - for( int j = 0; j < ps->numPortalPlanes - 1; j++ ) - { - if( !w.ClipInPlace( -ps->portalPlanes[j], ON_EPSILON ) ) - { - break; - } - } - - if( w.GetNumPoints() > 2 ) - { - // part of the winding is visible through the portalStack, - // so the light is not culled - return false; - } - } - - // nothing was visible - return true; - } return false; } diff --git a/neo/renderer/tr_frontend_main.cpp b/neo/renderer/tr_frontend_main.cpp index 951d7921..e9199c01 100644 --- a/neo/renderer/tr_frontend_main.cpp +++ b/neo/renderer/tr_frontend_main.cpp @@ -544,6 +544,8 @@ void R_RenderView( viewDef_t* parms ) { float bestDist = idMath::INFINITY; + tr.viewDef->globalProbeBounds.Clear(); + tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube; tr.viewDef->radianceImage = globalImages->defaultUACRadianceCube; @@ -554,6 +556,7 @@ void R_RenderView( viewDef_t* parms ) { if( vProbe->irradianceImage->IsLoaded() && !vProbe->irradianceImage->IsDefaulted() ) { + tr.viewDef->globalProbeBounds = vProbe->globalProbeBounds; tr.viewDef->irradianceImage = vProbe->irradianceImage; tr.viewDef->radianceImage = vProbe->radianceImage;