mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-14 22:50:45 +00:00
Added parallax correction for local cubemaps
This commit is contained in:
parent
c40ab1e7e8
commit
5d26aaddb3
10 changed files with 294 additions and 132 deletions
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -147,6 +147,7 @@ enum renderParm_t
|
|||
// RB begin
|
||||
RENDERPARM_AMBIENT_COLOR,
|
||||
|
||||
// RENDERPARM_GLOBALVIEWORIGIN,
|
||||
RENDERPARM_GLOBALLIGHTORIGIN,
|
||||
RENDERPARM_JITTERTEXSCALE,
|
||||
RENDERPARM_JITTERTEXOFFSET,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue