mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-17 05:33:47 +00:00
'frontend' wipwork for the probe array. takes up to 50 probes, calcs a weighted blend, and displays them all in a batch.
This commit is contained in:
parent
8573e28e79
commit
0fa3568e07
3 changed files with 175 additions and 82 deletions
|
|
@ -7,37 +7,38 @@
|
|||
struct ConvexConnectP
|
||||
{
|
||||
float4 pos : TORQUE_POSITION;
|
||||
float4 wsEyeDir : TEXCOORD0;
|
||||
float4 ssPos : TEXCOORD1;
|
||||
float4 uv0 : TEXCOORD1;
|
||||
float4 vsEyeDir : TEXCOORD2;
|
||||
};
|
||||
|
||||
TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 1);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 2);
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(cubeMap, 3);
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(irradianceCubemap, 4);
|
||||
TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 5);
|
||||
uniform float cubeMips;
|
||||
|
||||
uniform float4 rtParams0;
|
||||
|
||||
uniform float3 probeWSPos;
|
||||
uniform float3 probeLSPos;
|
||||
uniform float4 vsFarPlane;
|
||||
|
||||
uniform float radius;
|
||||
uniform float2 attenuation;
|
||||
|
||||
uniform float4x4 worldToObj;
|
||||
uniform float4x4 cameraToWorld;
|
||||
|
||||
uniform float3 eyePosWorld;
|
||||
uniform float3 bbMin;
|
||||
uniform float3 bbMax;
|
||||
|
||||
uniform float useSphereMode;
|
||||
//cubemap arrays require all the same size. so shared mips# value
|
||||
uniform float cubeMips;
|
||||
#define MAX_PROBES 50
|
||||
|
||||
uniform float numProbes;
|
||||
TORQUE_UNIFORM_SAMPLERCUBEARRAY(cubeMap[MAX_PROBES], 3);
|
||||
TORQUE_UNIFORM_SAMPLERCUBEARRAY(irradianceCubemap[MAX_PROBES] 4);
|
||||
uniform float3 inProbePosArray[MAX_PROBES];
|
||||
uniform float4x4 worldToObjArray[MAX_PROBES];
|
||||
uniform float3 bbMinArray[MAX_PROBES];
|
||||
uniform float3 bbMaxArray[MAX_PROBES];
|
||||
uniform float useSphereMode[MAX_PROBES];
|
||||
uniform float radius[MAX_PROBES];
|
||||
uniform float2 attenuation[MAX_PROBES];
|
||||
|
||||
// Box Projected IBL Lighting
|
||||
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
||||
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
||||
float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
|
||||
{
|
||||
float3 nrdir = reflectDir;
|
||||
|
|
@ -52,12 +53,23 @@ float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3
|
|||
return posonbox - boxWSPos;
|
||||
}
|
||||
|
||||
float3 iblBoxDiffuse( Surface surface,
|
||||
TORQUE_SAMPLERCUBE(irradianceCube),
|
||||
float3 boxPos,
|
||||
float3 boxMin,
|
||||
float3 boxMax)
|
||||
{
|
||||
float3 cubeN = boxProject(surface.P, surface.N, boxPos, boxMin, boxMax);
|
||||
cubeN.z *=-1;
|
||||
return TORQUE_TEXCUBELOD(irradianceCube, float4(cubeN,0)).xyz;
|
||||
}
|
||||
|
||||
float3 iblBoxSpecular(float3 normal, float3 wsPos, float roughness, float3 surfToEye,
|
||||
TORQUE_SAMPLER2D(brdfTexture),
|
||||
//TORQUE_SAMPLERCUBE(radianceCube),
|
||||
float3 boxPos,
|
||||
float3 boxMin,
|
||||
float3 boxMax)
|
||||
TORQUE_SAMPLERCUBE(radianceCube),
|
||||
float3 boxPos,
|
||||
float3 boxMin,
|
||||
float3 boxMax)
|
||||
{
|
||||
float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0);
|
||||
|
||||
|
|
@ -65,88 +77,115 @@ float3 iblBoxSpecular(float3 normal, float3 wsPos, float roughness, float3 surfT
|
|||
float2 brdf = TORQUE_TEX2DLOD(brdfTexture, float4(roughness, ndotv,0.0,0.0)).xy;
|
||||
|
||||
// Radiance (Specular)
|
||||
float maxmip = pow(cubeMips+1,2);
|
||||
float lod = roughness*maxmip;
|
||||
float lod = roughness*cubeMips;
|
||||
float3 r = reflect(surfToEye, normal);
|
||||
float3 cubeR = normalize(r);
|
||||
cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax);
|
||||
|
||||
float3 radiance = float3(1,1,1);//TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y);
|
||||
float3 radiance = TORQUE_TEXCUBELOD(radianceCube, float4(cubeR, lod)).xyz * (brdf.x + brdf.y);
|
||||
|
||||
return radiance;
|
||||
}
|
||||
|
||||
float4 main(ConvexConnectP IN) : SV_TARGET
|
||||
float defineBoxSpaceInfluence(float3 surfPosWS, float3 probePos, float4x4 worldToObj, float radius, float atten)
|
||||
{
|
||||
// Compute scene UV
|
||||
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||
float3 surfPosLS = mul( worldToObj, float4(surfPosWS,1.0)).xyz;
|
||||
|
||||
float3 boxMinLS = probePos-(float3(1,1,1)*radius);
|
||||
float3 boxMaxLS = probePos+(float3(1,1,1)*radius);
|
||||
|
||||
float boxOuterRange = length(boxMaxLS - boxMinLS);
|
||||
float boxInnerRange = boxOuterRange / atten;
|
||||
|
||||
float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
|
||||
localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
|
||||
|
||||
return max(localDir.x, max(localDir.y, localDir.z)) * -1;
|
||||
}
|
||||
|
||||
float4 main( ConvexConnectP IN ) : SV_TARGET
|
||||
{
|
||||
//eye ray WS/LS
|
||||
float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||
float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
|
||||
|
||||
//unpack normal and linear depth
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
float blendVal = 1.0;
|
||||
IN.uv0, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
discard;
|
||||
}
|
||||
float blendVal[MAX_PROBES];
|
||||
float3 surfToEye = normalize(surface.P - eyePosWorld);
|
||||
|
||||
[unroll]
|
||||
for(float i=0; i < 10; i++)
|
||||
{
|
||||
float3 probeWSPos = float3(i * 1.1, 0, 2);
|
||||
float3 L = probeWSPos - surface.P;
|
||||
blendVal = 1.0-length(L)/radius;
|
||||
clip(blendVal);
|
||||
}
|
||||
int i;
|
||||
float3 irradiance = float3(0,0,0);
|
||||
float3 specular = float3(0,0,0);
|
||||
float blendSum = 0;
|
||||
float invBlendSum = 0;
|
||||
|
||||
for(i=0; i < numProbes; i++)
|
||||
{
|
||||
float3 probeWS = inProbePosArray[i];
|
||||
float3 L = probeWS - surface.P;
|
||||
|
||||
if(useSphereMode[i])
|
||||
{
|
||||
float3 L = inProbePosArray[i] - surface.P;
|
||||
blendVal[i] = 1.0-length(L)/radius[i];
|
||||
blendVal[i] = max(0,blendVal[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
float tempAttenVal = 3.5;
|
||||
blendVal[i] = defineBoxSpaceInfluence(surface.P, inProbePosArray[i], worldToObjArray[i], radius[i], tempAttenVal);
|
||||
blendVal[i] = max(0,blendVal[i]);
|
||||
}
|
||||
blendSum += blendVal[i];
|
||||
invBlendSum +=(1.0f - blendVal[i]);
|
||||
}
|
||||
|
||||
// Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
|
||||
// And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1).
|
||||
// respect constraint B.
|
||||
// Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
|
||||
// and respect constraint A.
|
||||
for(i=0; i < numProbes; i++)
|
||||
{
|
||||
blendVal[i] = (1.0f - ( blendVal[i] / blendSum)) / (numProbes - 1);
|
||||
blendVal[i] *= ((1.0f - blendVal[i]) / invBlendSum);
|
||||
blendSum += blendVal[i];
|
||||
}
|
||||
|
||||
//render into the bound space defined above
|
||||
float3 surfToEye = normalize(surface.P - eyePosWorld);
|
||||
float3 irradiance = float3(1,0,0);//TORQUE_TEXCUBELOD(irradianceCubemap, float4(surface.N,0)).xyz;
|
||||
float3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture)/*, TORQUE_SAMPLERCUBE_MAKEARG(cubeMap)*/, probeWSPos, bbMin, bbMax);
|
||||
// Normalize blendVal
|
||||
if (blendSum == 0.0f) // Possible with custom weight
|
||||
{
|
||||
blendSum = 1.0f;
|
||||
}
|
||||
|
||||
float invBlendSumWeighted = 1.0f / blendSum;
|
||||
for (int i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendVal[i] *= invBlendSumWeighted;
|
||||
}
|
||||
|
||||
float3 irradiance = float3(0,0,0);
|
||||
float3 specular = float3(0,0,0);
|
||||
float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
specular *= F;
|
||||
//energy conservation
|
||||
float3 kD = 1.0.xxx - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
float3 kD = 1.0.xxx - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
for (int i = 0; i < numProbes; ++i)
|
||||
{
|
||||
irradiance += blendVal[i]*iblBoxDiffuse(surface,TORQUE_SAMPLERCUBE_MAKEARG(irradianceCubemap[i]), inProbePosArray[i], bbMinArray[i], bbMaxArray[i]);
|
||||
specular += blendVal[i]*F*iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), TORQUE_SAMPLERCUBE_MAKEARG(cubeMap[i]), inProbePosArray[i], bbMinArray[i], bbMaxArray[i]);
|
||||
}
|
||||
//final diffuse color
|
||||
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
|
||||
return float4(diffuse + specular * surface.ao, blendVal);
|
||||
|
||||
/*float3 N = getCubeDir(face,IN.uv);
|
||||
float3 irradiance = 0;
|
||||
|
||||
// tangent space calculation from origin point
|
||||
float3 up = float3(0.0, 0.0, 1.0);
|
||||
float3 right = cross(up, N);
|
||||
up = cross(N, right);
|
||||
|
||||
float sampleDelta = 0.025;
|
||||
int nrSamples = 0;
|
||||
for(float phi = 0.0; phi < M_2PI_F; phi += sampleDelta)
|
||||
{
|
||||
for(float theta = 0.0; theta < M_HALFPI_F; theta += sampleDelta)
|
||||
{
|
||||
// spherical to cartesian (in tangent space)
|
||||
float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
||||
// tangent space to world
|
||||
float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
||||
|
||||
irradiance += TORQUE_TEXCUBE(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
|
||||
nrSamples++;
|
||||
}
|
||||
}
|
||||
irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
|
||||
|
||||
return float4(irradiance, 1.0);*/
|
||||
|
||||
//return float4(1,0,0,1);
|
||||
|
||||
//float4 texCoord = float4( 1,0,0, 1 );
|
||||
|
||||
//return texCoord;
|
||||
}
|
||||
return float4(diffuse + specular * surface.ao, blendVal);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../hlslStructs.hlsl"
|
||||
#include "../../shaderModel.hlsl"
|
||||
#include "../../torque.hlsl"
|
||||
|
||||
struct GFXVertexPT
|
||||
{
|
||||
float3 pos : POSITION;
|
||||
float4 uv : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct ConnectData
|
||||
{
|
||||
float4 hpos : TORQUE_POSITION;
|
||||
float4 uv0 : TEXCOORD1;
|
||||
float4 vsEyeDir : TEXCOORD2;
|
||||
};
|
||||
|
||||
uniform float4 rtParams0;
|
||||
uniform float4x4 worldViewOnly;
|
||||
|
||||
ConnectData main( GFXVertexPT IN )
|
||||
{
|
||||
ConnectData OUT;
|
||||
|
||||
OUT.hpos = float4(IN.pos,1.0);
|
||||
OUT.uv0 = float4(viewportCoordToRenderTarget( IN.uv, rtParams0 ),0,0);
|
||||
OUT.vsEyeDir = mul(worldViewOnly, float4(IN.pos, 1.0));
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
|
@ -40,12 +40,14 @@
|
|||
#define TORQUE_UNIFORM_SAMPLER2DCMP(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerComparisonState tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform Texture3D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform TextureCube texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLERCUBEARRAY(tex,regist) uniform TextureCubeArray texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
|
||||
// Sampling functions
|
||||
#define TORQUE_TEX1D(tex,coords) texture_##tex.Sample(tex,coords)
|
||||
#define TORQUE_TEX2D(tex,coords) texture_##tex.Sample(tex,coords)
|
||||
#define TORQUE_TEX2DPROJ(tex,coords) texture_##tex.Sample(tex,coords.xy / coords.w)
|
||||
#define TORQUE_TEX3D(tex,coords) texture_##tex.Sample(tex,coords)
|
||||
#define TORQUE_TEXCUBE(tex,coords) texture_##tex.Sample(tex,coords)
|
||||
#define TORQUE_TEXCUBEARRAY(tex,coords) texture_##tex.Sample(tex,coords)
|
||||
// The mipmap LOD is specified in coord.w
|
||||
#define TORQUE_TEX2DLOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xy,coords.w)
|
||||
#define TORQUE_TEXCUBELOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xyz,coords.w)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue