555 lines
21 KiB
HLSL
555 lines
21 KiB
HLSL
#pragma dcl position
|
|
|
|
#include "../common.fxh"
|
|
#include "../Util/macros.fxh"
|
|
#include "../../renderer/Lights/LightCommon.h"
|
|
|
|
// We don't care for no skinning matrices here, so we can use a bigger constant register file
|
|
#pragma constant 130
|
|
|
|
#if LIGHTSHAFT_USE_SHADOWS
|
|
#define SHADOW_CASTING (0)
|
|
#define SHADOW_CASTING_TECHNIQUES (0)
|
|
#define SHADOW_RECEIVING (1)
|
|
#define SHADOW_RECEIVING_VS (0)
|
|
#include "Shadows/cascadeshadows.fxh"
|
|
#endif // LIGHTSHAFT_USE_SHADOWS
|
|
|
|
#define DEFERRED_UNPACK_LIGHT
|
|
#include "lights\light_structs.fxh"
|
|
#include "lighting.fxh"
|
|
#undef DEFERRED_UNPACK_LIGHT
|
|
|
|
|
|
BEGIN_RAGE_CONSTANT_BUFFER(deferred_volume_locals,b0)
|
|
float4 deferredVolumePosition; // w=unused
|
|
float4 deferredVolumeDirection; // w=unused
|
|
float4 deferredVolumeTangentXAndShaftRadius;
|
|
float4 deferredVolumeTangentYAndShaftLength;
|
|
float4 deferredVolumeColour; // w=unused
|
|
float4 deferredVolumeShaftPlanes[3];
|
|
float4 deferredVolumeShaftGradient;
|
|
float4 deferredVolumeShaftGradientColourInv; // w=softness
|
|
ROW_MAJOR float4x4 deferredVolumeShaftCompositeMtx;
|
|
|
|
EndConstantBufferDX10(deferred_volume_locals)
|
|
|
|
|
|
DECLARE_SAMPLER(sampler2D, deferredVolumeDepthBuffer, deferredVolumeDepthBufferSamp,
|
|
AddressU = CLAMP;
|
|
AddressV = CLAMP;
|
|
MIPFILTER = NONE;
|
|
MINFILTER = POINT;
|
|
MAGFILTER = POINT;
|
|
);
|
|
|
|
// texture used by lights and modifiers - all bi-linear filtered
|
|
BeginDX10Sampler(sampler, Texture2D<float4>, gVolumeLightsTexture,gVolumeLightsSampler,gVolumeLightsTexture)
|
|
ContinueSampler(sampler, gVolumeLightsTexture,gVolumeLightsSampler,gVolumeLightsTexture)
|
|
AddressU = CLAMP;
|
|
AddressV = CLAMP;
|
|
AddressW = CLAMP;
|
|
MINFILTER = LINEAR;//POINT;
|
|
MAGFILTER = LINEAR;//POINT;
|
|
MIPFILTER = LINEAR;//POINT;
|
|
EndSampler;
|
|
|
|
BeginDX10Sampler(sampler, Texture2D<float>, gLowResDepthTexture,gLowResDepthSampler,gLowResDepthTexture)
|
|
ContinueSampler(sampler, gLowResDepthTexture,gLowResDepthSampler,gLowResDepthTexture)
|
|
AddressU = CLAMP;
|
|
AddressV = CLAMP;
|
|
AddressW = CLAMP;
|
|
MINFILTER = POINT;
|
|
MAGFILTER = POINT;
|
|
MIPFILTER = POINT;
|
|
EndSampler;
|
|
|
|
#define g_fBilateralCoefficient 0.007f
|
|
|
|
struct vertexInputVolume
|
|
{
|
|
float3 pos : POSITION;
|
|
};
|
|
|
|
struct vertexOutputVolumeShaft
|
|
{
|
|
DECLARE_POSITION(pos)
|
|
float3 worldPos : TEXCOORD0;
|
|
float4 screenPos : TEXCOORD1; // z is 1 - fog opacity, w is oPos.w
|
|
float3 planeP : TEXCOORD2;
|
|
float3 planeQ : TEXCOORD3;
|
|
};
|
|
|
|
vertexOutputVolumeShaft volumeShaft_internal(vertexInputVolume IN, bool shadowed)
|
|
{
|
|
vertexOutputVolumeShaft OUT;
|
|
|
|
const float2 quadPos = IN.pos.xy - 0.5; // -[1/2..1/2]
|
|
|
|
const float3 dirx = deferredVolumeTangentXAndShaftRadius.xyz;
|
|
const float3 diry = deferredVolumeTangentYAndShaftLength.xyz;
|
|
const float3 dirz = deferredVolumeDirection.xyz;
|
|
const float3 qpos = deferredVolumePosition.xyz + dirx*quadPos.x + diry*quadPos.y; // position on shaft quad
|
|
|
|
const float shaftLength = deferredVolumeTangentYAndShaftLength.w; // how far to extend in light direction
|
|
|
|
//if (shadowed) // this doesn't work, remove it?
|
|
//{
|
|
// length = min(CalcCascadeShadowSampleVS(wpos, true, false), length);
|
|
//}
|
|
|
|
const float3 worldPos = qpos + dirz*shaftLength*IN.pos.z;
|
|
const float3 eyePos = gViewInverse[3].xyz;
|
|
const float3 eyeRay = worldPos - eyePos;
|
|
const float4 oPos = mul(float4(worldPos, 1), gWorldViewProj);
|
|
|
|
OUT.pos = mul(float4(worldPos, 1), deferredVolumeShaftCompositeMtx);
|
|
OUT.worldPos = worldPos;
|
|
OUT.screenPos = float4(convertToVpos(MonoToStereoClipSpace(oPos), deferredLightScreenSize).xy, 1 - CalcFogData(eyeRay).w, oPos.w);
|
|
|
|
OUT.planeP = float3(
|
|
-dot(float4(eyePos, 1), deferredVolumeShaftPlanes[0]),
|
|
-dot(float4(eyePos, 1), deferredVolumeShaftPlanes[1]),
|
|
-dot(float4(eyePos, 1), deferredVolumeShaftPlanes[2])
|
|
);
|
|
OUT.planeQ = float3(
|
|
dot(eyeRay, deferredVolumeShaftPlanes[0].xyz),
|
|
dot(eyeRay, deferredVolumeShaftPlanes[1].xyz),
|
|
dot(eyeRay, deferredVolumeShaftPlanes[2].xyz)
|
|
);
|
|
|
|
return (OUT);
|
|
}
|
|
|
|
vertexOutputVolumeShaft VS_volumeShaft(vertexInputVolume IN)
|
|
{
|
|
return volumeShaft_internal(IN, false);
|
|
}
|
|
|
|
float intersectPlane(float3 p, float3 v, float4 plane)
|
|
{
|
|
return -dot(float4(p, 1), plane)/dot(v, plane.xyz);
|
|
}
|
|
|
|
half4 volumeShaft_internal(vertexOutputVolumeShaft IN, int volumeType, int densityType)
|
|
{
|
|
const float3 worldPos = IN.worldPos; // world pos on backface
|
|
const float3 eyePos = gViewInverse[3].xyz;
|
|
const float3 eyeRay = worldPos - eyePos;
|
|
const float depthSample = tex2D(deferredVolumeDepthBufferSamp, IN.screenPos.xy/IN.screenPos.w).x;
|
|
const float depth = getLinearGBufferDepth(depthSample, deferredProjectionParams.zw)/IN.screenPos.w;
|
|
|
|
const float r = deferredVolumeTangentXAndShaftRadius.w; // radius
|
|
const float3 a = deferredVolumeDirection.xyz; // direction
|
|
const float b = 1; // cos cone angle
|
|
const float3 q = eyePos - deferredVolumePosition.xyz;
|
|
const float3 v = eyeRay;
|
|
|
|
// =========================================================================================================================
|
|
// sphere: |q + t*v| == r
|
|
// t = (-qv +/- sqrt((rr - qq)*vv + qv^2))/vv
|
|
//
|
|
// cylinder: |q - (q.a)*a + t*(v - (v.a)*a)| == r
|
|
// t = (qa*va - qv +/- sqrt((rr - qq + qa^2)*vv + (qq - rr)*va^2 - 2*qa*qv*va + qv^2))/(vv - va^2)
|
|
//
|
|
// cone: (q + t*v).a == b*|q + t*v|
|
|
// t = (qa*va - bb*qv +/- sqrt((bb*qa^2 - bb^2*qq)*vv + bb*qq*va^2 - 2*bb*qa*qv*va + bb^2*qv^2))/(bb*vv - va^2)
|
|
//
|
|
// more generalised ..
|
|
// t = ( - qv +/- sqrt((rr - qq )*vv + qv^2))/( vv )
|
|
// t = (qa*va - qv +/- sqrt((rr - qq + qa^2)*vv + ( qq - rr)*va^2 - 2* qa*qv*va + qv^2))/( vv - va^2)
|
|
// t = (qa*va - bb*qv +/- sqrt(( - bb^2*qq + bb*qa^2)*vv + (bb*qq )*va^2 - 2*bb*qa*qv*va + bb^2*qv^2))/(bb*vv - va^2)
|
|
// ..
|
|
// t = (qa*va - bb*qv +/- sqrt((rr - bb^2*qq + bb*qa^2)*vv + (bb*qq - rr)*va^2 - 2*bb*qa*qv*va + bb^2*qv^2))/(bb*vv - va^2)
|
|
//
|
|
// where:
|
|
// b = 1 for sphere and cylinder
|
|
// a = 0 for sphere (therefore qa = va = 0)
|
|
// r = 0 for cone
|
|
// =========================================================================================================================
|
|
|
|
const float rr = r*r; // constant
|
|
const float bb = b*b; // constant
|
|
|
|
const float vv = dot(v, v);
|
|
const float qv = dot(q, v);
|
|
const float qq = dot(q, q); // constant
|
|
const float qa = dot(q, a); // constant
|
|
const float qr = qq - rr; // constant (same as -xx and -yy for sphere)
|
|
const float va = dot(v, a);
|
|
const float xx = rr - qq*bb*bb + qa*qa*bb; // constant
|
|
const float yy = rr - qq*bb; // constant
|
|
|
|
float g = 1;
|
|
|
|
float t0 = 0;
|
|
float t1 = 1;
|
|
|
|
if (volumeType == LIGHTSHAFT_VOLUMETYPE_SHAFT)
|
|
{
|
|
const float3 f = IN.planeP/IN.planeQ;
|
|
|
|
//f.x = intersectPlane(eyePos, eyeRay, deferredVolumeShaftPlanes[0]);
|
|
//f.y = intersectPlane(eyePos, eyeRay, deferredVolumeShaftPlanes[1]);
|
|
//f.z = intersectPlane(eyePos, eyeRay, deferredVolumeShaftPlanes[2]);
|
|
|
|
t0 = max(max(f.x, f.y), f.z);
|
|
t1 = saturate(depth);
|
|
}
|
|
else // sphere/cylinder/cone use the same underlying intersection code
|
|
{
|
|
g = xx*vv - yy*va*va + qv*bb*(qv*bb - 2*qa*va);
|
|
|
|
t0 = min(saturate((qa*va - bb*qv - sqrt(g))/(bb*vv - va*va)), depth);
|
|
t1 = min(saturate((qa*va - bb*qv + sqrt(g))/(bb*vv - va*va)), depth);
|
|
}
|
|
|
|
const float s0 = 1;
|
|
const float s1 = t0*s0 + t1;
|
|
const float s2 = t0*s1 + t1*t1;
|
|
const float s3 = t0*s2 + t1*t1*t1;
|
|
const float s4 = t0*s3 + t1*t1*t1*t1;
|
|
|
|
float integral_1 = 0;
|
|
float integral_2 = 0;
|
|
float integral_3 = 0;
|
|
|
|
/*if (volumeType == LIGHTSHAFT_VOLUMETYPE_SPHERE)
|
|
{
|
|
// integral through radial density function: density(t) = d = (1 - |q + t*v|^2/r^2)
|
|
integral_1 =
|
|
(
|
|
+ s0*(3*qr)
|
|
+ s1*(3*qv)
|
|
+ s2*(1*vv)
|
|
)
|
|
/(-3*rr);
|
|
|
|
// integral through radial density function: density(t) = d^2 --> this function produces too much noise
|
|
integral_2 =
|
|
(
|
|
+ s0*(15*qr*qr )
|
|
+ s1*(30*qr*qv )
|
|
+ s2*(10*vv*qr + 20*qv*qv)
|
|
+ s3*(15*vv*qv )
|
|
+ s4*( 3*vv*vv )
|
|
)
|
|
/(15*rr*rr);
|
|
}
|
|
else*/ // shaft and cylinder use the same underlying density code
|
|
{
|
|
const float gp = dot(deferredVolumeShaftGradient.xyzw, float4(eyePos, 1)); // constant
|
|
const float gv = dot(deferredVolumeShaftGradient.xyz, eyeRay);
|
|
|
|
// integral through density function: density(t) = d = (p + t*v).gradient_xyz + gradient_w
|
|
integral_1 =
|
|
(
|
|
+ s0*(gp)
|
|
+ s1*(gv)/2
|
|
);
|
|
|
|
// integral through density function: density(t) = d^2
|
|
integral_2 =
|
|
(
|
|
+ s0*(gp*gp)
|
|
+ s1*(gv*gp)
|
|
+ s2*(gv*gv)/3
|
|
);
|
|
|
|
// integral through density function: density(t) = d^3
|
|
integral_3 = integral_1*
|
|
(
|
|
+ (s0 )*(gp*gp)
|
|
+ (s1 )*(gv*gp)
|
|
+ (t1*t1 + t0*t0)*(gv*gv)/2
|
|
);
|
|
|
|
// integral through density function: density(t) = exp(-k*(1 - d))
|
|
const float k = 5;
|
|
const float integral_exp = exp(k*(gp - 1))*(exp(k*gv*t1) - exp(k*gv*t0))/(k*gv); // note that this is not divided by t1 - t0
|
|
}
|
|
|
|
float3 intensity = saturate(t1 - t0);
|
|
|
|
if (0) {}
|
|
else if (densityType == LIGHTSHAFT_DENSITYTYPE_LINEAR ) { intensity = saturate(t1 - t0)*integral_1; }
|
|
else if (densityType == LIGHTSHAFT_DENSITYTYPE_LINEAR_GRADIENT ) { intensity = saturate(t1 - t0)*pow(abs(integral_1), deferredVolumeShaftGradientColourInv.xyz); }
|
|
else if (densityType == LIGHTSHAFT_DENSITYTYPE_QUADRATIC ) { intensity = saturate(t1 - t0)*integral_2; }
|
|
else if (densityType == LIGHTSHAFT_DENSITYTYPE_QUADRATIC_GRADIENT) { intensity = saturate(t1 - t0)*pow(abs(integral_2), deferredVolumeShaftGradientColourInv.xyz); }
|
|
|
|
#if LIGHTSHAFT_USE_SHADOWS
|
|
if (densityType == LIGHTSHAFT_DENSITYTYPE_SOFT_SHADOW ||
|
|
densityType == LIGHTSHAFT_DENSITYTYPE_SOFT_SHADOW_HD)
|
|
{
|
|
const int cascadeIndex = (densityType == LIGHTSHAFT_DENSITYTYPE_SOFT_SHADOW_HD) ? 0 : 1;
|
|
const int numSamples = (densityType == LIGHTSHAFT_DENSITYTYPE_SOFT_SHADOW_HD) ? 24 : 8;
|
|
|
|
intensity *= CalcCascadeShadowAccum(SHADOWSAMPLER_TEXSAMP, true, eyePos + eyeRay*t0, eyeRay*saturate(t1 - t0)/(float)numSamples, numSamples, cascadeIndex);
|
|
}
|
|
#endif // LIGHTSHAFT_USE_SHADOWS
|
|
|
|
intensity *= length(eyeRay)*(g > 0);
|
|
intensity *= IN.screenPos.z; // apply fog
|
|
|
|
if (densityType != LIGHTSHAFT_DENSITYTYPE_CONSTANT)
|
|
{
|
|
intensity *= lerp(float3(1,1,1), intensity, deferredVolumeShaftGradientColourInv.w);
|
|
}
|
|
|
|
return PackColor(float4(intensity*deferredVolumeColour.xyz, 0));
|
|
}
|
|
|
|
// =============================================================================================== //
|
|
// VOLUME LIGHTS INTERLEAVE RECONSTRUCTION
|
|
// =============================================================================================== //
|
|
// This is placed here as deferred_lighting.fx is too big to handle new techniques
|
|
|
|
struct volumeReconstructVertexIn {
|
|
float3 pos : POSITION;
|
|
float4 diffuse : COLOR0;
|
|
float2 texCoord0 : TEXCOORD0;
|
|
};
|
|
|
|
struct volumeReconstructVertex {
|
|
|
|
DECLARE_POSITION(pos)
|
|
float2 texCoord0 : TEXCOORD0;
|
|
};
|
|
|
|
volumeReconstructVertex VS_VolumeLight_Interleave_Reconstruction(volumeReconstructVertexIn IN)
|
|
{
|
|
volumeReconstructVertex OUT;
|
|
OUT.pos = float4( IN.pos.xyz, 1.0f);
|
|
OUT.texCoord0 = IN.texCoord0;
|
|
return(OUT);
|
|
}
|
|
|
|
// -------------------------------------------------------------
|
|
// Bilateral up-sampling. Preserves edge discontinuities.
|
|
// -------------------------------------------------------------
|
|
float BilateralWeight( float fOriginal, float fSample)
|
|
{
|
|
// Just like a gaussian weight but based on difference between samples
|
|
// rather than distance from kernel center
|
|
|
|
const float fDiff = fSample-fOriginal;
|
|
//const float fDiffSqrd = fDiff * fDiff;
|
|
//const float f2CoefSqrd = 2.0f * fBilateralCoef*fBilateralCoef;
|
|
//static const float fTwoPi = 6.283185f;
|
|
|
|
//float fWeight = ( 1.0f / ( fTwoPi * f2CoefSqrd ) ) * exp( -(fDiffSqrd) / f2CoefSqrd );
|
|
float fExp = ( abs(fDiff)/g_fBilateralCoefficient );
|
|
float fWeight = exp( -0.5f * ( fExp*fExp ) );
|
|
return fWeight;
|
|
}
|
|
|
|
half3 VolumeUnPack(half3 c) { return UnpackHdr_3h(c); }
|
|
half3 VolumePack(half3 c) { return PackHdr_3h(c); }
|
|
|
|
half4 PS_VolumeLight_Interleave_Reconstruction( volumeReconstructVertex IN , bool bApplyDepthWeights, bool bAlphaClipped )
|
|
{
|
|
float3 color = 0.0f;
|
|
|
|
if ( bApplyDepthWeights )
|
|
{
|
|
// Using depth weights in 3*3 grid of pixels because the reconstruction is a blur. Any objects closer to
|
|
// camera would get a halo around them
|
|
|
|
// +---+---+---+
|
|
// | 1 | 4 | 6 |
|
|
// +---+---+---+
|
|
// | 2 | 0 | 7 |
|
|
// +---+---+---+
|
|
// | 3 | 5 | 8 |
|
|
// +---+---+---+
|
|
|
|
float2 vCoordUpLeft = IN.texCoord0.xy + float2(-0.5,-0.5) * gooScreenSize.xy;
|
|
float2 vCoordDownRight = IN.texCoord0.xy + float2( 0.5, 0.5) * gooScreenSize.xy;
|
|
|
|
#if __SHADERMODEL >= 50
|
|
float4 vDepths2041 = gLowResDepthTexture.Gather(gLowResDepthSampler, vCoordUpLeft );
|
|
float4 vDepths5870 = gLowResDepthTexture.Gather(gLowResDepthSampler, vCoordDownRight);
|
|
#elif __SHADERMODEL >= 40
|
|
float4 vDepths2041 = float4( gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2(-1, 0)),
|
|
gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy),
|
|
gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2( 0, -1)),
|
|
gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2(-1, -1)) );
|
|
float4 vDepths5870 = float4( gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2(0, 1) ),
|
|
gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2(1, 1) ),
|
|
gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2(1, 0) ),
|
|
vDepths2041.y );
|
|
#else
|
|
float4 vDepths2041 = float4( tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2(-1, 0)).x,
|
|
tex2D(gLowResDepthSampler, IN.texCoord0.xy).x,
|
|
tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2( 0, -1)).x,
|
|
tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2(-1, -1)).x );
|
|
float4 vDepths5870 = float4( tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2(0, 1)).x,
|
|
tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2(1, 1)).x,
|
|
tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2(1, 0)).x,
|
|
vDepths2041.y );
|
|
#endif
|
|
|
|
#if __SHADERMODEL >= 40
|
|
float fDepth3 = gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2(-1, 1));
|
|
float fDepth6 = gLowResDepthTexture.Sample(gLowResDepthSampler, IN.texCoord0.xy, int2( 1,-1));
|
|
#else
|
|
float fDepth3 = tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2(-1, 1)).x;
|
|
float fDepth6 = tex2D(gLowResDepthSampler, IN.texCoord0.xy+int2( 1,-1)).x;
|
|
#endif
|
|
const float depths[9] = { vDepths2041.y, vDepths2041.w, vDepths2041.x, fDepth3, vDepths2041.z, vDepths5870.x, fDepth6, vDepths5870.z, vDepths5870.y };
|
|
|
|
|
|
#if __SHADERMODEL >= 40
|
|
const half3 colors[9] = {
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy).rgb), // 0
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2(-1,-1)).rgb), // 1
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2(-1, 0)).rgb), // 2
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2(-1, 1)).rgb), // 3
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 0,-1)).rgb), // 4
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 0, 1)).rgb), // 5
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 1,-1)).rgb), // 6
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 1, 0)).rgb), // 7
|
|
VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 1, 1)).rgb) }; // 8
|
|
#else
|
|
const half3 colors[9] = {
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy).rgb), // 0
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2(-1,-1)).rgb), // 1
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2(-1, 0)).rgb), // 2
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2(-1, 1)).rgb), // 3
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 0,-1)).rgb), // 4
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 0, 1)).rgb), // 5
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 1,-1)).rgb), // 6
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 1, 0)).rgb), // 7
|
|
VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 1, 1)).rgb) }; // 8
|
|
#endif
|
|
|
|
float weight = 0.0f;
|
|
float fAccumWeight = 0.0f;
|
|
float3 colorWithoutWeights = 0.0f;
|
|
//Compute weights based on depth of center pixel
|
|
[unroll] for( int i=0; i<9; i++ )
|
|
{
|
|
weight = BilateralWeight( depths[0], depths[i] );
|
|
color += colors[i] * weight;
|
|
colorWithoutWeights += colors[i];
|
|
fAccumWeight += weight;
|
|
}
|
|
|
|
//Having additional check to see if only 1-3 pixels gets all the weightage
|
|
//We might end up with completely contrasting pixels in this case
|
|
//We check for condition to see if weights is less than 2. If so, then apply,
|
|
//equal weights to all colors
|
|
colorWithoutWeights.rgb /= 9.0f;
|
|
color.rgb /= fAccumWeight.xxx;
|
|
color.rgb = (fAccumWeight < 3.0f) ? colorWithoutWeights.rgb : color.rgb;
|
|
}
|
|
else
|
|
{
|
|
#if __SHADERMODEL >= 40
|
|
float4 vCenterSample = gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy);
|
|
#else
|
|
float4 vCenterSample = tex2D(gVolumeLightsSampler, IN.texCoord0.xy);
|
|
#endif
|
|
|
|
if ( bAlphaClipped )
|
|
{
|
|
rageDiscard( vCenterSample.a < 0.5/255.0 );
|
|
}
|
|
|
|
#if __SHADERMODEL >= 40
|
|
color = VolumeUnPack(vCenterSample.rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2(-1,-1)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2(-1, 0)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2(-1, 1)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 0,-1)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 0, 1)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 1,-1)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 1, 0)).rgb);
|
|
color += VolumeUnPack(gVolumeLightsTexture.Sample(gVolumeLightsSampler, IN.texCoord0.xy, int2( 1, 1)).rgb);
|
|
color /= 9.0f;
|
|
#else
|
|
color = VolumeUnPack(vCenterSample.rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2(-1,-1)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2(-1, 0)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2(-1, 1)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 0,-1)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 0, 1)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 1,-1)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 1, 0)).rgb);
|
|
color += VolumeUnPack(tex2D(gVolumeLightsSampler, IN.texCoord0.xy+int2( 1, 1)).rgb);
|
|
color /= 9.0f;
|
|
#endif
|
|
}
|
|
|
|
color = VolumePack(color);
|
|
|
|
return half4(color,1);
|
|
}
|
|
|
|
half4 PS_VolumeLight_Interleave_Reconstruction_Weighted(volumeReconstructVertex IN ):COLOR
|
|
{
|
|
return PS_VolumeLight_Interleave_Reconstruction(IN, true, false);
|
|
}
|
|
|
|
half4 PS_VolumeLight_Interleave_Reconstruction_Unweighted_AlphaClipped(volumeReconstructVertex IN ):COLOR
|
|
{
|
|
return PS_VolumeLight_Interleave_Reconstruction(IN, false, true);
|
|
}
|
|
|
|
|
|
technique volume_Interleave_Reconstruction
|
|
{
|
|
pass p0
|
|
{
|
|
VertexShader = compile VERTEXSHADER VS_VolumeLight_Interleave_Reconstruction();
|
|
PixelShader = compile PIXELSHADER PS_VolumeLight_Interleave_Reconstruction_Weighted();
|
|
}
|
|
pass p1
|
|
{
|
|
VertexShader = compile VERTEXSHADER VS_VolumeLight_Interleave_Reconstruction();
|
|
PixelShader = compile PIXELSHADER PS_VolumeLight_Interleave_Reconstruction_Unweighted_AlphaClipped();
|
|
}
|
|
}
|
|
|
|
#define DEF_TECHNIQUE_VOLUMESHAFT_PASS(type) \
|
|
pass pass_volumeShaft_##type \
|
|
{ \
|
|
VertexShader = compile VERTEXSHADER VS_volumeShaft(); \
|
|
PixelShader = compile PIXELSHADER PS_volumeShaft_##type() CGC_FLAGS(CGC_DEFAULTFLAGS); \
|
|
}
|
|
|
|
#define DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,dtype) \
|
|
half4 PS_volumeShaft_##vtype##_##dtype(vertexOutputVolumeShaft IN) : COLOR \
|
|
{ \
|
|
return volumeShaft_internal(IN, LIGHTSHAFT_VOLUMETYPE_##vtype, LIGHTSHAFT_DENSITYTYPE_##dtype); \
|
|
}
|
|
|
|
#define DEF_TECHNIQUE_VOLUMESHAFT(vtype) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,CONSTANT ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,SOFT ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,SOFT_SHADOW ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,SOFT_SHADOW_HD ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,LINEAR ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,LINEAR_GRADIENT ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,QUADRATIC ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_CODE(vtype,QUADRATIC_GRADIENT) \
|
|
\
|
|
technique volumeShaft_##vtype \
|
|
{ \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_CONSTANT ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_SOFT ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_SOFT_SHADOW ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_SOFT_SHADOW_HD ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_LINEAR ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_LINEAR_GRADIENT ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_QUADRATIC ) \
|
|
DEF_TECHNIQUE_VOLUMESHAFT_PASS(vtype##_QUADRATIC_GRADIENT) \
|
|
}
|
|
|
|
DEF_TECHNIQUE_VOLUMESHAFT(SHAFT )
|
|
DEF_TECHNIQUE_VOLUMESHAFT(CYLINDER)
|
|
|
|
#undef DEF_TECHNIQUE_VOLUMESHAFT
|
|
#undef DEF_TECHNIQUE_VOLUMESHAFT_CODE
|
|
#undef DEF_TECHNIQUE_VOLUMESHAFT_PASS
|