mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-04-24 02:32:18 +00:00
Merge branch '545-irradiance-light-grid'
This commit is contained in:
commit
5b0a3a8ac8
33 changed files with 4826 additions and 329 deletions
|
@ -15,6 +15,8 @@ return
|
|||
"builtin/debug/shadowDebug_skinned.vs.hlsl",
|
||||
"builtin/debug/octahedron.ps.hlsl",
|
||||
"builtin/debug/octahedron.vs.hlsl",
|
||||
"builtin/debug/lightgrid.ps.hlsl",
|
||||
"builtin/debug/lightgrid.vs.hlsl",
|
||||
|
||||
"builtin/fog/blendLight.ps.hlsl",
|
||||
"builtin/fog/blendLight.vs.hlsl",
|
||||
|
@ -40,6 +42,8 @@ return
|
|||
"builtin/lighting/ambient_lighting.vs.hlsl",
|
||||
"builtin/lighting/ambient_lighting_IBL.ps.hlsl",
|
||||
"builtin/lighting/ambient_lighting_IBL.vs.hlsl",
|
||||
"builtin/lighting/ambient_lightgrid_IBL.ps.hlsl",
|
||||
"builtin/lighting/ambient_lightgrid_IBL.vs.hlsl",
|
||||
"builtin/lighting/interaction.ps.hlsl",
|
||||
"builtin/lighting/interaction.vs.hlsl",
|
||||
"builtin/lighting/interactionAmbient.ps.hlsl",
|
||||
|
|
129
base/renderprogs/builtin/debug/lightgrid.ps.hlsl
Normal file
129
base/renderprogs/builtin/debug/lightgrid.ps.hlsl
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2021 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "renderprogs/global.inc.hlsl"
|
||||
|
||||
|
||||
// *INDENT-OFF*
|
||||
uniform sampler2D samp0 : register(s0); // texture 0 is octahedron cube map atlas
|
||||
|
||||
struct PS_IN {
|
||||
float4 position : VPOS;
|
||||
float3 texcoord0 : TEXCOORD0_centroid;
|
||||
float3 texcoord1 : TEXCOORD1_centroid;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
|
||||
struct PS_OUT {
|
||||
float4 color : COLOR;
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
|
||||
int3 GetBaseGridCoord( float3 origin )
|
||||
{
|
||||
float3 lightGridOrigin = rpGlobalLightOrigin.xyz;
|
||||
float3 lightGridSize = rpJitterTexScale.xyz;
|
||||
int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z );
|
||||
|
||||
int3 pos;
|
||||
|
||||
float3 lightOrigin = origin - lightGridOrigin;
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
float v;
|
||||
|
||||
v = lightOrigin[i] * ( 1.0f / lightGridSize[i] );
|
||||
pos[i] = int( floor( v ) );
|
||||
|
||||
if( pos[i] < 0 )
|
||||
{
|
||||
pos[i] = 0;
|
||||
}
|
||||
else if( pos[i] >= lightGridBounds[i] - 1 )
|
||||
{
|
||||
pos[i] = lightGridBounds[i] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void main( PS_IN fragment, out PS_OUT result )
|
||||
{
|
||||
const int LIGHTGRID_IRRADIANCE_SIZE = 32;
|
||||
|
||||
float3 globalPosition = fragment.texcoord0.xyz;
|
||||
float3 globalNormal = normalize( fragment.texcoord1 );
|
||||
|
||||
float2 normalizedOctCoord = octEncode( globalNormal );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
|
||||
float3 lightGridOrigin = rpGlobalLightOrigin.xyz;
|
||||
float3 lightGridSize = rpJitterTexScale.xyz;
|
||||
int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z );
|
||||
|
||||
float invXZ = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[2] ) );
|
||||
float invY = ( 1.0 / lightGridBounds[1] );
|
||||
|
||||
normalizedOctCoordZeroOne.x *= invXZ;
|
||||
normalizedOctCoordZeroOne.y *= invY;
|
||||
|
||||
int3 gridStep;
|
||||
|
||||
gridStep[0] = 1;
|
||||
gridStep[1] = lightGridBounds[0];
|
||||
gridStep[2] = lightGridBounds[0] * lightGridBounds[1];
|
||||
|
||||
int3 gridCoord = GetBaseGridCoord( globalPosition );
|
||||
|
||||
normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * invXZ;
|
||||
normalizedOctCoordZeroOne.y += ( gridCoord[1] * invY );
|
||||
|
||||
// offset by one pixel border bleed size for linear filtering
|
||||
#if 1
|
||||
// rpScreenCorrectionFactor.x = probeSize - borderSize, e.g. ( 18 - 2 ) = 16
|
||||
// rpScreenCorrectionFactor.y = probeSize including border, e.g = 18
|
||||
// rpScreenCorrectionFactor.z = borderSize e.g = 2
|
||||
// rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888
|
||||
float2 octCoordNormalizedToTextureDimensions = normalizedOctCoordZeroOne * rpScreenCorrectionFactor.w;
|
||||
|
||||
float2 probeTopLeftPosition;
|
||||
probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;
|
||||
probeTopLeftPosition.y = ( gridCoord[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;
|
||||
|
||||
float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;
|
||||
|
||||
normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;
|
||||
#endif
|
||||
|
||||
float4 envMap = texture( samp0, normalizedOctCoordZeroOne, 0 );
|
||||
|
||||
result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color;
|
||||
}
|
126
base/renderprogs/builtin/debug/lightgrid.vs.hlsl
Normal file
126
base/renderprogs/builtin/debug/lightgrid.vs.hlsl
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2021 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "renderprogs/global.inc.hlsl"
|
||||
|
||||
|
||||
uniform matrices_ubo { float4 matrices[408]; };
|
||||
|
||||
// *INDENT-OFF*
|
||||
struct VS_IN {
|
||||
float4 position : POSITION;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 normal : NORMAL;
|
||||
float4 tangent : TANGENT;
|
||||
float4 color : COLOR0;
|
||||
float4 color2 : COLOR1;
|
||||
};
|
||||
|
||||
struct VS_OUT {
|
||||
float4 position : POSITION;
|
||||
float3 texcoord0 : TEXCOORD0;
|
||||
float3 texcoord1 : TEXCOORD1;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
void main( VS_IN vertex, out VS_OUT result )
|
||||
{
|
||||
float4 vNormal = vertex.normal * 2.0 - 1.0;
|
||||
|
||||
#if defined( USE_GPU_SKINNING )
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// GPU transformation of the normal / binormal / bitangent
|
||||
//
|
||||
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
|
||||
//--------------------------------------------------------------
|
||||
const float w0 = vertex.color2.x;
|
||||
const float w1 = vertex.color2.y;
|
||||
const float w2 = vertex.color2.z;
|
||||
const float w3 = vertex.color2.w;
|
||||
|
||||
float4 matX, matY, matZ; // must be float4 for vec4
|
||||
int joint = int( vertex.color.x * 255.1 * 3.0 );
|
||||
matX = matrices[int( joint + 0 )] * w0;
|
||||
matY = matrices[int( joint + 1 )] * w0;
|
||||
matZ = matrices[int( joint + 2 )] * w0;
|
||||
|
||||
joint = int( vertex.color.y * 255.1 * 3.0 );
|
||||
matX += matrices[int( joint + 0 )] * w1;
|
||||
matY += matrices[int( joint + 1 )] * w1;
|
||||
matZ += matrices[int( joint + 2 )] * w1;
|
||||
|
||||
joint = int( vertex.color.z * 255.1 * 3.0 );
|
||||
matX += matrices[int( joint + 0 )] * w2;
|
||||
matY += matrices[int( joint + 1 )] * w2;
|
||||
matZ += matrices[int( joint + 2 )] * w2;
|
||||
|
||||
joint = int( vertex.color.w * 255.1 * 3.0 );
|
||||
matX += matrices[int( joint + 0 )] * w3;
|
||||
matY += matrices[int( joint + 1 )] * w3;
|
||||
matZ += matrices[int( joint + 2 )] * w3;
|
||||
|
||||
float3 normal;
|
||||
normal.x = dot3( matX, vNormal );
|
||||
normal.y = dot3( matY, vNormal );
|
||||
normal.z = dot3( matZ, vNormal );
|
||||
normal = normalize( normal );
|
||||
|
||||
float4 modelPosition;
|
||||
modelPosition.x = dot4( matX, vertex.position );
|
||||
modelPosition.y = dot4( matY, vertex.position );
|
||||
modelPosition.z = dot4( matZ, vertex.position );
|
||||
modelPosition.w = 1.0;
|
||||
|
||||
#else
|
||||
|
||||
float4 modelPosition = vertex.position;
|
||||
float4 normal = vNormal;
|
||||
|
||||
#endif
|
||||
|
||||
result.position.x = dot4( modelPosition, rpMVPmatrixX );
|
||||
result.position.y = dot4( modelPosition, rpMVPmatrixY );
|
||||
result.position.z = dot4( modelPosition, rpMVPmatrixZ );
|
||||
result.position.w = dot4( modelPosition, rpMVPmatrixW );
|
||||
|
||||
result.texcoord1.x = dot3( normal, rpModelMatrixX );
|
||||
result.texcoord1.y = dot3( normal, rpModelMatrixY );
|
||||
result.texcoord1.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.texcoord0 = worldPosition.xyz;
|
||||
|
||||
result.color = sRGBAToLinearRGBA( rpColor );
|
||||
}
|
|
@ -58,7 +58,19 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
float2 normalizedOctCoord = octEncode( reflectionVector );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
|
||||
float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne );
|
||||
// offset by one pixel border bleed size for linear filtering
|
||||
#if 0
|
||||
float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy;
|
||||
|
||||
result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;
|
||||
float2 probeTopLeftPosition = float2( 1.0, 1.0 );
|
||||
float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;
|
||||
|
||||
normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;
|
||||
#endif
|
||||
|
||||
//normalizedOctCoordZeroOne = TextureCoordFromDirection( reflectionVector, 0, int( rpCascadeDistances.x ), int( rpCascadeDistances.y ), int( rpCascadeDistances.x ) - 2 );
|
||||
|
||||
float4 envMap = texture( samp0, normalizedOctCoordZeroOne, 0 );
|
||||
|
||||
result.color = float4( envMap.xyz, 1.0f ) * fragment.color * 1.0;
|
||||
}
|
||||
|
|
435
base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl
Normal file
435
base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl
Normal file
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
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").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "renderprogs/global.inc.hlsl"
|
||||
|
||||
#include "renderprogs/BRDF.inc.hlsl"
|
||||
|
||||
|
||||
// *INDENT-OFF*
|
||||
uniform sampler2D samp0 : register(s0); // texture 0 is the per-surface normal map
|
||||
uniform sampler2D samp1 : register(s1); // texture 1 is the per-surface specular or roughness/metallic/AO mixer map
|
||||
uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map
|
||||
uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT
|
||||
uniform sampler2D samp4 : register(s4); // texture 4 is SSAO
|
||||
|
||||
uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map
|
||||
uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1
|
||||
uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2
|
||||
uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3
|
||||
|
||||
struct PS_IN
|
||||
{
|
||||
half4 position : VPOS;
|
||||
half4 texcoord0 : TEXCOORD0_centroid;
|
||||
half4 texcoord1 : TEXCOORD1_centroid;
|
||||
half4 texcoord2 : TEXCOORD2_centroid;
|
||||
half4 texcoord3 : TEXCOORD3_centroid;
|
||||
half4 texcoord4 : TEXCOORD4_centroid;
|
||||
half4 texcoord5 : TEXCOORD5_centroid;
|
||||
half4 texcoord6 : TEXCOORD6_centroid;
|
||||
half4 texcoord7 : TEXCOORD7_centroid;
|
||||
half4 color : COLOR0;
|
||||
};
|
||||
|
||||
struct PS_OUT
|
||||
{
|
||||
half4 color : COLOR;
|
||||
};
|
||||
// *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 )
|
||||
{
|
||||
half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );
|
||||
half4 YCoCG = tex2D( samp2, fragment.texcoord1.xy );
|
||||
half4 specMapSRGB = tex2D( samp1, fragment.texcoord2.xy );
|
||||
half4 specMap = sRGBAToLinearRGBA( specMapSRGB );
|
||||
|
||||
half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) );
|
||||
|
||||
half3 localNormal;
|
||||
#if defined(USE_NORMAL_FMT_RGB8)
|
||||
localNormal.xy = bumpMap.rg - 0.5;
|
||||
#else
|
||||
localNormal.xy = bumpMap.wy - 0.5;
|
||||
#endif
|
||||
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
|
||||
localNormal = normalize( localNormal );
|
||||
|
||||
float3 globalNormal;
|
||||
globalNormal.x = dot3( localNormal, fragment.texcoord4 );
|
||||
globalNormal.y = dot3( localNormal, fragment.texcoord5 );
|
||||
globalNormal.z = dot3( localNormal, fragment.texcoord6 );
|
||||
globalNormal = normalize( globalNormal );
|
||||
|
||||
float3 globalPosition = fragment.texcoord7.xyz;
|
||||
|
||||
float3 globalView = normalize( rpGlobalEyePos.xyz - globalPosition );
|
||||
|
||||
float3 reflectionVector = globalNormal * dot3( globalView, globalNormal );
|
||||
reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView );
|
||||
|
||||
#if 0
|
||||
// parallax box correction using portal area bounds
|
||||
float hitScale = 0.0;
|
||||
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.0;
|
||||
|
||||
// only do a box <-> ray intersection test if we use a local cubemap
|
||||
if( ( rpWobbleSkyX.w > 0.0 ) && AABBRayIntersection( bounds, rayStart, -reflectionVector, hitScale ) )
|
||||
{
|
||||
float3 hitPoint = rayStart - reflectionVector * hitScale;
|
||||
|
||||
// rpWobbleSkyZ is cubemap center
|
||||
reflectionVector = hitPoint - rpWobbleSkyZ.xyz;
|
||||
}
|
||||
#endif
|
||||
|
||||
half vDotN = saturate( dot3( globalView, globalNormal ) );
|
||||
|
||||
#if defined( USE_PBR )
|
||||
const half metallic = specMapSRGB.g;
|
||||
const half roughness = specMapSRGB.r;
|
||||
const half glossiness = 1.0 - roughness;
|
||||
|
||||
// the vast majority of real-world materials (anything not metal or gems) have F(0°)
|
||||
// values in a very narrow range (~0.02 - 0.08)
|
||||
|
||||
// approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4)
|
||||
const half3 dielectricColor = half3( 0.04 );
|
||||
|
||||
// derive diffuse and specular from albedo(m) base color
|
||||
const half3 baseColor = diffuseMap;
|
||||
|
||||
half3 diffuseColor = baseColor * ( 1.0 - metallic );
|
||||
half3 specularColor = lerp( dielectricColor, baseColor, metallic );
|
||||
|
||||
#if defined( DEBUG_PBR )
|
||||
diffuseColor = half3( 0.0, 0.0, 0.0 );
|
||||
specularColor = half3( 0.0, 1.0, 0.0 );
|
||||
#endif
|
||||
|
||||
float3 kS = Fresnel_SchlickRoughness( specularColor, vDotN, roughness );
|
||||
float3 kD = ( float3( 1.0, 1.0, 1.0 ) - kS ) * ( 1.0 - metallic );
|
||||
|
||||
#else
|
||||
const float roughness = EstimateLegacyRoughness( specMapSRGB.rgb );
|
||||
|
||||
half3 diffuseColor = diffuseMap;
|
||||
half3 specularColor = specMap.rgb;
|
||||
|
||||
#if defined( DEBUG_PBR )
|
||||
diffuseColor = half3( 0.0, 0.0, 0.0 );
|
||||
specularColor = half3( 1.0, 0.0, 0.0 );
|
||||
#endif
|
||||
|
||||
float3 kS = Fresnel_SchlickRoughness( specularColor, vDotN, roughness );
|
||||
|
||||
// NOTE: metalness is missing
|
||||
float3 kD = ( float3( 1.0, 1.0, 1.0 ) - kS );
|
||||
|
||||
#endif
|
||||
|
||||
//diffuseColor = half3( 1.0, 1.0, 1.0 );
|
||||
//diffuseColor = half3( 0.0, 0.0, 0.0 );
|
||||
|
||||
// calculate the screen texcoord in the 0.0 to 1.0 range
|
||||
//float2 screenTexCoord = vposToScreenPosTexCoord( fragment.position.xy );
|
||||
float2 screenTexCoord = fragment.position.xy * rpWindowCoord.xy;
|
||||
|
||||
float ao = 1.0;
|
||||
ao = tex2D( samp4, screenTexCoord ).r;
|
||||
//diffuseColor.rgb *= ao;
|
||||
|
||||
// evaluate diffuse IBL
|
||||
|
||||
float2 normalizedOctCoord = octEncode( globalNormal );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
|
||||
// lightgrid atlas
|
||||
|
||||
//float3 lightGridOrigin = float3( -192.0, -128.0, 0 );
|
||||
//float3 lightGridSize = float3( 64.0, 64.0, 128.0 );
|
||||
//int3 lightGridBounds = int3( 7, 7, 3 );
|
||||
|
||||
float3 lightGridOrigin = rpGlobalLightOrigin.xyz;
|
||||
float3 lightGridSize = rpJitterTexScale.xyz;
|
||||
int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z );
|
||||
|
||||
float invXZ = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[2] ) );
|
||||
float invY = ( 1.0 / lightGridBounds[1] );
|
||||
|
||||
normalizedOctCoordZeroOne.x *= invXZ;
|
||||
normalizedOctCoordZeroOne.y *= invY;
|
||||
|
||||
int3 gridCoord;
|
||||
float3 frac;
|
||||
float3 lightOrigin = globalPosition - lightGridOrigin;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
float v;
|
||||
|
||||
// walls can be sampled behind the grid sometimes so avoid negative weights
|
||||
v = max( 0, lightOrigin[i] * ( 1.0 / lightGridSize[i] ) );
|
||||
gridCoord[i] = int( floor( v ) );
|
||||
frac[ i ] = v - gridCoord[ i ];
|
||||
|
||||
/*
|
||||
if( gridCoord[i] < 0 )
|
||||
{
|
||||
gridCoord[i] = 0;
|
||||
}
|
||||
else
|
||||
*/
|
||||
if( gridCoord[i] >= lightGridBounds[i] - 1 )
|
||||
{
|
||||
gridCoord[i] = lightGridBounds[i] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// trilerp the light value
|
||||
int3 gridStep;
|
||||
|
||||
gridStep[0] = 1;
|
||||
gridStep[1] = lightGridBounds[0];
|
||||
gridStep[2] = lightGridBounds[0] * lightGridBounds[1];
|
||||
|
||||
float totalFactor = 0.0;
|
||||
float3 irradiance = float3( 0.0, 0.0, 0.0 );
|
||||
|
||||
/*
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
if( i & ( 1 << j ) )
|
||||
|
||||
results in these offsets
|
||||
*/
|
||||
const float3 cornerOffsets[8] = float3[](
|
||||
float3( 0.0, 0.0, 0.0 ),
|
||||
float3( 1.0, 0.0, 0.0 ),
|
||||
float3( 0.0, 2.0, 0.0 ),
|
||||
float3( 1.0, 2.0, 0.0 ),
|
||||
float3( 0.0, 0.0, 4.0 ),
|
||||
float3( 1.0, 0.0, 4.0 ),
|
||||
float3( 0.0, 2.0, 4.0 ),
|
||||
float3( 1.0, 2.0, 4.0 ) );
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
float factor = 1.0;
|
||||
|
||||
int3 gridCoord2 = gridCoord;
|
||||
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
if( cornerOffsets[ i ][ j ] > 0.0 )
|
||||
{
|
||||
factor *= frac[ j ];
|
||||
|
||||
gridCoord2[ j ] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
factor *= ( 1.0 - frac[ j ] );
|
||||
}
|
||||
}
|
||||
|
||||
// build P
|
||||
//float3 P = lightGridOrigin + ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] + gridCoord2[2] * gridStep[2] );
|
||||
|
||||
float2 atlasOffset;
|
||||
|
||||
atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ;
|
||||
atlasOffset.y = ( gridCoord2[1] * invY );
|
||||
|
||||
// offset by one pixel border bleed size for linear filtering
|
||||
#if 1
|
||||
// rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888
|
||||
float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne + atlasOffset ) * rpScreenCorrectionFactor.w;
|
||||
|
||||
// skip by default 2 pixels for each grid cell and offset the start position by (1,1)
|
||||
// rpScreenCorrectionFactor.z = borderSize e.g = 2
|
||||
float2 probeTopLeftPosition;
|
||||
probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;
|
||||
probeTopLeftPosition.y = ( gridCoord2[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;
|
||||
|
||||
float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;
|
||||
|
||||
float2 atlasCoord = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;
|
||||
#else
|
||||
float2 atlasCoord = normalizedOctCoordZeroOne + atlasOffset;
|
||||
#endif
|
||||
|
||||
float3 color = texture( samp7, atlasCoord, 0 ).rgb;
|
||||
|
||||
if( ( color.r + color.g + color.b ) < 0.0001 )
|
||||
{
|
||||
// ignore samples in walls
|
||||
continue;
|
||||
}
|
||||
|
||||
irradiance += color * factor;
|
||||
totalFactor += factor;
|
||||
}
|
||||
|
||||
if( totalFactor > 0.0 && totalFactor < 0.9999 )
|
||||
{
|
||||
totalFactor = 1.0 / totalFactor;
|
||||
|
||||
irradiance *= totalFactor;
|
||||
}
|
||||
|
||||
// lightgrid atlas
|
||||
|
||||
|
||||
float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );
|
||||
|
||||
// evaluate specular IBL
|
||||
|
||||
// should be 8 = numMips - 1, 256^2 = 9 mips
|
||||
const float MAX_REFLECTION_LOD = 10.0;
|
||||
float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD );
|
||||
//float mip = 0.0;
|
||||
|
||||
normalizedOctCoord = octEncode( reflectionVector );
|
||||
normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
|
||||
float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x;
|
||||
radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y;
|
||||
radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z;
|
||||
//radiance = float3( 0.0 );
|
||||
|
||||
// RB: HACK dim down room radiance by better local irradiance brightness
|
||||
//float luma = PhotoLuma( irradiance );
|
||||
//float luma = dot( irradiance, LUMINANCE_LINEAR.rgb );
|
||||
//float luma = length( irradiance.rgb );
|
||||
//radiance *= ( luma * rpSpecularModifier.x * 3.0 );
|
||||
|
||||
float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;
|
||||
|
||||
#if 0
|
||||
result.color.rgb = float3( envBRDF.x, envBRDF.y, 0.0 );
|
||||
result.color.w = fragment.color.a;
|
||||
return;
|
||||
#endif
|
||||
|
||||
float specAO = ComputeSpecularAO( vDotN, ao, roughness );
|
||||
float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 );
|
||||
|
||||
#if 1
|
||||
// Marmoset Horizon Fade trick
|
||||
const half horizonFade = 1.3;
|
||||
half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );
|
||||
horiz *= horiz;
|
||||
//horiz = clamp( horiz, 0.0, 1.0 );
|
||||
#endif
|
||||
|
||||
half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );
|
||||
//half3 lightColor = ( rpAmbientColor.rgb );
|
||||
|
||||
//result.color.rgb = diffuseLight;
|
||||
//result.color.rgb = diffuseLight * lightColor;
|
||||
//result.color.rgb = specularLight;
|
||||
result.color.rgb = ( diffuseLight + specularLight * horiz ) * lightColor * fragment.color.rgb;
|
||||
//result.color.rgb = localNormal.xyz * 0.5 + 0.5;
|
||||
//result.color.rgb = float3( ao );
|
||||
result.color.w = fragment.color.a;
|
||||
}
|
196
base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl
Normal file
196
base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2013-2015 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "renderprogs/global.inc.hlsl"
|
||||
|
||||
|
||||
#if defined( USE_GPU_SKINNING )
|
||||
uniform matrices_ubo { float4 matrices[408]; };
|
||||
#endif
|
||||
|
||||
// *INDENT-OFF*
|
||||
struct VS_IN {
|
||||
float4 position : POSITION;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
float4 normal : NORMAL;
|
||||
float4 tangent : TANGENT;
|
||||
float4 color : COLOR0;
|
||||
float4 color2 : COLOR1;
|
||||
};
|
||||
|
||||
struct VS_OUT {
|
||||
float4 position : POSITION;
|
||||
float4 texcoord0 : TEXCOORD0;
|
||||
float4 texcoord1 : TEXCOORD1;
|
||||
float4 texcoord2 : TEXCOORD2;
|
||||
float4 texcoord3 : TEXCOORD3;
|
||||
float4 texcoord4 : TEXCOORD4;
|
||||
float4 texcoord5 : TEXCOORD5;
|
||||
float4 texcoord6 : TEXCOORD6;
|
||||
float4 texcoord7 : TEXCOORD7;
|
||||
float4 color : COLOR0;
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
void main( VS_IN vertex, out VS_OUT result )
|
||||
{
|
||||
|
||||
float4 vNormal = vertex.normal * 2.0 - 1.0;
|
||||
float4 vTangent = vertex.tangent * 2.0 - 1.0;
|
||||
float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;
|
||||
|
||||
#if defined( USE_GPU_SKINNING )
|
||||
//--------------------------------------------------------------
|
||||
// GPU transformation of the normal / tangent / bitangent
|
||||
//
|
||||
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
|
||||
//--------------------------------------------------------------
|
||||
const float w0 = vertex.color2.x;
|
||||
const float w1 = vertex.color2.y;
|
||||
const float w2 = vertex.color2.z;
|
||||
const float w3 = vertex.color2.w;
|
||||
|
||||
float4 matX, matY, matZ; // must be float4 for vec4
|
||||
int joint = int( vertex.color.x * 255.1 * 3.0 );
|
||||
matX = matrices[int( joint + 0 )] * w0;
|
||||
matY = matrices[int( joint + 1 )] * w0;
|
||||
matZ = matrices[int( joint + 2 )] * w0;
|
||||
|
||||
joint = int( vertex.color.y * 255.1 * 3.0 );
|
||||
matX += matrices[int( joint + 0 )] * w1;
|
||||
matY += matrices[int( joint + 1 )] * w1;
|
||||
matZ += matrices[int( joint + 2 )] * w1;
|
||||
|
||||
joint = int( vertex.color.z * 255.1 * 3.0 );
|
||||
matX += matrices[int( joint + 0 )] * w2;
|
||||
matY += matrices[int( joint + 1 )] * w2;
|
||||
matZ += matrices[int( joint + 2 )] * w2;
|
||||
|
||||
joint = int( vertex.color.w * 255.1 * 3.0 );
|
||||
matX += matrices[int( joint + 0 )] * w3;
|
||||
matY += matrices[int( joint + 1 )] * w3;
|
||||
matZ += matrices[int( joint + 2 )] * w3;
|
||||
|
||||
float3 normal;
|
||||
normal.x = dot3( matX, vNormal );
|
||||
normal.y = dot3( matY, vNormal );
|
||||
normal.z = dot3( matZ, vNormal );
|
||||
normal = normalize( normal );
|
||||
|
||||
float3 tangent;
|
||||
tangent.x = dot3( matX, vTangent );
|
||||
tangent.y = dot3( matY, vTangent );
|
||||
tangent.z = dot3( matZ, vTangent );
|
||||
tangent = normalize( tangent );
|
||||
|
||||
float3 bitangent;
|
||||
bitangent.x = dot3( matX, vBitangent );
|
||||
bitangent.y = dot3( matY, vBitangent );
|
||||
bitangent.z = dot3( matZ, vBitangent );
|
||||
bitangent = normalize( bitangent );
|
||||
|
||||
float4 modelPosition;
|
||||
modelPosition.x = dot4( matX, vertex.position );
|
||||
modelPosition.y = dot4( matY, vertex.position );
|
||||
modelPosition.z = dot4( matZ, vertex.position );
|
||||
modelPosition.w = 1.0;
|
||||
|
||||
#else
|
||||
float4 modelPosition = vertex.position;
|
||||
float3 normal = vNormal.xyz;
|
||||
float3 tangent = vTangent.xyz;
|
||||
float3 bitangent = vBitangent.xyz;
|
||||
#endif
|
||||
|
||||
result.position.x = dot4( modelPosition, rpMVPmatrixX );
|
||||
result.position.y = dot4( modelPosition, rpMVPmatrixY );
|
||||
result.position.z = dot4( modelPosition, rpMVPmatrixZ );
|
||||
result.position.w = dot4( modelPosition, rpMVPmatrixW );
|
||||
|
||||
float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
|
||||
//# textures 0 takes the base coordinates by the texture matrix
|
||||
result.texcoord0 = defaultTexCoord;
|
||||
result.texcoord0.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );
|
||||
result.texcoord0.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );
|
||||
|
||||
//# textures 1 takes the base coordinates by the texture matrix
|
||||
result.texcoord1 = defaultTexCoord;
|
||||
result.texcoord1.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS );
|
||||
result.texcoord1.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT );
|
||||
|
||||
//# textures 2 takes the base coordinates by the texture matrix
|
||||
result.texcoord2 = defaultTexCoord;
|
||||
result.texcoord2.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS );
|
||||
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 );
|
||||
result.texcoord3.y = dot3( toEye, rpModelMatrixY );
|
||||
result.texcoord3.z = dot3( toEye, rpModelMatrixZ );
|
||||
|
||||
result.texcoord4.x = dot3( tangent, rpModelMatrixX );
|
||||
result.texcoord5.x = dot3( tangent, rpModelMatrixY );
|
||||
result.texcoord6.x = dot3( tangent, rpModelMatrixZ );
|
||||
|
||||
result.texcoord4.y = dot3( bitangent, rpModelMatrixX );
|
||||
result.texcoord5.y = dot3( bitangent, rpModelMatrixY );
|
||||
result.texcoord6.y = dot3( bitangent, rpModelMatrixZ );
|
||||
|
||||
result.texcoord4.z = dot3( normal, rpModelMatrixX );
|
||||
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
|
||||
// effects that need vertex color...
|
||||
result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
#else
|
||||
//# generate the vertex color, which can be 1.0, color, or 1.0 - color
|
||||
//# for 1.0 : env[16] = 0, env[17] = 1
|
||||
//# for color : env[16] = 1, env[17] = 0
|
||||
//# for 1.0-color : env[16] = -1, env[17] = 1
|
||||
result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;
|
||||
#endif
|
||||
}
|
|
@ -40,7 +40,9 @@ uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT
|
|||
uniform sampler2D samp4 : register(s4); // texture 4 is SSAO
|
||||
|
||||
uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map
|
||||
uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map
|
||||
uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1
|
||||
uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2
|
||||
uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3
|
||||
|
||||
struct PS_IN
|
||||
{
|
||||
|
@ -62,6 +64,7 @@ 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 )
|
||||
|
@ -118,6 +121,26 @@ bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale
|
|||
hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] );
|
||||
}
|
||||
|
||||
|
||||
float2 OctTexCoord( float3 worldDir )
|
||||
{
|
||||
float2 normalizedOctCoord = octEncode( worldDir );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
|
||||
// offset by one pixel border bleed size for linear filtering
|
||||
#if 0
|
||||
// texcoord sizes in rpCascadeDistances are not valid
|
||||
float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy;
|
||||
|
||||
float2 probeTopLeftPosition = float2( 1.0, 1.0 );
|
||||
float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;
|
||||
|
||||
normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;
|
||||
#endif
|
||||
|
||||
return normalizedOctCoordZeroOne;
|
||||
}
|
||||
|
||||
void main( PS_IN fragment, out PS_OUT result )
|
||||
{
|
||||
half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );
|
||||
|
@ -144,15 +167,14 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
|
||||
float3 globalPosition = fragment.texcoord7.xyz;
|
||||
|
||||
// RB: rpGlobalLightOrigin is global view origin
|
||||
float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition );
|
||||
float3 globalView = normalize( rpGlobalEyePos.xyz - globalPosition );
|
||||
|
||||
float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );
|
||||
reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );
|
||||
float3 reflectionVector = globalNormal * dot3( globalView, globalNormal );
|
||||
reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView );
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
// parallax box correction using portal area bounds
|
||||
float hitScale;
|
||||
float hitScale = 0.0;
|
||||
float3 bounds[2];
|
||||
bounds[0].x = rpWobbleSkyX.x;
|
||||
bounds[0].y = rpWobbleSkyX.y;
|
||||
|
@ -178,7 +200,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
}
|
||||
#endif
|
||||
|
||||
half vDotN = saturate( dot3( globalEye, globalNormal ) );
|
||||
half vDotN = saturate( dot3( globalView, globalNormal ) );
|
||||
|
||||
#if defined( USE_PBR )
|
||||
const half metallic = specMapSRGB.g;
|
||||
|
@ -236,8 +258,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
|
||||
// evaluate diffuse IBL
|
||||
|
||||
float2 normalizedOctCoord = octEncode( globalNormal );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
float2 normalizedOctCoordZeroOne = OctTexCoord( globalNormal );
|
||||
|
||||
float3 irradiance = tex2D( samp7, normalizedOctCoordZeroOne ).rgb;
|
||||
float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );
|
||||
|
@ -249,10 +270,11 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD );
|
||||
//float mip = 0.0;
|
||||
|
||||
normalizedOctCoord = octEncode( reflectionVector );
|
||||
normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;
|
||||
normalizedOctCoordZeroOne = OctTexCoord( reflectionVector );
|
||||
|
||||
float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;
|
||||
float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x;
|
||||
radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y;
|
||||
radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z;
|
||||
//radiance = float3( 0.0 );
|
||||
|
||||
float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;
|
||||
|
@ -266,7 +288,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
float specAO = ComputeSpecularAO( vDotN, ao, roughness );
|
||||
float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 );
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
// Marmoset Horizon Fade trick
|
||||
const half horizonFade = 1.3;
|
||||
half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );
|
||||
|
@ -275,11 +297,12 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
#endif
|
||||
|
||||
half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );
|
||||
//half3 lightColor = ( rpAmbientColor.rgb );
|
||||
|
||||
//result.color.rgb = diffuseLight;
|
||||
//result.color.rgb = diffuseLight * lightColor;
|
||||
//result.color.rgb = specularLight;
|
||||
result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb;
|
||||
result.color.rgb = ( diffuseLight + specularLight * horiz ) * lightColor * fragment.color.rgb;
|
||||
//result.color.rgb = localNormal.xyz * 0.5 + 0.5;
|
||||
//result.color.rgb = float3( ao );
|
||||
result.color.w = fragment.color.a;
|
||||
|
|
|
@ -66,7 +66,7 @@ struct PS_OUT
|
|||
#define USE_CAS 0
|
||||
|
||||
#define USE_DITHERING 1
|
||||
#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits
|
||||
#define Dithering_QuantizationSteps 16.0 // 8.0 = 2 ^ 3 quantization bits
|
||||
#define Dithering_NoiseBoost 1.0
|
||||
#define Dithering_Wide 1.0
|
||||
#define DITHER_IN_LINEAR_SPACE 0
|
||||
|
|
|
@ -2040,7 +2040,7 @@ struct evarPrefix_t
|
|||
const char* prefix;
|
||||
};
|
||||
|
||||
const evarPrefix_t EvarPrefixes[] =
|
||||
static const evarPrefix_t EvarPrefixes[] =
|
||||
{
|
||||
{ EVAR_STRING, "editor_var " },
|
||||
{ EVAR_INT, "editor_int " },
|
||||
|
@ -2053,15 +2053,15 @@ const evarPrefix_t EvarPrefixes[] =
|
|||
{ EVAR_SOUND, "editor_snd "}
|
||||
};
|
||||
|
||||
const int NumEvarPrefixes = sizeof( EvarPrefixes ) / sizeof( evarPrefix_t );
|
||||
static const int NumEvarPrefixes = sizeof( EvarPrefixes ) / sizeof( evarPrefix_t );
|
||||
|
||||
typedef struct evar_s
|
||||
struct LocalEvar_t
|
||||
{
|
||||
int type;
|
||||
idStr fullname;
|
||||
idStr name;
|
||||
idStr desc;
|
||||
} evar_t;
|
||||
};
|
||||
|
||||
#include <d3xp/anim/Anim.h> // idDeclModelDef
|
||||
|
||||
|
@ -2091,15 +2091,15 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
|
||||
bool exportModels = false;
|
||||
|
||||
if( !idStr::Icmp( args.Argv( 1 ), "models" ) )
|
||||
if( !idStr::Icmp( args.Argv( 1 ), "nomodels" ) )
|
||||
{
|
||||
exportModels = true;
|
||||
common->Printf( "exporting entity decls to FGDs with models:\n" );
|
||||
exportModels = false;
|
||||
common->Printf( "exporting entity decls to FGDs without models:\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
exportModels = false;
|
||||
common->Printf( "exporting entity decls to FGDs:\n" );
|
||||
exportModels = true;
|
||||
common->Printf( "exporting entity decls to FGDs with models:\n" );
|
||||
}
|
||||
|
||||
if( exportModels )
|
||||
|
@ -2361,14 +2361,14 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
}
|
||||
|
||||
// collect editor specific spawn flags
|
||||
idList<evar_t> evars;
|
||||
idList<LocalEvar_t> evars;
|
||||
|
||||
for( int i = 0; i < NumEvarPrefixes; i++ )
|
||||
{
|
||||
kv = decl->dict.MatchPrefix( EvarPrefixes[i].prefix );
|
||||
while( kv )
|
||||
{
|
||||
evar_t ev;
|
||||
LocalEvar_t ev;
|
||||
ev.fullname = kv->GetKey();
|
||||
kv->GetKey().Right( kv->GetKey().Length() - strlen( EvarPrefixes[i].prefix ), ev.name );
|
||||
ev.desc = kv->GetValue();
|
||||
|
@ -2386,7 +2386,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
|
||||
// add missing property to control the radius
|
||||
|
||||
evar_t ev;
|
||||
LocalEvar_t ev;
|
||||
ev.fullname = "editor_int light";
|
||||
ev.name = "light";
|
||||
ev.desc = "light radius";
|
||||
|
@ -2401,7 +2401,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
{
|
||||
// entities with dynamic models
|
||||
|
||||
evar_t ev;
|
||||
LocalEvar_t ev;
|
||||
ev.fullname = "editor_model model";
|
||||
ev.name = "model";
|
||||
ev.desc = "Model Selection (ex mapobjects/model.obj)";
|
||||
|
@ -2437,7 +2437,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
//}
|
||||
|
||||
// is it an editor var or a regular spawn argument?
|
||||
evar_t* ev = nullptr;
|
||||
LocalEvar_t* ev = nullptr;
|
||||
int vc = evars.Num();
|
||||
for( int j = 0; j < vc; j++ )
|
||||
{
|
||||
|
@ -2464,7 +2464,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
// add editor_vars that aren't already covered by the default vars
|
||||
for( int i = 0; i < evars.Num(); i++ )
|
||||
{
|
||||
const evar_t* ev = &evars[ i ];
|
||||
const LocalEvar_t* ev = &evars[ i ];
|
||||
|
||||
const idKeyValue* kv2 = dictToWrite.FindKey( ev->name );
|
||||
if( !kv2 )
|
||||
|
@ -2538,7 +2538,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args )
|
|||
kv = dictToWrite.GetKeyVal( i );
|
||||
|
||||
// is it an editor var or a regular spawn argument?
|
||||
evar_t* ev = nullptr;
|
||||
LocalEvar_t* ev = nullptr;
|
||||
int vc = evars.Num();
|
||||
for( int j = 0; j < vc; j++ )
|
||||
{
|
||||
|
|
|
@ -26,6 +26,10 @@ SOFTWARE.
|
|||
#ifndef __MATH_SPHERICAL_HARMONICS_H__
|
||||
#define __MATH_SPHERICAL_HARMONICS_H__
|
||||
|
||||
// RB: there is a very good talk by Yuriy O'Donnell that explains the the functions used in this library
|
||||
// Precomputed Global Illumination in Frostbite (GDC 2018)
|
||||
// https://www.gdcvault.com/play/1025214/Precomputed-Global-Illumination-in
|
||||
|
||||
// https://graphics.stanford.edu/papers/envmap/envmap.pdf
|
||||
|
||||
template <typename T, size_t L>
|
||||
|
|
|
@ -35,7 +35,7 @@ static const int MAX_SSAO_BUFFERS = 2;
|
|||
static const int MAX_HIERARCHICAL_ZBUFFERS = 6; // native resolution + 5 MIP LEVELS
|
||||
|
||||
static const int RADIANCE_CUBEMAP_SIZE = 256;
|
||||
static const int IRRADIANCE_CUBEMAP_SIZE = 128;
|
||||
static const int IRRADIANCE_CUBEMAP_SIZE = 30 + 2;
|
||||
|
||||
#if 1
|
||||
static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 };
|
||||
|
|
|
@ -309,6 +309,11 @@ public:
|
|||
return opts.height;
|
||||
}
|
||||
|
||||
idVec2i GetUploadResolution() const
|
||||
{
|
||||
return idVec2i( opts.width, opts.height );
|
||||
}
|
||||
|
||||
void SetReferencedOutsideLevelLoad()
|
||||
{
|
||||
referencedOutsideLevelLoad = true;
|
||||
|
|
|
@ -751,7 +751,7 @@ void idImage::Reload( bool force )
|
|||
if( !force )
|
||||
{
|
||||
ID_TIME_T current;
|
||||
if( cubeFiles != CF_2D )
|
||||
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA )
|
||||
{
|
||||
R_LoadCubeImages( imgName, cubeFiles, NULL, NULL, ¤t );
|
||||
}
|
||||
|
|
|
@ -615,70 +615,62 @@ void idImage::AllocImage()
|
|||
GL_CheckErrors();
|
||||
PurgeImage();
|
||||
|
||||
int sRGB = r_useSRGB.GetInteger();
|
||||
|
||||
switch( opts.format )
|
||||
{
|
||||
case FMT_RGBA8:
|
||||
//internalFormat = GL_RGBA8;
|
||||
//internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
|
||||
internalFormat = GL_RGBA8;
|
||||
dataFormat = GL_RGBA;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_XRGB8:
|
||||
internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB : GL_RGB;
|
||||
internalFormat = GL_RGB;
|
||||
dataFormat = GL_RGBA;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_RGB565:
|
||||
//internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB : GL_RGB;
|
||||
internalFormat = GL_RGB;
|
||||
dataFormat = GL_RGB;
|
||||
dataType = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
|
||||
case FMT_ALPHA:
|
||||
#if 1
|
||||
if( ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) )
|
||||
{
|
||||
internalFormat = GL_SRGB;
|
||||
dataFormat = GL_RED;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
internalFormat = GL_R8;
|
||||
dataFormat = GL_RED;
|
||||
}
|
||||
internalFormat = GL_R8;
|
||||
dataFormat = GL_RED;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_L8A8:
|
||||
internalFormat = GL_RG8;
|
||||
dataFormat = GL_RG;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_LUM8:
|
||||
internalFormat = GL_R8;
|
||||
dataFormat = GL_RED;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_INT8:
|
||||
internalFormat = GL_R8;
|
||||
dataFormat = GL_RED;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_DXT1:
|
||||
internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
//internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
dataFormat = GL_RGBA;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_DXT5:
|
||||
internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) && opts.colorFormat != CFM_YCOCG_DXT5 && opts.colorFormat != CFM_NORMAL_DXT5 ) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
//internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
dataFormat = GL_RGBA;
|
||||
dataType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case FMT_DEPTH:
|
||||
internalFormat = GL_DEPTH_COMPONENT;
|
||||
dataFormat = GL_DEPTH_COMPONENT;
|
||||
|
@ -731,7 +723,6 @@ void idImage::AllocImage()
|
|||
internalFormat = GL_R11F_G11F_B10F;
|
||||
dataFormat = GL_RGB;
|
||||
dataType = GL_UNSIGNED_INT_10F_11F_11F_REV;
|
||||
//dataType = GL_FLOAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -276,10 +276,6 @@ static void R_CheckPortableExtensions()
|
|||
glConfig.seamlessCubeMapAvailable = GLEW_ARB_seamless_cube_map != 0;
|
||||
r_useSeamlessCubeMap.SetModified(); // the CheckCvars() next frame will enable / disable it
|
||||
|
||||
// GL_ARB_framebuffer_sRGB
|
||||
glConfig.sRGBFramebufferAvailable = GLEW_ARB_framebuffer_sRGB != 0;
|
||||
r_useSRGB.SetModified(); // the CheckCvars() next frame will enable / disable it
|
||||
|
||||
// GL_ARB_vertex_buffer_object
|
||||
if( glConfig.driverType == GLDRV_OPENGL_MESA_CORE_PROFILE )
|
||||
{
|
||||
|
@ -1423,21 +1419,6 @@ void idRenderBackend::GL_Clear( bool color, bool depth, bool stencil, byte stenc
|
|||
glClear( clearFlags );
|
||||
|
||||
// RB begin
|
||||
/*
|
||||
if( r_useHDR.GetBool() && clearHDR && globalFramebuffers.hdrFBO != NULL )
|
||||
{
|
||||
bool isDefaultFramebufferActive = Framebuffer::IsDefaultFramebufferActive();
|
||||
|
||||
globalFramebuffers.hdrFBO->Bind();
|
||||
glClear( clearFlags );
|
||||
|
||||
if( isDefaultFramebufferActive )
|
||||
{
|
||||
Framebuffer::Unbind();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if( r_useHDR.GetBool() && clearHDR )
|
||||
{
|
||||
bool isDefaultFramebufferActive = Framebuffer::IsDefaultFramebufferActive();
|
||||
|
@ -1534,21 +1515,6 @@ void idRenderBackend::CheckCVars()
|
|||
}
|
||||
}
|
||||
|
||||
if( r_useSRGB.IsModified() )
|
||||
{
|
||||
r_useSRGB.ClearModified();
|
||||
if( glConfig.sRGBFramebufferAvailable )
|
||||
{
|
||||
if( r_useSRGB.GetBool() && r_useSRGB.GetInteger() != 3 )
|
||||
{
|
||||
glEnable( GL_FRAMEBUFFER_SRGB );
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable( GL_FRAMEBUFFER_SRGB );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SRS - Enable SDL-driven vync changes without restart for UNIX-like OSs
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
|
@ -1570,7 +1536,6 @@ void idRenderBackend::CheckCVars()
|
|||
}
|
||||
#endif
|
||||
// SRS end
|
||||
|
||||
if( r_antiAliasing.IsModified() )
|
||||
{
|
||||
switch( r_antiAliasing.GetInteger() )
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2014-2016 Robert Beckebans
|
||||
Copyright (C) 2014-2021 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
Copyright (C) 2016-2017 Dustin Land
|
||||
|
||||
|
@ -1702,9 +1702,38 @@ void idRenderBackend::DBG_ShowLights()
|
|||
==============
|
||||
RB_ShowViewEnvprobes
|
||||
|
||||
Visualize all environemnt probes used in the current scene
|
||||
Visualize all environment probes used in the current scene
|
||||
==============
|
||||
*/
|
||||
class idSort_DebugCompareViewEnvprobe : public idSort_Quick< RenderEnvprobeLocal*, idSort_DebugCompareViewEnvprobe >
|
||||
{
|
||||
idVec3 viewOrigin;
|
||||
|
||||
public:
|
||||
idSort_DebugCompareViewEnvprobe( const idVec3& origin )
|
||||
{
|
||||
viewOrigin = origin;
|
||||
}
|
||||
|
||||
int Compare( RenderEnvprobeLocal* const& a, RenderEnvprobeLocal* const& b ) const
|
||||
{
|
||||
float adist = ( viewOrigin - a->parms.origin ).LengthSqr();
|
||||
float bdist = ( viewOrigin - b->parms.origin ).LengthSqr();
|
||||
|
||||
if( adist < bdist )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( adist > bdist )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
void idRenderBackend::DBG_ShowViewEnvprobes()
|
||||
{
|
||||
if( !r_showViewEnvprobes.GetInteger() )
|
||||
|
@ -1719,16 +1748,15 @@ void idRenderBackend::DBG_ShowViewEnvprobes()
|
|||
{
|
||||
count++;
|
||||
|
||||
renderProgManager.BindShader_Octahedron();
|
||||
renderProgManager.BindShader_DebugOctahedron();
|
||||
|
||||
GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK );
|
||||
GL_Color( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
float modelMatrix[16];
|
||||
|
||||
idMat3 axis;
|
||||
axis.Identity();
|
||||
|
||||
float modelMatrix[16];
|
||||
R_AxisToModelMatrix( axis, vProbe->globalOrigin, modelMatrix );
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
|
@ -1757,16 +1785,26 @@ void idRenderBackend::DBG_ShowViewEnvprobes()
|
|||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin
|
||||
|
||||
idVec4 textureSize;
|
||||
|
||||
GL_SelectTexture( 0 );
|
||||
if( r_showViewEnvprobes.GetInteger() >= 2 )
|
||||
{
|
||||
vProbe->irradianceImage->Bind();
|
||||
|
||||
idVec2i res = vProbe->irradianceImage->GetUploadResolution();
|
||||
textureSize.Set( res.x, res.y, 1.0f / res.x, 1.0f / res.y );
|
||||
}
|
||||
else
|
||||
{
|
||||
vProbe->radianceImage->Bind();
|
||||
|
||||
idVec2i res = vProbe->radianceImage->GetUploadResolution();
|
||||
textureSize.Set( res.x, res.y, 1.0f / res.x, 1.0f / res.y );
|
||||
}
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
|
||||
// non-hidden lines
|
||||
|
@ -1785,6 +1823,457 @@ void idRenderBackend::DBG_ShowViewEnvprobes()
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//if( r_showViewEnvprobes.GetInteger() >= 3 )
|
||||
if( tr.primaryWorld )
|
||||
{
|
||||
/*
|
||||
idList<viewEnvprobe_t*, TAG_RENDER_ENVPROBE> viewEnvprobes;
|
||||
for( viewEnvprobe_t* vProbe = viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next )
|
||||
{
|
||||
viewEnvprobes.AddUnique( vProbe );
|
||||
}
|
||||
*/
|
||||
|
||||
idList<RenderEnvprobeLocal*, TAG_RENDER_ENVPROBE> viewEnvprobes;
|
||||
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
||||
{
|
||||
RenderEnvprobeLocal* vProbe = tr.primaryWorld->envprobeDefs[i];
|
||||
if( vProbe )
|
||||
{
|
||||
viewEnvprobes.AddUnique( vProbe );
|
||||
}
|
||||
}
|
||||
|
||||
if( viewEnvprobes.Num() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 testOrigin = viewDef->renderView.vieworg;
|
||||
//testOrigin += viewDef->renderView.viewaxis[0] * 150.0f;
|
||||
//testOrigin -= viewDef->renderView.viewaxis[2] * 16.0f;
|
||||
|
||||
// sort by distance
|
||||
viewEnvprobes.SortWithTemplate( idSort_DebugCompareViewEnvprobe( testOrigin ) );
|
||||
|
||||
// draw 3 nearest probes
|
||||
renderProgManager.BindShader_Color();
|
||||
|
||||
const int numColors = 3;
|
||||
static idVec4 colors[numColors] = { colorRed, colorGreen, colorBlue };
|
||||
|
||||
// form a triangle of the 3 closest probes
|
||||
idVec3 verts[3];
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
verts[i] = viewEnvprobes[0]->parms.origin;
|
||||
}
|
||||
|
||||
for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ )
|
||||
{
|
||||
RenderEnvprobeLocal* vProbe = viewEnvprobes[i];
|
||||
|
||||
verts[i] = vProbe->parms.origin;
|
||||
}
|
||||
|
||||
idVec3 closest = R_ClosestPointPointTriangle( testOrigin, verts[0], verts[1], verts[2] );
|
||||
idVec3 barycentricWeights;
|
||||
|
||||
// find the barycentric coordinates
|
||||
float denom = idWinding::TriangleArea( verts[0], verts[1], verts[2] );
|
||||
if( denom == 0 )
|
||||
{
|
||||
// all points at same location
|
||||
barycentricWeights.Set( 1, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
float a, b, c;
|
||||
|
||||
a = idWinding::TriangleArea( closest, verts[1], verts[2] ) / denom;
|
||||
b = idWinding::TriangleArea( closest, verts[2], verts[0] ) / denom;
|
||||
c = idWinding::TriangleArea( closest, verts[0], verts[1] ) / denom;
|
||||
|
||||
barycentricWeights.Set( a, b, c );
|
||||
}
|
||||
|
||||
idMat3 axis;
|
||||
axis.Identity();
|
||||
|
||||
for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ )
|
||||
{
|
||||
RenderEnvprobeLocal* vProbe = viewEnvprobes[i];
|
||||
|
||||
verts[i] = vProbe->parms.origin;
|
||||
|
||||
//GL_Color( colors[i] );
|
||||
|
||||
idVec4 color = Lerp( colorBlack, colors[i], barycentricWeights[i] );
|
||||
GL_Color( color );
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( vProbe->parms.origin, axis, modelRenderMatrix );
|
||||
|
||||
// calculate the matrix that transforms the unit cube to exactly cover the model in world space
|
||||
const float size = 16.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
RB_SetMVP( invProjectMVPMatrix );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
}
|
||||
|
||||
// draw closest hit
|
||||
{
|
||||
GL_Color( colorYellow );
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( closest, axis, modelRenderMatrix );
|
||||
|
||||
// calculate the matrix that transforms the unit cube to exactly cover the model in world space
|
||||
const float size = 4.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
RB_SetMVP( invProjectMVPMatrix );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void idRenderBackend::DBG_ShowLightGrid()
|
||||
{
|
||||
if( r_showLightGrid.GetInteger() <= 0 || !tr.primaryWorld )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// all volumes are expressed in world coordinates
|
||||
|
||||
GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK );
|
||||
GL_Color( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
idMat3 axis;
|
||||
axis.Identity();
|
||||
|
||||
// only show current area
|
||||
int cameraArea = tr.primaryWorld->PointInArea( viewDef->renderView.vieworg );
|
||||
if( cameraArea == -1 && r_showLightGrid.GetInteger() < 3 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int numColors = 7;
|
||||
static idVec4 colors[numColors] = { colorBrown, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite };
|
||||
|
||||
for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ )
|
||||
{
|
||||
if( r_showLightGrid.GetInteger() < 3 && ( cameraArea != a ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
portalArea_t* area = &tr.primaryWorld->portalAreas[a];
|
||||
|
||||
// use rpGlobalLightOrigin for lightGrid center
|
||||
idVec4 lightGridOrigin( area->lightGrid.lightGridOrigin.x, area->lightGrid.lightGridOrigin.y, area->lightGrid.lightGridOrigin.z, 1.0f );
|
||||
idVec4 lightGridSize( area->lightGrid.lightGridSize.x, area->lightGrid.lightGridSize.y, area->lightGrid.lightGridSize.z, 1.0f );
|
||||
idVec4 lightGridBounds( area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], 1.0f );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() );
|
||||
|
||||
// individual probe sizes on the atlas image
|
||||
idVec4 probeSize;
|
||||
probeSize[0] = area->lightGrid.imageSingleProbeSize - area->lightGrid.imageBorderSize;
|
||||
probeSize[1] = area->lightGrid.imageSingleProbeSize;
|
||||
probeSize[2] = area->lightGrid.imageBorderSize;
|
||||
probeSize[3] = float( area->lightGrid.imageSingleProbeSize - area->lightGrid.imageBorderSize ) / area->lightGrid.imageSingleProbeSize;
|
||||
renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor
|
||||
|
||||
for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ )
|
||||
{
|
||||
lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i];
|
||||
if( !gridPoint->valid && r_showLightGrid.GetInteger() < 3 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg;
|
||||
if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) && r_showLightGrid.GetInteger() < 3 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if( i > 53 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// move center into the cube so we can void using negative results with GetBaseGridCoord
|
||||
idVec3 gridPointOrigin = gridPoint->origin + idVec3( 4, 4, 4 );
|
||||
|
||||
idVec4 localViewOrigin( 1.0f );
|
||||
idVec4 globalViewOrigin;
|
||||
globalViewOrigin.x = viewDef->renderView.vieworg.x;
|
||||
globalViewOrigin.y = viewDef->renderView.vieworg.y;
|
||||
globalViewOrigin.z = viewDef->renderView.vieworg.z;
|
||||
globalViewOrigin.w = 1.0f;
|
||||
|
||||
float modelMatrix[16];
|
||||
R_AxisToModelMatrix( axis, gridPointOrigin, modelMatrix );
|
||||
|
||||
R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin
|
||||
|
||||
// RB: if we want to get the normals in world space so we need the model -> world matrix
|
||||
idRenderMatrix modelMatrix2;
|
||||
idRenderMatrix::Transpose( *( idRenderMatrix* )modelMatrix, modelMatrix2 );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_X, &modelMatrix2[0][0] );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Y, &modelMatrix2[1][0] );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Z, &modelMatrix2[2][0] );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_W, &modelMatrix2[3][0] );
|
||||
|
||||
|
||||
#if 0
|
||||
renderProgManager.BindShader_Color();
|
||||
|
||||
int gridCoord[3];
|
||||
area->lightGrid.GetBaseGridCoord( gridPoint->origin, gridCoord );
|
||||
|
||||
idVec3 color = area->lightGrid.GetGridCoordDebugColor( gridCoord );
|
||||
//idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i );
|
||||
//idVec4 color = colors[ i % numColors ];
|
||||
GL_Color( color );
|
||||
#else
|
||||
|
||||
if( r_showLightGrid.GetInteger() == 4 || !area->lightGrid.GetIrradianceImage() )
|
||||
{
|
||||
renderProgManager.BindShader_Color();
|
||||
|
||||
idVec4 color;
|
||||
if( !gridPoint->valid )
|
||||
{
|
||||
color = colorPurple;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = colors[ a % numColors ];
|
||||
}
|
||||
|
||||
GL_Color( color );
|
||||
}
|
||||
else
|
||||
{
|
||||
renderProgManager.BindShader_DebugLightGrid();
|
||||
|
||||
GL_SelectTexture( 0 );
|
||||
area->lightGrid.GetIrradianceImage()->Bind();
|
||||
|
||||
idVec2i res = area->lightGrid.GetIrradianceImage()->GetUploadResolution();
|
||||
idVec4 textureSize( res.x, res.y, 1.0f / res.x, 1.0f / res.y );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() );
|
||||
}
|
||||
#endif
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix );
|
||||
|
||||
// calculate the matrix that transforms the unit cube to exactly cover the model in world space
|
||||
const float size = 3.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
RB_SetMVP( invProjectMVPMatrix );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
//DrawElementsWithCounters( &zeroOneCubeSurface );
|
||||
}
|
||||
}
|
||||
|
||||
if( r_showLightGrid.GetInteger() == 2 )
|
||||
{
|
||||
// show 8 nearest grid points around the camera and illustrate how the trilerping works
|
||||
|
||||
idVec3 lightOrigin;
|
||||
int pos[3];
|
||||
int gridPointIndex;
|
||||
int gridPointIndex2;
|
||||
lightGridPoint_t* gridPoint;
|
||||
lightGridPoint_t* gridPoint2;
|
||||
float frac[3];
|
||||
int gridStep[3];
|
||||
float totalFactor;
|
||||
|
||||
portalArea_t* area = &tr.primaryWorld->portalAreas[cameraArea];
|
||||
|
||||
renderProgManager.BindShader_Color();
|
||||
|
||||
lightOrigin = viewDef->renderView.vieworg;
|
||||
lightOrigin += viewDef->renderView.viewaxis[0] * 150.0f;
|
||||
lightOrigin -= viewDef->renderView.viewaxis[2] * 16.0f;
|
||||
|
||||
// draw sample origin we want to test the grid with
|
||||
{
|
||||
GL_Color( colorYellow );
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( lightOrigin, axis, modelRenderMatrix );
|
||||
|
||||
// calculate the matrix that transforms the unit cube to exactly cover the model in world space
|
||||
const float size = 2.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
RB_SetMVP( invProjectMVPMatrix );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
}
|
||||
|
||||
// find base grid point
|
||||
lightOrigin -= area->lightGrid.lightGridOrigin;
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
float v;
|
||||
|
||||
v = lightOrigin[i] * ( 1.0f / area->lightGrid.lightGridSize[i] );
|
||||
pos[i] = floor( v );
|
||||
frac[i] = v - pos[i];
|
||||
|
||||
if( pos[i] < 0 )
|
||||
{
|
||||
pos[i] = 0;
|
||||
}
|
||||
else if( pos[i] >= area->lightGrid.lightGridBounds[i] - 1 )
|
||||
{
|
||||
pos[i] = area->lightGrid.lightGridBounds[i] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// trilerp the light value
|
||||
gridStep[0] = 1;
|
||||
gridStep[1] = area->lightGrid.lightGridBounds[0];
|
||||
gridStep[2] = area->lightGrid.lightGridBounds[0] * area->lightGrid.lightGridBounds[1];
|
||||
|
||||
gridPointIndex = pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2];
|
||||
gridPoint = &area->lightGrid.lightGridPoints[ gridPointIndex ];
|
||||
|
||||
totalFactor = 0;
|
||||
idVec3 cornerOffsets[8];
|
||||
|
||||
for( int i = 0; i < 8; i++ )
|
||||
{
|
||||
float factor = 1.0;
|
||||
|
||||
gridPoint2 = gridPoint;
|
||||
gridPointIndex2 = gridPointIndex;
|
||||
|
||||
for( int j = 0; j < 3; j++ )
|
||||
{
|
||||
cornerOffsets[i][j] = i & ( 1 << j );
|
||||
|
||||
if( cornerOffsets[i][j] > 0.0f )
|
||||
{
|
||||
factor *= frac[j];
|
||||
|
||||
#if 1
|
||||
gridPointIndex2 += gridStep[j];
|
||||
if( gridPointIndex2 < 0 || gridPointIndex2 >= area->lightGrid.lightGridPoints.Num() )
|
||||
{
|
||||
// ignore values outside lightgrid
|
||||
continue;
|
||||
}
|
||||
|
||||
gridPoint2 = &area->lightGrid.lightGridPoints[ gridPointIndex2 ];
|
||||
#else
|
||||
if( pos[j] + 1 > area->lightGrid.lightGridBounds[j] - 1 )
|
||||
{
|
||||
// ignore values outside lightgrid
|
||||
break;
|
||||
}
|
||||
|
||||
gridPoint2 += gridStep[j];
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
factor *= ( 1.0f - frac[j] );
|
||||
}
|
||||
}
|
||||
|
||||
if( !gridPoint2->valid )
|
||||
{
|
||||
// ignore samples in walls
|
||||
continue;
|
||||
}
|
||||
|
||||
totalFactor += factor;
|
||||
|
||||
idVec4 color = Lerp( colorBlack, colorGreen, factor );
|
||||
GL_Color( color );
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( gridPoint2->origin, axis, modelRenderMatrix );
|
||||
|
||||
// calculate the matrix that transforms the unit cube to exactly cover the model in world space
|
||||
const float size = 4.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
RB_SetMVP( invProjectMVPMatrix );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
}
|
||||
|
||||
// draw main grid point where camera position snapped to
|
||||
GL_Color( colorRed );
|
||||
|
||||
idRenderMatrix modelRenderMatrix;
|
||||
idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix );
|
||||
|
||||
// calculate the matrix that transforms the unit cube to exactly cover the model in world space
|
||||
const float size = 5.0f;
|
||||
idBounds debugBounds( idVec3( -size ), idVec3( size ) );
|
||||
|
||||
idRenderMatrix inverseBaseModelProject;
|
||||
idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject );
|
||||
|
||||
idRenderMatrix invProjectMVPMatrix;
|
||||
idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix );
|
||||
RB_SetMVP( invProjectMVPMatrix );
|
||||
|
||||
DrawElementsWithCounters( &zeroOneSphereSurface );
|
||||
}
|
||||
}
|
||||
|
||||
void idRenderBackend::DBG_ShowShadowMapLODs()
|
||||
|
@ -3125,6 +3614,11 @@ idRenderBackend::DBG_RenderDebugTools
|
|||
*/
|
||||
void idRenderBackend::DBG_RenderDebugTools( drawSurf_t** drawSurfs, int numDrawSurfs )
|
||||
{
|
||||
if( viewDef->renderView.rdflags & RDF_IRRADIANCE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// don't do much if this was a 2D rendering
|
||||
if( !viewDef->viewEntitys )
|
||||
{
|
||||
|
@ -3158,6 +3652,7 @@ void idRenderBackend::DBG_RenderDebugTools( drawSurf_t** drawSurfs, int numDrawS
|
|||
DBG_ShowViewEntitys( viewDef->viewEntitys );
|
||||
DBG_ShowLights();
|
||||
// RB begin
|
||||
DBG_ShowLightGrid();
|
||||
DBG_ShowViewEnvprobes();
|
||||
DBG_ShowShadowMapLODs();
|
||||
DBG_ShowShadowMaps();
|
||||
|
|
|
@ -1200,9 +1200,13 @@ const int INTERACTION_TEXUNIT_JITTER = 6;
|
|||
#if defined( USE_VULKAN )
|
||||
const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 5;
|
||||
const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 6;
|
||||
const int INTERACTION_TEXUNIT_SPECULAR_CUBE2 = 7;
|
||||
const int INTERACTION_TEXUNIT_SPECULAR_CUBE3 = 8;
|
||||
#else
|
||||
const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 7;
|
||||
const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 8;
|
||||
const int INTERACTION_TEXUNIT_SPECULAR_CUBE2 = 9;
|
||||
const int INTERACTION_TEXUNIT_SPECULAR_CUBE3 = 10;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1323,7 +1327,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
const textureUsage_t specUsage = din->specularImage->GetUsage();
|
||||
|
||||
// RB begin
|
||||
if( useIBL )
|
||||
if( useIBL && currentSpace->useLightGrid && r_useLightGrid.GetBool() )
|
||||
{
|
||||
idVec4 probeMins, probeMaxs, probeCenter;
|
||||
|
||||
|
@ -1344,6 +1348,108 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() );
|
||||
SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() );
|
||||
|
||||
// use rpGlobalLightOrigin for lightGrid center
|
||||
idVec4 lightGridOrigin( currentSpace->lightGridOrigin.x, currentSpace->lightGridOrigin.y, currentSpace->lightGridOrigin.z, 1.0f );
|
||||
idVec4 lightGridSize( currentSpace->lightGridSize.x, currentSpace->lightGridSize.y, currentSpace->lightGridSize.z, 1.0f );
|
||||
idVec4 lightGridBounds( currentSpace->lightGridBounds[0], currentSpace->lightGridBounds[1], currentSpace->lightGridBounds[2], 1.0f );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() );
|
||||
renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() );
|
||||
|
||||
// individual probe sizes on the atlas image
|
||||
idVec4 probeSize;
|
||||
probeSize[0] = currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize;
|
||||
probeSize[1] = currentSpace->lightGridAtlasSingleProbeSize;
|
||||
probeSize[2] = currentSpace->lightGridAtlasBorderSize;
|
||||
probeSize[3] = float( currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize ) / currentSpace->lightGridAtlasSingleProbeSize;
|
||||
renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor
|
||||
|
||||
// specular cubemap blend weights
|
||||
renderProgManager.SetUniformValue( RENDERPARM_LOCALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() );
|
||||
|
||||
if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD )
|
||||
{
|
||||
// PBR path with roughness, metal and AO
|
||||
if( din->surf->jointCache )
|
||||
{
|
||||
renderProgManager.BindShader_ImageBasedLightGridSkinned_PBR();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderProgManager.BindShader_ImageBasedLightGrid_PBR();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( din->surf->jointCache )
|
||||
{
|
||||
renderProgManager.BindShader_ImageBasedLightGridSkinned();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderProgManager.BindShader_ImageBasedLightGrid();
|
||||
}
|
||||
}
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_FALLOFF );
|
||||
globalImages->brdfLutImage->Bind();
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_PROJECTION );
|
||||
#if defined( USE_VULKAN )
|
||||
globalImages->whiteImage->Bind();
|
||||
#else
|
||||
if( !r_useSSAO.GetBool() )
|
||||
{
|
||||
globalImages->whiteImage->Bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalImages->ambientOcclusionImage[0]->Bind();
|
||||
}
|
||||
#endif
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 );
|
||||
currentSpace->lightGridAtlasImage->Bind();
|
||||
|
||||
idVec2i res = currentSpace->lightGridAtlasImage->GetUploadResolution();
|
||||
idVec4 textureSize( res.x, res.y, 1.0f / res.x, 1.0f / res.y );
|
||||
|
||||
renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() );
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 );
|
||||
viewDef->radianceImages[0]->Bind();
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE2 );
|
||||
viewDef->radianceImages[1]->Bind();
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE3 );
|
||||
viewDef->radianceImages[2]->Bind();
|
||||
}
|
||||
else 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() ? 0.0f : 1.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() );
|
||||
|
||||
// specular cubemap blend weights
|
||||
renderProgManager.SetUniformValue( RENDERPARM_LOCALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() );
|
||||
|
||||
if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD )
|
||||
{
|
||||
// PBR path with roughness, metal and AO
|
||||
|
@ -1385,26 +1491,17 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas
|
|||
}
|
||||
#endif
|
||||
|
||||
// TODO bind the 3 closest probes
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 );
|
||||
if( viewDef->irradianceImage )
|
||||
{
|
||||
viewDef->irradianceImage->Bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalImages->defaultUACIrradianceCube->Bind();
|
||||
}
|
||||
viewDef->irradianceImage->Bind();
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 );
|
||||
if( viewDef->radianceImage )
|
||||
{
|
||||
viewDef->radianceImage->Bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
globalImages->defaultUACRadianceCube->Bind();
|
||||
}
|
||||
viewDef->radianceImages[0]->Bind();
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE2 );
|
||||
viewDef->radianceImages[1]->Bind();
|
||||
|
||||
GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE3 );
|
||||
viewDef->radianceImages[2]->Bind();
|
||||
}
|
||||
else if( setInteractionShader )
|
||||
{
|
||||
|
@ -2229,10 +2326,6 @@ 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 );
|
||||
|
||||
|
@ -2318,16 +2411,6 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
|
|||
R_GlobalPointToLocal( drawSurf->space->modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() );
|
||||
SetVertexParm( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() );
|
||||
|
||||
//if( !isWorldModel )
|
||||
//{
|
||||
// // tranform the light direction into model local space
|
||||
// idVec3 globalLightDirection( 0.0f, 0.0f, -1.0f ); // HACK
|
||||
// idVec4 localLightDirection( 0.0f );
|
||||
// R_GlobalVectorToLocal( drawSurf->space->modelMatrix, globalLightDirection, localLightDirection.ToVec3() );
|
||||
//
|
||||
// SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLightDirection.ToFloatPtr() );
|
||||
//}
|
||||
|
||||
// RB: if we want to store the normals in world space so we need the model -> world matrix
|
||||
idRenderMatrix modelMatrix;
|
||||
idRenderMatrix::Transpose( *( idRenderMatrix* )drawSurf->space->modelMatrix, modelMatrix );
|
||||
|
@ -2340,27 +2423,6 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
|
|||
SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, modelViewMatrixTranspose, 4 );
|
||||
}
|
||||
|
||||
#if 0
|
||||
if( !isWorldModel )
|
||||
{
|
||||
idVec4 directedColor;
|
||||
directedColor.x = drawSurf->space->gridDirectedLight.x;
|
||||
directedColor.y = drawSurf->space->gridDirectedLight.y;
|
||||
directedColor.z = drawSurf->space->gridDirectedLight.z;
|
||||
directedColor.w = 1;
|
||||
|
||||
idVec4 ambientColor;
|
||||
ambientColor.x = drawSurf->space->gridAmbientLight.x;
|
||||
ambientColor.y = drawSurf->space->gridAmbientLight.y;
|
||||
ambientColor.z = drawSurf->space->gridAmbientLight.z;
|
||||
ambientColor.w = 1;
|
||||
|
||||
renderProgManager.SetRenderParm( RENDERPARM_COLOR, directedColor.ToFloatPtr() );
|
||||
renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() );
|
||||
}
|
||||
float ambientBoost = r_useHDR.GetBool() ? 1.5 : 1.0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
uint64 surfGLState = 0;
|
||||
|
||||
|
|
|
@ -427,6 +427,7 @@ private:
|
|||
void DBG_ShowDominantTris( drawSurf_t** drawSurfs, int numDrawSurfs );
|
||||
void DBG_ShowEdges( drawSurf_t** drawSurfs, int numDrawSurfs );
|
||||
void DBG_ShowLights();
|
||||
void DBG_ShowLightGrid(); // RB
|
||||
void DBG_ShowViewEnvprobes(); // RB
|
||||
void DBG_ShowShadowMapLODs(); // RB
|
||||
void DBG_ShowPortals();
|
||||
|
|
|
@ -450,6 +450,17 @@ struct viewEntity_t
|
|||
// be linked to the lights or added to the drawsurf list in a serial code section
|
||||
drawSurf_t* drawSurfs;
|
||||
|
||||
// RB: use light grid of the best area this entity is in
|
||||
bool useLightGrid;
|
||||
idImage* lightGridAtlasImage;
|
||||
int lightGridAtlasSingleProbeSize; // including border
|
||||
int lightGridAtlasBorderSize;
|
||||
|
||||
idVec3 lightGridOrigin;
|
||||
idVec3 lightGridSize;
|
||||
int lightGridBounds[3];
|
||||
// RB end
|
||||
|
||||
// R_AddSingleModel will build a chain of parameters here to setup shadow volumes
|
||||
staticShadowVolumeParms_t* staticShadowVolumes;
|
||||
dynamicShadowVolumeParms_t* dynamicShadowVolumes;
|
||||
|
@ -498,7 +509,28 @@ struct calcEnvprobeParms_t
|
|||
idStr filename;
|
||||
|
||||
// output
|
||||
halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas
|
||||
halfFloat_t* outBuffer; // HDR R11G11B11F packed octahedron atlas
|
||||
int time; // execution time in milliseconds
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const int LIGHTGRID_IRRADIANCE_BORDER_SIZE = 2; // one pixel border all around the octahedron so 2 on each side
|
||||
static const int LIGHTGRID_IRRADIANCE_SIZE = 30 + LIGHTGRID_IRRADIANCE_BORDER_SIZE;
|
||||
|
||||
struct calcLightGridPointParms_t
|
||||
{
|
||||
// input
|
||||
byte* radiance[6]; // HDR RGB16F standard OpenGL cubemap sides
|
||||
int gridCoord[3];
|
||||
|
||||
int outWidth; // LIGHTGRID_IRRADIANCE_SIZE
|
||||
int outHeight;
|
||||
|
||||
// output
|
||||
SphericalHarmonicsT<idVec3, 3> shRadiance; // L3 Spherical Harmonics
|
||||
|
||||
halfFloat_t* outBuffer; // HDR R11G11B11F octahedron LIGHTGRID_IRRADIANCE_SIZE^2
|
||||
int time; // execution time in milliseconds
|
||||
};
|
||||
// RB end
|
||||
|
@ -616,8 +648,8 @@ struct viewDef_t
|
|||
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
|
||||
// RB end
|
||||
idImage* radianceImages[3]; // cubemap image used for specular IBL by backend
|
||||
idVec4 radianceImageBlends; // blending weights
|
||||
};
|
||||
|
||||
|
||||
|
@ -858,6 +890,7 @@ public:
|
|||
|
||||
virtual void RenderCommandBuffers( const emptyCommand_t* commandBuffers );
|
||||
virtual void TakeScreenshot( int width, int height, const char* fileName, int downSample, renderView_t* ref, int exten );
|
||||
virtual byte* CaptureRenderToBuffer( int width, int height, renderView_t* ref );
|
||||
virtual void CropRenderSize( int width, int height );
|
||||
virtual void CaptureRenderToImage( const char* imageName, bool clearColorAfterCopy = false );
|
||||
virtual void CaptureRenderToFile( const char* fileName, bool fixAlpha );
|
||||
|
@ -940,6 +973,8 @@ public:
|
|||
|
||||
unsigned short gammaTable[256]; // brightness / gamma modify this
|
||||
|
||||
idMat3 cubeAxis[6]; // RB
|
||||
|
||||
srfTriangles_t* unitSquareTriangles;
|
||||
srfTriangles_t* zeroOneCubeTriangles;
|
||||
srfTriangles_t* zeroOneSphereTriangles;
|
||||
|
@ -956,8 +991,9 @@ public:
|
|||
idParallelJobList* frontEndJobList;
|
||||
|
||||
// RB irradiance and GGX background jobs
|
||||
idParallelJobList* envprobeJobList;
|
||||
idList<calcEnvprobeParms_t*> irradianceJobs;
|
||||
idParallelJobList* envprobeJobList;
|
||||
idList<calcEnvprobeParms_t*> envprobeJobs;
|
||||
idList<calcLightGridPointParms_t*> lightGridJobs;
|
||||
|
||||
idRenderBackend backend;
|
||||
|
||||
|
@ -1029,7 +1065,6 @@ extern idCVar r_useShadowDepthBounds; // use depth bounds test on individual sh
|
|||
extern idCVar r_useShadowMapping; // use shadow mapping instead of stencil shadows
|
||||
extern idCVar r_useHalfLambertLighting; // use Half-Lambert lighting instead of classic Lambert
|
||||
extern idCVar r_useHDR;
|
||||
extern idCVar r_useSRGB;
|
||||
extern idCVar r_useSeamlessCubeMap;
|
||||
// RB end
|
||||
|
||||
|
@ -1175,6 +1210,9 @@ extern idCVar r_useHierarchicalDepthBuffer;
|
|||
extern idCVar r_usePBR;
|
||||
extern idCVar r_pbrDebug;
|
||||
extern idCVar r_showViewEnvprobes;
|
||||
extern idCVar r_showLightGrid; // show Quake 3 style light grid points
|
||||
|
||||
extern idCVar r_useLightGrid;
|
||||
|
||||
extern idCVar r_exposure;
|
||||
// RB end
|
||||
|
@ -1353,6 +1391,85 @@ RENDERWORLD_PORTALS
|
|||
viewEntity_t* R_SetEntityDefViewEntity( idRenderEntityLocal* def );
|
||||
viewLight_t* R_SetLightDefViewLight( idRenderLightLocal* def );
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
RENDERWORLD_ENVPROBES
|
||||
|
||||
============================================================
|
||||
*/
|
||||
|
||||
void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float result[3], float& u, float& v );
|
||||
void R_SampleCubeMapHDR16F( const idVec3& dir, int size, halfFloat_t* buffers[6], float result[3], float& u, float& v );
|
||||
|
||||
idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength );
|
||||
|
||||
class CommandlineProgressBar
|
||||
{
|
||||
private:
|
||||
size_t tics = 0;
|
||||
size_t nextTicCount = 0;
|
||||
int count = 0;
|
||||
int expectedCount = 0;
|
||||
|
||||
public:
|
||||
CommandlineProgressBar( int _expectedCount )
|
||||
{
|
||||
expectedCount = _expectedCount;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
common->Printf( "0%% 10 20 30 40 50 60 70 80 90 100%%\n" );
|
||||
common->Printf( "|----|----|----|----|----|----|----|----|----|----|\n" );
|
||||
|
||||
common->UpdateScreen( false );
|
||||
}
|
||||
|
||||
void Increment()
|
||||
{
|
||||
if( ( count + 1 ) >= nextTicCount )
|
||||
{
|
||||
size_t ticsNeeded = ( size_t )( ( ( double )( count + 1 ) / expectedCount ) * 50.0 );
|
||||
|
||||
do
|
||||
{
|
||||
common->Printf( "*" );
|
||||
}
|
||||
while( ++tics < ticsNeeded );
|
||||
|
||||
nextTicCount = ( size_t )( ( tics / 50.0 ) * expectedCount );
|
||||
if( count == ( expectedCount - 1 ) )
|
||||
{
|
||||
if( tics < 51 )
|
||||
{
|
||||
common->Printf( "*" );
|
||||
}
|
||||
common->Printf( "\n" );
|
||||
}
|
||||
|
||||
common->UpdateScreen( false );
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
count = 0;
|
||||
tics = 0;
|
||||
nextTicCount = 0;
|
||||
}
|
||||
|
||||
void Reset( int expected )
|
||||
{
|
||||
expectedCount = expected;
|
||||
count = 0;
|
||||
tics = 0;
|
||||
nextTicCount = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
|
@ -1501,6 +1618,9 @@ void R_InitDrawSurfFromTri( drawSurf_t& ds, srfTriangles_t& tri );
|
|||
// time, rather than being re-created each frame in the frame temporary buffers.
|
||||
void R_CreateStaticBuffersForTri( srfTriangles_t& tri );
|
||||
|
||||
// RB
|
||||
idVec3 R_ClosestPointPointTriangle( const idVec3& point, const idVec3& vertex1, const idVec3& vertex2, const idVec3& vertex3 );
|
||||
|
||||
// deformable meshes precalculate as much as possible from a base frame, then generate
|
||||
// complete srfTriangles_t from just a new set of vertexes
|
||||
struct deformInfo_t
|
||||
|
@ -1559,7 +1679,6 @@ struct localTrace_t
|
|||
localTrace_t R_LocalTrace( const idVec3& start, const idVec3& end, const float radius, const srfTriangles_t* tri );
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============================================================
|
||||
|
||||
|
@ -1590,6 +1709,9 @@ void RB_DrawBounds( const idBounds& bounds );
|
|||
void RB_ShutdownDebugTools();
|
||||
void RB_SetVertexColorParms( stageVertexColor_t svc );
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================
|
||||
|
||||
#include "ResolutionScale.h"
|
||||
|
|
|
@ -109,10 +109,17 @@ void idRenderProgManager::Init()
|
|||
{ BUILTIN_VERTEX_COLOR, "builtin/vertex_color", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTING, "builtin/lighting/ambient_lighting", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTING_SKINNED, "builtin/lighting/ambient_lighting", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
|
||||
{ BUILTIN_AMBIENT_LIGHTING_IBL, "builtin/lighting/ambient_lighting_IBL", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "builtin/lighting/ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTING_IBL_PBR, "builtin/lighting/ambient_lighting_IBL", "_PBR", BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED, "builtin/lighting/ambient_lighting_IBL", "_PBR_skinned", BIT( USE_GPU_SKINNING | USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
|
||||
{ BUILTIN_AMBIENT_LIGHTGRID_IBL, "builtin/lighting/ambient_lightgrid_IBL", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED, "builtin/lighting/ambient_lightgrid_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR, "builtin/lighting/ambient_lightgrid_IBL", "_PBR", BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED, "builtin/lighting/ambient_lightgrid_IBL", "_PBR_skinned", BIT( USE_GPU_SKINNING | USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
|
||||
{ BUILTIN_SMALL_GEOMETRY_BUFFER, "builtin/gbuffer", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED, "builtin/gbuffer", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
// RB end
|
||||
|
@ -154,8 +161,12 @@ void idRenderProgManager::Init()
|
|||
{ BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL, "builtin/lighting/interactionSM", "_parallel_PBR", BIT( LIGHT_PARALLEL ) | BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED, "builtin/lighting/interactionSM", "_parallel_skinned_PBR", BIT( USE_GPU_SKINNING ) | BIT( LIGHT_PARALLEL ) | BIT( USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
|
||||
{ BUILTIN_OCTAHEDRON, "builtin/debug/octahedron", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_OCTAHEDRON_SKINNED, "builtin/debug/octahedron", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
// debug stuff
|
||||
{ BUILTIN_DEBUG_LIGHTGRID, "builtin/debug/lightgrid", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_DEBUG_LIGHTGRID_SKINNED, "builtin/debug/lightgrid", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
|
||||
{ BUILTIN_DEBUG_OCTAHEDRON, "builtin/debug/octahedron", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
{ BUILTIN_DEBUG_OCTAHEDRON_SKINNED, "builtin/debug/octahedron", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
// RB end
|
||||
|
||||
{ BUILTIN_ENVIRONMENT, "builtin/legacy/environment", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT },
|
||||
|
@ -272,10 +283,16 @@ void idRenderProgManager::Init()
|
|||
renderProgs[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
|
||||
// RB begin
|
||||
renderProgs[builtinShaders[BUILTIN_OCTAHEDRON_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_DEBUG_LIGHTGRID_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_DEBUG_OCTAHEDRON_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_SKINNED]].usesJoints = true;
|
||||
|
||||
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED]].usesJoints = true;
|
||||
|
||||
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED]].usesJoints = true;
|
||||
|
||||
renderProgs[builtinShaders[BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED]].usesJoints = true;
|
||||
renderProgs[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED]].usesJoints = true;
|
||||
|
|
|
@ -147,7 +147,6 @@ enum renderParm_t
|
|||
// RB begin
|
||||
RENDERPARM_AMBIENT_COLOR,
|
||||
|
||||
// RENDERPARM_GLOBALVIEWORIGIN,
|
||||
RENDERPARM_GLOBALLIGHTORIGIN,
|
||||
RENDERPARM_JITTERTEXSCALE,
|
||||
RENDERPARM_JITTERTEXOFFSET,
|
||||
|
@ -311,6 +310,28 @@ public:
|
|||
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED );
|
||||
}
|
||||
|
||||
|
||||
void BindShader_ImageBasedLightGrid()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL );
|
||||
}
|
||||
|
||||
void BindShader_ImageBasedLightGridSkinned()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED );
|
||||
}
|
||||
|
||||
void BindShader_ImageBasedLightGrid_PBR()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR );
|
||||
}
|
||||
|
||||
void BindShader_ImageBasedLightGridSkinned_PBR()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED );
|
||||
}
|
||||
|
||||
|
||||
void BindShader_SmallGeometryBuffer()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_SMALL_GEOMETRY_BUFFER );
|
||||
|
@ -451,14 +472,24 @@ public:
|
|||
BindShader_Builtin( BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED );
|
||||
}
|
||||
|
||||
void BindShader_Octahedron()
|
||||
void BindShader_DebugLightGrid()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_OCTAHEDRON );
|
||||
BindShader_Builtin( BUILTIN_DEBUG_LIGHTGRID );
|
||||
}
|
||||
|
||||
void BindShader_OctahedronSkinned()
|
||||
void BindShader_DebugLightGridSkinned()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_OCTAHEDRON_SKINNED );
|
||||
BindShader_Builtin( BUILTIN_DEBUG_LIGHTGRID_SKINNED );
|
||||
}
|
||||
|
||||
void BindShader_DebugOctahedron()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_DEBUG_OCTAHEDRON );
|
||||
}
|
||||
|
||||
void BindShader_DebugOctahedronSkinned()
|
||||
{
|
||||
BindShader_Builtin( BUILTIN_DEBUG_OCTAHEDRON_SKINNED );
|
||||
}
|
||||
// RB end
|
||||
|
||||
|
@ -731,10 +762,17 @@ private:
|
|||
BUILTIN_VERTEX_COLOR,
|
||||
BUILTIN_AMBIENT_LIGHTING,
|
||||
BUILTIN_AMBIENT_LIGHTING_SKINNED,
|
||||
|
||||
BUILTIN_AMBIENT_LIGHTING_IBL,
|
||||
BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED,
|
||||
BUILTIN_AMBIENT_LIGHTING_IBL_PBR,
|
||||
BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED,
|
||||
|
||||
BUILTIN_AMBIENT_LIGHTGRID_IBL,
|
||||
BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED,
|
||||
BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR,
|
||||
BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED,
|
||||
|
||||
BUILTIN_SMALL_GEOMETRY_BUFFER,
|
||||
BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED,
|
||||
// RB end
|
||||
|
@ -767,8 +805,11 @@ private:
|
|||
BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL,
|
||||
BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED,
|
||||
|
||||
BUILTIN_OCTAHEDRON,
|
||||
BUILTIN_OCTAHEDRON_SKINNED,
|
||||
BUILTIN_DEBUG_LIGHTGRID,
|
||||
BUILTIN_DEBUG_LIGHTGRID_SKINNED,
|
||||
|
||||
BUILTIN_DEBUG_OCTAHEDRON,
|
||||
BUILTIN_DEBUG_OCTAHEDRON_SKINNED,
|
||||
// RB end
|
||||
BUILTIN_ENVIRONMENT,
|
||||
BUILTIN_ENVIRONMENT_SKINNED,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -199,7 +199,6 @@ struct glconfig_t
|
|||
bool anisotropicFilterAvailable;
|
||||
bool textureLODBiasAvailable;
|
||||
bool seamlessCubeMapAvailable;
|
||||
bool sRGBFramebufferAvailable;
|
||||
bool vertexBufferObjectAvailable;
|
||||
bool mapBufferRangeAvailable;
|
||||
bool vertexArrayObjectAvailable;
|
||||
|
@ -405,6 +404,9 @@ public:
|
|||
// markers. Use WriteRender() instead.
|
||||
virtual void TakeScreenshot( int width, int height, const char* fileName, int samples, struct renderView_s* ref, int exten ) = 0;
|
||||
|
||||
// RB
|
||||
virtual byte* CaptureRenderToBuffer( int width, int height, renderView_t* ref ) = 0;
|
||||
|
||||
// the render output can be cropped down to a subset of the real screen, as
|
||||
// for save-game reviews and split-screen multiplayer. Users of the renderer
|
||||
// will not know the actual pixel size of the area they are rendering to
|
||||
|
|
|
@ -94,7 +94,6 @@ idCVar r_useNodeCommonChildren( "r_useNodeCommonChildren", "1", CVAR_RENDERER |
|
|||
idCVar r_useShadowSurfaceScissor( "r_useShadowSurfaceScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor shadows by the scissor rect of the interaction surfaces" );
|
||||
idCVar r_useCachedDynamicModels( "r_useCachedDynamicModels", "1", CVAR_RENDERER | CVAR_BOOL, "cache snapshots of dynamic models" );
|
||||
idCVar r_useSeamlessCubeMap( "r_useSeamlessCubeMap", "1", CVAR_RENDERER | CVAR_BOOL, "use ARB_seamless_cube_map if available" );
|
||||
idCVar r_useSRGB( "r_useSRGB", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 = both texture and framebuffer, 2 = framebuffer only, 3 = texture only" );
|
||||
idCVar r_maxAnisotropicFiltering( "r_maxAnisotropicFiltering", "8", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "limit aniso filtering" );
|
||||
idCVar r_useTrilinearFiltering( "r_useTrilinearFiltering", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Extra quality filtering" );
|
||||
// RB: not used anymore
|
||||
|
@ -271,9 +270,9 @@ idCVar r_shadowMapSunDepthBiasScale( "r_shadowMapSunDepthBiasScale", "0.999991",
|
|||
|
||||
// RB: HDR parameters
|
||||
#if defined( USE_VULKAN )
|
||||
idCVar r_useHDR( "r_useHDR", "0", CVAR_RENDERER | CVAR_ROM | CVAR_STATIC | CVAR_BOOL, "use high dynamic range rendering" );
|
||||
idCVar r_useHDR( "r_useHDR", "0", CVAR_RENDERER | CVAR_ROM | CVAR_STATIC | CVAR_BOOL, "Can't be changed, is broken on Vulkan backend" );
|
||||
#else
|
||||
idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use high dynamic range rendering" );
|
||||
idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ROM | CVAR_STATIC | CVAR_BOOL, "Can't be changed: Use high dynamic range rendering" );
|
||||
#endif
|
||||
|
||||
idCVar r_hdrAutoExposure( "r_hdrAutoExposure", "0", CVAR_RENDERER | CVAR_BOOL, "EXPENSIVE: enables adapative HDR tone mapping otherwise the exposure is derived by r_exposure" );
|
||||
|
@ -313,6 +312,9 @@ idCVar r_useHierarchicalDepthBuffer( "r_useHierarchicalDepthBuffer", "1", CVAR_R
|
|||
idCVar r_usePBR( "r_usePBR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use PBR and Image Based Lighting instead of old Quake 4 style ambient lighting" );
|
||||
idCVar r_pbrDebug( "r_pbrDebug", "0", CVAR_RENDERER | CVAR_INTEGER, "show which materials have PBR support (green = PBR, red = oldschool D3)" );
|
||||
idCVar r_showViewEnvprobes( "r_showViewEnvprobes", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = displays the bounding boxes of all view environment probes, 2 = show irradiance" );
|
||||
idCVar r_showLightGrid( "r_showLightGrid", "0", CVAR_RENDERER | CVAR_INTEGER, "show Quake 3 style light grid points" );
|
||||
|
||||
idCVar r_useLightGrid( "r_useLightGrid", "1", CVAR_RENDERER | CVAR_BOOL, "" );
|
||||
|
||||
idCVar r_exposure( "r_exposure", "0.5", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_FLOAT, "HDR exposure or LDR brightness [0.0 .. 1.0]", 0.0f, 1.0f );
|
||||
// RB end
|
||||
|
@ -751,7 +753,7 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref =
|
|||
if( ref && ref->rdflags & RDF_IRRADIANCE )
|
||||
{
|
||||
// * 2 = sizeof( half float )
|
||||
temp = ( byte* )R_StaticAlloc( RADIANCE_CUBEMAP_SIZE * RADIANCE_CUBEMAP_SIZE * 3 * 2 );
|
||||
//temp = ( byte* )R_StaticAlloc( RADIANCE_CUBEMAP_SIZE * RADIANCE_CUBEMAP_SIZE * 3 * 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -778,8 +780,12 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref =
|
|||
|
||||
int originalNativeWidth = glConfig.nativeScreenWidth;
|
||||
int originalNativeHeight = glConfig.nativeScreenHeight;
|
||||
glConfig.nativeScreenWidth = sysWidth;
|
||||
glConfig.nativeScreenHeight = sysHeight;
|
||||
|
||||
//if( !ref || ( ref && !( ref->rdflags & RDF_IRRADIANCE ) ) )
|
||||
{
|
||||
glConfig.nativeScreenWidth = sysWidth;
|
||||
glConfig.nativeScreenHeight = sysHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
// disable scissor, so we don't need to adjust all those rects
|
||||
|
@ -878,8 +884,11 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref =
|
|||
// discard anything currently on the list
|
||||
tr.SwapCommandBuffers( NULL, NULL, NULL, NULL, NULL, NULL );
|
||||
|
||||
glConfig.nativeScreenWidth = originalNativeWidth;
|
||||
glConfig.nativeScreenHeight = originalNativeHeight;
|
||||
if( !ref || ( ref && !( ref->rdflags & RDF_IRRADIANCE ) ) )
|
||||
{
|
||||
glConfig.nativeScreenWidth = originalNativeWidth;
|
||||
glConfig.nativeScreenHeight = originalNativeHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
r_useScissor.SetBool( true );
|
||||
|
@ -1024,6 +1033,33 @@ void idRenderSystemLocal::TakeScreenshot( int width, int height, const char* fil
|
|||
takingScreenshot = false;
|
||||
}
|
||||
|
||||
// RB begin
|
||||
byte* idRenderSystemLocal::CaptureRenderToBuffer( int width, int height, renderView_t* ref )
|
||||
{
|
||||
byte* buffer;
|
||||
|
||||
takingScreenshot = true;
|
||||
|
||||
int pix = width * height;
|
||||
const int bufferSize = pix * 3 + 18;
|
||||
|
||||
// HDR only for now
|
||||
//if( exten == EXR )
|
||||
{
|
||||
buffer = ( byte* )R_StaticAlloc( pix * 3 * 2 );
|
||||
}
|
||||
//else if( exten == PNG )
|
||||
//{
|
||||
// buffer = ( byte* )R_StaticAlloc( pix * 3 );
|
||||
//}
|
||||
|
||||
R_ReadTiledPixels( width, height, buffer, ref );
|
||||
|
||||
takingScreenshot = false;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_ScreenshotFilename
|
||||
|
@ -1283,11 +1319,6 @@ void R_EnvShot_f( const idCmdArgs& args )
|
|||
|
||||
//============================================================================
|
||||
|
||||
static idMat3 cubeAxis[6];
|
||||
|
||||
|
||||
|
||||
|
||||
void R_TransformCubemap( const char* orgDirection[6], const char* orgDir, const char* destDirection[6], const char* destDir, const char* baseName )
|
||||
{
|
||||
idStr fullname;
|
||||
|
@ -1707,6 +1738,7 @@ void idRenderSystemLocal::Clear()
|
|||
guiRecursionLevel = 0;
|
||||
guiModel = NULL;
|
||||
memset( gammaTable, 0, sizeof( gammaTable ) );
|
||||
memset( &cubeAxis, 0, sizeof( cubeAxis ) ); // RB
|
||||
takingScreenshot = false;
|
||||
|
||||
if( unitSquareTriangles != NULL )
|
||||
|
@ -1737,7 +1769,8 @@ void idRenderSystemLocal::Clear()
|
|||
|
||||
// RB
|
||||
envprobeJobList = NULL;
|
||||
irradianceJobs.Clear();
|
||||
envprobeJobs.Clear();
|
||||
lightGridJobs.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1921,7 +1954,7 @@ static srfTriangles_t* R_MakeZeroOneSphereTris()
|
|||
|
||||
verts[ numVerts ].SetTexCoord( s * S, r * R );
|
||||
verts[ numVerts ].xyz = idVec3( x, y, z ) * radius;
|
||||
verts[ numVerts ].SetNormal( -x, -y, -z );
|
||||
verts[ numVerts ].SetNormal( x, y, z );
|
||||
verts[ numVerts ].SetColor( 0xffffffff );
|
||||
numVerts++;
|
||||
|
||||
|
@ -2053,6 +2086,38 @@ void idRenderSystemLocal::Init()
|
|||
identitySpace.modelMatrix[1 * 4 + 1] = 1.0f;
|
||||
identitySpace.modelMatrix[2 * 4 + 2] = 1.0f;
|
||||
|
||||
// set cubemap axis for cubemap sampling tools
|
||||
|
||||
// +X
|
||||
cubeAxis[0][0][0] = 1;
|
||||
cubeAxis[0][1][2] = 1;
|
||||
cubeAxis[0][2][1] = 1;
|
||||
|
||||
// -X
|
||||
cubeAxis[1][0][0] = -1;
|
||||
cubeAxis[1][1][2] = -1;
|
||||
cubeAxis[1][2][1] = 1;
|
||||
|
||||
// +Y
|
||||
cubeAxis[2][0][1] = 1;
|
||||
cubeAxis[2][1][0] = -1;
|
||||
cubeAxis[2][2][2] = -1;
|
||||
|
||||
// -Y
|
||||
cubeAxis[3][0][1] = -1;
|
||||
cubeAxis[3][1][0] = -1;
|
||||
cubeAxis[3][2][2] = 1;
|
||||
|
||||
// +Z
|
||||
cubeAxis[4][0][2] = 1;
|
||||
cubeAxis[4][1][0] = -1;
|
||||
cubeAxis[4][2][1] = 1;
|
||||
|
||||
// -Z
|
||||
cubeAxis[5][0][2] = -1;
|
||||
cubeAxis[5][1][0] = 1;
|
||||
cubeAxis[5][2][1] = 1;
|
||||
|
||||
// make sure the tr.unitSquareTriangles data is current in the vertex / index cache
|
||||
if( unitSquareTriangles == NULL )
|
||||
{
|
||||
|
|
|
@ -769,7 +769,7 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe )
|
|||
|
||||
// TODO get preconvolved cubemaps
|
||||
fullname.Format( "env/%s/envprobe%i_amb", basename.c_str(), probeIndex );
|
||||
probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
|
||||
fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex );
|
||||
probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
|
|
|
@ -171,7 +171,6 @@ void idRenderWorldLocal::AddAreaViewEnvprobes( int areaNum, const portalStack_t*
|
|||
R_SampleCubeMapHDR
|
||||
==================
|
||||
*/
|
||||
static idMat3 cubeAxis[6];
|
||||
static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" };
|
||||
|
||||
void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float result[3], float& u, float& v )
|
||||
|
@ -208,8 +207,8 @@ void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float re
|
|||
axis = 5;
|
||||
}
|
||||
|
||||
float fx = ( dir * cubeAxis[axis][1] ) / ( dir * cubeAxis[axis][0] );
|
||||
float fy = ( dir * cubeAxis[axis][2] ) / ( dir * cubeAxis[axis][0] );
|
||||
float fx = ( dir * tr.cubeAxis[axis][1] ) / ( dir * tr.cubeAxis[axis][0] );
|
||||
float fy = ( dir * tr.cubeAxis[axis][2] ) / ( dir * tr.cubeAxis[axis][0] );
|
||||
|
||||
fx = -fx;
|
||||
fy = -fy;
|
||||
|
@ -252,56 +251,74 @@ void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float re
|
|||
r11g11b10f_to_float3( tmp.i, result );
|
||||
}
|
||||
|
||||
class CommandlineProgressBar
|
||||
void R_SampleCubeMapHDR16F( const idVec3& dir, int size, halfFloat_t* buffers[6], float result[3], float& u, float& v )
|
||||
{
|
||||
private:
|
||||
size_t tics = 0;
|
||||
size_t nextTicCount = 0;
|
||||
int count = 0;
|
||||
int expectedCount = 0;
|
||||
float adir[3];
|
||||
int axis, x, y;
|
||||
|
||||
public:
|
||||
CommandlineProgressBar( int _expectedCount )
|
||||
adir[0] = fabs( dir[0] );
|
||||
adir[1] = fabs( dir[1] );
|
||||
adir[2] = fabs( dir[2] );
|
||||
|
||||
if( dir[0] >= adir[1] && dir[0] >= adir[2] )
|
||||
{
|
||||
expectedCount = _expectedCount;
|
||||
axis = 0;
|
||||
}
|
||||
else if( -dir[0] >= adir[1] && -dir[0] >= adir[2] )
|
||||
{
|
||||
axis = 1;
|
||||
}
|
||||
else if( dir[1] >= adir[0] && dir[1] >= adir[2] )
|
||||
{
|
||||
axis = 2;
|
||||
}
|
||||
else if( -dir[1] >= adir[0] && -dir[1] >= adir[2] )
|
||||
{
|
||||
axis = 3;
|
||||
}
|
||||
else if( dir[2] >= adir[1] && dir[2] >= adir[2] )
|
||||
{
|
||||
axis = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
axis = 5;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
common->Printf( "0%% 10 20 30 40 50 60 70 80 90 100%%\n" );
|
||||
common->Printf( "|----|----|----|----|----|----|----|----|----|----|\n" );
|
||||
float fx = ( dir * tr.cubeAxis[axis][1] ) / ( dir * tr.cubeAxis[axis][0] );
|
||||
float fy = ( dir * tr.cubeAxis[axis][2] ) / ( dir * tr.cubeAxis[axis][0] );
|
||||
|
||||
common->UpdateScreen( false );
|
||||
fx = -fx;
|
||||
fy = -fy;
|
||||
x = size * 0.5 * ( fx + 1 );
|
||||
y = size * 0.5 * ( fy + 1 );
|
||||
if( x < 0 )
|
||||
{
|
||||
x = 0;
|
||||
}
|
||||
else if( x >= size )
|
||||
{
|
||||
x = size - 1;
|
||||
}
|
||||
if( y < 0 )
|
||||
{
|
||||
y = 0;
|
||||
}
|
||||
else if( y >= size )
|
||||
{
|
||||
y = size - 1;
|
||||
}
|
||||
|
||||
void Increment()
|
||||
{
|
||||
if( ( count + 1 ) >= nextTicCount )
|
||||
{
|
||||
size_t ticsNeeded = ( size_t )( ( ( double )( count + 1 ) / expectedCount ) * 50.0 );
|
||||
u = x;
|
||||
v = y;
|
||||
|
||||
do
|
||||
{
|
||||
common->Printf( "*" );
|
||||
}
|
||||
while( ++tics < ticsNeeded );
|
||||
// unpack RGB16F to 3 floats
|
||||
result[0] = F16toF32( buffers[axis][( y * size + x ) * 3 + 0] );
|
||||
result[1] = F16toF32( buffers[axis][( y * size + x ) * 3 + 1] );
|
||||
result[2] = F16toF32( buffers[axis][( y * size + x ) * 3 + 2] );
|
||||
}
|
||||
|
||||
nextTicCount = ( size_t )( ( tics / 50.0 ) * expectedCount );
|
||||
if( count == ( expectedCount - 1 ) )
|
||||
{
|
||||
if( tics < 51 )
|
||||
{
|
||||
common->Printf( "*" );
|
||||
}
|
||||
common->Printf( "\n" );
|
||||
}
|
||||
|
||||
common->UpdateScreen( false );
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
||||
|
@ -432,14 +449,41 @@ idVec2 IntegrateBRDF( float NdotV, float roughness, int sampleCount )
|
|||
|
||||
|
||||
// Compute normalized oct coord, mapping top left of top left pixel to (-1,-1)
|
||||
idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength )
|
||||
idVec2 NormalizedOctCoord( int x, int y, const int probeWithBorderSide )
|
||||
{
|
||||
const int margin = 0;
|
||||
#if 0
|
||||
// 1 pixel border
|
||||
const int margin = 1;
|
||||
|
||||
int probeWithBorderSide = probeSideLength + margin;
|
||||
int probeSideLength = Max( 2, probeWithBorderSide - ( margin * 2 ) );
|
||||
|
||||
idVec2 octFragCoord;
|
||||
octFragCoord.x = idMath::ClampInt( 0, probeSideLength - 1, x - margin );
|
||||
octFragCoord.y = idMath::ClampInt( 0, probeSideLength - 1, y - margin );
|
||||
|
||||
return ( idVec2( octFragCoord ) ) * ( 2.0f / float( probeSideLength ) ) - idVec2( 1.0f, 1.0f );
|
||||
#else
|
||||
|
||||
const int margin = 2;
|
||||
|
||||
// RB: FIXME - margin * 2 is wrong but looks better
|
||||
// figure out why
|
||||
int probeSideLength = Max( 2, probeWithBorderSide - ( margin * 2 ) );
|
||||
|
||||
idVec2 octFragCoord = idVec2( ( x - margin ) % probeWithBorderSide, ( y - margin ) % probeWithBorderSide );
|
||||
|
||||
// Add back the half pixel to get pixel center normalized coordinates
|
||||
return ( idVec2( octFragCoord ) + idVec2( 0.5f, 0.5f ) ) * ( 2.0f / float( probeSideLength ) ) - idVec2( 1.0f, 1.0f );
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline idVec2 NormalizedOctCoordNoBorder( int x, int y, const int probeWithBorderSide )
|
||||
{
|
||||
int probeSideLength = probeWithBorderSide;
|
||||
|
||||
idVec2 octFragCoord = idVec2( x % probeWithBorderSide, y % probeWithBorderSide );
|
||||
|
||||
// Add back the half pixel to get pixel center normalized coordinates
|
||||
return ( idVec2( octFragCoord ) + idVec2( 0.5f, 0.5f ) ) * ( 2.0f / float( probeSideLength ) ) - idVec2( 1.0f, 1.0f );
|
||||
}
|
||||
|
@ -562,10 +606,10 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms )
|
|||
progressBar.Start();
|
||||
}
|
||||
|
||||
// build L4 Spherical Harmonics from source image
|
||||
SphericalHarmonicsT<idVec3, 4> shRadiance;
|
||||
// build L3 Spherical Harmonics from source image
|
||||
SphericalHarmonicsT<idVec3, 3> shRadiance;
|
||||
|
||||
for( int i = 0; i < shSize( 4 ); i++ )
|
||||
for( int i = 0; i < shSize( 3 ); i++ )
|
||||
{
|
||||
shRadiance[i].Zero();
|
||||
}
|
||||
|
@ -582,7 +626,7 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms )
|
|||
{
|
||||
for( int y = dstRect.y; y < ( dstRect.y + dstRect.w ); y++ )
|
||||
{
|
||||
idVec2 octCoord = NormalizedOctCoord( x, y, dstRect.z );
|
||||
idVec2 octCoord = NormalizedOctCoordNoBorder( x, y, dstRect.z );
|
||||
|
||||
// convert UV coord to 3D direction
|
||||
idVec3 dir;
|
||||
|
@ -647,7 +691,7 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms )
|
|||
|
||||
float texelArea = CubemapTexelSolidAngle( uu, vv, invDstSize );
|
||||
|
||||
const SphericalHarmonicsT<float, 4>& sh = shEvaluate<4>( dir );
|
||||
const SphericalHarmonicsT<float, 3>& sh = shEvaluate<3>( dir );
|
||||
|
||||
bool shValid = true;
|
||||
for( int i = 0; i < 25; i++ )
|
||||
|
@ -694,11 +738,11 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms )
|
|||
if( mip > 0 )
|
||||
{
|
||||
// move back to [0, 1] coords
|
||||
octCoord = NormalizedOctCoord( x - dstRect.x, y - dstRect.y, dstRect.z );
|
||||
octCoord = NormalizedOctCoordNoBorder( x - dstRect.x, y - dstRect.y, dstRect.z );
|
||||
}
|
||||
else
|
||||
{
|
||||
octCoord = NormalizedOctCoord( x, y, dstRect.z );
|
||||
octCoord = NormalizedOctCoordNoBorder( x, y, dstRect.z );
|
||||
}
|
||||
|
||||
// convert UV coord to 3D direction
|
||||
|
@ -709,10 +753,10 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms )
|
|||
idVec3 outColor( 0, 0, 0 );
|
||||
|
||||
#if 1
|
||||
// generate ambient colors by evaluating the L4 Spherical Harmonics
|
||||
SphericalHarmonicsT<float, 4> shDirection = shEvaluate<4>( dir );
|
||||
// generate ambient colors by evaluating the L3 Spherical Harmonics
|
||||
SphericalHarmonicsT<float, 3> shDirection = shEvaluate<3>( dir );
|
||||
|
||||
idVec3 sampleIrradianceSh = shEvaluateDiffuse<idVec3, 4>( shRadiance, dir ) / idMath::PI;
|
||||
idVec3 sampleIrradianceSh = shEvaluateDiffuse<idVec3, 3>( shRadiance, dir ) / idMath::PI;
|
||||
|
||||
outColor[0] = Max( 0.0f, sampleIrradianceSh.x );
|
||||
outColor[1] = Max( 0.0f, sampleIrradianceSh.y );
|
||||
|
@ -805,11 +849,11 @@ void CalculateRadianceJob( calcEnvprobeParms_t* parms )
|
|||
if( mip > 0 )
|
||||
{
|
||||
// move back to [0, 1] coords
|
||||
octCoord = NormalizedOctCoord( x - dstRect.x, y - dstRect.y, dstRect.z );
|
||||
octCoord = NormalizedOctCoordNoBorder( x - dstRect.x, y - dstRect.y, dstRect.z );
|
||||
}
|
||||
else
|
||||
{
|
||||
octCoord = NormalizedOctCoord( x, y, dstRect.z );
|
||||
octCoord = NormalizedOctCoordNoBorder( x, y, dstRect.z );
|
||||
}
|
||||
|
||||
// convert UV coord to 3D direction
|
||||
|
@ -921,7 +965,7 @@ void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, bo
|
|||
jobParms->outHeight = outSize;
|
||||
jobParms->outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( outSize * outSize * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE );
|
||||
|
||||
tr.irradianceJobs.Append( jobParms );
|
||||
tr.envprobeJobs.Append( jobParms );
|
||||
|
||||
if( useThreads )
|
||||
{
|
||||
|
@ -957,7 +1001,7 @@ void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, bo
|
|||
}
|
||||
}
|
||||
|
||||
CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL )
|
||||
CONSOLE_COMMAND( bakeEnvironmentProbes, "Bake environment probes", NULL )
|
||||
{
|
||||
idStr fullname;
|
||||
idStr baseName;
|
||||
|
@ -990,38 +1034,6 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL
|
|||
|
||||
const viewDef_t primary = *tr.primaryView;
|
||||
|
||||
memset( &cubeAxis, 0, sizeof( cubeAxis ) );
|
||||
|
||||
// +X
|
||||
cubeAxis[0][0][0] = 1;
|
||||
cubeAxis[0][1][2] = 1;
|
||||
cubeAxis[0][2][1] = 1;
|
||||
|
||||
// -X
|
||||
cubeAxis[1][0][0] = -1;
|
||||
cubeAxis[1][1][2] = -1;
|
||||
cubeAxis[1][2][1] = 1;
|
||||
|
||||
// +Y
|
||||
cubeAxis[2][0][1] = 1;
|
||||
cubeAxis[2][1][0] = -1;
|
||||
cubeAxis[2][2][2] = -1;
|
||||
|
||||
// -Y
|
||||
cubeAxis[3][0][1] = -1;
|
||||
cubeAxis[3][1][0] = -1;
|
||||
cubeAxis[3][2][2] = 1;
|
||||
|
||||
// +Z
|
||||
cubeAxis[4][0][2] = 1;
|
||||
cubeAxis[4][1][0] = -1;
|
||||
cubeAxis[4][2][1] = 1;
|
||||
|
||||
// -Z
|
||||
cubeAxis[5][0][2] = -1;
|
||||
cubeAxis[5][1][0] = 1;
|
||||
cubeAxis[5][2][1] = 1;
|
||||
|
||||
//--------------------------------------------
|
||||
// CAPTURE SCENE LIGHTING TO CUBEMAPS
|
||||
//--------------------------------------------
|
||||
|
@ -1042,7 +1054,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL
|
|||
ref.fov_x = ref.fov_y = 90;
|
||||
|
||||
ref.vieworg = def->parms.origin;
|
||||
ref.viewaxis = cubeAxis[j];
|
||||
ref.viewaxis = tr.cubeAxis[j];
|
||||
|
||||
extension = envDirection[ j ];
|
||||
fullname.Format( "env/%s/envprobe%i%s", baseName.c_str(), i, extension );
|
||||
|
@ -1082,9 +1094,9 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL
|
|||
tr.envprobeJobList->Wait();
|
||||
}
|
||||
|
||||
for( int j = 0; j < tr.irradianceJobs.Num(); j++ )
|
||||
for( int j = 0; j < tr.envprobeJobs.Num(); j++ )
|
||||
{
|
||||
calcEnvprobeParms_t* job = tr.irradianceJobs[ j ];
|
||||
calcEnvprobeParms_t* job = tr.envprobeJobs[ j ];
|
||||
|
||||
R_WriteEXR( job->filename, ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" );
|
||||
|
||||
|
@ -1103,11 +1115,26 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL
|
|||
delete job;
|
||||
}
|
||||
|
||||
tr.irradianceJobs.Clear();
|
||||
tr.envprobeJobs.Clear();
|
||||
|
||||
int end = Sys_Milliseconds();
|
||||
|
||||
common->Printf( "convolved probes in %5.1f seconds\n\n", ( end - start ) * 0.001f );
|
||||
|
||||
//--------------------------------------------
|
||||
// LOAD CONVOLVED OCTAHEDRONS INTO THE GPU
|
||||
//--------------------------------------------
|
||||
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
||||
{
|
||||
RenderEnvprobeLocal* def = tr.primaryWorld->envprobeDefs[i];
|
||||
if( def == NULL )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
def->irradianceImage->Reload( false );
|
||||
def->radianceImage->Reload( false );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
1560
neo/renderer/RenderWorld_lightgrid.cpp
Normal file
1560
neo/renderer/RenderWorld_lightgrid.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -858,6 +858,7 @@ bool idRenderWorldLocal::InitFromMap( const char* name )
|
|||
TouchWorldModels();
|
||||
AddWorldModelEntities();
|
||||
ClearPortalStates();
|
||||
SetupLightGrid();
|
||||
return true;
|
||||
}
|
||||
common->Printf( "idRenderWorldLocal::InitFromMap: timestamp has changed, reloading.\n" );
|
||||
|
@ -1047,6 +1048,7 @@ bool idRenderWorldLocal::InitFromMap( const char* name )
|
|||
|
||||
AddWorldModelEntities();
|
||||
ClearPortalStates();
|
||||
SetupLightGrid();
|
||||
|
||||
// done!
|
||||
return true;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2014-2016 Robert Beckebans
|
||||
Copyright (C) 2014-2021 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
@ -59,6 +59,57 @@ typedef struct doublePortal_s
|
|||
struct doublePortal_s* nextFoggedPortal;
|
||||
} doublePortal_t;
|
||||
|
||||
// RB: added Quake 3 style light grid
|
||||
// however this 2021 version features Spherical Harmonics instead of ambient + directed color
|
||||
struct lightGridPoint_t
|
||||
{
|
||||
idVec3 origin; // not saved to .proc
|
||||
byte valid; // is not in the void
|
||||
|
||||
SphericalHarmonicsT<idVec3, 4> shRadiance; // L4 Spherical Harmonics
|
||||
};
|
||||
|
||||
class LightGrid
|
||||
{
|
||||
public:
|
||||
idVec3 lightGridOrigin;
|
||||
idVec3 lightGridSize;
|
||||
int lightGridBounds[3];
|
||||
|
||||
idList<lightGridPoint_t> lightGridPoints;
|
||||
|
||||
int area;
|
||||
idImage* irradianceImage;
|
||||
int imageSingleProbeSize; // including border
|
||||
int imageBorderSize;
|
||||
|
||||
LightGrid();
|
||||
|
||||
// setup light grid for given world bounds
|
||||
void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int _area, int limit );
|
||||
|
||||
void GetBaseGridCoord( const idVec3& origin, int gridCoord[3] );
|
||||
|
||||
int GridCoordToProbeIndex( int gridCoord[3] );
|
||||
void ProbeIndexToGridCoord( const int probeIndex, int gridCoord[3] );
|
||||
|
||||
idVec3 GetGridCoordDebugColor( int gridCoord[3] );
|
||||
idVec3 GetProbeIndexDebugColor( const int probeIndex );
|
||||
|
||||
int CountValidGridPoints() const;
|
||||
|
||||
idImage* GetIrradianceImage() const
|
||||
{
|
||||
return irradianceImage;
|
||||
}
|
||||
|
||||
// fetch grid lighting on a per object basis
|
||||
void SetupEntityGridLighting( idRenderEntityLocal* def );
|
||||
|
||||
private:
|
||||
void CalculateLightGridPointPositions( const idRenderWorld* world, int area );
|
||||
};
|
||||
// RB end
|
||||
|
||||
typedef struct portalArea_s
|
||||
{
|
||||
|
@ -68,6 +119,8 @@ typedef struct portalArea_s
|
|||
|
||||
idBounds globalBounds; // RB: AABB of the BSP area used for light grid density
|
||||
|
||||
LightGrid lightGrid;
|
||||
|
||||
int viewCount; // set by R_FindViewLightsAndEntities
|
||||
portal_t* portals; // never changes after load
|
||||
areaReference_t entityRefs; // head/tail of doubly linked list, may change
|
||||
|
@ -337,6 +390,24 @@ public:
|
|||
//-------------------------------
|
||||
// tr_light.c
|
||||
void CreateLightDefInteractions( idRenderLightLocal* const ldef, const int renderViewID );
|
||||
|
||||
// RB begin
|
||||
|
||||
//--------------------------
|
||||
// RenderWorld_lightgrid.cpp
|
||||
|
||||
//private:
|
||||
void SetupLightGrid();
|
||||
|
||||
void WriteLightGridsToFile( const char* filename );
|
||||
void WriteLightGrid( idFile* fp, const LightGrid& lightGrid );
|
||||
|
||||
bool LoadLightGridFile( const char* name );
|
||||
void LoadLightGridImages();
|
||||
|
||||
void ParseLightGridPoints( idLexer* src, idFile* fileOut );
|
||||
void ReadBinaryLightGridPoints( idFile* file );
|
||||
// RB end
|
||||
};
|
||||
|
||||
// if an entity / light combination has been evaluated and found to not genrate any surfaces or shadows,
|
||||
|
|
|
@ -373,6 +373,9 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
vEntity->staticShadowVolumes = NULL;
|
||||
vEntity->dynamicShadowVolumes = NULL;
|
||||
|
||||
// RB
|
||||
vEntity->useLightGrid = false;
|
||||
|
||||
// globals we really should pass in...
|
||||
const viewDef_t* viewDef = tr.viewDef;
|
||||
|
||||
|
@ -549,6 +552,32 @@ void R_AddSingleModel( viewEntity_t* vEntity )
|
|||
}
|
||||
}
|
||||
|
||||
// RB: use first valid lightgrid
|
||||
for( areaReference_t* ref = entityDef->entityRefs; ref != NULL; ref = ref->ownerNext )
|
||||
{
|
||||
idImage* lightGridImage = ref->area->lightGrid.GetIrradianceImage();
|
||||
|
||||
if( ref->area->lightGrid.lightGridPoints.Num() && lightGridImage && !lightGridImage->IsDefaulted() )
|
||||
{
|
||||
vEntity->useLightGrid = true;
|
||||
vEntity->lightGridAtlasImage = lightGridImage;
|
||||
vEntity->lightGridAtlasSingleProbeSize = ref->area->lightGrid.imageSingleProbeSize;
|
||||
vEntity->lightGridAtlasBorderSize = ref->area->lightGrid.imageBorderSize;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
vEntity->lightGridOrigin[i] = ref->area->lightGrid.lightGridOrigin[i];
|
||||
vEntity->lightGridSize[i] = ref->area->lightGrid.lightGridSize[i];
|
||||
vEntity->lightGridBounds[i] = ref->area->lightGrid.lightGridBounds[i];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// RB end
|
||||
|
||||
//---------------------------
|
||||
// copy matrix related stuff for back-end use
|
||||
// and setup a render matrix for faster culling
|
||||
|
|
|
@ -454,6 +454,121 @@ static void R_SetupSplitFrustums( viewDef_t* viewDef )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class idSort_CompareEnvprobe : public idSort_Quick< RenderEnvprobeLocal*, idSort_CompareEnvprobe >
|
||||
{
|
||||
idVec3 viewOrigin;
|
||||
|
||||
public:
|
||||
idSort_CompareEnvprobe( const idVec3& origin )
|
||||
{
|
||||
viewOrigin = origin;
|
||||
}
|
||||
|
||||
int Compare( RenderEnvprobeLocal* const& a, RenderEnvprobeLocal* const& b ) const
|
||||
{
|
||||
float adist = ( viewOrigin - a->parms.origin ).LengthSqr();
|
||||
float bdist = ( viewOrigin - b->parms.origin ).LengthSqr();
|
||||
|
||||
if( adist < bdist )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( adist > bdist )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
static void R_FindClosestEnvironmentProbes()
|
||||
{
|
||||
// set safe defaults
|
||||
tr.viewDef->globalProbeBounds.Clear();
|
||||
|
||||
tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube;
|
||||
tr.viewDef->radianceImageBlends.Set( 1, 0, 0, 0 );
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
tr.viewDef->radianceImages[i] = globalImages->defaultUACRadianceCube;
|
||||
}
|
||||
|
||||
// early out
|
||||
if( tr.viewDef->areaNum == -1 || tr.viewDef->isSubview )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
idList<RenderEnvprobeLocal*, TAG_RENDER_ENVPROBE> viewEnvprobes;
|
||||
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
||||
{
|
||||
RenderEnvprobeLocal* vProbe = tr.primaryWorld->envprobeDefs[i];
|
||||
if( vProbe )
|
||||
{
|
||||
viewEnvprobes.AddUnique( vProbe );
|
||||
}
|
||||
}
|
||||
|
||||
if( viewEnvprobes.Num() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 testOrigin = tr.viewDef->renderView.vieworg;
|
||||
|
||||
// sort by distance
|
||||
// RB: each Doom 3 level has ~50 - 150 probes so this should be ok for each frame
|
||||
viewEnvprobes.SortWithTemplate( idSort_CompareEnvprobe( testOrigin ) );
|
||||
|
||||
RenderEnvprobeLocal* nearest = viewEnvprobes[0];
|
||||
tr.viewDef->globalProbeBounds = nearest->globalProbeBounds;
|
||||
tr.viewDef->irradianceImage = nearest->irradianceImage;
|
||||
|
||||
// form a triangle of the 3 closest probes
|
||||
idVec3 verts[3];
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
verts[i] = viewEnvprobes[0]->parms.origin;
|
||||
}
|
||||
|
||||
for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ )
|
||||
{
|
||||
RenderEnvprobeLocal* vProbe = viewEnvprobes[i];
|
||||
|
||||
verts[i] = vProbe->parms.origin;
|
||||
}
|
||||
|
||||
idVec3 closest = R_ClosestPointPointTriangle( testOrigin, verts[0], verts[1], verts[2] );
|
||||
idVec3 bary;
|
||||
|
||||
// find the barycentric coordinates
|
||||
float denom = idWinding::TriangleArea( verts[0], verts[1], verts[2] );
|
||||
if( denom == 0 )
|
||||
{
|
||||
// all points at same location
|
||||
bary.Set( 1, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
float a, b, c;
|
||||
|
||||
a = idWinding::TriangleArea( closest, verts[1], verts[2] ) / denom;
|
||||
b = idWinding::TriangleArea( closest, verts[2], verts[0] ) / denom;
|
||||
c = idWinding::TriangleArea( closest, verts[0], verts[1] ) / denom;
|
||||
|
||||
bary.Set( a, b, c );
|
||||
}
|
||||
|
||||
tr.viewDef->radianceImageBlends.Set( bary.x, bary.y, bary.z, 0.0f );
|
||||
|
||||
for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ )
|
||||
{
|
||||
tr.viewDef->radianceImages[i] = viewEnvprobes[i]->radianceImage;
|
||||
}
|
||||
}
|
||||
// RB end
|
||||
|
||||
/*
|
||||
|
@ -539,32 +654,8 @@ void R_RenderView( viewDef_t* parms )
|
|||
}
|
||||
}
|
||||
|
||||
// RB: find closest environment probe
|
||||
if( tr.viewDef->areaNum != -1 && !tr.viewDef->isSubview )
|
||||
{
|
||||
float bestDist = idMath::INFINITY;
|
||||
|
||||
tr.viewDef->globalProbeBounds.Clear();
|
||||
|
||||
tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube;
|
||||
tr.viewDef->radianceImage = globalImages->defaultUACRadianceCube;
|
||||
|
||||
for( viewEnvprobe_t* vProbe = tr.viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next )
|
||||
{
|
||||
float dist = ( tr.viewDef->renderView.vieworg - vProbe->globalOrigin ).Length();
|
||||
if( ( dist < bestDist ) )
|
||||
{
|
||||
if( vProbe->irradianceImage->IsLoaded() && !vProbe->irradianceImage->IsDefaulted() )
|
||||
{
|
||||
tr.viewDef->globalProbeBounds = vProbe->globalProbeBounds;
|
||||
tr.viewDef->irradianceImage = vProbe->irradianceImage;
|
||||
tr.viewDef->radianceImage = vProbe->radianceImage;
|
||||
|
||||
bestDist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// RB: find closest environment probes so we can interpolate between them in the ambient shaders
|
||||
R_FindClosestEnvironmentProbes();
|
||||
|
||||
// write everything needed to the demo file
|
||||
if( common->WriteDemo() )
|
||||
|
|
|
@ -2367,4 +2367,82 @@ static void SetUpMikkTSpaceContext( SMikkTSpaceContext* context )
|
|||
context->m_pInterface = &mikkTSpaceInterface.mkInterface;
|
||||
}
|
||||
|
||||
// SP end
|
||||
// SP end
|
||||
|
||||
|
||||
// RB: Determines the closest point between a point and a triangle
|
||||
idVec3 R_ClosestPointPointTriangle( const idVec3& point, const idVec3& vertex1, const idVec3& vertex2, const idVec3& vertex3 )
|
||||
{
|
||||
idVec3 result;
|
||||
|
||||
// Source: Real-Time Collision Detection by Christer Ericson
|
||||
// Reference: Page 136
|
||||
|
||||
// check if P in vertex region outside A
|
||||
idVec3 ab = vertex2 - vertex1;
|
||||
idVec3 ac = vertex3 - vertex1;
|
||||
idVec3 ap = point - vertex1;
|
||||
|
||||
float d1 = ( ab * ap );
|
||||
float d2 = ( ac * ap );
|
||||
if( d1 <= 0.0f && d2 <= 0.0f )
|
||||
{
|
||||
result = vertex1; //Barycentric coordinates (1,0,0)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside B
|
||||
idVec3 bp = point - vertex2;
|
||||
float d3 = ( ab * bp );
|
||||
float d4 = ( ac * bp );
|
||||
if( d3 >= 0.0f && d4 <= d3 )
|
||||
{
|
||||
result = vertex2; // barycentric coordinates (0,1,0)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if P in edge region of AB, if so return projection of P onto AB
|
||||
float vc = d1 * d4 - d3 * d2;
|
||||
if( vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f )
|
||||
{
|
||||
float v = d1 / ( d1 - d3 );
|
||||
result = vertex1 + v * ab; //Barycentric coordinates (1-v,v,0)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if P in vertex region outside C
|
||||
idVec3 cp = point - vertex3;
|
||||
float d5 = ( ab * cp );
|
||||
float d6 = ( ac * cp );
|
||||
if( d6 >= 0.0f && d5 <= d6 )
|
||||
{
|
||||
result = vertex3; //Barycentric coordinates (0,0,1)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if P in edge region of AC, if so return projection of P onto AC
|
||||
float vb = d5 * d2 - d1 * d6;
|
||||
if( vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f )
|
||||
{
|
||||
float w = d2 / ( d2 - d6 );
|
||||
result = vertex1 + w * ac; //Barycentric coordinates (1-w,0,w)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check if P in edge region of BC, if so return projection of P onto BC
|
||||
float va = d3 * d6 - d5 * d4;
|
||||
if( va <= 0.0f && ( d4 - d3 ) >= 0.0f && ( d5 - d6 ) >= 0.0f )
|
||||
{
|
||||
float w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
|
||||
result = vertex2 + w * ( vertex3 - vertex2 ); //Barycentric coordinates (0,1-w,w)
|
||||
return result;
|
||||
}
|
||||
|
||||
// P inside face region. Compute Q through its barycentric coordinates (u,v,w)
|
||||
float denom = 1.0f / ( va + vb + vc );
|
||||
float v2 = vb * denom;
|
||||
float w2 = vc * denom;
|
||||
result = vertex1 + ab * v2 + ac * w2; //= u*vertex1 + v*vertex2 + w*vertex3, u = va * denom = 1.0f - v - w
|
||||
|
||||
return result;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2013-2015 Robert Beckebans
|
||||
Copyright (C) 2013-2021 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
|
|
Loading…
Reference in a new issue