Updating BaseGame to work with PBR, and a PBR example module
|
|
@ -45,6 +45,8 @@ S32 GFXTextureManager::smTextureReductionLevel = 0;
|
|||
String GFXTextureManager::smMissingTexturePath(Con::getVariable("$Core::MissingTexturePath"));
|
||||
String GFXTextureManager::smUnavailableTexturePath(Con::getVariable("$Core::UnAvailableTexturePath"));
|
||||
String GFXTextureManager::smWarningTexturePath(Con::getVariable("$Core::WarningTexturePath"));
|
||||
String GFXTextureManager::smDefaultIrradianceCubemapPath(Con::getVariable("$Core::DefaultIrradianceCubemap"));
|
||||
String GFXTextureManager::smDefaultPrefilterCubemapPath(Con::getVariable("$Core::DefaultPrefilterCubemap"));
|
||||
|
||||
GFXTextureManager::EventSignal GFXTextureManager::smEventSignal;
|
||||
|
||||
|
|
@ -70,6 +72,14 @@ void GFXTextureManager::init()
|
|||
Con::addVariable( "$pref::Video::warningTexturePath", TypeRealString, &smWarningTexturePath,
|
||||
"The file path of the texture used to warn the developer.\n"
|
||||
"@ingroup GFX\n" );
|
||||
|
||||
Con::addVariable("$Core::DefaultIrradianceCubemap", TypeRealString, &smDefaultIrradianceCubemapPath,
|
||||
"The file path of the texture used as the default irradiance cubemap for PBR.\n"
|
||||
"@ingroup GFX\n");
|
||||
|
||||
Con::addVariable("$Core::DefaultPrefilterCubemap", TypeRealString, &smDefaultPrefilterCubemapPath,
|
||||
"The file path of the texture used as the default specular cubemap for PBR.\n"
|
||||
"@ingroup GFX\n");
|
||||
}
|
||||
|
||||
GFXTextureManager::GFXTextureManager()
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ public:
|
|||
/// Provide the path to the texture used to warn the developer
|
||||
static const String& getWarningTexturePath() { return smWarningTexturePath; }
|
||||
|
||||
static const String& getDefaultIrradianceCubemapPath() { return smDefaultIrradianceCubemapPath; }
|
||||
static const String& getDefaultPrefilterCubemapPath() { return smDefaultPrefilterCubemapPath; }
|
||||
|
||||
/// Update width and height based on available resources.
|
||||
///
|
||||
/// We provide a simple interface for managing texture memory usage. Specifically,
|
||||
|
|
@ -210,6 +213,9 @@ protected:
|
|||
/// File path to the warning texture
|
||||
static String smWarningTexturePath;
|
||||
|
||||
static String smDefaultIrradianceCubemapPath;
|
||||
static String smDefaultPrefilterCubemapPath;
|
||||
|
||||
GFXTextureObject *mListHead;
|
||||
GFXTextureObject *mListTail;
|
||||
|
||||
|
|
|
|||
|
|
@ -199,7 +199,8 @@ RenderProbeMgr::RenderProbeMgr()
|
|||
: RenderBinManager(RenderPassManager::RIT_Probes, 1.0f, 1.0f),
|
||||
mLastShader(nullptr),
|
||||
mLastConstants(nullptr),
|
||||
mProbesDirty(false)
|
||||
mProbesDirty(false),
|
||||
hasSkylight(false)
|
||||
{
|
||||
mEffectiveProbeCount = 0;
|
||||
mMipCount = 0;
|
||||
|
|
@ -250,13 +251,17 @@ bool RenderProbeMgr::onAdd()
|
|||
//create our own default default skylight
|
||||
mDefaultSkyLight = new ProbeRenderInst;
|
||||
mDefaultSkyLight->mProbeShapeType = ProbeRenderInst::Skylight;
|
||||
if (!mDefaultSkyLight->mIrradianceCubemap.set("core/art/pbr/default_irradiance.dds"))
|
||||
mDefaultSkyLight->mIsEnabled = false;
|
||||
|
||||
String defaultIrradMapPath = GFXTextureManager::getDefaultIrradianceCubemapPath();
|
||||
if (!mDefaultSkyLight->mIrradianceCubemap.set(defaultIrradMapPath))
|
||||
{
|
||||
Con::errorf("RenderProbeMgr::onAdd: Failed to load default irradiance cubemap");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDefaultSkyLight->mPrefilterCubemap.set("core/art/pbr/default_prefilter.dds"))
|
||||
String defaultPrefilterPath = GFXTextureManager::getDefaultPrefilterCubemapPath();
|
||||
if (!mDefaultSkyLight->mPrefilterCubemap.set(defaultPrefilterPath))
|
||||
{
|
||||
Con::errorf("RenderProbeMgr::onAdd: Failed to load default prefilter cubemap");
|
||||
return false;
|
||||
|
|
@ -825,15 +830,15 @@ void RenderProbeMgr::render( SceneRenderState *state )
|
|||
|
||||
mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
|
||||
}
|
||||
|
||||
mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
|
||||
mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
|
||||
mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
|
||||
mProbeArrayEffect->setShaderConst("$bbMinArray", probeBBMinData);
|
||||
mProbeArrayEffect->setShaderConst("$bbMaxArray", probeBBMaxData);
|
||||
mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
|
||||
}
|
||||
|
||||
mProbeArrayEffect->setShaderConst("$inProbePosArray", probePositionsData);
|
||||
mProbeArrayEffect->setShaderConst("$inRefPosArray", probeRefPositionsData);
|
||||
mProbeArrayEffect->setShaderConst("$worldToObjArray", probeWorldToObjData);
|
||||
mProbeArrayEffect->setShaderConst("$bbMinArray", probeBBMinData);
|
||||
mProbeArrayEffect->setShaderConst("$bbMaxArray", probeBBMaxData);
|
||||
mProbeArrayEffect->setShaderConst("$probeConfigData", probeConfigData);
|
||||
|
||||
// Make sure the effect is gonna render.
|
||||
getProbeArrayEffect()->setSkip(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -210,10 +210,10 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
mat->mSpecularMapFilename[0] = cleanTextureName(torquePath, cleanFile);
|
||||
}
|
||||
|
||||
LinearColorF specularColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
/*LinearColorF specularColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_COLOR_SPECULAR, read_color))
|
||||
specularColor.set(read_color.r, read_color.g, read_color.b, opacity);
|
||||
mat->mSpecular[0] = specularColor;
|
||||
mat->mMetalness[0] = specularColor;
|
||||
|
||||
// Specular Power
|
||||
F32 specularPower = 1.0f;
|
||||
|
|
@ -223,7 +223,7 @@ void AssimpAppMaterial::initMaterial(const Torque::Path& path, Material* mat) co
|
|||
// Specular
|
||||
F32 specularStrength = 0.0f;
|
||||
if (AI_SUCCESS == mAIMat->Get(AI_MATKEY_SHININESS, specularStrength))
|
||||
mat->mSpecularStrength[0] = specularStrength;
|
||||
mat->mSpecularStrength[0] = specularStrength;*/
|
||||
#endif
|
||||
|
||||
// Double-Sided
|
||||
|
|
@ -343,4 +343,4 @@ void AssimpAppMaterial::enumerateMaterialProperties(aiMaterial* mtl)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ function clientCmdMissionStartPhase1(%seq, %missionName)
|
|||
echo ("*** New Mission: " @ %missionName);
|
||||
echo ("*** Phase 1: Download Datablocks & Targets");
|
||||
|
||||
$Client::MissionFile = %missionName;
|
||||
$pref::ReflectionProbes::CurrentLevelPath = filePath($Client::MissionFile) @ "/" @ fileBase($Client::MissionFile) @ "/probes/";
|
||||
|
||||
//Prep the postFX stuff
|
||||
// Load the post effect presets for this mission.
|
||||
%path = filePath( %missionName ) @ "/" @ fileBase( %missionName ) @ $PostFXManager::fileExtension;
|
||||
|
|
|
|||
|
|
@ -30,9 +30,16 @@ new GFXStateBlockData( AL_VectorLightState )
|
|||
blendDest = GFXBlendOne;
|
||||
blendOp = GFXBlendOpAdd;
|
||||
|
||||
colorWriteDefined = true;
|
||||
colorWriteRed = true;
|
||||
colorWriteBlue = true;
|
||||
colorWriteGreen = true;
|
||||
colorWriteAlpha = false; //disable alpha write
|
||||
|
||||
zDefined = true;
|
||||
zEnable = false;
|
||||
zWriteEnable = false;
|
||||
zWriteEnable = true;
|
||||
zFunc = GFXCmpGreater;
|
||||
|
||||
samplersDefined = true;
|
||||
samplerStates[0] = SamplerClampPoint; // G-buffer
|
||||
|
|
@ -49,12 +56,8 @@ new GFXStateBlockData( AL_VectorLightState )
|
|||
cullMode = GFXCullNone;
|
||||
|
||||
stencilDefined = true;
|
||||
stencilEnable = true;
|
||||
stencilFailOp = GFXStencilOpKeep;
|
||||
stencilZFailOp = GFXStencilOpKeep;
|
||||
stencilPassOp = GFXStencilOpKeep;
|
||||
stencilFunc = GFXCmpLess;
|
||||
stencilRef = 0;
|
||||
stencilEnable = false;
|
||||
|
||||
};
|
||||
|
||||
// Vector Light Material
|
||||
|
|
@ -87,11 +90,11 @@ new CustomMaterial( AL_VectorLightMaterial )
|
|||
sampler["shadowMap"] = "$dynamiclight";
|
||||
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
||||
sampler["ssaoMask"] = "#ssaoMask";
|
||||
sampler["lightBuffer"] = "#lightinfo";
|
||||
sampler["lightBuffer"] = "#specularLighting";
|
||||
sampler["colorBuffer"] = "#color";
|
||||
sampler["matInfoBuffer"] = "#matinfo";
|
||||
|
||||
target = "lightinfo";
|
||||
target = "AL_FormatToken";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
|
@ -107,10 +110,16 @@ new GFXStateBlockData( AL_ConvexLightState )
|
|||
blendDest = GFXBlendOne;
|
||||
blendOp = GFXBlendOpAdd;
|
||||
|
||||
colorWriteDefined = true;
|
||||
colorWriteRed = true;
|
||||
colorWriteBlue = true;
|
||||
colorWriteGreen = true;
|
||||
colorWriteAlpha = false; //disable alpha write
|
||||
|
||||
zDefined = true;
|
||||
zEnable = true;
|
||||
zWriteEnable = false;
|
||||
zFunc = GFXCmpGreaterEqual;
|
||||
zFunc = GFXCmpGreater;
|
||||
|
||||
samplersDefined = true;
|
||||
samplerStates[0] = SamplerClampPoint; // G-buffer
|
||||
|
|
@ -126,12 +135,8 @@ new GFXStateBlockData( AL_ConvexLightState )
|
|||
cullMode = GFXCullCW;
|
||||
|
||||
stencilDefined = true;
|
||||
stencilEnable = true;
|
||||
stencilFailOp = GFXStencilOpKeep;
|
||||
stencilZFailOp = GFXStencilOpKeep;
|
||||
stencilPassOp = GFXStencilOpKeep;
|
||||
stencilFunc = GFXCmpLess;
|
||||
stencilRef = 0;
|
||||
stencilEnable = false;
|
||||
|
||||
};
|
||||
|
||||
// Point Light Material
|
||||
|
|
@ -164,11 +169,11 @@ new CustomMaterial( AL_PointLightMaterial )
|
|||
sampler["shadowMap"] = "$dynamiclight";
|
||||
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
||||
sampler["cookieMap"] = "$dynamiclightmask";
|
||||
sampler["lightBuffer"] = "#lightinfo";
|
||||
sampler["lightBuffer"] = "#specularLighting";
|
||||
sampler["colorBuffer"] = "#color";
|
||||
sampler["matInfoBuffer"] = "#matinfo";
|
||||
|
||||
target = "lightinfo";
|
||||
target = "AL_FormatToken";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
|
@ -203,11 +208,11 @@ new CustomMaterial( AL_SpotLightMaterial )
|
|||
sampler["shadowMap"] = "$dynamiclight";
|
||||
sampler["dynamicShadowMap"] = "$dynamicShadowMap";
|
||||
sampler["cookieMap"] = "$dynamiclightmask";
|
||||
sampler["lightBuffer"] = "#lightinfo";
|
||||
sampler["lightBuffer"] = "#specularLighting";
|
||||
sampler["colorBuffer"] = "#color";
|
||||
sampler["matInfoBuffer"] = "#matinfo";
|
||||
|
||||
target = "lightinfo";
|
||||
target = "AL_FormatToken";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
|
@ -270,7 +275,84 @@ new CustomMaterial( AL_ParticlePointLightMaterial )
|
|||
stateBlock = AL_ConvexLightState;
|
||||
|
||||
sampler["deferredBuffer"] = "#deferred";
|
||||
target = "lightinfo";
|
||||
target = "diffuseLighting";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
||||
//Probe Processing
|
||||
new ShaderData( IrradianceShader )
|
||||
{
|
||||
DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/cubemapV.hlsl";
|
||||
DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/irradianceP.hlsl";
|
||||
|
||||
OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/cubemapV.glsl";
|
||||
OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/irradianceP.glsl";
|
||||
|
||||
samplerNames[0] = "$environmentMap";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
||||
new ShaderData( PrefiterCubemapShader )
|
||||
{
|
||||
DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/cubemapV.hlsl";
|
||||
DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/prefilterP.hlsl";
|
||||
|
||||
OGLVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/cubemapV.glsl";
|
||||
OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/prefilterP.glsl";
|
||||
|
||||
samplerNames[0] = "$environmentMap";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
||||
//
|
||||
singleton ShaderData( PFX_ReflectionProbeArray )
|
||||
{
|
||||
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFx/postFxV.hlsl";
|
||||
DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/reflectionProbeArrayP.hlsl";
|
||||
|
||||
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFx/gl/postFxV.glsl";
|
||||
OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/reflectionProbeArrayP.glsl";
|
||||
|
||||
samplerNames[0] = "$deferredBuffer";
|
||||
samplerNames[1] = "$colorBuffer";
|
||||
samplerNames[2] = "$matInfoBuffer";
|
||||
samplerNames[3] = "$BRDFTexture";
|
||||
samplerNames[4] = "$specularCubemapAR";
|
||||
samplerNames[5] = "$irradianceCubemapAR";
|
||||
samplerNames[6] = "$skylightSpecularMap";
|
||||
samplerNames[7] = "$skylightIrradMap";
|
||||
|
||||
pixVersion = 2.0;
|
||||
};
|
||||
|
||||
singleton GFXStateBlockData( PFX_ReflectionProbeArrayStateBlock )
|
||||
{
|
||||
alphaDefined = true;
|
||||
alphaTestEnable = true;
|
||||
alphaTestRef = 1;
|
||||
alphaTestFunc = GFXCmpGreaterEqual;
|
||||
|
||||
// Do a one to one blend.
|
||||
blendDefined = true;
|
||||
blendEnable = true;
|
||||
blendSrc = GFXBlendOne;
|
||||
blendDest = GFXBlendOne;
|
||||
|
||||
zDefined = true;
|
||||
zEnable = false;
|
||||
zWriteEnable = false;
|
||||
|
||||
|
||||
samplersDefined = true;
|
||||
samplerStates[0] = SamplerClampPoint;
|
||||
samplerStates[1] = SamplerClampPoint;
|
||||
samplerStates[2] = SamplerClampPoint;
|
||||
samplerStates[3] = SamplerClampPoint;
|
||||
samplerStates[4] = SamplerClampLinear;
|
||||
samplerStates[5] = SamplerClampLinear;
|
||||
samplerStates[6] = SamplerClampLinear;
|
||||
samplerStates[7] = SamplerClampLinear;
|
||||
};
|
||||
|
|
@ -64,7 +64,7 @@ singleton CustomMaterial( BL_ProjectedShadowMaterial )
|
|||
function onActivateBasicLM()
|
||||
{
|
||||
// If HDR is enabled... enable the special format token.
|
||||
if ( $platform !$= "macos" && HDRPostFx.isEnabled )
|
||||
if ( HDRPostFx.isEnabled )
|
||||
AL_FormatToken.enable();
|
||||
|
||||
// Create render pass for projected shadow.
|
||||
|
|
|
|||
|
|
@ -1,14 +1,3 @@
|
|||
singleton ShaderData( ClearGBufferShader )
|
||||
{
|
||||
DXVertexShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredClearGBufferV.hlsl";
|
||||
DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredClearGBufferP.hlsl";
|
||||
|
||||
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
|
||||
OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredClearGBufferP.glsl";
|
||||
|
||||
pixVersion = 2.0;
|
||||
};
|
||||
|
||||
singleton ShaderData( DeferredColorShader )
|
||||
{
|
||||
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFx/postFxV.hlsl";
|
||||
|
|
@ -20,15 +9,15 @@ singleton ShaderData( DeferredColorShader )
|
|||
pixVersion = 2.0;
|
||||
};
|
||||
|
||||
// Primary Deferred Shader
|
||||
new GFXStateBlockData( AL_DeferredShadingState : PFX_DefaultStateBlock )
|
||||
{
|
||||
cullMode = GFXCullNone;
|
||||
new GFXStateBlockData( AL_DeferredCaptureState : PFX_DefaultStateBlock )
|
||||
{
|
||||
blendEnable = false;
|
||||
|
||||
blendDefined = true;
|
||||
blendEnable = true;
|
||||
blendSrc = GFXBlendSrcAlpha;
|
||||
blendDest = GFXBlendInvSrcAlpha;
|
||||
separateAlphaBlendDefined = true;
|
||||
separateAlphaBlendEnable = true;
|
||||
separateAlphaBlendSrc = GFXBlendSrcAlpha;
|
||||
separateAlphaBlendDest = GFXBlendDestAlpha;
|
||||
separateAlphaBlendOp = GFXBlendOpMin;
|
||||
|
||||
samplersDefined = true;
|
||||
samplerStates[0] = SamplerWrapLinear;
|
||||
|
|
@ -38,33 +27,33 @@ new GFXStateBlockData( AL_DeferredShadingState : PFX_DefaultStateBlock )
|
|||
samplerStates[4] = SamplerWrapLinear;
|
||||
};
|
||||
|
||||
new ShaderData( AL_DeferredShader )
|
||||
new ShaderData( AL_ProbeShader )
|
||||
{
|
||||
DXVertexShaderFile = $Core::CommonShaderPath @ "/postFX/postFxV.hlsl";
|
||||
DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/deferredShadingP.hlsl";
|
||||
DXPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/probeShadingP.hlsl";
|
||||
|
||||
OGLVertexShaderFile = $Core::CommonShaderPath @ "/postFX/gl/postFxV.glsl";
|
||||
OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/deferredShadingP.glsl";
|
||||
OGLPixelShaderFile = $Core::CommonShaderPath @ "/lighting/advanced/gl/probeShadingP.glsl";
|
||||
|
||||
samplerNames[0] = "colorBufferTex";
|
||||
samplerNames[1] = "lightDeferredTex";
|
||||
samplerNames[1] = "diffuseLightingBuffer";
|
||||
samplerNames[2] = "matInfoTex";
|
||||
samplerNames[3] = "deferredTex";
|
||||
|
||||
samplerNames[3] = "specularLightingBuffer";
|
||||
samplerNames[4] = "deferredTex";
|
||||
pixVersion = 2.0;
|
||||
};
|
||||
|
||||
singleton PostEffect( AL_DeferredShading )
|
||||
singleton PostEffect( AL_PreCapture )
|
||||
{
|
||||
renderTime = "PFXAfterBin";
|
||||
renderBin = "SkyBin";
|
||||
shader = AL_DeferredShader;
|
||||
stateBlock = AL_DeferredShadingState;
|
||||
renderTime = "PFXBeforeBin";
|
||||
renderBin = "EditorBin";
|
||||
shader = AL_ProbeShader;
|
||||
stateBlock = AL_DeferredCaptureState;
|
||||
texture[0] = "#color";
|
||||
texture[1] = "#lightinfo";
|
||||
texture[1] = "#diffuseLighting";
|
||||
texture[2] = "#matinfo";
|
||||
texture[3] = "#deferred";
|
||||
|
||||
texture[3] = "#specularLighting";
|
||||
texture[4] = "#deferred";
|
||||
target = "$backBuffer";
|
||||
renderPriority = 10000;
|
||||
allowReflectPass = true;
|
||||
|
|
|
|||
|
|
@ -170,7 +170,6 @@ singleton ShaderData( HDR_CombineShader )
|
|||
samplerNames[1] = "$luminanceTex";
|
||||
samplerNames[2] = "$bloomTex";
|
||||
samplerNames[3] = "$colorCorrectionTex";
|
||||
samplerNames[4] = "deferredTex";
|
||||
|
||||
pixVersion = 3.0;
|
||||
};
|
||||
|
|
@ -295,7 +294,7 @@ function HDRPostFX::onEnabled( %this )
|
|||
|
||||
// Change the format of the offscreen surface
|
||||
// to an HDR compatible format.
|
||||
AL_FormatToken.format = %format;
|
||||
%this.previousFormat = AL_FormatToken.format;
|
||||
setReflectFormat( %format );
|
||||
|
||||
// Reset the light manager which will ensure the new
|
||||
|
|
@ -312,7 +311,7 @@ function HDRPostFX::onDisabled( %this )
|
|||
GammaPostFX.enable();
|
||||
|
||||
// Restore the non-HDR offscreen surface format.
|
||||
%format = getBestHDRFormat();
|
||||
%format = %this.previousFormat;
|
||||
AL_FormatToken.format = %format;
|
||||
setReflectFormat( %format );
|
||||
|
||||
|
|
|
|||
19
Templates/BaseGame/game/core/postFX/scripts/pbr.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
singleton PostEffect( reflectionProbeArrayPostFX )
|
||||
{
|
||||
// Do not allow the selection effect to work in reflection
|
||||
// passes by default so we don't do the extra drawing.
|
||||
//allowReflectPass = false;
|
||||
|
||||
renderTime = "PFXAfterBin";
|
||||
renderBin = "ProbeBin";
|
||||
renderPriority = 9999;
|
||||
isEnabled = true;
|
||||
|
||||
shader = PFX_ReflectionProbeArray;
|
||||
stateBlock = PFX_ReflectionProbeArrayStateBlock;
|
||||
|
||||
texture[0] = "#deferred";
|
||||
texture[1] = "#color";
|
||||
texture[2] = "#matinfo";
|
||||
texture[3] = "core/rendering/images/brdfTexture.dds";
|
||||
};
|
||||
|
|
@ -5,6 +5,8 @@ function Core_Rendering::onCreate(%this)
|
|||
$Core::UnAvailableTexturePath = "core/rendering/images/unavailable";
|
||||
$Core::WarningTexturePath = "core/rendering/images/warnMat";
|
||||
$Core::CommonShaderPath = "core/rendering/shaders";
|
||||
$Core::DefaultIrradianceCubemap = "core/rendering/images/default_irradiance.dds";
|
||||
$Core::DefaultPrefilterCubemap = "core/rendering/images/default_prefilter.dds";
|
||||
|
||||
exec("./scripts/renderManager.cs");
|
||||
exec("./scripts/gfxData/clouds.cs");
|
||||
|
|
|
|||
BIN
Templates/BaseGame/game/core/rendering/images/brdfTexture.dds
Normal file
|
|
@ -48,9 +48,7 @@ function initRenderManager()
|
|||
};
|
||||
DiffuseRenderPassManager.addManager( new RenderPassStateBin() { renderOrder = 0.001; stateToken = AL_FormatToken; } );
|
||||
|
||||
// We really need to fix the sky to render after all the
|
||||
// meshes... but that causes issues in reflections.
|
||||
DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.1; processAddOrder = 0.1; } );
|
||||
DiffuseRenderPassManager.addManager( new RenderProbeMgr(ProbeBin) { bintype = "Probes"; renderOrder = 0.019; processAddOrder = 0.019; } );
|
||||
|
||||
//DiffuseRenderPassManager.addManager( new RenderVistaMgr() { bintype = "Vista"; renderOrder = 0.15; processAddOrder = 0.15; } );
|
||||
|
||||
|
|
@ -65,6 +63,10 @@ function initRenderManager()
|
|||
DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalRoadBin) { bintype = "DecalRoad"; renderOrder = 0.8; processAddOrder = 0.8; } );
|
||||
DiffuseRenderPassManager.addManager( new RenderMeshMgr(DecalBin) { bintype = "Decal"; renderOrder = 0.81; processAddOrder = 0.81; } );
|
||||
DiffuseRenderPassManager.addManager( new RenderOcclusionMgr(OccluderBin){ bintype = "Occluder"; renderOrder = 0.9; processAddOrder = 0.9; } );
|
||||
|
||||
// Render the sky last
|
||||
DiffuseRenderPassManager.addManager( new RenderObjectMgr(SkyBin) { bintype = "Sky"; renderOrder = 0.95; processAddOrder = 0.95; } );
|
||||
|
||||
|
||||
// We now render translucent objects that should handle
|
||||
// their own fogging and lighting.
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ ConnectData main( CloudVert IN )
|
|||
ConnectData OUT;
|
||||
|
||||
OUT.hpos = mul(modelview, float4(IN.pos,1.0));
|
||||
|
||||
OUT.hpos.z = OUT.hpos.w;
|
||||
float2 uv = IN.uv0;
|
||||
uv += texOffset;
|
||||
uv *= texScale;
|
||||
|
|
|
|||
98
Templates/BaseGame/game/core/rendering/shaders/brdf.hlsl
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2018 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef BRDF_HLSL
|
||||
#define BRDF_HLSL
|
||||
|
||||
#include "./torque.hlsl"
|
||||
|
||||
// BRDF from Frostbite presentation:
|
||||
// Moving Frostbite to Physically Based Rendering
|
||||
// S´ebastien Lagarde - Electronic Arts Frostbite
|
||||
// Charles de Rousiers - Electronic Arts Frostbite
|
||||
// SIGGRAPH 2014
|
||||
|
||||
float3 F_Schlick(in float3 f0, in float f90, in float u)
|
||||
{
|
||||
return f0 + (f90 - f0) * pow(1.f - u, 5.f);
|
||||
}
|
||||
|
||||
float3 F_Fresnel(float3 SpecularColor, float VoH)
|
||||
{
|
||||
float3 SpecularColorSqrt = sqrt(min(SpecularColor, float3(0.99, 0.99, 0.99)));
|
||||
float3 n = (1 + SpecularColorSqrt) / (1 - SpecularColorSqrt);
|
||||
float3 g = sqrt(n*n + VoH*VoH - 1);
|
||||
return 0.5 * sqr((g - VoH) / (g + VoH)) * (1 + sqr(((g + VoH)*VoH - 1) / ((g - VoH)*VoH + 1)));
|
||||
}
|
||||
|
||||
float3 FresnelSchlickRoughness(float cosTheta, float3 F0, float roughness)
|
||||
{
|
||||
float3 ret = float3(0.0, 0.0, 0.0);
|
||||
float powTheta = pow(1.0 - cosTheta, 5.0);
|
||||
float invRough = float(1.0 - roughness);
|
||||
|
||||
ret.x = F0.x + (max(invRough, F0.x) - F0.x) * powTheta;
|
||||
ret.y = F0.y + (max(invRough, F0.y) - F0.y) * powTheta;
|
||||
ret.z = F0.z + (max(invRough, F0.z) - F0.z) * powTheta;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float Fr_DisneyDiffuse(float NdotV, float NdotL, float LdotH, float linearRoughness)
|
||||
{
|
||||
float energyBias = lerp(0, 0.5, linearRoughness);
|
||||
float energyFactor = lerp(1.0, 1.0 / 1.51, linearRoughness);
|
||||
float fd90 = energyBias + 2.0 * LdotH*LdotH * linearRoughness;
|
||||
float3 f0 = float3(1.0f, 1.0f, 1.0f);
|
||||
float lightScatter = F_Schlick(f0, fd90, NdotL).r;
|
||||
float viewScatter = F_Schlick(f0, fd90, NdotV).r;
|
||||
|
||||
return lightScatter * viewScatter * energyFactor;
|
||||
}
|
||||
|
||||
float V_SmithGGXCorrelated(float NdotL, float NdotV, float alphaG2)
|
||||
{
|
||||
// Original formulation of G_SmithGGX Correlated
|
||||
// lambda_v = (-1 + sqrt(alphaG2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
|
||||
// lambda_l = (-1 + sqrt(alphaG2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
|
||||
// G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l);
|
||||
// V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0f * NdotL * NdotV);
|
||||
|
||||
|
||||
// This is the optimized version
|
||||
//float alphaG2 = alphaG * alphaG;
|
||||
|
||||
// Caution: the "NdotL *" and "NdotV *" are explicitely inversed , this is not a mistake.
|
||||
float Lambda_GGXV = NdotL * sqrt((-NdotV * alphaG2 + NdotV) * NdotV + alphaG2);
|
||||
float Lambda_GGXL = NdotV * sqrt((-NdotL * alphaG2 + NdotL) * NdotL + alphaG2);
|
||||
|
||||
return 0.5f / (Lambda_GGXV + Lambda_GGXL);
|
||||
}
|
||||
|
||||
float D_GGX(float NdotH, float m2)
|
||||
{
|
||||
// Divide by PI is apply later
|
||||
//float m2 = m * m;
|
||||
float f = (NdotH * m2 - NdotH) * NdotH + 1;
|
||||
return m2 / (f * f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -63,6 +63,7 @@ ConnectData main( CloudVert IN )
|
|||
ConnectData OUT;
|
||||
|
||||
OUT.hpos = mul(modelview, float4(IN.pos,1.0));
|
||||
OUT.hpos.z = OUT.hpos.w;
|
||||
// Offset the uv so we don't have a seam directly over our head.
|
||||
float2 uv = IN.uv0 + float2( 0.5, 0.5 );
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ out vec2 texCoord;
|
|||
void main()
|
||||
{
|
||||
gl_Position = tMul(modelview, IN_pos);
|
||||
gl_Position.z = gl_Position.w;
|
||||
|
||||
vec2 uv = IN_uv0;
|
||||
uv += texOffset;
|
||||
|
|
|
|||
98
Templates/BaseGame/game/core/rendering/shaders/gl/brdf.glsl
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2018 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef BRDF_HLSL
|
||||
#define BRDF_HLSL
|
||||
|
||||
#include "./torque.glsl"
|
||||
|
||||
// BRDF from Frostbite presentation:
|
||||
// Moving Frostbite to Physically Based Rendering
|
||||
// S´ebastien Lagarde - Electronic Arts Frostbite
|
||||
// Charles de Rousiers - Electronic Arts Frostbite
|
||||
// SIGGRAPH 2014
|
||||
|
||||
vec3 F_Schlick(in vec3 f0, in float f90, in float u)
|
||||
{
|
||||
return f0 + (f90 - f0) * pow(1.f - u, 5.f);
|
||||
}
|
||||
|
||||
vec3 F_Fresnel(vec3 SpecularColor, float VoH)
|
||||
{
|
||||
vec3 SpecularColorSqrt = sqrt(min(SpecularColor, vec3(0.99, 0.99, 0.99)));
|
||||
vec3 n = (1 + SpecularColorSqrt) / (1 - SpecularColorSqrt);
|
||||
vec3 g = sqrt(n*n + VoH*VoH - 1);
|
||||
return 0.5 * sqr((g - VoH) / (g + VoH)) * (1 + sqr(((g + VoH)*VoH - 1) / ((g - VoH)*VoH + 1)));
|
||||
}
|
||||
|
||||
vec3 FresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness)
|
||||
{
|
||||
vec3 ret = vec3(0.0, 0.0, 0.0);
|
||||
float powTheta = pow(1.0 - cosTheta, 5.0);
|
||||
float invRough = float(1.0 - roughness);
|
||||
|
||||
ret.x = F0.x + (max(invRough, F0.x) - F0.x) * powTheta;
|
||||
ret.y = F0.y + (max(invRough, F0.y) - F0.y) * powTheta;
|
||||
ret.z = F0.z + (max(invRough, F0.z) - F0.z) * powTheta;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
float Fr_DisneyDiffuse(float NdotV, float NdotL, float LdotH, float linearRoughness)
|
||||
{
|
||||
float energyBias = lerp(0, 0.5, linearRoughness);
|
||||
float energyFactor = lerp(1.0, 1.0 / 1.51, linearRoughness);
|
||||
float fd90 = energyBias + 2.0 * LdotH*LdotH * linearRoughness;
|
||||
vec3 f0 = vec3(1.0f, 1.0f, 1.0f);
|
||||
float lightScatter = F_Schlick(f0, fd90, NdotL).r;
|
||||
float viewScatter = F_Schlick(f0, fd90, NdotV).r;
|
||||
|
||||
return lightScatter * viewScatter * energyFactor;
|
||||
}
|
||||
|
||||
float V_SmithGGXCorrelated(float NdotL, float NdotV, float alphaG2)
|
||||
{
|
||||
// Original formulation of G_SmithGGX Correlated
|
||||
// lambda_v = (-1 + sqrt(alphaG2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f;
|
||||
// lambda_l = (-1 + sqrt(alphaG2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
|
||||
// G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l);
|
||||
// V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0f * NdotL * NdotV);
|
||||
|
||||
|
||||
// This is the optimized version
|
||||
//float alphaG2 = alphaG * alphaG;
|
||||
|
||||
// Caution: the "NdotL *" and "NdotV *" are explicitely inversed , this is not a mistake.
|
||||
float Lambda_GGXV = NdotL * sqrt((-NdotV * alphaG2 + NdotV) * NdotV + alphaG2);
|
||||
float Lambda_GGXL = NdotV * sqrt((-NdotL * alphaG2 + NdotL) * NdotL + alphaG2);
|
||||
|
||||
return 0.5f / (Lambda_GGXV + Lambda_GGXL);
|
||||
}
|
||||
|
||||
float D_GGX(float NdotH, float m2)
|
||||
{
|
||||
// Divide by PI is apply later
|
||||
//float m2 = m * m;
|
||||
float f = (NdotH * m2 - NdotH) * NdotH + 1;
|
||||
return m2 / (f * f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -62,6 +62,7 @@ void main()
|
|||
vec2 IN_uv0 = vTexCoord0.st;
|
||||
|
||||
gl_Position = modelview * IN_pos;
|
||||
gl_Position.z = gl_Position.w;
|
||||
|
||||
// Offset the uv so we don't have a seam directly over our head.
|
||||
vec2 uv = IN_uv0 + vec2( 0.5, 0.5 );
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 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 "hlslCompat.glsl"
|
||||
#include "torque.glsl"
|
||||
|
||||
uniform samplerCube cubemapTex;
|
||||
|
||||
in float3 face_pos_x;
|
||||
in float3 face_neg_x;
|
||||
in float3 face_pos_y;
|
||||
in float3 face_neg_y;
|
||||
in float3 face_pos_z;
|
||||
in float3 face_neg_z;
|
||||
|
||||
out float4 target0;
|
||||
out float4 target1;
|
||||
out float4 target2;
|
||||
out float4 target3;
|
||||
out float4 target4;
|
||||
out float4 target5;
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main
|
||||
//-----------------------------------------------------------------------------
|
||||
void main()
|
||||
{
|
||||
target0 = texture(cubemapTex, face_pos_x);
|
||||
target1 = texture(cubemapTex, face_neg_x);
|
||||
target2 = texture(cubemapTex, face_pos_y);
|
||||
target3 = texture(cubemapTex, face_neg_y);
|
||||
target4 = texture(cubemapTex, face_pos_z);
|
||||
target5 = texture(cubemapTex, face_neg_z);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 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 "hlslCompat.glsl"
|
||||
#include "torque.glsl"
|
||||
|
||||
uniform float4x4 matrix0;
|
||||
uniform float4x4 matrix1;
|
||||
uniform float4x4 matrix2;
|
||||
uniform float4x4 matrix3;
|
||||
uniform float4x4 matrix4;
|
||||
uniform float4x4 matrix5;
|
||||
|
||||
out float3 face_pos_x;
|
||||
out float3 face_neg_x;
|
||||
out float3 face_pos_y;
|
||||
out float3 face_neg_y;
|
||||
out float3 face_pos_z;
|
||||
out float3 face_neg_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
float4 vertex = float4(float2((gl_VertexID << 1) & 2, gl_VertexID & 2) * float2(2, -2) + float2(-1, 1), 0, 1);
|
||||
gl_Position = vertex;
|
||||
correctSSP(gl_Position);
|
||||
face_pos_x = tMul(matrix0, vertex).xyz;
|
||||
face_neg_x = tMul(matrix1, vertex).xyz;
|
||||
face_pos_y = tMul(matrix2, vertex).xyz;
|
||||
face_neg_y = tMul(matrix3, vertex).xyz;
|
||||
face_pos_z = tMul(matrix4, vertex).xyz;
|
||||
face_neg_z = tMul(matrix5, vertex).xyz;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Portions Copyright Zefiros
|
||||
// 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
|
||||
|
|
@ -21,9 +21,9 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "./torque.glsl"
|
||||
|
||||
#include "./brdf.glsl"
|
||||
#ifndef TORQUE_SHADERGEN
|
||||
|
||||
#line 26
|
||||
// These are the uniforms used by most lighting shaders.
|
||||
|
||||
uniform vec4 inLightPos[3];
|
||||
|
|
@ -38,11 +38,31 @@ uniform vec4 inLightColor[4];
|
|||
|
||||
uniform vec4 ambient;
|
||||
#define ambientCameraFactor 0.3
|
||||
uniform float specularPower;
|
||||
uniform vec4 specularColor;
|
||||
uniform float smoothness;
|
||||
uniform float metalness;
|
||||
uniform vec4 albedo;
|
||||
|
||||
#endif // !TORQUE_SHADERGEN
|
||||
|
||||
#define MAX_PROBES 50
|
||||
#define MAX_FORWARD_PROBES 4
|
||||
|
||||
vec3 getDistanceVectorToPlane( vec3 origin, vec3 direction, vec4 plane )
|
||||
{
|
||||
float denum = dot( plane.xyz, direction.xyz );
|
||||
float num = dot( plane, vec4( origin, 1.0 ) );
|
||||
float t = -num / denum;
|
||||
|
||||
return direction.xyz * t;
|
||||
}
|
||||
|
||||
vec3 getDistanceVectorToPlane( float negFarPlaneDotEye, vec3 direction, vec4 plane )
|
||||
{
|
||||
float denum = dot( plane.xyz, direction.xyz );
|
||||
float t = negFarPlaneDotEye / denum;
|
||||
|
||||
return direction.xyz * t;
|
||||
}
|
||||
|
||||
void compute4Lights( vec3 wsView,
|
||||
vec3 wsPosition,
|
||||
|
|
@ -57,193 +77,366 @@ void compute4Lights( vec3 wsView,
|
|||
vec4 inLightSpotDir[3],
|
||||
vec4 inLightSpotAngle,
|
||||
vec4 inLightSpotFalloff,
|
||||
float specularPower,
|
||||
vec4 specularColor,
|
||||
float smoothness,
|
||||
float metalness,
|
||||
vec4 albedo,
|
||||
|
||||
#endif // TORQUE_SHADERGEN
|
||||
|
||||
out vec4 outDiffuse,
|
||||
out vec4 outSpecular )
|
||||
{
|
||||
// NOTE: The light positions and spotlight directions
|
||||
// are stored in SoA order, so inLightPos[0] is the
|
||||
// x coord for all 4 lights... inLightPos[1] is y... etc.
|
||||
//
|
||||
// This is the key to fully utilizing the vector units and
|
||||
// saving a huge amount of instructions.
|
||||
//
|
||||
// For example this change saved more than 10 instructions
|
||||
// over a simple for loop for each light.
|
||||
|
||||
int i;
|
||||
|
||||
vec4 lightVectors[3];
|
||||
for ( i = 0; i < 3; i++ )
|
||||
lightVectors[i] = wsPosition[i] - inLightPos[i];
|
||||
|
||||
vec4 squareDists = vec4(0);
|
||||
for ( i = 0; i < 3; i++ )
|
||||
squareDists += lightVectors[i] * lightVectors[i];
|
||||
|
||||
// Accumulate the dot product between the light
|
||||
// vector and the normal.
|
||||
//
|
||||
// The normal is negated because it faces away from
|
||||
// the surface and the light faces towards the
|
||||
// surface... this keeps us from needing to flip
|
||||
// the light vector direction which complicates
|
||||
// the spot light calculations.
|
||||
//
|
||||
// We normalize the result a little later.
|
||||
//
|
||||
vec4 nDotL = vec4(0);
|
||||
for ( i = 0; i < 3; i++ )
|
||||
nDotL += lightVectors[i] * -wsNormal[i];
|
||||
|
||||
vec4 rDotL = vec4(0);
|
||||
#ifndef TORQUE_BL_NOSPECULAR
|
||||
|
||||
// We're using the Phong specular reflection model
|
||||
// here where traditionally Torque has used Blinn-Phong
|
||||
// which has proven to be more accurate to real materials.
|
||||
//
|
||||
// We do so because its cheaper as do not need to
|
||||
// calculate the half angle for all 4 lights.
|
||||
//
|
||||
// Advanced Lighting still uses Blinn-Phong, but the
|
||||
// specular reconstruction it does looks fairly similar
|
||||
// to this.
|
||||
//
|
||||
vec3 R = reflect( wsView, -wsNormal );
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
rDotL += lightVectors[i] * R[i];
|
||||
|
||||
#endif
|
||||
|
||||
// Normalize the dots.
|
||||
//
|
||||
// Notice we're using the half type here to get a
|
||||
// much faster sqrt via the rsq_pp instruction at
|
||||
// the loss of some precision.
|
||||
//
|
||||
// Unless we have some extremely large point lights
|
||||
// i don't believe the precision loss will matter.
|
||||
//
|
||||
half4 correction = half4(inversesqrt( squareDists ));
|
||||
nDotL = saturate( nDotL * correction );
|
||||
rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
|
||||
|
||||
// First calculate a simple point light linear
|
||||
// attenuation factor.
|
||||
//
|
||||
// If this is a directional light the inverse
|
||||
// radius should be greater than the distance
|
||||
// causing the attenuation to have no affect.
|
||||
//
|
||||
vec4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) );
|
||||
|
||||
#ifndef TORQUE_BL_NOSPOTLIGHT
|
||||
|
||||
// The spotlight attenuation factor. This is really
|
||||
// fast for what it does... 6 instructions for 4 spots.
|
||||
|
||||
vec4 spotAtten = vec4(0);
|
||||
for ( i = 0; i < 3; i++ )
|
||||
spotAtten += lightVectors[i] * inLightSpotDir[i];
|
||||
|
||||
vec4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle;
|
||||
atten *= saturate( cosAngle * inLightSpotFalloff );
|
||||
|
||||
#endif
|
||||
|
||||
// Finally apply the shadow masking on the attenuation.
|
||||
atten *= shadowMask;
|
||||
|
||||
// Get the final light intensity.
|
||||
vec4 intensity = nDotL * atten;
|
||||
|
||||
// Combine the light colors for output.
|
||||
outDiffuse = vec4(0);
|
||||
for ( i = 0; i < 4; i++ )
|
||||
outDiffuse += intensity[i] * inLightColor[i];
|
||||
|
||||
// Output the specular power.
|
||||
vec4 specularIntensity = pow( rDotL, vec4(specularPower) ) * atten;
|
||||
|
||||
// Apply the per-light specular attenuation.
|
||||
vec4 specular = vec4(0,0,0,1);
|
||||
for ( i = 0; i < 4; i++ )
|
||||
specular += vec4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
|
||||
|
||||
// Add the final specular intensity values together
|
||||
// using a single dot product operation then get the
|
||||
// final specular lighting color.
|
||||
outSpecular = specularColor * specular;
|
||||
outDiffuse = vec4(0,0,0,0);
|
||||
outSpecular = vec4(0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
// This value is used in AL as a constant power to raise specular values
|
||||
// to, before storing them into the light info buffer. The per-material
|
||||
// specular value is then computer by using the integer identity of
|
||||
// exponentiation:
|
||||
//
|
||||
// (a^m)^n = a^(m*n)
|
||||
//
|
||||
// or
|
||||
//
|
||||
// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular)
|
||||
//
|
||||
#define AL_ConstantSpecularPower 12.0f
|
||||
|
||||
/// The specular calculation used in Advanced Lighting.
|
||||
///
|
||||
/// @param toLight Normalized vector representing direction from the pixel
|
||||
/// being lit, to the light source, in world space.
|
||||
///
|
||||
/// @param normal Normalized surface normal.
|
||||
///
|
||||
/// @param toEye The normalized vector representing direction from the pixel
|
||||
/// being lit to the camera.
|
||||
///
|
||||
float AL_CalcSpecular( vec3 toLight, vec3 normal, vec3 toEye )
|
||||
struct Surface
|
||||
{
|
||||
// (R.V)^c
|
||||
float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye );
|
||||
vec3 P; // world space position
|
||||
vec3 N; // world space normal
|
||||
vec3 V; // world space view vector
|
||||
vec4 baseColor; // base color [0 -> 1] (rgba)
|
||||
float metalness; // metalness [0:dielectric -> 1:metal]
|
||||
float roughness; // roughness: [0:smooth -> 1:rough] (linear)
|
||||
float roughness_brdf; // roughness remapped from linear to BRDF
|
||||
float depth; // depth: [0:near -> 1:far] (linear)
|
||||
float ao; // ambient occlusion [0 -> 1]
|
||||
float matFlag; // material flag - use getFlag to retreive
|
||||
|
||||
// Return the specular factor.
|
||||
return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower );
|
||||
float NdotV; // cos(angle between normal and view vector)
|
||||
vec3 f0; // fresnel value (rgb)
|
||||
vec3 albedo; // diffuse light absorbtion value (rgb)
|
||||
vec3 R; // reflection vector
|
||||
vec3 F; // fresnel term computed from f0, N and V
|
||||
void Update();
|
||||
};
|
||||
|
||||
void Surface::Update()
|
||||
{
|
||||
NdotV = abs(dot(N, V)) + 1e-5f; // avoid artifact
|
||||
|
||||
albedo = baseColor.rgb * (1.0 - metalness);
|
||||
f0 = lerp(vec3(0.04), baseColor.rgb, metalness);
|
||||
R = -reflect(V, N);
|
||||
float f90 = saturate(50.0 * dot(f0, vec3(0.33,0.33,0.33)));
|
||||
F = F_Schlick(f0, f90, NdotV);
|
||||
}
|
||||
|
||||
Surface createSurface(vec4 normDepth, sampler2D colorBuffer, sampler2D matInfoBuffer, in vec2 uv, in vec3 wsEyePos, in vec3 wsEyeRay, in mat4 invView)
|
||||
{
|
||||
Surface surface;// = Surface();
|
||||
|
||||
vec4 gbuffer1 = texture(colorBuffer, uv);
|
||||
vec4 gbuffer2 = texture(matInfoBuffer, uv);
|
||||
surface.depth = normDepth.a;
|
||||
surface.P = wsEyePos + wsEyeRay * surface.depth;
|
||||
surface.N = tMul(invView, vec4(normDepth.xyz,0)).xyz; //TODO move t3d to use WS normals
|
||||
surface.V = normalize(wsEyePos - surface.P);
|
||||
surface.baseColor = gbuffer1;
|
||||
const float minRoughness=1e-4;
|
||||
surface.roughness = clamp(1.0 - gbuffer2.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
|
||||
surface.roughness_brdf = surface.roughness * surface.roughness;
|
||||
surface.metalness = gbuffer2.a;
|
||||
surface.ao = gbuffer2.g;
|
||||
surface.matFlag = gbuffer2.r;
|
||||
surface.Update();
|
||||
return surface;
|
||||
}
|
||||
|
||||
/// The output for Deferred Lighting
|
||||
///
|
||||
/// @param toLight Normalized vector representing direction from the pixel
|
||||
/// being lit, to the light source, in world space.
|
||||
///
|
||||
/// @param normal Normalized surface normal.
|
||||
///
|
||||
/// @param toEye The normalized vector representing direction from the pixel
|
||||
/// being lit to the camera.
|
||||
///
|
||||
vec4 AL_DeferredOutput(
|
||||
vec3 lightColor,
|
||||
vec3 diffuseColor,
|
||||
vec4 matInfo,
|
||||
vec4 ambient,
|
||||
float specular,
|
||||
float shadowAttenuation)
|
||||
Surface createForwardSurface(vec4 baseColor, vec4 normal, vec4 pbrProperties, in vec2 uv, in vec3 wsPosition, in vec3 wsEyePos, in vec3 wsEyeRay, in mat4x4 invView)
|
||||
{
|
||||
vec3 specularColor = vec3(specular);
|
||||
bool metalness = getFlag(matInfo.r, 3);
|
||||
if ( metalness )
|
||||
{
|
||||
specularColor = 0.04 * (1 - specular) + diffuseColor * specular;
|
||||
Surface surface;// = Surface();
|
||||
|
||||
surface.depth = 0;
|
||||
surface.P = wsPosition;
|
||||
surface.N = tMul(invView, vec4(normal.xyz,0)).xyz; //TODO move t3d to use WS normals
|
||||
surface.V = normalize(wsEyePos - surface.P);
|
||||
surface.baseColor = baseColor;
|
||||
const float minRoughness=1e-4;
|
||||
surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
|
||||
surface.roughness_brdf = surface.roughness * surface.roughness;
|
||||
surface.metalness = pbrProperties.a;
|
||||
surface.ao = pbrProperties.g;
|
||||
surface.matFlag = pbrProperties.r;
|
||||
|
||||
surface.Update();
|
||||
return surface;
|
||||
}
|
||||
|
||||
struct SurfaceToLight
|
||||
{
|
||||
vec3 L; // surface to light vector
|
||||
vec3 Lu; // un-normalized surface to light vector
|
||||
vec3 H; // half-vector between view vector and light vector
|
||||
float NdotL; // cos(angle between N and L)
|
||||
float HdotV; // cos(angle between H and V) = HdotL = cos(angle between H and L)
|
||||
float NdotH; // cos(angle between N and H)
|
||||
|
||||
};
|
||||
|
||||
SurfaceToLight createSurfaceToLight(in Surface surface, in vec3 L)
|
||||
{
|
||||
SurfaceToLight surfaceToLight;// = SurfaceToLight();
|
||||
surfaceToLight.Lu = L;
|
||||
surfaceToLight.L = normalize(L);
|
||||
surfaceToLight.H = normalize(surface.V + surfaceToLight.L);
|
||||
surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N));
|
||||
surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V));
|
||||
surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N));
|
||||
return surfaceToLight;
|
||||
}
|
||||
|
||||
vec3 BRDF_GetSpecular(in Surface surface, in SurfaceToLight surfaceToLight)
|
||||
{
|
||||
float f90 = saturate(50.0 * dot(surface.f0, vec3(0.33,0.33,0.33)));
|
||||
vec3 F = F_Schlick(surface.f0, f90, surfaceToLight.HdotV);
|
||||
float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.roughness_brdf);
|
||||
float D = D_GGX(surfaceToLight.NdotH, surface.roughness_brdf);
|
||||
vec3 Fr = D * F * Vis / M_PI_F;
|
||||
return Fr;
|
||||
}
|
||||
|
||||
vec3 BRDF_GetDiffuse(in Surface surface, in SurfaceToLight surfaceToLight)
|
||||
{
|
||||
//getting some banding with disney method, using lambert instead - todo futher testing
|
||||
float Fd = 1.0 / M_PI_F;
|
||||
//energy conservation - remove this if reverting back to disney method
|
||||
vec3 kD = vec3(1.0) - surface.F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
vec3 diffuse = kD * surface.baseColor.rgb * Fd;
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
//attenuations functions from "moving frostbite to pbr paper"
|
||||
//https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
|
||||
float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius )
|
||||
{
|
||||
float factor = squaredDistance * invSqrAttRadius ;
|
||||
float smoothFactor = saturate (1.0f - factor * factor );
|
||||
return sqr(smoothFactor);
|
||||
}
|
||||
|
||||
float getDistanceAtt( vec3 unormalizedLightVector , float invSqrAttRadius )
|
||||
{
|
||||
float sqrDist = dot ( unormalizedLightVector , unormalizedLightVector );
|
||||
float attenuation = 1.0 / (max ( sqrDist , 0.01*0.01) );
|
||||
attenuation *= smoothDistanceAtt ( sqrDist , invSqrAttRadius );
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
float getSpotAngleAtt( vec3 normalizedLightVector , vec3 lightDir , vec2 lightSpotParams )
|
||||
{
|
||||
float cd = dot ( lightDir , normalizedLightVector );
|
||||
float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y );
|
||||
// smooth the transition
|
||||
return sqr(attenuation);
|
||||
}
|
||||
|
||||
vec3 getDirectionalLight(in Surface surface, in SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float shadow)
|
||||
{
|
||||
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity;
|
||||
vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
|
||||
vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
|
||||
|
||||
vec3 final = max(vec3(0.0f), diffuse + spec * surface.ao);
|
||||
return final;
|
||||
}
|
||||
|
||||
vec3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLight, vec3 lightColor, float lightIntensity, float radius, float shadow)
|
||||
{
|
||||
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
|
||||
vec3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
|
||||
|
||||
vec3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
|
||||
vec3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
|
||||
|
||||
vec3 final = max(vec3(0.0f), diffuse + spec * surface.ao * surface.F);
|
||||
return final;
|
||||
}
|
||||
|
||||
float G1V(float dotNV, float k)
|
||||
{
|
||||
return 1.0f/(dotNV*(1.0f-k)+k);
|
||||
}
|
||||
|
||||
vec3 directSpecular(vec3 N, vec3 V, vec3 L, float roughness, float F0)
|
||||
{
|
||||
float alpha = roughness*roughness;
|
||||
|
||||
//TODO don't need to calculate all this again timmy!!!!!!
|
||||
vec3 H = normalize(V + L);
|
||||
float dotNL = clamp(dot(N,L), 0.0, 1.0);
|
||||
float dotNV = clamp(dot(N,V), 0.0, 1.0);
|
||||
float dotNH = clamp(dot(N,H), 0.0, 1.0);
|
||||
float dotHV = clamp(dot(H,V), 0.0, 1.0);
|
||||
float dotLH = clamp(dot(L,H), 0.0, 1.0);
|
||||
|
||||
float F, D, vis;
|
||||
|
||||
// D
|
||||
float alphaSqr = alpha*alpha;
|
||||
float pi = 3.14159f;
|
||||
float denom = dotNH * dotNH *(alphaSqr-1.0) + 1.0f;
|
||||
D = alphaSqr/(pi * denom * denom);
|
||||
|
||||
// F
|
||||
float dotLH5 = pow(1.0f-dotLH,5);
|
||||
F = F0 + (1.0-F0)*(dotLH5);
|
||||
|
||||
// V
|
||||
float k = alpha/2.0f;
|
||||
vis = G1V(dotNL,k)*G1V(dotNV,k);
|
||||
|
||||
float specular = dotNL * D * F * vis;
|
||||
return vec3(specular,specular,specular);
|
||||
}
|
||||
|
||||
//Probe IBL stuff
|
||||
float defineSphereSpaceInfluence(vec3 wsPosition, vec3 wsProbePosition, float radius)
|
||||
{
|
||||
vec3 L = wsProbePosition.xyz - wsPosition;
|
||||
float contribution = 1.0 - length(L) / radius;
|
||||
return contribution;
|
||||
}
|
||||
|
||||
float getDistBoxToPoint(vec3 pt, vec3 extents)
|
||||
{
|
||||
vec3 d = max(max(-extents - pt, 0), pt - extents);
|
||||
return max(max(d.x, d.y), d.z);
|
||||
}
|
||||
|
||||
float defineBoxSpaceInfluence(vec3 wsPosition, mat4 worldToObj, float attenuation)
|
||||
{
|
||||
vec3 surfPosLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
|
||||
float atten = 1.0 - attenuation;
|
||||
float baseVal = 0.25;
|
||||
float dist = getDistBoxToPoint(surfPosLS, vec3(baseVal, baseVal, baseVal));
|
||||
return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist));
|
||||
}
|
||||
|
||||
// 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/
|
||||
vec3 boxProject(vec3 wsPosition, vec3 wsReflectVec, mat4 worldToObj, vec3 bbMin, vec3 bbMax, vec3 refPosition)
|
||||
{
|
||||
vec3 RayLS = tMul(worldToObj, vec4(wsReflectVec, 0.0)).xyz;
|
||||
vec3 PositionLS = tMul(worldToObj, vec4(wsPosition, 1.0)).xyz;
|
||||
|
||||
vec3 unit = bbMax.xyz - bbMin.xyz;
|
||||
vec3 plane1vec = (unit / 2 - PositionLS) / RayLS;
|
||||
vec3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
|
||||
vec3 furthestPlane = max(plane1vec, plane2vec);
|
||||
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
||||
vec3 posonbox = wsPosition + wsReflectVec * dist;
|
||||
|
||||
return posonbox - refPosition.xyz;
|
||||
}
|
||||
|
||||
vec4 computeForwardProbes(Surface surface,
|
||||
float cubeMips, float numProbes, mat4x4 worldToObjArray[MAX_FORWARD_PROBES], vec4 probeConfigData[MAX_FORWARD_PROBES],
|
||||
vec4 inProbePosArray[MAX_FORWARD_PROBES], vec4 bbMinArray[MAX_FORWARD_PROBES], vec4 bbMaxArray[MAX_FORWARD_PROBES], vec4 inRefPosArray[MAX_FORWARD_PROBES],
|
||||
float hasSkylight, sampler2D BRDFTexture,
|
||||
samplerCube skylightIrradMap, samplerCube skylightSpecularMap,
|
||||
samplerCubeArray irradianceCubemapAR, samplerCubeArray specularCubemapAR)
|
||||
{
|
||||
int i = 0;
|
||||
float blendFactor[MAX_FORWARD_PROBES];
|
||||
float blendSum = 0;
|
||||
float blendFacSum = 0;
|
||||
float invBlendSum = 0;
|
||||
float probehits = 0;
|
||||
//Set up our struct data
|
||||
float contribution[MAX_FORWARD_PROBES];
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
contribution[i] = 0;
|
||||
|
||||
if (probeConfigData[i].r == 0) //box
|
||||
{
|
||||
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
|
||||
if (contribution[i] > 0.0)
|
||||
probehits++;
|
||||
}
|
||||
else if (probeConfigData[i].r == 1) //sphere
|
||||
{
|
||||
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
|
||||
if (contribution[i] > 0.0)
|
||||
probehits++;
|
||||
}
|
||||
|
||||
contribution[i] = max(contribution[i], 0);
|
||||
|
||||
blendSum += contribution[i];
|
||||
invBlendSum += (1.0f - contribution[i]);
|
||||
}
|
||||
|
||||
//specular = color * map * spec^gloss
|
||||
float specularOut = (specularColor * matInfo.b * min(pow(max(specular,1.0f), max((matInfo.a / AL_ConstantSpecularPower),1.0f)),matInfo.a)).r;
|
||||
|
||||
lightColor *= vec3(shadowAttenuation);
|
||||
lightColor += ambient.rgb;
|
||||
return vec4(lightColor.rgb, specularOut);
|
||||
}
|
||||
if (probehits > 1.0)
|
||||
{
|
||||
for (i = 0; i < numProbes; i++)
|
||||
{
|
||||
blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
|
||||
blendFactor[i] *= ((contribution[i]) / invBlendSum);
|
||||
blendFactor[i] = saturate(blendFactor[i]);
|
||||
blendFacSum += blendFactor[i];
|
||||
}
|
||||
|
||||
// Normalize blendVal
|
||||
if (blendFacSum == 0.0f) // Possible with custom weight
|
||||
{
|
||||
blendFacSum = 1.0f;
|
||||
}
|
||||
|
||||
float invBlendSumWeighted = 1.0f / blendFacSum;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendFactor[i] *= invBlendSumWeighted;
|
||||
contribution[i] *= blendFactor[i];
|
||||
}
|
||||
}
|
||||
|
||||
vec3 irradiance = vec3(0, 0, 0);
|
||||
vec3 specular = vec3(0, 0, 0);
|
||||
|
||||
// Radiance (Specular)
|
||||
float lod = surface.roughness*cubeMips;
|
||||
|
||||
//1
|
||||
float alpha = 1.0f;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
float contrib = contribution[i];
|
||||
if (contrib != 0)
|
||||
{
|
||||
int cubemapIdx = int(probeConfigData[i].a);
|
||||
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
|
||||
|
||||
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
|
||||
specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;
|
||||
alpha -= contrib;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSkylight == 1 && alpha > 0.001)
|
||||
{
|
||||
irradiance += textureLod(skylightIrradMap, surface.R, 0).xyz * alpha;
|
||||
specular += textureLod(skylightSpecularMap, surface.R, lod).xyz * alpha;
|
||||
}
|
||||
|
||||
vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
|
||||
//energy conservation
|
||||
vec3 kD = vec3(1.0,1.0,1.0) - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
|
||||
//apply brdf
|
||||
//Do it once to save on texture samples
|
||||
vec2 brdf = textureLod(BRDFTexture, vec2(surface.roughness, surface.NdotV),0).xy;
|
||||
specular *= brdf.x * F + brdf.y;
|
||||
|
||||
//final diffuse color
|
||||
vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
vec4 finalColor = vec4(diffuse + specular * surface.ao, 1.0);
|
||||
|
||||
finalColor = vec4(irradiance.rgb,1);
|
||||
return finalColor;
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#ifndef _TORQUE_GLSL_
|
||||
#define _TORQUE_GLSL_
|
||||
|
||||
#line 25
|
||||
|
||||
float M_HALFPI_F = 1.57079632679489661923;
|
||||
float M_PI_F = 3.14159265358979323846;
|
||||
|
|
@ -336,4 +336,53 @@ vec3 toGamma(vec3 tex)
|
|||
}
|
||||
#endif //
|
||||
|
||||
vec3 PBRFresnel(vec3 albedo, vec3 indirect, float metalness, float fresnel)
|
||||
{
|
||||
vec3 diffuseColor = albedo - (albedo * metalness);
|
||||
vec3 reflectColor = mix(indirect*albedo, indirect, fresnel);
|
||||
|
||||
return diffuseColor + reflectColor;
|
||||
}
|
||||
|
||||
vec3 simpleFresnel(vec3 diffuseColor, vec3 reflectColor, float metalness, float angle, float bias, float power)
|
||||
{
|
||||
float fresnelTerm = bias + (1.0 - bias) * pow(abs(1.0 - max(angle, 0)), power);
|
||||
|
||||
fresnelTerm *= metalness;
|
||||
|
||||
return mix(diffuseColor, reflectColor, fresnelTerm);
|
||||
}
|
||||
|
||||
//get direction for a cube face
|
||||
vec3 getCubeDir(int face, vec2 uv)
|
||||
{
|
||||
vec2 debiased = uv * 2.0f - 1.0f;
|
||||
|
||||
vec3 dir = vec3(0);
|
||||
|
||||
switch (face)
|
||||
{
|
||||
case 0: dir = vec3(1, -debiased.y, -debiased.x);
|
||||
break;
|
||||
|
||||
case 1: dir = vec3(-1, -debiased.y, debiased.x);
|
||||
break;
|
||||
|
||||
case 2: dir = vec3(debiased.x, 1, debiased.y);
|
||||
break;
|
||||
|
||||
case 3: dir = vec3(debiased.x, -1, -debiased.y);
|
||||
break;
|
||||
|
||||
case 4: dir = vec3(debiased.x, -debiased.y, 1);
|
||||
break;
|
||||
|
||||
case 5: dir = vec3(-debiased.x, -debiased.y, -1);
|
||||
break;
|
||||
};
|
||||
|
||||
return normalize(dir);
|
||||
}
|
||||
|
||||
#define sqr(a) ((a)*(a))
|
||||
#endif // _TORQUE_GLSL_
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Portions Copyright Zefiros
|
||||
// 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
|
||||
|
|
@ -21,6 +21,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "./torque.hlsl"
|
||||
#include "./brdf.hlsl"
|
||||
#include "./shaderModelAutoGen.hlsl"
|
||||
|
||||
#ifndef TORQUE_SHADERGEN
|
||||
|
||||
|
|
@ -37,13 +39,33 @@ uniform float4 inLightColor[4];
|
|||
#endif
|
||||
|
||||
uniform float4 ambient;
|
||||
#define ambientCameraFactor 0.3
|
||||
uniform float specularPower;
|
||||
uniform float4 specularColor;
|
||||
uniform float smoothness;
|
||||
uniform float metalness;
|
||||
uniform float4 albedo;
|
||||
|
||||
#endif // !TORQUE_SHADERGEN
|
||||
|
||||
#define MAX_PROBES 50
|
||||
#define MAX_FORWARD_PROBES 4
|
||||
|
||||
inline float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane )
|
||||
{
|
||||
float denum = dot( plane.xyz, direction.xyz );
|
||||
float num = dot( plane, float4( origin, 1.0 ) );
|
||||
float t = -num / denum;
|
||||
|
||||
return direction.xyz * t;
|
||||
}
|
||||
|
||||
inline float3 getDistanceVectorToPlane( float negFarPlaneDotEye, float3 direction, float4 plane )
|
||||
{
|
||||
float denum = dot( plane.xyz, direction.xyz );
|
||||
float t = negFarPlaneDotEye / denum;
|
||||
|
||||
return direction.xyz * t;
|
||||
}
|
||||
|
||||
//TODO fix compute 4 lights
|
||||
void compute4Lights( float3 wsView,
|
||||
float3 wsPosition,
|
||||
float3 wsNormal,
|
||||
|
|
@ -57,193 +79,331 @@ void compute4Lights( float3 wsView,
|
|||
float4 inLightSpotDir[3],
|
||||
float4 inLightSpotAngle,
|
||||
float4 inLightSpotFalloff,
|
||||
float specularPower,
|
||||
float4 specularColor,
|
||||
float smoothness,
|
||||
float metalness,
|
||||
float4 albedo,
|
||||
|
||||
#endif // TORQUE_SHADERGEN
|
||||
|
||||
out float4 outDiffuse,
|
||||
out float4 outSpecular )
|
||||
{
|
||||
// NOTE: The light positions and spotlight directions
|
||||
// are stored in SoA order, so inLightPos[0] is the
|
||||
// x coord for all 4 lights... inLightPos[1] is y... etc.
|
||||
//
|
||||
// This is the key to fully utilizing the vector units and
|
||||
// saving a huge amount of instructions.
|
||||
//
|
||||
// For example this change saved more than 10 instructions
|
||||
// over a simple for loop for each light.
|
||||
|
||||
int i;
|
||||
|
||||
float4 lightVectors[3];
|
||||
for ( i = 0; i < 3; i++ )
|
||||
lightVectors[i] = wsPosition[i] - inLightPos[i];
|
||||
|
||||
float4 squareDists = 0;
|
||||
for ( i = 0; i < 3; i++ )
|
||||
squareDists += lightVectors[i] * lightVectors[i];
|
||||
|
||||
// Accumulate the dot product between the light
|
||||
// vector and the normal.
|
||||
//
|
||||
// The normal is negated because it faces away from
|
||||
// the surface and the light faces towards the
|
||||
// surface... this keeps us from needing to flip
|
||||
// the light vector direction which complicates
|
||||
// the spot light calculations.
|
||||
//
|
||||
// We normalize the result a little later.
|
||||
//
|
||||
float4 nDotL = 0;
|
||||
for ( i = 0; i < 3; i++ )
|
||||
nDotL += lightVectors[i] * -wsNormal[i];
|
||||
|
||||
float4 rDotL = 0;
|
||||
#ifndef TORQUE_BL_NOSPECULAR
|
||||
|
||||
// We're using the Phong specular reflection model
|
||||
// here where traditionally Torque has used Blinn-Phong
|
||||
// which has proven to be more accurate to real materials.
|
||||
//
|
||||
// We do so because its cheaper as do not need to
|
||||
// calculate the half angle for all 4 lights.
|
||||
//
|
||||
// Advanced Lighting still uses Blinn-Phong, but the
|
||||
// specular reconstruction it does looks fairly similar
|
||||
// to this.
|
||||
//
|
||||
float3 R = reflect( wsView, -wsNormal );
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
rDotL += lightVectors[i] * R[i];
|
||||
|
||||
#endif
|
||||
|
||||
// Normalize the dots.
|
||||
//
|
||||
// Notice we're using the half type here to get a
|
||||
// much faster sqrt via the rsq_pp instruction at
|
||||
// the loss of some precision.
|
||||
//
|
||||
// Unless we have some extremely large point lights
|
||||
// i don't believe the precision loss will matter.
|
||||
//
|
||||
half4 correction = (half4)rsqrt( squareDists );
|
||||
nDotL = saturate( nDotL * correction );
|
||||
rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
|
||||
|
||||
// First calculate a simple point light linear
|
||||
// attenuation factor.
|
||||
//
|
||||
// If this is a directional light the inverse
|
||||
// radius should be greater than the distance
|
||||
// causing the attenuation to have no affect.
|
||||
//
|
||||
float4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) );
|
||||
|
||||
#ifndef TORQUE_BL_NOSPOTLIGHT
|
||||
|
||||
// The spotlight attenuation factor. This is really
|
||||
// fast for what it does... 6 instructions for 4 spots.
|
||||
|
||||
float4 spotAtten = 0;
|
||||
for ( i = 0; i < 3; i++ )
|
||||
spotAtten += lightVectors[i] * inLightSpotDir[i];
|
||||
|
||||
float4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle;
|
||||
atten *= saturate( cosAngle * inLightSpotFalloff );
|
||||
|
||||
#endif
|
||||
|
||||
// Finally apply the shadow masking on the attenuation.
|
||||
atten *= shadowMask;
|
||||
|
||||
// Get the final light intensity.
|
||||
float4 intensity = nDotL * atten;
|
||||
|
||||
// Combine the light colors for output.
|
||||
outDiffuse = 0;
|
||||
for ( i = 0; i < 4; i++ )
|
||||
outDiffuse += intensity[i] * inLightColor[i];
|
||||
|
||||
// Output the specular power.
|
||||
float4 specularIntensity = pow( rDotL, specularPower.xxxx ) * atten;
|
||||
|
||||
// Apply the per-light specular attenuation.
|
||||
float4 specular = float4(0,0,0,1);
|
||||
for ( i = 0; i < 4; i++ )
|
||||
specular += float4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
|
||||
|
||||
// Add the final specular intensity values together
|
||||
// using a single dot product operation then get the
|
||||
// final specular lighting color.
|
||||
outSpecular = specularColor * specular;
|
||||
outDiffuse = float4(0,0,0,0);
|
||||
outSpecular = float4(0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
// This value is used in AL as a constant power to raise specular values
|
||||
// to, before storing them into the light info buffer. The per-material
|
||||
// specular value is then computer by using the integer identity of
|
||||
// exponentiation:
|
||||
//
|
||||
// (a^m)^n = a^(m*n)
|
||||
//
|
||||
// or
|
||||
//
|
||||
// (specular^constSpecular)^(matSpecular/constSpecular) = specular^(matSpecular*constSpecular)
|
||||
//
|
||||
#define AL_ConstantSpecularPower 12.0f
|
||||
|
||||
/// The specular calculation used in Advanced Lighting.
|
||||
///
|
||||
/// @param toLight Normalized vector representing direction from the pixel
|
||||
/// being lit, to the light source, in world space.
|
||||
///
|
||||
/// @param normal Normalized surface normal.
|
||||
///
|
||||
/// @param toEye The normalized vector representing direction from the pixel
|
||||
/// being lit to the camera.
|
||||
///
|
||||
float AL_CalcSpecular( float3 toLight, float3 normal, float3 toEye )
|
||||
struct Surface
|
||||
{
|
||||
// (R.V)^c
|
||||
float specVal = dot( normalize( -reflect( toLight, normal ) ), toEye );
|
||||
float3 P; // world space position
|
||||
float3 N; // world space normal
|
||||
float3 V; // world space view vector
|
||||
float4 baseColor; // base color [0 -> 1] (rgba)
|
||||
float metalness; // metalness [0:dielectric -> 1:metal]
|
||||
float roughness; // roughness: [0:smooth -> 1:rough] (linear)
|
||||
float roughness_brdf; // roughness remapped from linear to BRDF
|
||||
float depth; // depth: [0:near -> 1:far] (linear)
|
||||
float ao; // ambient occlusion [0 -> 1]
|
||||
float matFlag; // material flag - use getFlag to retreive
|
||||
|
||||
// Return the specular factor.
|
||||
return pow( max( specVal, 0.00001f ), AL_ConstantSpecularPower );
|
||||
float NdotV; // cos(angle between normal and view vector)
|
||||
float3 f0; // fresnel value (rgb)
|
||||
float3 albedo; // diffuse light absorbtion value (rgb)
|
||||
float3 R; // reflection vector
|
||||
float3 F; // fresnel term computed from f0, N and V
|
||||
|
||||
inline void Update()
|
||||
{
|
||||
NdotV = abs(dot(N, V)) + 1e-5f; // avoid artifact
|
||||
|
||||
albedo = baseColor.rgb * (1.0 - metalness);
|
||||
f0 = lerp(0.04.xxx, baseColor.rgb, metalness);
|
||||
|
||||
R = -reflect(V, N);
|
||||
float f90 = saturate(50.0 * dot(f0, 0.33));
|
||||
F = F_Schlick(f0, f90, NdotV);
|
||||
}
|
||||
};
|
||||
|
||||
inline Surface createSurface(float4 gbuffer0, TORQUE_SAMPLER2D(gbufferTex1), TORQUE_SAMPLER2D(gbufferTex2), in float2 uv, in float3 wsEyePos, in float3 wsEyeRay, in float4x4 invView)
|
||||
{
|
||||
Surface surface = (Surface)0;
|
||||
|
||||
float4 gbuffer1 = TORQUE_TEX2DLOD(gbufferTex1, float4(uv,0,0));
|
||||
float4 gbuffer2 = TORQUE_TEX2DLOD(gbufferTex2, float4(uv,0,0));
|
||||
|
||||
surface.depth = gbuffer0.a;
|
||||
surface.P = wsEyePos + wsEyeRay * surface.depth;
|
||||
surface.N = mul(invView, float4(gbuffer0.xyz,0)).xyz; //TODO move t3d to use WS normals
|
||||
surface.V = normalize(wsEyePos - surface.P);
|
||||
surface.baseColor = gbuffer1;
|
||||
const float minRoughness=1e-4;
|
||||
surface.roughness = clamp(1.0 - gbuffer2.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
|
||||
surface.roughness_brdf = surface.roughness * surface.roughness;
|
||||
surface.metalness = gbuffer2.a;
|
||||
surface.ao = gbuffer2.g;
|
||||
surface.matFlag = gbuffer2.r;
|
||||
|
||||
surface.Update();
|
||||
return surface;
|
||||
}
|
||||
|
||||
/// The output for Deferred Lighting
|
||||
///
|
||||
/// @param toLight Normalized vector representing direction from the pixel
|
||||
/// being lit, to the light source, in world space.
|
||||
///
|
||||
/// @param normal Normalized surface normal.
|
||||
///
|
||||
/// @param toEye The normalized vector representing direction from the pixel
|
||||
/// being lit to the camera.
|
||||
///
|
||||
float4 AL_DeferredOutput(
|
||||
float3 lightColor,
|
||||
float3 diffuseColor,
|
||||
float4 matInfo,
|
||||
float4 ambient,
|
||||
float specular,
|
||||
float shadowAttenuation)
|
||||
inline Surface createForwardSurface(float4 baseColor, float3 normal, float4 pbrProperties, in float2 uv,
|
||||
in float3 wsPosition, in float3 wsEyePos, in float3 wsEyeRay)
|
||||
{
|
||||
float3 specularColor = float3(specular, specular, specular);
|
||||
bool metalness = getFlag(matInfo.r, 3);
|
||||
if ( metalness )
|
||||
{
|
||||
specularColor = 0.04 * (1 - specular) + diffuseColor * specular;
|
||||
Surface surface = (Surface)0;
|
||||
|
||||
surface.depth = 0;
|
||||
surface.P = wsPosition;
|
||||
surface.N = normal;
|
||||
surface.V = normalize(wsEyePos - surface.P);
|
||||
surface.baseColor = baseColor;
|
||||
const float minRoughness=1e-4;
|
||||
surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1); //t3d uses smoothness, so we convert to roughness.
|
||||
surface.roughness_brdf = surface.roughness * surface.roughness;
|
||||
surface.metalness = pbrProperties.a;
|
||||
surface.ao = pbrProperties.g;
|
||||
surface.matFlag = pbrProperties.r;
|
||||
|
||||
surface.Update();
|
||||
return surface;
|
||||
}
|
||||
|
||||
struct SurfaceToLight
|
||||
{
|
||||
float3 L; // surface to light vector
|
||||
float3 Lu; // un-normalized surface to light vector
|
||||
float3 H; // half-vector between view vector and light vector
|
||||
float NdotL; // cos(angle between N and L)
|
||||
float HdotV; // cos(angle between H and V) = HdotL = cos(angle between H and L)
|
||||
float NdotH; // cos(angle between N and H)
|
||||
};
|
||||
|
||||
inline SurfaceToLight createSurfaceToLight(in Surface surface, in float3 L)
|
||||
{
|
||||
SurfaceToLight surfaceToLight = (SurfaceToLight)0;
|
||||
surfaceToLight.Lu = L;
|
||||
surfaceToLight.L = normalize(L);
|
||||
surfaceToLight.H = normalize(surface.V + surfaceToLight.L);
|
||||
surfaceToLight.NdotL = saturate(dot(surfaceToLight.L, surface.N));
|
||||
surfaceToLight.HdotV = saturate(dot(surfaceToLight.H, surface.V));
|
||||
surfaceToLight.NdotH = saturate(dot(surfaceToLight.H, surface.N));
|
||||
|
||||
return surfaceToLight;
|
||||
}
|
||||
|
||||
float3 BRDF_GetSpecular(in Surface surface, in SurfaceToLight surfaceToLight)
|
||||
{
|
||||
float f90 = saturate(50.0 * dot(surface.f0, 0.33));
|
||||
float3 F = F_Schlick(surface.f0, f90, surfaceToLight.HdotV);
|
||||
float Vis = V_SmithGGXCorrelated(surface.NdotV, surfaceToLight.NdotL, surface.roughness_brdf);
|
||||
float D = D_GGX(surfaceToLight.NdotH, surface.roughness_brdf);
|
||||
float3 Fr = D * F * Vis / M_PI_F;
|
||||
return Fr;
|
||||
}
|
||||
|
||||
float3 BRDF_GetDiffuse(in Surface surface, in SurfaceToLight surfaceToLight)
|
||||
{
|
||||
//getting some banding with disney method, using lambert instead - todo futher testing
|
||||
float Fd = 1.0 / M_PI_F;
|
||||
//energy conservation - remove this if reverting back to disney method
|
||||
float3 kD = 1.0.xxx - surface.F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
float3 diffuse = kD * surface.baseColor.rgb * Fd;
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
//attenuations functions from "moving frostbite to pbr paper"
|
||||
//https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
|
||||
float smoothDistanceAtt ( float squaredDistance , float invSqrAttRadius )
|
||||
{
|
||||
float factor = squaredDistance * invSqrAttRadius ;
|
||||
float smoothFactor = saturate (1.0f - factor * factor );
|
||||
return sqr(smoothFactor);
|
||||
}
|
||||
|
||||
float getDistanceAtt( float3 unormalizedLightVector , float invSqrAttRadius )
|
||||
{
|
||||
float sqrDist = dot ( unormalizedLightVector , unormalizedLightVector );
|
||||
float attenuation = 1.0 / (max ( sqrDist , 0.01*0.01) );
|
||||
attenuation *= smoothDistanceAtt ( sqrDist , invSqrAttRadius );
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
float getSpotAngleAtt( float3 normalizedLightVector , float3 lightDir , float2 lightSpotParams )
|
||||
{
|
||||
float cd = dot ( lightDir , normalizedLightVector );
|
||||
float attenuation = saturate ( ( cd - lightSpotParams.x ) / lightSpotParams.y );
|
||||
// smooth the transition
|
||||
return sqr(attenuation);
|
||||
}
|
||||
|
||||
inline float3 getDirectionalLight(in Surface surface, in SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float shadow)
|
||||
{
|
||||
float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity;
|
||||
float3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
|
||||
float3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
|
||||
|
||||
float3 final = max(0.0f, diffuse + spec * surface.ao);
|
||||
return final;
|
||||
}
|
||||
|
||||
inline float3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLight, float3 lightColor, float lightIntensity, float radius, float shadow)
|
||||
{
|
||||
float attenuation = getDistanceAtt(surfaceToLight.Lu, radius);
|
||||
float3 factor = lightColor * max(surfaceToLight.NdotL, 0) * shadow * lightIntensity * attenuation;
|
||||
|
||||
float3 diffuse = BRDF_GetDiffuse(surface,surfaceToLight) * factor;
|
||||
float3 spec = BRDF_GetSpecular(surface,surfaceToLight) * factor;
|
||||
|
||||
float3 final = max(0.0f, diffuse + spec * surface.ao * surface.F);
|
||||
return final;
|
||||
}
|
||||
|
||||
//Probe IBL stuff
|
||||
float defineSphereSpaceInfluence(float3 wsPosition, float3 wsProbePosition, float radius)
|
||||
{
|
||||
float3 L = wsProbePosition.xyz - wsPosition;
|
||||
float contribution = 1.0 - length(L) / radius;
|
||||
return contribution;
|
||||
}
|
||||
|
||||
float getDistBoxToPoint(float3 pt, float3 extents)
|
||||
{
|
||||
float3 d = max(max(-extents - pt, 0), pt - extents);
|
||||
return max(max(d.x, d.y), d.z);
|
||||
}
|
||||
|
||||
float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float attenuation)
|
||||
{
|
||||
float3 surfPosLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
|
||||
float atten = 1.0 - attenuation;
|
||||
float baseVal = 0.25;
|
||||
float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal));
|
||||
return saturate(smoothstep(baseVal + 0.0001, atten*baseVal, dist));
|
||||
}
|
||||
|
||||
// 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 wsReflectVec, float4x4 worldToObj, float3 bbMin, float3 bbMax, float3 refPosition)
|
||||
{
|
||||
float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz;
|
||||
float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
|
||||
|
||||
float3 unit = bbMax.xyz - bbMin.xyz;
|
||||
float3 plane1vec = (unit / 2 - PositionLS) / RayLS;
|
||||
float3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
|
||||
float3 furthestPlane = max(plane1vec, plane2vec);
|
||||
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
||||
float3 posonbox = wsPosition + wsReflectVec * dist;
|
||||
|
||||
return posonbox - refPosition.xyz;
|
||||
}
|
||||
|
||||
float4 computeForwardProbes(Surface surface,
|
||||
float cubeMips, float numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES],
|
||||
float4 inProbePosArray[MAX_FORWARD_PROBES], float4 bbMinArray[MAX_FORWARD_PROBES], float4 bbMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
|
||||
float hasSkylight, TORQUE_SAMPLER2D(BRDFTexture),
|
||||
TORQUE_SAMPLERCUBE(skylightIrradMap), TORQUE_SAMPLERCUBE(skylightSpecularMap),
|
||||
TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
|
||||
{
|
||||
int i = 0;
|
||||
float blendFactor[MAX_FORWARD_PROBES];
|
||||
float blendSum = 0;
|
||||
float blendFacSum = 0;
|
||||
float invBlendSum = 0;
|
||||
float probehits = 0;
|
||||
//Set up our struct data
|
||||
float contribution[MAX_FORWARD_PROBES];
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
contribution[i] = 0;
|
||||
|
||||
if (probeConfigData[i].r == 0) //box
|
||||
{
|
||||
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
|
||||
if (contribution[i] > 0.0)
|
||||
probehits++;
|
||||
}
|
||||
else if (probeConfigData[i].r == 1) //sphere
|
||||
{
|
||||
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
|
||||
if (contribution[i] > 0.0)
|
||||
probehits++;
|
||||
}
|
||||
|
||||
contribution[i] = max(contribution[i], 0);
|
||||
|
||||
blendSum += contribution[i];
|
||||
invBlendSum += (1.0f - contribution[i]);
|
||||
}
|
||||
|
||||
//specular = color * map * spec^gloss
|
||||
float specularOut = (specularColor * matInfo.b * min(pow(abs(specular), max(( matInfo.a/ AL_ConstantSpecularPower),1.0f)),matInfo.a)).r;
|
||||
|
||||
lightColor *= shadowAttenuation;
|
||||
lightColor += ambient.rgb;
|
||||
return float4(lightColor.rgb, specularOut);
|
||||
}
|
||||
|
||||
if (probehits > 1.0)
|
||||
{
|
||||
for (i = 0; i < numProbes; i++)
|
||||
{
|
||||
blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
|
||||
blendFactor[i] *= ((contribution[i]) / invBlendSum);
|
||||
blendFactor[i] = saturate(blendFactor[i]);
|
||||
blendFacSum += blendFactor[i];
|
||||
}
|
||||
|
||||
// Normalize blendVal
|
||||
if (blendFacSum == 0.0f) // Possible with custom weight
|
||||
{
|
||||
blendFacSum = 1.0f;
|
||||
}
|
||||
|
||||
float invBlendSumWeighted = 1.0f / blendFacSum;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendFactor[i] *= invBlendSumWeighted;
|
||||
contribution[i] *= blendFactor[i];
|
||||
}
|
||||
}
|
||||
|
||||
float3 irradiance = float3(0, 0, 0);
|
||||
float3 specular = float3(0, 0, 0);
|
||||
|
||||
// Radiance (Specular)
|
||||
float lod = surface.roughness*cubeMips;
|
||||
|
||||
float alpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
float contrib = contribution[i];
|
||||
if (contrib != 0)
|
||||
{
|
||||
int cubemapIdx = probeConfigData[i].a;
|
||||
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
|
||||
|
||||
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
|
||||
specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
|
||||
alpha -= contrib;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSkylight && alpha > 0.001)
|
||||
{
|
||||
irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz;
|
||||
specular = TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz;
|
||||
}
|
||||
|
||||
float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
|
||||
//energy conservation
|
||||
float3 kD = 1.0.xxx - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
|
||||
//apply brdf
|
||||
//Do it once to save on texture samples
|
||||
float2 brdf = TORQUE_TEX2DLOD(BRDFTexture,float4(surface.roughness, 1.0-surface.NdotV, 0.0, 0.0)).xy;
|
||||
specular *= brdf.x * F + brdf.y;
|
||||
|
||||
//final diffuse color
|
||||
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
float4 finalColor = float4(diffuse + specular, 1);
|
||||
//finalColor.rgb += abs(surface.N);
|
||||
return finalColor;
|
||||
}
|
||||
|
|
@ -37,11 +37,12 @@ struct ConvexConnectV
|
|||
float4 vsEyeDir : TEXCOORD2;
|
||||
};
|
||||
|
||||
ConvexConnectV main( VertData IN,
|
||||
uniform float4x4 modelview,
|
||||
uniform float4x4 objTrans,
|
||||
uniform float4x4 worldViewOnly,
|
||||
uniform float3 eyePosWorld )
|
||||
uniform float4x4 modelview;
|
||||
uniform float4x4 objTrans;
|
||||
uniform float4x4 worldViewOnly;
|
||||
uniform float3 eyePosWorld;
|
||||
|
||||
ConvexConnectV main( VertData IN )
|
||||
{
|
||||
ConvexConnectV OUT;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../shaderModel.hlsl"
|
||||
|
||||
struct ConnectData
|
||||
{
|
||||
float4 hpos : TORQUE_POSITION;
|
||||
float2 uv : TEXCOORD;
|
||||
};
|
||||
|
||||
ConnectData main( uint vertexID : SV_VertexID )
|
||||
{
|
||||
ConnectData result;
|
||||
result.uv = float2((vertexID << 1) & 2, vertexID & 2);
|
||||
result.hpos = float4(result.uv * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -23,9 +23,9 @@
|
|||
#include "../../hlslStructs.hlsl"
|
||||
#include "farFrustumQuad.hlsl"
|
||||
|
||||
uniform float4 rtParams0;
|
||||
|
||||
FarFrustumQuadConnectV main( VertexIn_PNTT IN,
|
||||
uniform float4 rtParams0 )
|
||||
FarFrustumQuadConnectV main( VertexIn_PNTT IN )
|
||||
{
|
||||
FarFrustumQuadConnectV OUT;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../torque.glsl"
|
||||
#line 24
|
||||
in vec4 hpos;
|
||||
in vec2 uv0;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
|
||||
// efficient VanDerCorpus calculation.
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
|
||||
{
|
||||
float a = roughness*roughness;
|
||||
|
||||
float phi = 2.0 * M_PI_F * Xi.x;
|
||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||
|
||||
// from spherical coordinates to cartesian coordinates - halfway vector
|
||||
vec3 H;
|
||||
H.x = cos(phi) * sinTheta;
|
||||
H.y = sin(phi) * sinTheta;
|
||||
H.z = cosTheta;
|
||||
|
||||
// from tangent-space H vector to world-space sample vector
|
||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 tangent = normalize(cross(up, N));
|
||||
vec3 bitangent = cross(N, tangent);
|
||||
|
||||
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||
return normalize(sampleVec);
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||
{
|
||||
// note that we use a different k for IBL
|
||||
float a = roughness;
|
||||
float k = (a * a) / 2.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||
{
|
||||
float NdotV = max(dot(N, V), 0.0);
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
vec2 IntegrateBRDF(float NdotV, float roughness)
|
||||
{
|
||||
vec3 V;
|
||||
V.x = sqrt(1.0 - NdotV*NdotV);
|
||||
V.y = 0.0;
|
||||
V.z = NdotV;
|
||||
|
||||
float A = 0.0;
|
||||
float B = 0.0;
|
||||
|
||||
vec3 N = vec3(0.0, 0.0, 1.0);
|
||||
|
||||
const uint SAMPLE_COUNT = 1024u;
|
||||
for(uint i = 0u; i < SAMPLE_COUNT; ++i)
|
||||
{
|
||||
// generates a sample vector that's biased towards the
|
||||
// preferred alignment direction (importance sampling).
|
||||
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
|
||||
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
|
||||
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||
|
||||
float NdotL = max(L.z, 0.0);
|
||||
float NdotH = max(H.z, 0.0);
|
||||
float VdotH = max(dot(V, H), 0.0);
|
||||
|
||||
if(NdotL > 0.0)
|
||||
{
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
float G_Vis = (G * VdotH) / (NdotH * NdotV);
|
||||
float Fc = pow(1.0 - VdotH, 5.0);
|
||||
|
||||
A += (1.0 - Fc) * G_Vis;
|
||||
B += Fc * G_Vis;
|
||||
}
|
||||
}
|
||||
A /= float(SAMPLE_COUNT);
|
||||
B /= float(SAMPLE_COUNT);
|
||||
return vec2(A, B);
|
||||
}
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
OUT_col = vec4(IntegrateBRDF(uv0.x, uv0.y).rg,0,1);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../gl/hlslCompat.glsl"
|
||||
out vec2 uv0;
|
||||
|
||||
void main()
|
||||
{
|
||||
float x = float((gl_VertexID & 1) << 2)-1.0;
|
||||
float y = float((gl_VertexID & 2) << 1)-1.0;
|
||||
gl_Position = vec4(x, y, 0, 1);
|
||||
uv0.x = (x+1.0)*0.5;
|
||||
uv0.y = (y+1.0)*0.5;
|
||||
}
|
||||
|
|
@ -26,8 +26,9 @@
|
|||
#include "../../../gl/torque.glsl"
|
||||
|
||||
uniform sampler2D colorBufferTex;
|
||||
uniform sampler2D lightDeferredTex;
|
||||
uniform sampler2D diffuseLightingBuffer;
|
||||
uniform sampler2D matInfoTex;
|
||||
uniform sampler2D specularLightingBuffer;
|
||||
uniform sampler2D deferredTex;
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
|
@ -40,20 +41,26 @@ void main()
|
|||
OUT_col = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
vec4 lightBuffer = texture( lightDeferredTex, uv0 );
|
||||
vec4 colorBuffer = texture( colorBufferTex, uv0 );
|
||||
vec4 matInfo = texture( matInfoTex, uv0 );
|
||||
float specular = clamp(lightBuffer.a,0.0,1.0);
|
||||
|
||||
vec3 albedo = texture( colorBufferTex, uv0 ).rgb; //albedo
|
||||
vec4 matInfo = texture( matInfoTex, uv0 ); //flags|smoothness|ao|metallic
|
||||
|
||||
// Diffuse Color Altered by Metalness
|
||||
bool metalness = getFlag(matInfo.r, 3);
|
||||
if ( metalness )
|
||||
bool emissive = getFlag(matInfo.r, 0);
|
||||
if (emissive)
|
||||
{
|
||||
colorBuffer *= (1.0 - colorBuffer.a);
|
||||
OUT_col = float4(albedo, 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 diffuse = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular
|
||||
vec4 specular = texture( specularLightingBuffer, uv0 ); //environment mapping*lightmaps
|
||||
|
||||
colorBuffer += vec4(specular, specular, specular, 1.0);
|
||||
colorBuffer *= vec4(lightBuffer.rgb, 1.0);
|
||||
float metalness = matInfo.a;
|
||||
|
||||
vec3 diffuseColor = albedo - (albedo * metalness);
|
||||
vec3 specularColor = lerp(float3(0.04,0.04,0.04), albedo, metalness);
|
||||
|
||||
OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) );
|
||||
vec3 light = (diffuseColor * diffuse.rgb) + (specularColor * specular.rgb);
|
||||
|
||||
OUT_col = hdrEncode(vec4(light, 1.0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../gl/torque.glsl"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform int face;
|
||||
|
||||
uniform samplerCube environmentMap;
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 N = getCubeDir(face, uv0);
|
||||
vec3 irradiance = vec3(0.0);
|
||||
|
||||
// tangent space calculation from origin point
|
||||
vec3 up = vec3(0.0, 0.0, 1.0);
|
||||
vec3 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)
|
||||
vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));
|
||||
// tangent space to world
|
||||
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
|
||||
|
||||
irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
|
||||
nrSamples++;
|
||||
}
|
||||
}
|
||||
irradiance = M_PI_F * irradiance * (1.0 / float(nrSamples));
|
||||
|
||||
OUT_col = vec4(irradiance, 1.0);
|
||||
}
|
||||
|
|
@ -33,34 +33,6 @@ float attenuate( vec4 lightColor, vec2 attParams, float dist )
|
|||
#endif
|
||||
}
|
||||
|
||||
// Calculate the specular coefficent
|
||||
//
|
||||
// pxlToLight - Normalized vector representing direction from the pixel being lit, to the light source, in world space
|
||||
// normal - Normalized surface normal
|
||||
// pxlToEye - Normalized vector representing direction from pixel being lit, to the camera, in world space
|
||||
// specPwr - Specular exponent
|
||||
// specularScale - A scalar on the specular output used in RGB accumulation.
|
||||
//
|
||||
float calcSpecular( vec3 pxlToLight, vec3 normal, vec3 pxlToEye, float specPwr, float specularScale )
|
||||
{
|
||||
#ifdef PHONG_SPECULAR
|
||||
// (R.V)^c
|
||||
float specVal = dot( normalize( -reflect( pxlToLight, normal ) ), pxlToEye );
|
||||
#else
|
||||
// (N.H)^c [Blinn-Phong, TGEA style, default]
|
||||
float specVal = dot( normal, normalize( pxlToLight + pxlToEye ) );
|
||||
#endif
|
||||
|
||||
#ifdef ACCUMULATE_LUV
|
||||
return pow( max( specVal, 0.00001f ), specPwr );
|
||||
#else
|
||||
// If this is RGB accumulation, than there is no facility for the luminance
|
||||
// of the light to play in to the specular intensity. In LUV, the luminance
|
||||
// of the light color gets rolled into N.L * Attenuation
|
||||
return specularScale * pow( max( specVal, 0.00001f ), specPwr );
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 getDistanceVectorToPlane( vec3 origin, vec3 direction, vec4 plane )
|
||||
{
|
||||
float denum = dot( plane.xyz, direction.xyz );
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@
|
|||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
#include "farFrustumQuad.glsl"
|
||||
#include "lightingUtils.glsl"
|
||||
#include "../../../gl/lighting.glsl"
|
||||
#include "../../shadowMap/shadowMapIO_GLSL.h"
|
||||
#include "softShadow.glsl"
|
||||
#include "../../../gl/torque.glsl"
|
||||
#line 31
|
||||
|
||||
in vec4 wsEyeDir;
|
||||
in vec4 ssPos;
|
||||
|
|
@ -38,7 +38,7 @@ in vec4 color;
|
|||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
/// The texture for cookie rendering.
|
||||
uniform samplerCube cookieMap ;
|
||||
uniform samplerCube cookieMap;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -85,7 +85,9 @@ uniform samplerCube cookieMap ;
|
|||
// this value was found via experementation
|
||||
// NOTE: this is wrong, it only biases in one direction, not towards the uv
|
||||
// center ( 0.5 0.5 ).
|
||||
//shadowCoord.xy *= 0.997;
|
||||
float offsetVal = 0.95;
|
||||
shadowCoord.xy *= offsetVal;
|
||||
shadowCoord.xy += vec2(1.0-offsetVal) / 2.0;
|
||||
|
||||
#ifndef SHADOW_PARABOLOID
|
||||
|
||||
|
|
@ -122,152 +124,86 @@ uniform vec3 lightPosition;
|
|||
uniform vec4 lightColor;
|
||||
uniform float lightBrightness;
|
||||
uniform float lightRange;
|
||||
uniform vec2 lightAttenuation;
|
||||
uniform vec4 lightMapParams;
|
||||
uniform vec4 vsFarPlane;
|
||||
uniform mat3 viewToLightProj;
|
||||
uniform mat3 dynamicViewToLightProj;
|
||||
uniform vec4 lightParams;
|
||||
|
||||
uniform float lightInvSqrRange;
|
||||
uniform float shadowSoftness;
|
||||
uniform mat3 worldToLightProj;
|
||||
uniform mat3 dynamicWorldToLightProj;
|
||||
|
||||
uniform vec3 eyePosWorld;
|
||||
uniform mat4 cameraToWorld;
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Compute scene UV
|
||||
vec3 ssPos = ssPos.xyz / ssPos.w;
|
||||
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||
vec2 uvScene = getUVFromSSPos(ssPos.xyz/ssPos.w, rtParams0);
|
||||
|
||||
//unpack normal and linear depth
|
||||
vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
|
||||
|
||||
//eye ray WS/VS
|
||||
vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
||||
vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
|
||||
// Emissive.
|
||||
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
||||
bool emissive = getFlag( matInfo.r, 0 );
|
||||
if ( emissive )
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
return;
|
||||
OUT_col = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uvScene );
|
||||
vec3 subsurface = vec3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
vec3 L = lightPosition - surface.P;
|
||||
float dist = length(L);
|
||||
vec3 lighting = vec3(0.0);
|
||||
if(dist < lightRange)
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = vec3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = vec3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene );
|
||||
vec3 normal = deferredSample.rgb;
|
||||
float depth = deferredSample.a;
|
||||
|
||||
// Eye ray - Eye -> Pixel
|
||||
vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
||||
vec3 viewSpacePos = eyeRay * depth;
|
||||
|
||||
// Build light vec, get length, clip pixel if needed
|
||||
vec3 lightVec = lightPosition - viewSpacePos;
|
||||
float lenLightV = length( lightVec );
|
||||
clip( lightRange - lenLightV );
|
||||
|
||||
// Get the attenuated falloff.
|
||||
float atten = attenuate( lightColor, lightAttenuation, lenLightV );
|
||||
clip( atten - 1e-6 );
|
||||
|
||||
// Normalize lightVec
|
||||
lightVec /= lenLightV;
|
||||
|
||||
// If we can do dynamic branching then avoid wasting
|
||||
// fillrate on pixels that are backfacing to the light.
|
||||
float nDotL = dot( lightVec, normal );
|
||||
//DB_CLIP( nDotL < 0 );
|
||||
float distToLight = dist / lightRange;
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
|
||||
|
||||
#ifdef NO_SHADOW
|
||||
|
||||
float shadowed = 1.0;
|
||||
|
||||
#else
|
||||
|
||||
// Get a linear depth from the light source.
|
||||
float distToLight = lenLightV / lightRange;
|
||||
|
||||
#ifdef SHADOW_CUBE
|
||||
|
||||
// TODO: We need to fix shadow cube to handle soft shadows!
|
||||
float occ = texture( shadowMap, tMul( viewToLightProj, -lightVec ) ).r;
|
||||
float occ = texture( shadowMap, ttMul( worldToLightProj, -surfaceToLight.L ) ).r;
|
||||
float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
|
||||
|
||||
#else
|
||||
|
||||
vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
|
||||
|
||||
float static_shadowed = softShadow_filter( shadowMap,
|
||||
ssPos.xy,
|
||||
shadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
|
||||
vec2 dynamicShadowCoord = decodeShadowCoord( tMul( dynamicViewToLightProj, -lightVec ) ).xy;
|
||||
float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
|
||||
ssPos.xy,
|
||||
dynamicShadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
|
||||
vec2 shadowCoord = decodeShadowCoord( tMul( worldToLightProj, -surfaceToLight.L ) ).xy;
|
||||
vec2 dynShadowCoord = decodeShadowCoord( tMul( dynamicWorldToLightProj, -surfaceToLight.L ) ).xy;
|
||||
float static_shadowed = softShadow_filter(shadowMap, ssPos.xy/ssPos.w, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float dynamic_shadowed = softShadow_filter(dynamicShadowMap, ssPos.xy/ssPos.w, dynShadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
#endif
|
||||
|
||||
#endif // !NO_SHADOW
|
||||
|
||||
vec3 lightcol = lightColor.rgb;
|
||||
vec3 lightCol = lightColor.rgb;
|
||||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
// Lookup the cookie sample.
|
||||
vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) );
|
||||
|
||||
vec4 cookie = texture(cookieMap, ttMul(worldToLightProj, -surfaceToLight.L));
|
||||
// Multiply the light with the cookie tex.
|
||||
lightcol *= cookie.rgb;
|
||||
|
||||
lightCol *= cookie.rgb;
|
||||
// Use a maximum channel luminance to attenuate
|
||||
// the lighting else we get specular in the dark
|
||||
// regions of the cookie texture.
|
||||
atten *= max( cookie.r, max( cookie.g, cookie.b ) );
|
||||
|
||||
lightCol *= max(cookie.r, max(cookie.g, cookie.b));
|
||||
#endif
|
||||
|
||||
// NOTE: Do not clip on fully shadowed pixels as it would
|
||||
// cause the hardware occlusion query to disable the shadow.
|
||||
|
||||
// Specular term
|
||||
float specular = AL_CalcSpecular( lightVec,
|
||||
normal,
|
||||
normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
|
||||
|
||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
||||
vec3 lightColorOut = lightMapParams.rgb * lightcol;
|
||||
vec4 addToResult = vec4(0.0);
|
||||
|
||||
// TODO: This needs to be removed when lightmapping is disabled
|
||||
// as its extra work per-pixel on dynamic lit scenes.
|
||||
//
|
||||
// Special lightmapping pass.
|
||||
if ( lightMapParams.a < 0.0 )
|
||||
{
|
||||
// This disables shadows on the backsides of objects.
|
||||
shadowed = nDotL < 0.0f ? 1.0f : shadowed;
|
||||
|
||||
Sat_NL_Att = 1.0f;
|
||||
shadowed = mix( 1.0f, shadowed, atten );
|
||||
lightColorOut = vec3(shadowed);
|
||||
specular *= lightBrightness;
|
||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
//get punctual light contribution
|
||||
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
|
||||
}
|
||||
|
||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
OUT_col = vec4(lighting, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../gl/torque.glsl"
|
||||
|
||||
in vec4 hpos;
|
||||
in vec2 uv0;
|
||||
|
||||
uniform samplerCube environmentMap;
|
||||
|
||||
uniform float roughness;
|
||||
uniform int face;
|
||||
uniform int mipSize;
|
||||
uniform int resolution;
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||
{
|
||||
float a = roughness * roughness;
|
||||
float a2 = a * a;
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float NdotH2 = NdotH * NdotH;
|
||||
|
||||
float nom = a2;
|
||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||
denom = M_PI_F * denom * denom;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N)
|
||||
{
|
||||
float a = roughness * roughness;
|
||||
|
||||
float phi = 2.0 * M_PI_F * Xi.x;
|
||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
|
||||
// from spherical coordinates to cartesian coordinates
|
||||
vec3 H;
|
||||
H.x = cos(phi) * sinTheta;
|
||||
H.y = sin(phi) * sinTheta;
|
||||
H.z = cosTheta;
|
||||
|
||||
// from tangent-space vector to world-space sample vector
|
||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 tangent = normalize(cross(up, N));
|
||||
vec3 bitangent = cross(N, tangent);
|
||||
|
||||
vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||
return normalize(sampleVec);
|
||||
}
|
||||
|
||||
vec4 prefilterEnvMap(vec3 R)
|
||||
{
|
||||
int sampleCount = resolution*2;
|
||||
vec3 N = R;
|
||||
vec3 V = R;
|
||||
float totalWeight = 0.0;
|
||||
vec4 prefilteredColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < sampleCount; ++i)
|
||||
{
|
||||
vec2 Xi = Hammersley(i, sampleCount);
|
||||
vec3 H = ImportanceSampleGGX(Xi, N);
|
||||
vec3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
if (NdotL > 0.0)
|
||||
{
|
||||
// sample from the environment's mip level based on roughness/pdf
|
||||
float D = DistributionGGX(N, H, roughness);
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float HdotV = max(dot(H, V), 0.0);
|
||||
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
|
||||
|
||||
float saTexel = 4.0 * M_PI_F / float(6.0 * sampleCount * sampleCount);
|
||||
float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001);
|
||||
|
||||
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
|
||||
|
||||
prefilteredColor += texture(environmentMap, L, mipLevel) * NdotL;
|
||||
|
||||
totalWeight += NdotL;
|
||||
}
|
||||
}
|
||||
|
||||
return (prefilteredColor / totalWeight);
|
||||
}
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
vec3 N = getCubeDir(face, uv0);
|
||||
OUT_col = prefilterEnvMap(N);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "../../../postFx/gl/postFX.glsl"
|
||||
#include "../../../gl/torque.glsl"
|
||||
|
||||
uniform sampler2D colorBufferTex;
|
||||
uniform sampler2D diffuseLightingBuffer;
|
||||
uniform sampler2D matInfoTex;
|
||||
uniform sampler2D specularLightingBuffer;
|
||||
uniform sampler2D deferredTex;
|
||||
|
||||
uniform float radius;
|
||||
uniform vec2 targetSize;
|
||||
uniform int captureRez;
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = deferredUncondition( deferredTex, uv0 ).w;
|
||||
if (depth>0.9999)
|
||||
{
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
vec3 colorBuffer = texture( colorBufferTex, uv0 ).rgb; //albedo
|
||||
vec4 matInfo = texture(matInfoTex, uv0); //flags|smoothness|ao|metallic
|
||||
|
||||
bool emissive = getFlag(matInfo.r, 0);
|
||||
if (emissive)
|
||||
{
|
||||
OUT_col = vec4(colorBuffer, 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 diffuseLighting = texture( diffuseLightingBuffer, uv0 ); //shadowmap*specular
|
||||
colorBuffer *= diffuseLighting.rgb;
|
||||
vec2 relUV = uv0*targetSize/captureRez;
|
||||
|
||||
//we use a 1k depth range in the capture frustum.
|
||||
//reduce that a bit to get something resembling depth fidelity out of 8 bits
|
||||
depth*=2000/radius;
|
||||
|
||||
float rLen = length(vec3(relUV,depth)-vec3(0.5,0.5,0));
|
||||
OUT_col = hdrEncode( vec4(colorBuffer,rLen));
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "../../../postFx/gl/postFx.glsl"
|
||||
#include "../../../gl/torque.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "../../../gl/lighting.glsl"
|
||||
|
||||
#line 7
|
||||
|
||||
uniform sampler2D deferredBuffer;
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D matInfoBuffer;
|
||||
uniform sampler2D BRDFTexture;
|
||||
|
||||
uniform vec4 rtParams0;
|
||||
uniform vec4 vsFarPlane;
|
||||
uniform mat4 cameraToWorld;
|
||||
uniform vec3 eyePosWorld;
|
||||
|
||||
//cubemap arrays require all the same size. so shared mips# value
|
||||
uniform float cubeMips;
|
||||
|
||||
uniform float numProbes;
|
||||
uniform samplerCubeArray specularCubemapAR;
|
||||
uniform samplerCubeArray irradianceCubemapAR;
|
||||
|
||||
uniform vec4 inProbePosArray[MAX_PROBES];
|
||||
uniform vec4 inRefPosArray[MAX_PROBES];
|
||||
uniform mat4 worldToObjArray[MAX_PROBES];
|
||||
uniform vec4 bbMinArray[MAX_PROBES];
|
||||
uniform vec4 bbMaxArray[MAX_PROBES];
|
||||
uniform vec4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
||||
|
||||
#if DEBUGVIZ_CONTRIB
|
||||
uniform vec4 probeContribColors[MAX_PROBES];
|
||||
#endif
|
||||
|
||||
uniform samplerCube skylightSpecularMap;
|
||||
uniform samplerCube skylightIrradMap;
|
||||
uniform float hasSkylight;
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
//unpack normal and linear depth
|
||||
vec4 normDepth = deferredUncondition(deferredBuffer, IN_uv0.xy);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface(normDepth, colorBuffer, matInfoBuffer, IN_uv0.xy, eyePosWorld, IN_wsEyeRay, cameraToWorld);
|
||||
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
float alpha = 1;
|
||||
|
||||
int i = 0;
|
||||
float blendFactor[MAX_PROBES];
|
||||
float blendSum = 0;
|
||||
float blendFacSum = 0;
|
||||
float invBlendSum = 0;
|
||||
float probehits = 0;
|
||||
//Set up our struct data
|
||||
float contribution[MAX_PROBES];
|
||||
if (alpha > 0)
|
||||
{
|
||||
//Process prooooobes
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
contribution[i] = 0;
|
||||
|
||||
if (probeConfigData[i].r == 0) //box
|
||||
{
|
||||
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
|
||||
if (contribution[i]>0.0)
|
||||
probehits++;
|
||||
}
|
||||
else if (probeConfigData[i].r == 1) //sphere
|
||||
{
|
||||
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
|
||||
if (contribution[i]>0.0)
|
||||
probehits++;
|
||||
}
|
||||
|
||||
contribution[i] = max(contribution[i],0);
|
||||
|
||||
blendSum += contribution[i];
|
||||
invBlendSum += (1.0f - contribution[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.
|
||||
|
||||
if (probehits>1.0)
|
||||
{
|
||||
for (i = 0; i < numProbes; i++)
|
||||
{
|
||||
blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
|
||||
blendFactor[i] *= ((contribution[i]) / invBlendSum);
|
||||
blendFactor[i] = saturate(blendFactor[i]);
|
||||
blendFacSum += blendFactor[i];
|
||||
}
|
||||
|
||||
// Normalize blendVal
|
||||
#if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior
|
||||
if (blendFacSum == 0.0f) // Possible with custom weight
|
||||
{
|
||||
blendFacSum = 1.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
float invBlendSumWeighted = 1.0f / blendFacSum;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendFactor[i] *= invBlendSumWeighted;
|
||||
contribution[i] *= blendFactor[i];
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUGVIZ_ATTENUATION == 1
|
||||
float contribAlpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
contribAlpha -= contribution[i];
|
||||
}
|
||||
|
||||
OUT_col = vec4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1);
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if DEBUGVIZ_CONTRIB == 1
|
||||
vec3 finalContribColor = vec3(0, 0, 0);
|
||||
float contribAlpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
finalContribColor += contribution[i] *probeContribColors[i].rgb;
|
||||
contribAlpha -= contribution[i];
|
||||
}
|
||||
|
||||
//Skylight coloration for anything not covered by probes above
|
||||
finalContribColor += vec3(0.3, 0.3, 0.3) * contribAlpha;
|
||||
|
||||
OUT_col = vec4(finalContribColor, 1);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec3 irradiance = vec3(0, 0, 0);
|
||||
vec3 specular = vec3(0, 0, 0);
|
||||
|
||||
// Radiance (Specular)
|
||||
#if DEBUGVIZ_SPECCUBEMAP == 0
|
||||
float lod = surface.roughness*cubeMips;
|
||||
#elif DEBUGVIZ_SPECCUBEMAP == 1
|
||||
float lod = 0;
|
||||
#endif
|
||||
|
||||
alpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
float contrib = contribution[i];
|
||||
if (contrib != 0)
|
||||
{
|
||||
float cubemapIdx = probeConfigData[i].a;
|
||||
vec3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
|
||||
|
||||
irradiance += textureLod(irradianceCubemapAR, vec4(dir, cubemapIdx), 0).xyz * contrib;
|
||||
specular += textureLod(specularCubemapAR, vec4(dir, cubemapIdx), lod).xyz * contrib;
|
||||
//irradiance += vec3(1,1,1) * contrib;
|
||||
//specular += vec3(1,1,1) * contrib;
|
||||
alpha -= contrib;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSkylight == 1 && alpha > 0.001)
|
||||
{
|
||||
irradiance += textureLod(skylightIrradMap, surface.R, 0).xyz * alpha;
|
||||
specular += textureLod(skylightSpecularMap, surface.R, lod).xyz * alpha;
|
||||
}
|
||||
|
||||
#if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
|
||||
OUT_col = vec4(specular, 1);
|
||||
return;
|
||||
#elif DEBUGVIZ_DIFFCUBEMAP == 1
|
||||
OUT_col = vec4(irradiance, 1);
|
||||
return;
|
||||
#endif
|
||||
|
||||
vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
|
||||
//energy conservation
|
||||
vec3 kD = vec3(1,1,1) - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
|
||||
//apply brdf
|
||||
//Do it once to save on texture samples
|
||||
vec2 brdf = textureLod(BRDFTexture, vec2(surface.roughness, surface.NdotV),0).xy;
|
||||
specular *= brdf.x * F + brdf.y;
|
||||
|
||||
//final diffuse color
|
||||
vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
vec4 finalColor = vec4(diffuse + specular * surface.ao, 1.0);
|
||||
|
||||
OUT_col = finalColor;
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "farFrustumQuad.glsl"
|
||||
#include "../../../gl/torque.glsl"
|
||||
#include "../../../gl/lighting.glsl"
|
||||
#line 27
|
||||
|
||||
in vec4 pos;
|
||||
in vec4 wsEyeDir;
|
||||
in vec4 ssPos;
|
||||
in vec4 vsEyeDir;
|
||||
|
||||
uniform sampler2D deferredBuffer;
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D matInfoBuffer;
|
||||
uniform samplerCube cubeMap;
|
||||
uniform samplerCube irradianceCubemap;
|
||||
uniform sampler2D BRDFTexture;
|
||||
uniform float cubeMips;
|
||||
|
||||
uniform vec4 rtParams0;
|
||||
|
||||
uniform vec3 probeWSPos;
|
||||
uniform vec3 probeLSPos;
|
||||
uniform vec4 vsFarPlane;
|
||||
|
||||
uniform float radius;
|
||||
uniform vec2 attenuation;
|
||||
|
||||
uniform mat4 worldToObj;
|
||||
uniform mat4 cameraToWorld;
|
||||
|
||||
uniform vec3 eyePosWorld;
|
||||
uniform vec3 bbMin;
|
||||
uniform vec3 bbMax;
|
||||
|
||||
uniform float useSphereMode;
|
||||
|
||||
// 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/
|
||||
vec3 boxProject(vec3 wsPosition, vec3 reflectDir, vec3 boxWSPos, vec3 boxMin, vec3 boxMax)
|
||||
{
|
||||
vec3 nrdir = reflectDir;
|
||||
vec3 offset = wsPosition;
|
||||
vec3 plane1vec = (boxMax - offset) / nrdir;
|
||||
vec3 plane2vec = (boxMin - offset) / nrdir;
|
||||
|
||||
vec3 furthestPlane = max(plane1vec, plane2vec);
|
||||
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
||||
vec3 posonbox = offset + nrdir * dist;
|
||||
|
||||
return posonbox - boxWSPos;
|
||||
}
|
||||
|
||||
vec3 iblBoxSpecular(vec3 normal, vec3 wsPos, float roughness, vec3 surfToEye,
|
||||
sampler2D brdfTexture,
|
||||
samplerCube radianceCube,
|
||||
vec3 boxPos,
|
||||
vec3 boxMin,
|
||||
vec3 boxMax)
|
||||
{
|
||||
float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0);
|
||||
|
||||
// BRDF
|
||||
vec2 brdf = textureLod(brdfTexture, vec2(roughness, ndotv),0).xy;
|
||||
|
||||
// Radiance (Specular)
|
||||
float maxmip = pow(cubeMips+1,2);
|
||||
float lod = roughness*maxmip;
|
||||
vec3 r = reflect(surfToEye, normal);
|
||||
vec3 cubeR = normalize(r);
|
||||
cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax);
|
||||
|
||||
vec3 radiance = textureLod(radianceCube, cubeR, lod).xyz * (brdf.x + brdf.y);
|
||||
|
||||
return radiance;
|
||||
}
|
||||
|
||||
float defineBoxSpaceInfluence(vec3 surfPosWS, vec3 probePos, float radius, float atten)
|
||||
{
|
||||
vec3 surfPosLS = tMul( worldToObj, vec4(surfPosWS,1.0)).xyz;
|
||||
|
||||
vec3 boxMinLS = probePos-(vec3(1,1,1)*radius);
|
||||
vec3 boxMaxLS = probePos+(vec3(1,1,1)*radius);
|
||||
|
||||
float boxOuterRange = length(boxMaxLS - boxMinLS);
|
||||
float boxInnerRange = boxOuterRange / atten;
|
||||
|
||||
vec3 localDir = vec3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
|
||||
localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
|
||||
|
||||
return max(localDir.x, max(localDir.y, localDir.z)) * -1;
|
||||
}
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
// Compute scene UV
|
||||
vec2 uvScene = getUVFromSSPos( ssPos.xyz/ssPos.w, rtParams0 );
|
||||
|
||||
//eye ray WS/LS
|
||||
vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
||||
vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
|
||||
|
||||
//unpack normal and linear depth
|
||||
vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
float blendVal = 1.0;
|
||||
if(useSphereMode>0)
|
||||
{
|
||||
vec3 L = probeWSPos - surface.P;
|
||||
blendVal = 1.0-length(L)/radius;
|
||||
clip(blendVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
float tempAttenVal = 3.5;
|
||||
blendVal = defineBoxSpaceInfluence(surface.P, probeWSPos, radius, tempAttenVal);
|
||||
clip(blendVal);
|
||||
float compression = 0.05;
|
||||
blendVal=(1.0-compression)+blendVal*compression;
|
||||
}
|
||||
//render into the bound space defined above
|
||||
vec3 surfToEye = normalize(surface.P - eyePosWorld);
|
||||
vec3 irradiance = textureLod(irradianceCubemap, surface.N,0).xyz;
|
||||
vec3 specular = iblBoxSpecular(surface.N, surface.P, surface.roughness, surfToEye, BRDFTexture, cubeMap, probeWSPos, bbMin, bbMax);
|
||||
vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
specular *= F;
|
||||
//energy conservation
|
||||
vec3 kD = vec3(1.0) - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
//final diffuse color
|
||||
vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
|
||||
OUT_col = vec4(diffuse + specular * surface.ao, blendVal);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "../../torque.hlsl"
|
||||
|
||||
// This is the shader input
|
||||
struct Vert
|
||||
{
|
||||
float4 position : POSITION;
|
||||
float2 uv0 : TEXCOORD0;
|
||||
float3 wsEyeRay : TEXCOORD1;
|
||||
};
|
||||
|
||||
// This is the shader output data.
|
||||
struct Conn
|
||||
{
|
||||
float4 position : POSITION;
|
||||
float2 uv0 : TEXCOORD0;
|
||||
float3 wsEyeRay : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Render Target Paramaters
|
||||
float4 rtParams0;
|
||||
|
||||
Conn main(Vert IN,
|
||||
uniform float4x4 modelView : register(C0))
|
||||
{
|
||||
Conn OUT;
|
||||
OUT.position = IN.position;
|
||||
OUT.uv0 = viewportCoordToRenderTarget( IN.uv0, rtParams0 );
|
||||
OUT.wsEyeRay = IN.wsEyeRay;
|
||||
return OUT;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "farFrustumQuad.glsl"
|
||||
#include "../../../gl/lighting.glsl"
|
||||
#include "../../../gl/torque.glsl"
|
||||
#line 27
|
||||
|
||||
in vec4 pos;
|
||||
in vec4 wsEyeDir;
|
||||
in vec4 ssPos;
|
||||
in vec4 vsEyeDir;
|
||||
|
||||
uniform sampler2D deferredBuffer;
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D matInfoBuffer;
|
||||
uniform samplerCube cubeMap;
|
||||
uniform samplerCube irradianceCubemap;
|
||||
uniform sampler2D BRDFTexture;
|
||||
|
||||
uniform vec4 rtParams0;
|
||||
|
||||
uniform vec4 vsFarPlane;
|
||||
uniform mat4 cameraToWorld;
|
||||
uniform vec3 eyePosWorld;
|
||||
|
||||
vec3 iblSpecular(in Surface surface, vec3 F)
|
||||
{
|
||||
const float MAX_REFLECTION_LOD = 4.0;
|
||||
vec3 prefilteredColor = textureLod(cubeMap, surface.R, surface.roughness * MAX_REFLECTION_LOD).rgb;
|
||||
vec2 envBRDF = texture(BRDFTexture, vec2(surface.NdotV, surface.roughness)).rg;
|
||||
return prefilteredColor * (F * envBRDF.x + envBRDF.y);
|
||||
}
|
||||
|
||||
out vec4 OUT_col;
|
||||
void main()
|
||||
{
|
||||
// Compute scene UV
|
||||
vec2 uvScene = getUVFromSSPos( ssPos.xyz/ssPos.w, rtParams0 );
|
||||
|
||||
//eye ray WS/LS
|
||||
vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
||||
vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
|
||||
|
||||
//unpack normal and linear depth
|
||||
vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
|
||||
vec3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
vec3 irradiance = textureLod(irradianceCubemap, surface.N,0).rgb;
|
||||
vec3 specular = iblSpecular(surface, F);
|
||||
//energy conservation
|
||||
vec3 kD = vec3(1.0) - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
//final diffuse color
|
||||
vec3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
|
||||
OUT_col = vec4(diffuse + specular * surface.ao, 0);
|
||||
}
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "farFrustumQuad.glsl"
|
||||
#include "lightingUtils.glsl"
|
||||
#include "../../shadowMap/shadowMapIO_GLSL.h"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "softShadow.glsl"
|
||||
|
|
@ -34,11 +33,6 @@ in vec4 ssPos;
|
|||
in vec4 vsEyeDir;
|
||||
in vec4 color;
|
||||
|
||||
#define IN_wsEyeDir wsEyeDir
|
||||
#define IN_ssPos ssPos
|
||||
#define IN_vsEyeDir vsEyeDir
|
||||
#define IN_color color
|
||||
|
||||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
/// The texture for cookie rendering.
|
||||
|
|
@ -49,162 +43,99 @@ uniform sampler2D cookieMap;
|
|||
uniform sampler2D deferredBuffer;
|
||||
uniform sampler2D shadowMap;
|
||||
uniform sampler2D dynamicShadowMap;
|
||||
|
||||
uniform sampler2D lightBuffer;
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D matInfoBuffer;
|
||||
|
||||
uniform vec4 rtParams0;
|
||||
|
||||
uniform float lightBrightness;
|
||||
uniform vec3 lightPosition;
|
||||
uniform vec4 lightColor;
|
||||
uniform float lightBrightness;
|
||||
|
||||
uniform float lightRange;
|
||||
uniform vec2 lightAttenuation;
|
||||
uniform float lightInvSqrRange;
|
||||
uniform vec3 lightDirection;
|
||||
uniform vec4 lightSpotParams;
|
||||
uniform vec2 lightSpotParams;
|
||||
uniform vec4 lightMapParams;
|
||||
|
||||
uniform vec4 vsFarPlane;
|
||||
uniform mat4 viewToLightProj;
|
||||
uniform mat4 dynamicViewToLightProj;
|
||||
|
||||
uniform mat4 worldToLightProj;
|
||||
uniform mat4 dynamicWorldToLightProj;
|
||||
uniform vec4 lightParams;
|
||||
uniform float shadowSoftness;
|
||||
uniform vec3 eyePosWorld;
|
||||
|
||||
uniform mat4 cameraToWorld;
|
||||
uniform mat4 worldToCamera;
|
||||
|
||||
out vec4 OUT_col;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Compute scene UV
|
||||
vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
|
||||
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||
vec2 uvScene = getUVFromSSPos(ssPos.xyz/ssPos.w, rtParams0);
|
||||
|
||||
// Emissive.
|
||||
vec4 matInfo = texture( matInfoBuffer, uvScene );
|
||||
bool emissive = getFlag( matInfo.r, 0 );
|
||||
if ( emissive )
|
||||
//unpack normal and linear depth
|
||||
vec4 normDepth = deferredUncondition(deferredBuffer, uvScene);
|
||||
|
||||
//eye ray WS/VS
|
||||
vec3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
||||
vec3 wsEyeRay = tMul(cameraToWorld, vec4(vsEyeRay, 0)).xyz;
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, colorBuffer,matInfoBuffer,
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
OUT_col = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
OUT_col = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uvScene );
|
||||
vec3 subsurface = vec3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
vec3 L = lightPosition - surface.P;
|
||||
float dist = length(L);
|
||||
vec3 lighting = vec3(0.0);
|
||||
if(dist < lightRange)
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = vec3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = vec3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
vec4 deferredSample = deferredUncondition( deferredBuffer, uvScene );
|
||||
vec3 normal = deferredSample.rgb;
|
||||
float depth = deferredSample.a;
|
||||
|
||||
// Eye ray - Eye -> Pixel
|
||||
vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN_vsEyeDir.xyz, vsFarPlane );
|
||||
vec3 viewSpacePos = eyeRay * depth;
|
||||
|
||||
// Build light vec, get length, clip pixel if needed
|
||||
vec3 lightToPxlVec = viewSpacePos - lightPosition;
|
||||
float lenLightV = length( lightToPxlVec );
|
||||
lightToPxlVec /= lenLightV;
|
||||
|
||||
//lightDirection = vec3( -lightDirection.xy, lightDirection.z ); //vec3( 0, 0, -1 );
|
||||
float cosAlpha = dot( lightDirection, lightToPxlVec );
|
||||
clip( cosAlpha - lightSpotParams.x );
|
||||
clip( lightRange - lenLightV );
|
||||
|
||||
float atten = attenuate( lightColor, lightAttenuation, lenLightV );
|
||||
atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y;
|
||||
clip( atten - 1e-6 );
|
||||
atten = saturate( atten );
|
||||
|
||||
float nDotL = dot( normal, -lightToPxlVec );
|
||||
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
|
||||
#ifdef NO_SHADOW
|
||||
float shadowed = 1.0;
|
||||
#else
|
||||
// Get the shadow texture coordinate
|
||||
vec4 pxlPosLightProj = tMul( viewToLightProj, vec4( viewSpacePos, 1 ) );
|
||||
vec4 pxlPosLightProj = tMul( worldToLightProj, vec4( surface.P, 1 ) );
|
||||
vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
|
||||
shadowCoord.y = 1.0f - shadowCoord.y;
|
||||
|
||||
// Get the dynamic shadow texture coordinate
|
||||
vec4 dynpxlPosLightProj = tMul( dynamicViewToLightProj, vec4( viewSpacePos, 1 ) );
|
||||
vec2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
|
||||
dynshadowCoord.y = 1.0f - dynshadowCoord.y;
|
||||
#ifdef NO_SHADOW
|
||||
|
||||
float shadowed = 1.0;
|
||||
|
||||
#else
|
||||
vec4 dynPxlPosLightProj = tMul( dynamicWorldToLightProj, vec4( surface.P, 1 ) );
|
||||
vec2 dynShadowCoord = ( ( dynPxlPosLightProj.xy / dynPxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
|
||||
dynShadowCoord.y = 1.0f - dynShadowCoord.y;
|
||||
|
||||
// Get a linear depth from the light source.
|
||||
//distance to light in shadow map space
|
||||
float distToLight = pxlPosLightProj.z / lightRange;
|
||||
|
||||
float static_shadowed = softShadow_filter( shadowMap,
|
||||
ssPos.xy,
|
||||
shadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
|
||||
float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
|
||||
ssPos.xy,
|
||||
dynshadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
float dynDistToLight = dynPxlPosLightProj.z / lightRange;
|
||||
float static_shadowed = softShadow_filter(shadowMap, ssPos.xy/ssPos.w, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float dynamic_shadowed = softShadow_filter(dynamicShadowMap, ssPos.xy/ssPos.w, dynShadowCoord, shadowSoftness, dynDistToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
#endif // !NO_SHADOW
|
||||
#endif
|
||||
|
||||
vec3 lightcol = lightColor.rgb;
|
||||
vec3 lightCol = lightColor.rgb;
|
||||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
// Lookup the cookie sample.
|
||||
vec4 cookie = texture( cookieMap, shadowCoord );
|
||||
|
||||
vec4 cookie = texture(cookieMap, tMul(worldToLightProj, -surfaceToLight.L));
|
||||
// Multiply the light with the cookie tex.
|
||||
lightcol *= cookie.rgb;
|
||||
|
||||
lightCol *= cookie.rgb;
|
||||
// Use a maximum channel luminance to attenuate
|
||||
// the lighting else we get specular in the dark
|
||||
// regions of the cookie texture.
|
||||
atten *= max( cookie.r, max( cookie.g, cookie.b ) );
|
||||
|
||||
lightCol *= max(cookie.r, max(cookie.g, cookie.b));
|
||||
#endif
|
||||
|
||||
// NOTE: Do not clip on fully shadowed pixels as it would
|
||||
// cause the hardware occlusion query to disable the shadow.
|
||||
|
||||
// Specular term
|
||||
float specular = AL_CalcSpecular( -lightToPxlVec,
|
||||
normal,
|
||||
normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
|
||||
|
||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
||||
vec3 lightColorOut = lightMapParams.rgb * lightcol;
|
||||
vec4 addToResult = vec4(0.0);
|
||||
|
||||
// TODO: This needs to be removed when lightmapping is disabled
|
||||
// as its extra work per-pixel on dynamic lit scenes.
|
||||
//
|
||||
// Special lightmapping pass.
|
||||
if ( lightMapParams.a < 0.0 )
|
||||
{
|
||||
// This disables shadows on the backsides of objects.
|
||||
shadowed = nDotL < 0.0f ? 1.0f : shadowed;
|
||||
|
||||
Sat_NL_Att = 1.0f;
|
||||
shadowed = mix( 1.0f, shadowed, atten );
|
||||
lightColorOut = vec3(shadowed);
|
||||
specular *= lightBrightness;
|
||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
//get Punctual light contribution
|
||||
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
|
||||
//get spot angle attenuation
|
||||
lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
|
||||
}
|
||||
|
||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
OUT_col = vec4(lighting, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,15 +25,15 @@
|
|||
#include "farFrustumQuad.glsl"
|
||||
#include "../../../gl/torque.glsl"
|
||||
#include "../../../gl/lighting.glsl"
|
||||
#include "lightingUtils.glsl"
|
||||
#include "../../shadowMap/shadowMapIO_GLSL.h"
|
||||
#include "softShadow.glsl"
|
||||
|
||||
#line 30
|
||||
in vec4 hpos;
|
||||
in vec2 uv0;
|
||||
in vec3 wsEyeRay;
|
||||
in vec3 vsEyeRay;
|
||||
|
||||
uniform sampler2D deferredBuffer;
|
||||
uniform sampler2D shadowMap;
|
||||
uniform sampler2D dynamicShadowMap;
|
||||
|
||||
|
|
@ -42,68 +42,68 @@ uniform sampler2D ssaoMask ;
|
|||
uniform vec4 rtParams3;
|
||||
#endif
|
||||
|
||||
uniform sampler2D deferredBuffer;
|
||||
uniform sampler2D lightBuffer;
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D matInfoBuffer;
|
||||
uniform float lightBrightness;
|
||||
uniform vec3 lightDirection;
|
||||
uniform vec4 lightColor;
|
||||
uniform float lightBrightness;
|
||||
uniform vec4 lightAmbient;
|
||||
|
||||
uniform float shadowSoftness;
|
||||
uniform vec3 eyePosWorld;
|
||||
uniform mat4x4 eyeMat;
|
||||
|
||||
uniform vec4 atlasXOffset;
|
||||
uniform vec4 atlasYOffset;
|
||||
uniform vec2 atlasScale;
|
||||
uniform vec4 zNearFarInvNearFar;
|
||||
uniform vec4 lightMapParams;
|
||||
uniform vec2 fadeStartLength;
|
||||
uniform vec4 farPlaneScalePSSM;
|
||||
uniform vec4 overDarkPSSM;
|
||||
uniform float shadowSoftness;
|
||||
|
||||
|
||||
uniform vec2 fadeStartLength;
|
||||
uniform vec2 atlasScale;
|
||||
|
||||
uniform mat4 eyeMat;
|
||||
uniform mat4 cameraToWorld;
|
||||
|
||||
//static shadowMap
|
||||
uniform mat4x4 worldToLightProj;
|
||||
uniform mat4 worldToLightProj;
|
||||
uniform vec4 scaleX;
|
||||
uniform vec4 scaleY;
|
||||
uniform vec4 offsetX;
|
||||
uniform vec4 offsetY;
|
||||
uniform vec4 farPlaneScalePSSM;
|
||||
|
||||
//dynamic shadowMap
|
||||
uniform mat4x4 dynamicWorldToLightProj;
|
||||
uniform mat4 dynamicWorldToLightProj;
|
||||
uniform vec4 dynamicScaleX;
|
||||
uniform vec4 dynamicScaleY;
|
||||
uniform vec4 dynamicOffsetX;
|
||||
uniform vec4 dynamicOffsetY;
|
||||
uniform vec4 dynamicFarPlaneScalePSSM;
|
||||
|
||||
vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
|
||||
vec4 AL_VectorLightShadowCast( sampler2D _sourceShadowMap,
|
||||
vec2 _texCoord,
|
||||
mat4 _worldToLightProj,
|
||||
vec4 _worldPos,
|
||||
vec4 _scaleX, vec4 _scaleY,
|
||||
vec4 _offsetX, vec4 _offsetY,
|
||||
vec3 _worldPos,
|
||||
vec4 _scaleX,
|
||||
vec4 _scaleY,
|
||||
vec4 _offsetX,
|
||||
vec4 _offsetY,
|
||||
vec4 _farPlaneScalePSSM,
|
||||
vec4 _atlasXOffset, vec4 _atlasYOffset,
|
||||
vec2 _atlasScale,
|
||||
float _shadowSoftness,
|
||||
float _dotNL ,
|
||||
vec4 _overDarkPSSM
|
||||
)
|
||||
float _dotNL)
|
||||
{
|
||||
|
||||
// Compute shadow map coordinate
|
||||
vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos);
|
||||
vec4 pxlPosLightProj = tMul(_worldToLightProj, vec4(_worldPos,1));
|
||||
vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;
|
||||
|
||||
// Distance to light, in shadowMap space
|
||||
// Distance to light, in shadowmap space
|
||||
float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
|
||||
|
||||
// Figure out which split to sample from. Basically, we compute the shadowMap sample coord
|
||||
// for all of the splits and then check if its valid.
|
||||
vec4 shadowCoordX = vec4( baseShadowCoord.x );
|
||||
vec4 shadowCoordY = vec4( baseShadowCoord.y );
|
||||
vec4 farPlaneDists = vec4( distToLight );
|
||||
vec4 shadowCoordX = baseShadowCoord.xxxx;
|
||||
vec4 shadowCoordY = baseShadowCoord.yyyy;
|
||||
vec4 farPlaneDists = vec4(distToLight);
|
||||
shadowCoordX *= _scaleX;
|
||||
shadowCoordY *= _scaleY;
|
||||
shadowCoordX += _offsetX;
|
||||
|
|
@ -132,10 +132,10 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
|
|||
else
|
||||
finalMask = vec4(0, 0, 0, 1);
|
||||
|
||||
vec3 debugColor = vec3(0);
|
||||
vec3 debugColor = vec3(0,0,0);
|
||||
|
||||
#ifdef NO_SHADOW
|
||||
debugColor = vec3(1.0);
|
||||
debugColor = vec3(1.0,1.0,1.0);
|
||||
#endif
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
|
|
@ -164,16 +164,16 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
|
|||
shadowCoord = baseShadowCoord * finalScale;
|
||||
shadowCoord += finalOffset;
|
||||
|
||||
// Convert to _texCoord space
|
||||
// Convert to texcoord space
|
||||
shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
|
||||
shadowCoord.y = 1.0f - shadowCoord.y;
|
||||
|
||||
// Move around inside of atlas
|
||||
vec2 aOffset;
|
||||
aOffset.x = dot(finalMask, _atlasXOffset);
|
||||
aOffset.y = dot(finalMask, _atlasYOffset);
|
||||
aOffset.x = dot(finalMask, atlasXOffset);
|
||||
aOffset.y = dot(finalMask, atlasYOffset);
|
||||
|
||||
shadowCoord *= _atlasScale;
|
||||
shadowCoord *= atlasScale;
|
||||
shadowCoord += aOffset;
|
||||
|
||||
// Each split has a different far plane, take this into account.
|
||||
|
|
@ -181,147 +181,77 @@ vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
|
|||
distToLight *= farPlaneScale;
|
||||
|
||||
return vec4(debugColor,
|
||||
softShadow_filter( _sourceshadowMap,
|
||||
_texCoord,
|
||||
shadowCoord,
|
||||
farPlaneScale * _shadowSoftness,
|
||||
distToLight,
|
||||
_dotNL,
|
||||
dot( finalMask, _overDarkPSSM ) ) );
|
||||
softShadow_filter( _sourceShadowMap,
|
||||
_texCoord,
|
||||
shadowCoord,
|
||||
farPlaneScale * shadowSoftness,
|
||||
distToLight,
|
||||
_dotNL,
|
||||
dot( finalMask, overDarkPSSM ) ) );
|
||||
}
|
||||
|
||||
out vec4 OUT_col;
|
||||
void main()
|
||||
{
|
||||
// Emissive.
|
||||
float4 matInfo = texture( matInfoBuffer, uv0 );
|
||||
bool emissive = getFlag( matInfo.r, 0 );
|
||||
if ( emissive )
|
||||
{
|
||||
OUT_col = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
return;
|
||||
}
|
||||
//unpack normal and linear depth
|
||||
vec4 normDepth = deferredUncondition(deferredBuffer, uv0);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, colorBuffer, matInfoBuffer,
|
||||
uv0, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uv0 );
|
||||
vec3 subsurface = vec3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = vec3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = vec3(0.337255, 0.772549, 0.262745);
|
||||
OUT_col = vec4(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
vec4 deferredSample = deferredUncondition( deferredBuffer, uv0 );
|
||||
vec3 normal = deferredSample.rgb;
|
||||
float depth = deferredSample.a;
|
||||
//create surface to light
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, -lightDirection);
|
||||
|
||||
// Use eye ray to get ws pos
|
||||
vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f);
|
||||
|
||||
// Get the light attenuation.
|
||||
float dotNL = dot(-lightDirection, normal);
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
vec3 debugColor = vec3(0);
|
||||
#endif
|
||||
//light color might be changed by PSSM_DEBUG_RENDER
|
||||
vec3 lightingColor = lightColor.rgb;
|
||||
|
||||
#ifdef NO_SHADOW
|
||||
|
||||
// Fully unshadowed.
|
||||
float shadowed = 1.0;
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
debugColor = vec3(1.0);
|
||||
#endif
|
||||
|
||||
float shadow = 1.0;
|
||||
#else
|
||||
|
||||
vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap,
|
||||
uv0.xy,
|
||||
worldToLightProj,
|
||||
worldPos,
|
||||
scaleX, scaleY,
|
||||
offsetX, offsetY,
|
||||
farPlaneScalePSSM,
|
||||
atlasXOffset, atlasYOffset,
|
||||
atlasScale,
|
||||
shadowSoftness,
|
||||
dotNL,
|
||||
overDarkPSSM);
|
||||
vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap,
|
||||
uv0.xy,
|
||||
dynamicWorldToLightProj,
|
||||
worldPos,
|
||||
dynamicScaleX, dynamicScaleY,
|
||||
dynamicOffsetX, dynamicOffsetY,
|
||||
dynamicFarPlaneScalePSSM,
|
||||
atlasXOffset, atlasYOffset,
|
||||
atlasScale,
|
||||
shadowSoftness,
|
||||
dotNL,
|
||||
overDarkPSSM);
|
||||
// Fade out the shadow at the end of the range.
|
||||
vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * surface.depth);
|
||||
float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
|
||||
|
||||
vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap, uv0.xy, worldToLightProj, surface.P, scaleX, scaleY, offsetX, offsetY,
|
||||
farPlaneScalePSSM, surfaceToLight.NdotL);
|
||||
|
||||
vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap, uv0.xy, dynamicWorldToLightProj, surface.P, dynamicScaleX,
|
||||
dynamicScaleY, dynamicOffsetX, dynamicOffsetY, dynamicFarPlaneScalePSSM, surfaceToLight.NdotL);
|
||||
|
||||
float static_shadowed = static_shadowed_colors.a;
|
||||
float dynamic_shadowed = dynamic_shadowed_colors.a;
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
|
||||
lightingColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
|
||||
#endif
|
||||
|
||||
// Fade out the shadow at the end of the range.
|
||||
vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
|
||||
float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
|
||||
|
||||
static_shadowed = mix( static_shadowed, 1.0, saturate( fadeOutAmt ) );
|
||||
dynamic_shadowed = mix( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
|
||||
static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
|
||||
dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
|
||||
|
||||
// temp for debugging. uncomment one or the other.
|
||||
//float shadowed = static_shadowed;
|
||||
//float shadowed = dynamic_shadowed;
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
float shadow = min(static_shadowed, dynamic_shadowed);
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
if ( fadeOutAmt > 1.0 )
|
||||
debugColor = vec3(1.0);
|
||||
lightingColor = 1.0;
|
||||
#endif
|
||||
|
||||
#endif // !NO_SHADOW
|
||||
|
||||
// Specular term
|
||||
float specular = AL_CalcSpecular( -lightDirection,
|
||||
normal,
|
||||
normalize(-vsEyeRay) ) * lightBrightness * shadowed;
|
||||
|
||||
float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
|
||||
vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
|
||||
vec4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-vsEyeRay), normal)) );
|
||||
|
||||
// TODO: This needs to be removed when lightmapping is disabled
|
||||
// as its extra work per-pixel on dynamic lit scenes.
|
||||
//
|
||||
// Special lightmapping pass.
|
||||
if ( lightMapParams.a < 0.0 )
|
||||
{
|
||||
// This disables shadows on the backsides of objects.
|
||||
shadowed = dotNL < 0.0f ? 1.0f : shadowed;
|
||||
|
||||
Sat_NL_Att = 1.0f;
|
||||
lightColorOut = vec3(shadowed);
|
||||
specular *= lightBrightness;
|
||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
}
|
||||
|
||||
#endif //NO_SHADOW
|
||||
// Sample the AO texture.
|
||||
#ifdef USE_SSAO_MASK
|
||||
float ao = 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams3 ) ).r;
|
||||
addToResult *= ao;
|
||||
surface.ao *= 1.0 - texture( ssaoMask, viewportCoordToRenderTarget( uv0.xy, rtParams3 ) ).r;
|
||||
#endif
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
lightColorOut = debugColor;
|
||||
#endif
|
||||
//get directional light contribution
|
||||
vec3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);
|
||||
|
||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
OUT_col = vec4(lighting, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../torque.hlsl"
|
||||
|
||||
struct ConnectData
|
||||
{
|
||||
float4 hpos : TORQUE_POSITION;
|
||||
float2 uv : TEXCOORD;
|
||||
};
|
||||
|
||||
uniform int face;
|
||||
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
|
||||
|
||||
float4 main(ConnectData IN) : TORQUE_TARGET0
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
@ -23,7 +23,6 @@
|
|||
#include "../../shaderModelAutoGen.hlsl"
|
||||
|
||||
#include "farFrustumQuad.hlsl"
|
||||
#include "lightingUtils.hlsl"
|
||||
#include "../../lighting.hlsl"
|
||||
#include "../shadowMap/shadowMapIO_HLSL.h"
|
||||
#include "softShadow.hlsl"
|
||||
|
|
@ -37,7 +36,6 @@ struct ConvexConnectP
|
|||
float4 vsEyeDir : TEXCOORD2;
|
||||
};
|
||||
|
||||
|
||||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
/// The texture for cookie rendering.
|
||||
|
|
@ -88,7 +86,9 @@ TORQUE_UNIFORM_SAMPLERCUBE(cookieMap, 3);
|
|||
// this value was found via experementation
|
||||
// NOTE: this is wrong, it only biases in one direction, not towards the uv
|
||||
// center ( 0.5 0.5 ).
|
||||
//shadowCoord.xy *= 0.997;
|
||||
float offsetVal = 0.95;
|
||||
shadowCoord.xy *= offsetVal;
|
||||
shadowCoord.xy += (1.0-offsetVal).xx / 2.0;
|
||||
|
||||
#ifndef SHADOW_PARABOLOID
|
||||
|
||||
|
|
@ -129,149 +129,83 @@ uniform float4 lightMapParams;
|
|||
uniform float4 vsFarPlane;
|
||||
uniform float4 lightParams;
|
||||
|
||||
uniform float lightRange;
|
||||
uniform float lightRange;
|
||||
uniform float lightInvSqrRange;
|
||||
uniform float shadowSoftness;
|
||||
uniform float2 lightAttenuation;
|
||||
uniform float4x4 worldToCamera;
|
||||
uniform float3x3 worldToLightProj;
|
||||
uniform float3x3 dynamicWorldToLightProj;
|
||||
|
||||
uniform float3x3 viewToLightProj;
|
||||
uniform float3x3 dynamicViewToLightProj;
|
||||
uniform float3 eyePosWorld;
|
||||
uniform float4x4 cameraToWorld;
|
||||
|
||||
float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
||||
float4 main( ConvexConnectP IN ) : SV_TARGET
|
||||
{
|
||||
// Compute scene UV
|
||||
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||
|
||||
// Emissive.
|
||||
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );
|
||||
bool emissive = getFlag( matInfo.r, 0 );
|
||||
if ( emissive )
|
||||
{
|
||||
return float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
||||
float3 subsurface = float3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
|
||||
float3 normal = deferredSample.rgb;
|
||||
float depth = deferredSample.a;
|
||||
|
||||
// Eye ray - Eye -> Pixel
|
||||
float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||
float3 viewSpacePos = eyeRay * depth;
|
||||
float2 uvScene = getUVFromSSPos(ssPos, rtParams0);
|
||||
|
||||
//unpack normal and linear depth
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
|
||||
|
||||
// Build light vec, get length, clip pixel if needed
|
||||
float3 lightVec = lightPosition - viewSpacePos;
|
||||
float lenLightV = length( lightVec );
|
||||
clip( lightRange - lenLightV );
|
||||
//eye ray WS/VS
|
||||
float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||
float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
|
||||
|
||||
// Get the attenuated falloff.
|
||||
float atten = attenuate( lightColor, lightAttenuation, lenLightV );
|
||||
clip( atten - 1e-6 );
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
|
||||
// Normalize lightVec
|
||||
lightVec /= lenLightV;
|
||||
|
||||
// If we can do dynamic branching then avoid wasting
|
||||
// fillrate on pixels that are backfacing to the light.
|
||||
float nDotL = dot( lightVec, normal );
|
||||
//DB_CLIP( nDotL < 0 );
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
return 0.0.xxxx;
|
||||
}
|
||||
|
||||
float3 L = lightPosition - surface.P;
|
||||
float dist = length(L);
|
||||
float3 lighting = 0.0.xxx;
|
||||
[branch]
|
||||
if(dist < lightRange)
|
||||
{
|
||||
float distToLight = dist / lightRange;
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
|
||||
|
||||
#ifdef NO_SHADOW
|
||||
|
||||
float shadowed = 1.0;
|
||||
|
||||
#else
|
||||
|
||||
// Get a linear depth from the light source.
|
||||
float distToLight = lenLightV / lightRange;
|
||||
#ifdef SHADOW_CUBE
|
||||
|
||||
#ifdef SHADOW_CUBE
|
||||
|
||||
// TODO: We need to fix shadow cube to handle soft shadows!
|
||||
float occ = TORQUE_TEXCUBE( shadowMap, mul( viewToLightProj, -lightVec ) ).r;
|
||||
float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
|
||||
|
||||
#else
|
||||
|
||||
// Static
|
||||
float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
|
||||
float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
||||
ssPos.xy,
|
||||
shadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
|
||||
// Dynamic
|
||||
float2 dynamicShadowCoord = decodeShadowCoord( mul( dynamicViewToLightProj, -lightVec ) ).xy;
|
||||
float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
||||
ssPos.xy,
|
||||
dynamicShadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
|
||||
#endif
|
||||
// TODO: We need to fix shadow cube to handle soft shadows!
|
||||
float occ = TORQUE_TEXCUBE( shadowMap, mul( worldToLightProj, -surfaceToLight.L ) ).r;
|
||||
float shadowed = saturate( exp( lightParams.y * ( occ - distToLight ) ) );
|
||||
|
||||
#else
|
||||
float2 shadowCoord = decodeShadowCoord( mul( worldToLightProj, -surfaceToLight.L ) ).xy;
|
||||
float2 dynShadowCoord = decodeShadowCoord( mul( dynamicWorldToLightProj, -surfaceToLight.L ) ).xy;
|
||||
float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), ssPos.xy, dynShadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
#endif
|
||||
|
||||
#endif // !NO_SHADOW
|
||||
|
||||
float3 lightcol = lightColor.rgb;
|
||||
float3 lightCol = lightColor.rgb;
|
||||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
// Lookup the cookie sample.
|
||||
float4 cookie = TORQUE_TEXCUBE( cookieMap, mul( viewToLightProj, -lightVec ) );
|
||||
|
||||
float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(worldToLightProj, -surfaceToLight.L));
|
||||
// Multiply the light with the cookie tex.
|
||||
lightcol *= cookie.rgb;
|
||||
|
||||
lightCol *= cookie.rgb;
|
||||
// Use a maximum channel luminance to attenuate
|
||||
// the lighting else we get specular in the dark
|
||||
// regions of the cookie texture.
|
||||
atten *= max( cookie.r, max( cookie.g, cookie.b ) );
|
||||
|
||||
lightCol *= max(cookie.r, max(cookie.g, cookie.b));
|
||||
#endif
|
||||
|
||||
// NOTE: Do not clip on fully shadowed pixels as it would
|
||||
// cause the hardware occlusion query to disable the shadow.
|
||||
|
||||
// Specular term
|
||||
float specular = AL_CalcSpecular( lightVec,
|
||||
normal,
|
||||
normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
|
||||
|
||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
||||
float3 lightColorOut = lightMapParams.rgb * lightcol;
|
||||
float4 addToResult = 0.0;
|
||||
|
||||
// TODO: This needs to be removed when lightmapping is disabled
|
||||
// as its extra work per-pixel on dynamic lit scenes.
|
||||
//
|
||||
// Special lightmapping pass.
|
||||
if ( lightMapParams.a < 0.0 )
|
||||
{
|
||||
// This disables shadows on the backsides of objects.
|
||||
shadowed = nDotL < 0.0f ? 1.0f : shadowed;
|
||||
|
||||
Sat_NL_Att = 1.0f;
|
||||
shadowed = lerp( 1.0f, shadowed, atten );
|
||||
lightColorOut = shadowed;
|
||||
specular *= lightBrightness;
|
||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
//get punctual light contribution
|
||||
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
|
||||
}
|
||||
|
||||
return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
|
||||
return float4(lighting, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "../../torque.hlsl"
|
||||
|
||||
struct ConnectData
|
||||
{
|
||||
float4 hpos : SV_Position;
|
||||
float2 uv : TEXCOORD;
|
||||
};
|
||||
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(environmentMap, 0);
|
||||
|
||||
uniform float roughness;
|
||||
uniform int face;
|
||||
uniform int mipSize;
|
||||
uniform int resolution;
|
||||
float RadicalInverse_VdC(uint bits)
|
||||
{
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
float2 Hammersley(uint i, uint N)
|
||||
{
|
||||
return float2(float(i) / float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
float DistributionGGX(float3 N, float3 H, float roughness)
|
||||
{
|
||||
float a = roughness * roughness;
|
||||
float a2 = a * a;
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float NdotH2 = NdotH * NdotH;
|
||||
|
||||
float nom = a2;
|
||||
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||
denom = M_PI_F * denom * denom;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float3 ImportanceSampleGGX(float2 Xi, float3 N)
|
||||
{
|
||||
float a = roughness * roughness;
|
||||
|
||||
float phi = 2.0 * M_PI_F * Xi.x;
|
||||
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
|
||||
// from spherical coordinates to cartesian coordinates
|
||||
float3 H;
|
||||
H.x = cos(phi) * sinTheta;
|
||||
H.y = sin(phi) * sinTheta;
|
||||
H.z = cosTheta;
|
||||
|
||||
// from tangent-space vector to world-space sample vector
|
||||
float3 up = abs(N.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0);
|
||||
float3 tangent = normalize(cross(up, N));
|
||||
float3 bitangent = cross(N, tangent);
|
||||
|
||||
float3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;
|
||||
return normalize(sampleVec);
|
||||
}
|
||||
|
||||
float4 prefilterEnvMap(float3 R)
|
||||
{
|
||||
int sampleCount = resolution*2;
|
||||
float3 N = R;
|
||||
float3 V = R;
|
||||
float totalWeight = 0.0;
|
||||
float4 prefilteredColor = float4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (int i = 0; i < sampleCount; ++i)
|
||||
{
|
||||
float2 Xi = Hammersley(i, sampleCount);
|
||||
float3 H = ImportanceSampleGGX(Xi, N);
|
||||
float3 L = normalize(2.0 * dot(V, H) * H - V);
|
||||
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
if (NdotL > 0.0)
|
||||
{
|
||||
// sample from the environment's mip level based on roughness/pdf
|
||||
float D = DistributionGGX(N, H, roughness);
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
float HdotV = max(dot(H, V), 0.0);
|
||||
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
|
||||
|
||||
float saTexel = 4.0 * M_PI_F / (6.0 * sampleCount * sampleCount);
|
||||
float saSample = 1.0 / (float(sampleCount) * pdf + 0.0001);
|
||||
|
||||
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
|
||||
|
||||
prefilteredColor += TORQUE_TEXCUBELOD(environmentMap, float4(L, mipLevel)) * NdotL;
|
||||
|
||||
totalWeight += NdotL;
|
||||
}
|
||||
}
|
||||
|
||||
return (prefilteredColor / totalWeight);
|
||||
}
|
||||
|
||||
float4 main(ConnectData IN) : TORQUE_TARGET0
|
||||
{
|
||||
float3 N = getCubeDir(face, IN.uv);
|
||||
return prefilterEnvMap(N);
|
||||
}
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
#include "../../postFx/postFx.hlsl"
|
||||
#include "../../shaderModel.hlsl"
|
||||
#include "../../shaderModelAutoGen.hlsl"
|
||||
#include "../../lighting.hlsl"
|
||||
|
||||
TORQUE_UNIFORM_SAMPLER2D(deferredBuffer, 0);
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 1);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 2);
|
||||
TORQUE_UNIFORM_SAMPLER2D(BRDFTexture, 3);
|
||||
|
||||
uniform float4 rtParams0;
|
||||
uniform float4 vsFarPlane;
|
||||
uniform float4x4 cameraToWorld;
|
||||
uniform float3 eyePosWorld;
|
||||
|
||||
//cubemap arrays require all the same size. so shared mips# value
|
||||
uniform float cubeMips;
|
||||
|
||||
uniform float numProbes;
|
||||
TORQUE_UNIFORM_SAMPLERCUBEARRAY(specularCubemapAR, 4);
|
||||
TORQUE_UNIFORM_SAMPLERCUBEARRAY(irradianceCubemapAR, 5);
|
||||
|
||||
uniform float4 inProbePosArray[MAX_PROBES];
|
||||
uniform float4 inRefPosArray[MAX_PROBES];
|
||||
uniform float4x4 worldToObjArray[MAX_PROBES];
|
||||
uniform float4 bbMinArray[MAX_PROBES];
|
||||
uniform float4 bbMaxArray[MAX_PROBES];
|
||||
uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
||||
|
||||
#if DEBUGVIZ_CONTRIB
|
||||
uniform float4 probeContribColors[MAX_PROBES];
|
||||
#endif
|
||||
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(skylightSpecularMap, 6);
|
||||
TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7);
|
||||
uniform float hasSkylight;
|
||||
|
||||
float4 main(PFXVertToPix IN) : SV_TARGET
|
||||
{
|
||||
//unpack normal and linear depth
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0.xy);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface(normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
IN.uv0.xy, eyePosWorld, IN.wsEyeRay, cameraToWorld);
|
||||
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
float alpha = 1;
|
||||
|
||||
int i = 0;
|
||||
float blendFactor[MAX_PROBES];
|
||||
float blendSum = 0;
|
||||
float blendFacSum = 0;
|
||||
float invBlendSum = 0;
|
||||
float probehits = 0;
|
||||
//Set up our struct data
|
||||
float contribution[MAX_PROBES];
|
||||
if (alpha > 0)
|
||||
{
|
||||
//Process prooooobes
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
contribution[i] = 0;
|
||||
|
||||
if (probeConfigData[i].r == 0) //box
|
||||
{
|
||||
contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
|
||||
if (contribution[i]>0.0)
|
||||
probehits++;
|
||||
}
|
||||
else if (probeConfigData[i].r == 1) //sphere
|
||||
{
|
||||
contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
|
||||
if (contribution[i]>0.0)
|
||||
probehits++;
|
||||
}
|
||||
|
||||
contribution[i] = max(contribution[i],0);
|
||||
|
||||
blendSum += contribution[i];
|
||||
invBlendSum += (1.0f - contribution[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.
|
||||
|
||||
if (probehits>1.0)
|
||||
{
|
||||
for (i = 0; i < numProbes; i++)
|
||||
{
|
||||
blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
|
||||
blendFactor[i] *= ((contribution[i]) / invBlendSum);
|
||||
blendFactor[i] = saturate(blendFactor[i]);
|
||||
blendFacSum += blendFactor[i];
|
||||
}
|
||||
|
||||
// Normalize blendVal
|
||||
#if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior
|
||||
if (blendFacSum == 0.0f) // Possible with custom weight
|
||||
{
|
||||
blendFacSum = 1.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
float invBlendSumWeighted = 1.0f / blendFacSum;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
blendFactor[i] *= invBlendSumWeighted;
|
||||
contribution[i] *= blendFactor[i];
|
||||
alpha -= contribution[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
alpha -= blendSum;
|
||||
|
||||
#if DEBUGVIZ_ATTENUATION == 1
|
||||
float contribAlpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
contribAlpha -= contribution[i];
|
||||
}
|
||||
|
||||
return float4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1);
|
||||
#endif
|
||||
|
||||
#if DEBUGVIZ_CONTRIB == 1
|
||||
float3 finalContribColor = float3(0, 0, 0);
|
||||
float contribAlpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
finalContribColor += contribution[i] *probeContribColors[i].rgb;
|
||||
contribAlpha -= contribution[i];
|
||||
}
|
||||
|
||||
//Skylight coloration for anything not covered by probes above
|
||||
finalContribColor += float3(0.3, 0.3, 0.3) * contribAlpha;
|
||||
|
||||
return float4(finalContribColor, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
float3 irradiance = float3(0, 0, 0);
|
||||
float3 specular = float3(0, 0, 0);
|
||||
|
||||
// Radiance (Specular)
|
||||
#if DEBUGVIZ_SPECCUBEMAP == 0
|
||||
float lod = surface.roughness*cubeMips;
|
||||
#elif DEBUGVIZ_SPECCUBEMAP == 1
|
||||
float lod = 0;
|
||||
#endif
|
||||
|
||||
alpha = 1;
|
||||
for (i = 0; i < numProbes; ++i)
|
||||
{
|
||||
float contrib = contribution[i];
|
||||
if (contrib != 0)
|
||||
{
|
||||
int cubemapIdx = probeConfigData[i].a;
|
||||
float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
|
||||
|
||||
irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
|
||||
specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
|
||||
alpha -= contrib;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSkylight && alpha > 0.001)
|
||||
{
|
||||
irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz * alpha;
|
||||
specular += TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz * alpha;
|
||||
}
|
||||
|
||||
#if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
|
||||
return float4(specular, 1);
|
||||
#elif DEBUGVIZ_DIFFCUBEMAP == 1
|
||||
return float4(irradiance, 1);
|
||||
#endif
|
||||
|
||||
float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
|
||||
|
||||
//energy conservation
|
||||
float3 kD = 1.0.xxx - F;
|
||||
kD *= 1.0 - surface.metalness;
|
||||
|
||||
//apply brdf
|
||||
//Do it once to save on texture samples
|
||||
float2 brdf = TORQUE_TEX2DLOD(BRDFTexture, float4(surface.roughness, 1.0-surface.NdotV, 0.0, 0.0)).xy;
|
||||
specular *= brdf.x * F + brdf.y;
|
||||
|
||||
//final diffuse color
|
||||
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
||||
float4 finalColor = float4(diffuse + specular * surface.ao, 1.0);
|
||||
|
||||
//finalColor.rgb += abs(surface.N);
|
||||
return finalColor;
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@
|
|||
#include "../../shaderModelAutoGen.hlsl"
|
||||
|
||||
#include "farFrustumQuad.hlsl"
|
||||
#include "lightingUtils.hlsl"
|
||||
#include "../../lighting.hlsl"
|
||||
#include "../shadowMap/shadowMapIO_HLSL.h"
|
||||
#include "softShadow.hlsl"
|
||||
|
|
@ -48,10 +47,8 @@ TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap,2);
|
|||
TORQUE_UNIFORM_SAMPLER2D(cookieMap, 3);
|
||||
|
||||
#endif
|
||||
|
||||
TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5);
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7);
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 5);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 6);
|
||||
|
||||
uniform float4 rtParams0;
|
||||
|
||||
|
|
@ -60,150 +57,90 @@ uniform float3 lightPosition;
|
|||
|
||||
uniform float4 lightColor;
|
||||
|
||||
uniform float lightRange;
|
||||
uniform float lightRange;
|
||||
uniform float lightInvSqrRange;
|
||||
uniform float3 lightDirection;
|
||||
|
||||
uniform float4 lightSpotParams;
|
||||
uniform float2 lightSpotParams;
|
||||
uniform float4 lightMapParams;
|
||||
uniform float4 vsFarPlane;
|
||||
uniform float4x4 viewToLightProj;
|
||||
uniform float4x4 worldToLightProj;
|
||||
uniform float4x4 dynamicWorldToLightProj;
|
||||
uniform float4 lightParams;
|
||||
uniform float4x4 dynamicViewToLightProj;
|
||||
|
||||
uniform float2 lightAttenuation;
|
||||
uniform float shadowSoftness;
|
||||
uniform float3 eyePosWorld;
|
||||
|
||||
float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
||||
uniform float4x4 cameraToWorld;
|
||||
uniform float4x4 worldToCamera;
|
||||
|
||||
float4 main( ConvexConnectP IN ) : SV_TARGET
|
||||
{
|
||||
// Compute scene UV
|
||||
float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
|
||||
float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
||||
|
||||
// Emissive.
|
||||
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, uvScene );
|
||||
bool emissive = getFlag( matInfo.r, 0 );
|
||||
if ( emissive )
|
||||
{
|
||||
return float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
float2 uvScene = getUVFromSSPos(ssPos, rtParams0);
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
||||
float3 subsurface = float3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, uvScene );
|
||||
float3 normal = deferredSample.rgb;
|
||||
float depth = deferredSample.a;
|
||||
|
||||
// Eye ray - Eye -> Pixel
|
||||
float3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||
float3 viewSpacePos = eyeRay * depth;
|
||||
//unpack normal and linear depth
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, uvScene);
|
||||
|
||||
// Build light vec, get length, clip pixel if needed
|
||||
float3 lightToPxlVec = viewSpacePos - lightPosition;
|
||||
float lenLightV = length( lightToPxlVec );
|
||||
lightToPxlVec /= lenLightV;
|
||||
//eye ray WS/VS
|
||||
float3 vsEyeRay = getDistanceVectorToPlane( -vsFarPlane.w, IN.vsEyeDir.xyz, vsFarPlane );
|
||||
float3 wsEyeRay = mul(cameraToWorld, float4(vsEyeRay, 0)).xyz;
|
||||
|
||||
//lightDirection = float3( -lightDirection.xy, lightDirection.z ); //float3( 0, 0, -1 );
|
||||
float cosAlpha = dot( lightDirection, lightToPxlVec );
|
||||
clip( cosAlpha - lightSpotParams.x );
|
||||
clip( lightRange - lenLightV );
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
uvScene, eyePosWorld, wsEyeRay, cameraToWorld);
|
||||
|
||||
float atten = attenuate( lightColor, lightAttenuation, lenLightV );
|
||||
atten *= ( cosAlpha - lightSpotParams.x ) / lightSpotParams.y;
|
||||
clip( atten - 1e-6 );
|
||||
atten = saturate( atten );
|
||||
|
||||
float nDotL = dot( normal, -lightToPxlVec );
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
return 0.0.xxxx;
|
||||
}
|
||||
|
||||
// Get the shadow texture coordinate
|
||||
float4 pxlPosLightProj = mul( viewToLightProj, float4( viewSpacePos, 1 ) );
|
||||
float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
|
||||
shadowCoord.y = 1.0f - shadowCoord.y;
|
||||
float3 L = lightPosition - surface.P;
|
||||
float dist = length(L);
|
||||
float3 lighting = 0.0.xxx;
|
||||
[branch]
|
||||
if(dist < lightRange)
|
||||
{
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, L);
|
||||
#ifdef NO_SHADOW
|
||||
float shadowed = 1.0;
|
||||
#else
|
||||
// Get the shadow texture coordinate
|
||||
float4 pxlPosLightProj = mul( worldToLightProj, float4( surface.P, 1 ) );
|
||||
float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
|
||||
shadowCoord.y = 1.0f - shadowCoord.y;
|
||||
|
||||
// Get the dynamic shadow texture coordinate
|
||||
float4 dynpxlPosLightProj = mul( dynamicViewToLightProj, float4( viewSpacePos, 1 ) );
|
||||
float2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
|
||||
dynshadowCoord.y = 1.0f - dynshadowCoord.y;
|
||||
|
||||
#ifdef NO_SHADOW
|
||||
|
||||
float shadowed = 1.0;
|
||||
|
||||
#else
|
||||
float4 dynPxlPosLightProj = mul( dynamicWorldToLightProj, float4( surface.P, 1 ) );
|
||||
float2 dynShadowCoord = ( ( dynPxlPosLightProj.xy / dynPxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
|
||||
dynShadowCoord.y = 1.0f - dynShadowCoord.y;
|
||||
|
||||
// Get a linear depth from the light source.
|
||||
float distToLight = pxlPosLightProj.z / lightRange;
|
||||
//distance to light in shadow map space
|
||||
float distToLight = pxlPosLightProj.z / lightRange;
|
||||
float dynDistToLight = dynPxlPosLightProj.z / lightRange;
|
||||
float static_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(shadowMap), ssPos.xy, shadowCoord, shadowSoftness, distToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float dynamic_shadowed = softShadow_filter(TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), ssPos.xy, dynShadowCoord, shadowSoftness, dynDistToLight, surfaceToLight.NdotL, lightParams.y);
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
#endif
|
||||
|
||||
float static_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
||||
ssPos.xy,
|
||||
shadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
|
||||
float dynamic_shadowed = softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
||||
ssPos.xy,
|
||||
dynshadowCoord,
|
||||
shadowSoftness,
|
||||
distToLight,
|
||||
nDotL,
|
||||
lightParams.y );
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
#endif // !NO_SHADOW
|
||||
|
||||
float3 lightcol = lightColor.rgb;
|
||||
float3 lightCol = lightColor.rgb;
|
||||
#ifdef USE_COOKIE_TEX
|
||||
|
||||
// Lookup the cookie sample.
|
||||
float4 cookie = TORQUE_TEX2D( cookieMap, shadowCoord );
|
||||
|
||||
float4 cookie = TORQUE_TEXCUBE(cookieMap, mul(worldToLightProj, -surfaceToLight.L));
|
||||
// Multiply the light with the cookie tex.
|
||||
lightcol *= cookie.rgb;
|
||||
|
||||
lightCol *= cookie.rgb;
|
||||
// Use a maximum channel luminance to attenuate
|
||||
// the lighting else we get specular in the dark
|
||||
// regions of the cookie texture.
|
||||
atten *= max( cookie.r, max( cookie.g, cookie.b ) );
|
||||
|
||||
lightCol *= max(cookie.r, max(cookie.g, cookie.b));
|
||||
#endif
|
||||
|
||||
// NOTE: Do not clip on fully shadowed pixels as it would
|
||||
// cause the hardware occlusion query to disable the shadow.
|
||||
|
||||
// Specular term
|
||||
float specular = AL_CalcSpecular( -lightToPxlVec,
|
||||
normal,
|
||||
normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
|
||||
|
||||
float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
|
||||
float3 lightColorOut = lightMapParams.rgb * lightcol;
|
||||
float4 addToResult = 0.0;
|
||||
|
||||
// TODO: This needs to be removed when lightmapping is disabled
|
||||
// as its extra work per-pixel on dynamic lit scenes.
|
||||
//
|
||||
// Special lightmapping pass.
|
||||
if ( lightMapParams.a < 0.0 )
|
||||
{
|
||||
// This disables shadows on the backsides of objects.
|
||||
shadowed = nDotL < 0.0f ? 1.0f : shadowed;
|
||||
|
||||
Sat_NL_Att = 1.0f;
|
||||
shadowed = lerp( 1.0f, shadowed, atten );
|
||||
lightColorOut = shadowed;
|
||||
specular *= lightBrightness;
|
||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
//get Punctual light contribution
|
||||
lighting = getPunctualLight(surface, surfaceToLight, lightCol, lightBrightness, lightInvSqrRange, shadowed);
|
||||
//get spot angle attenuation
|
||||
lighting *= getSpotAngleAtt(-surfaceToLight.L, lightDirection, lightSpotParams );
|
||||
}
|
||||
|
||||
return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
|
||||
return float4(lighting, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include "farFrustumQuad.hlsl"
|
||||
#include "../../torque.hlsl"
|
||||
#include "../../lighting.hlsl"
|
||||
#include "lightingUtils.hlsl"
|
||||
#include "../shadowMap/shadowMapIO_HLSL.h"
|
||||
#include "softShadow.hlsl"
|
||||
|
||||
|
|
@ -38,8 +37,7 @@ TORQUE_UNIFORM_SAMPLER2D(dynamicShadowMap, 2);
|
|||
TORQUE_UNIFORM_SAMPLER2D(ssaoMask, 3);
|
||||
uniform float4 rtParams3;
|
||||
#endif
|
||||
//register 4?
|
||||
TORQUE_UNIFORM_SAMPLER2D(lightBuffer, 5);
|
||||
|
||||
TORQUE_UNIFORM_SAMPLER2D(colorBuffer, 6);
|
||||
TORQUE_UNIFORM_SAMPLER2D(matInfoBuffer, 7);
|
||||
|
||||
|
|
@ -63,6 +61,7 @@ uniform float2 fadeStartLength;
|
|||
uniform float2 atlasScale;
|
||||
|
||||
uniform float4x4 eyeMat;
|
||||
uniform float4x4 cameraToWorld;
|
||||
|
||||
// Static Shadows
|
||||
uniform float4x4 worldToLightProj;
|
||||
|
|
@ -81,21 +80,16 @@ uniform float4 dynamicFarPlaneScalePSSM;
|
|||
float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
|
||||
float2 texCoord,
|
||||
float4x4 worldToLightProj,
|
||||
float4 worldPos,
|
||||
float3 worldPos,
|
||||
float4 scaleX,
|
||||
float4 scaleY,
|
||||
float4 offsetX,
|
||||
float4 offsetY,
|
||||
float4 farPlaneScalePSSM,
|
||||
float4 atlasXOffset,
|
||||
float4 atlasYOffset,
|
||||
float2 atlasScale,
|
||||
float shadowSoftness,
|
||||
float dotNL ,
|
||||
float4 overDarkPSSM)
|
||||
float dotNL)
|
||||
{
|
||||
// Compute shadow map coordinate
|
||||
float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
|
||||
float4 pxlPosLightProj = mul(worldToLightProj, float4(worldPos,1));
|
||||
float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;
|
||||
|
||||
// Distance to light, in shadowmap space
|
||||
|
|
@ -139,7 +133,7 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
|
|||
#ifdef NO_SHADOW
|
||||
debugColor = float3(1.0,1.0,1.0);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
if ( finalMask.x > 0 )
|
||||
debugColor += float3( 1, 0, 0 );
|
||||
|
|
@ -182,147 +176,71 @@ float4 AL_VectorLightShadowCast( TORQUE_SAMPLER2D(sourceShadowMap),
|
|||
float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
|
||||
distToLight *= farPlaneScale;
|
||||
|
||||
return float4(debugColor,
|
||||
softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap),
|
||||
texCoord,
|
||||
shadowCoord,
|
||||
farPlaneScale * shadowSoftness,
|
||||
distToLight,
|
||||
dotNL,
|
||||
dot( finalMask, overDarkPSSM ) ) );
|
||||
return float4(debugColor, softShadow_filter( TORQUE_SAMPLER2D_MAKEARG(sourceShadowMap), texCoord, shadowCoord, farPlaneScale * shadowSoftness,
|
||||
distToLight, dotNL, dot( finalMask, overDarkPSSM ) ) );
|
||||
};
|
||||
|
||||
float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
|
||||
|
||||
float4 main(FarFrustumQuadConnectP IN) : SV_TARGET
|
||||
{
|
||||
// Emissive.
|
||||
float4 matInfo = TORQUE_TEX2D( matInfoBuffer, IN.uv0 );
|
||||
bool emissive = getFlag( matInfo.r, 0 );
|
||||
if ( emissive )
|
||||
{
|
||||
return float4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
|
||||
float3 subsurface = float3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||
//unpack normal and linear depth
|
||||
float4 normDepth = TORQUE_DEFERRED_UNCONDITION(deferredBuffer, IN.uv0);
|
||||
|
||||
//create surface
|
||||
Surface surface = createSurface( normDepth, TORQUE_SAMPLER2D_MAKEARG(colorBuffer),TORQUE_SAMPLER2D_MAKEARG(matInfoBuffer),
|
||||
IN.uv0, eyePosWorld, IN.wsEyeRay, cameraToWorld);
|
||||
|
||||
//early out if emissive
|
||||
if (getFlag(surface.matFlag, 0))
|
||||
{
|
||||
return 0.0.xxxx;
|
||||
}
|
||||
// Sample/unpack the normal/z data
|
||||
float4 deferredSample = TORQUE_DEFERRED_UNCONDITION( deferredBuffer, IN.uv0 );
|
||||
float3 normal = deferredSample.rgb;
|
||||
float depth = deferredSample.a;
|
||||
|
||||
// Use eye ray to get ws pos
|
||||
float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f);
|
||||
|
||||
// Get the light attenuation.
|
||||
float dotNL = dot(-lightDirection, normal);
|
||||
//create surface to light
|
||||
SurfaceToLight surfaceToLight = createSurfaceToLight(surface, -lightDirection);
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
float3 debugColor = float3(0,0,0);
|
||||
#endif
|
||||
//light color might be changed by PSSM_DEBUG_RENDER
|
||||
float3 lightingColor = lightColor.rgb;
|
||||
|
||||
#ifdef NO_SHADOW
|
||||
|
||||
// Fully unshadowed.
|
||||
float shadowed = 1.0;
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
debugColor = float3(1.0,1.0,1.0);
|
||||
#endif
|
||||
|
||||
float shadow = 1.0;
|
||||
#else
|
||||
|
||||
float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap),
|
||||
IN.uv0.xy,
|
||||
worldToLightProj,
|
||||
worldPos,
|
||||
scaleX, scaleY,
|
||||
offsetX, offsetY,
|
||||
farPlaneScalePSSM,
|
||||
atlasXOffset, atlasYOffset,
|
||||
atlasScale,
|
||||
shadowSoftness,
|
||||
dotNL,
|
||||
overDarkPSSM);
|
||||
float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap),
|
||||
IN.uv0.xy,
|
||||
dynamicWorldToLightProj,
|
||||
worldPos,
|
||||
dynamicScaleX, dynamicScaleY,
|
||||
dynamicOffsetX, dynamicOffsetY,
|
||||
dynamicFarPlaneScalePSSM,
|
||||
atlasXOffset, atlasYOffset,
|
||||
atlasScale,
|
||||
shadowSoftness,
|
||||
dotNL,
|
||||
overDarkPSSM);
|
||||
|
||||
|
||||
// Fade out the shadow at the end of the range.
|
||||
float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * surface.depth);
|
||||
float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
|
||||
|
||||
float4 static_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(shadowMap), IN.uv0.xy, worldToLightProj, surface.P, scaleX, scaleY, offsetX, offsetY,
|
||||
farPlaneScalePSSM, surfaceToLight.NdotL);
|
||||
|
||||
float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( TORQUE_SAMPLER2D_MAKEARG(dynamicShadowMap), IN.uv0.xy, dynamicWorldToLightProj, surface.P, dynamicScaleX,
|
||||
dynamicScaleY, dynamicOffsetX, dynamicOffsetY, dynamicFarPlaneScalePSSM, surfaceToLight.NdotL);
|
||||
|
||||
float static_shadowed = static_shadowed_colors.a;
|
||||
float dynamic_shadowed = dynamic_shadowed_colors.a;
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
|
||||
lightingColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
|
||||
#endif
|
||||
|
||||
// Fade out the shadow at the end of the range.
|
||||
float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
|
||||
float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
|
||||
|
||||
static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
|
||||
dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
|
||||
|
||||
// temp for debugging. uncomment one or the other.
|
||||
//float shadowed = static_shadowed;
|
||||
//float shadowed = dynamic_shadowed;
|
||||
float shadowed = min(static_shadowed, dynamic_shadowed);
|
||||
float shadow = min(static_shadowed, dynamic_shadowed);
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
if ( fadeOutAmt > 1.0 )
|
||||
debugColor = 1.0;
|
||||
lightingColor = 1.0;
|
||||
#endif
|
||||
|
||||
#endif // !NO_SHADOW
|
||||
|
||||
// Specular term
|
||||
float specular = AL_CalcSpecular( -lightDirection,
|
||||
normal,
|
||||
normalize(-IN.vsEyeRay) ) * lightBrightness * shadowed;
|
||||
|
||||
float Sat_NL_Att = saturate( dotNL * shadowed ) * lightBrightness;
|
||||
float3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
|
||||
|
||||
float4 addToResult = (lightAmbient * (1 - ambientCameraFactor)) + ( lightAmbient * ambientCameraFactor * saturate(dot(normalize(-IN.vsEyeRay), normal)) );
|
||||
|
||||
// TODO: This needs to be removed when lightmapping is disabled
|
||||
// as its extra work per-pixel on dynamic lit scenes.
|
||||
//
|
||||
// Special lightmapping pass.
|
||||
if ( lightMapParams.a < 0.0 )
|
||||
{
|
||||
// This disables shadows on the backsides of objects.
|
||||
shadowed = dotNL < 0.0f ? 1.0f : shadowed;
|
||||
|
||||
Sat_NL_Att = 1.0f;
|
||||
lightColorOut = shadowed;
|
||||
specular *= lightBrightness;
|
||||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
}
|
||||
|
||||
// Sample the AO texture.
|
||||
#endif //NO_SHADOW
|
||||
// Sample the AO texture.
|
||||
#ifdef USE_SSAO_MASK
|
||||
float ao = 1.0 - TORQUE_TEX2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r;
|
||||
addToResult *= ao;
|
||||
surface.ao *= 1.0 - TORQUE_TEX2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r;
|
||||
#endif
|
||||
|
||||
//get directional light contribution
|
||||
float3 lighting = getDirectionalLight(surface, surfaceToLight, lightingColor.rgb, lightBrightness, shadow);
|
||||
|
||||
#ifdef PSSM_DEBUG_RENDER
|
||||
lightColorOut = debugColor;
|
||||
#endif
|
||||
|
||||
return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
return float4(lighting, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,16 +24,16 @@
|
|||
|
||||
#define pkDepthBitShft 65536.0
|
||||
#define pkDepthChanMax 256.0
|
||||
#define bias -0.5/255.0
|
||||
#define coeff 0.9999991
|
||||
//#define coeff 1.0
|
||||
#define gbias -0.5/255.0
|
||||
#define gcoeff 0.9999991
|
||||
//#define gcoeff 1.0
|
||||
|
||||
vec4 encodeShadowMap( float depth )
|
||||
{
|
||||
#if defined(SM_Fmt_R8G8B8A8)
|
||||
return frac( vec4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + vec4(bias);
|
||||
return frac( vec4(1.0, 255.0, 65025.0, 160581375.0) * depth ) + vec4(gbias);
|
||||
|
||||
//float4 packedValue = frac((depth / coeff) * float4(16777216.0, 65536.0, 256.0, 1.0));
|
||||
//float4 packedValue = frac((depth / gcoeff) * float4(16777216.0, 65536.0, 256.0, 1.0));
|
||||
//return (packedValue - packedValue.xxyz * float4(0, 1.0 / 256, 1.0 / 256, 1.0 / 256));
|
||||
#else
|
||||
return vec4(depth);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ uniform float3 fogData;
|
|||
uniform float4 rtParams0;
|
||||
|
||||
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||
{
|
||||
//float2 deferredCoord = ( IN.uv0.xy * rtParams0.zw ) + rtParams0.xy;
|
||||
{
|
||||
float depth = TORQUE_DEFERRED_UNCONDITION( deferredTex, IN.uv0 ).w;
|
||||
//return float4( depth, 0, 0, 0.7 );
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,9 @@
|
|||
#include "../../shaderModel.hlsl"
|
||||
|
||||
#define FXAA_PC 1
|
||||
#if (TORQUE_SM <= 30)
|
||||
#define FXAA_HLSL_3 1
|
||||
#elif TORQUE_SM < 49
|
||||
#if TORQUE_SM == 40
|
||||
#define FXAA_HLSL_4 1
|
||||
#elif TORQUE_SM >=50
|
||||
#elif TORQUE_SM > 40
|
||||
#define FXAA_HLSL_5 1
|
||||
#endif
|
||||
#define FXAA_QUALITY__PRESET 12
|
||||
|
|
@ -48,9 +46,7 @@ uniform float2 oneOverTargetSize;
|
|||
|
||||
float4 main( VertToPix IN ) : TORQUE_TARGET0
|
||||
{
|
||||
#if (TORQUE_SM >= 10 && TORQUE_SM <=30)
|
||||
FxaaTex tex = colorTex;
|
||||
#elif TORQUE_SM >=40
|
||||
#if TORQUE_SM >=40
|
||||
FxaaTex tex;
|
||||
tex.smpl = colorTex;
|
||||
tex.tex = texture_colorTex;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
|||
color.rgb = ((color.rgb - 0.5f) * Contrast) + 0.5f;
|
||||
|
||||
// Apply brightness
|
||||
color.rgb += Brightness;
|
||||
|
||||
return color;
|
||||
//color.rgb += Brightness;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
|
@ -43,6 +43,30 @@ uniform float g_fOneOverGamma;
|
|||
uniform float Brightness;
|
||||
uniform float Contrast;
|
||||
|
||||
// uncharted 2 tonemapper see: http://filmicgames.com/archives/75
|
||||
float3 Uncharted2Tonemap(const float3 x)
|
||||
{
|
||||
const float A = 0.15;
|
||||
const float B = 0.50;
|
||||
const float C = 0.10;
|
||||
const float D = 0.20;
|
||||
const float E = 0.02;
|
||||
const float F = 0.30;
|
||||
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
|
||||
}
|
||||
|
||||
float3 tonemap(float3 color)
|
||||
{
|
||||
const float W = 11.2;
|
||||
float ExposureBias = 2.0f;
|
||||
//float ExposureAdjust = 1.5f;
|
||||
//c *= ExposureAdjust;
|
||||
color = Uncharted2Tonemap(ExposureBias*color);
|
||||
color = color * (1.0f / Uncharted2Tonemap(W));
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
||||
{
|
||||
float4 sample = hdrDecode( TORQUE_TEX2D( sceneTex, IN.uv0 ) );
|
||||
|
|
@ -71,22 +95,23 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
|||
|
||||
// Add the bloom effect.
|
||||
sample += g_fBloomScale * bloom;
|
||||
|
||||
// Map the high range of color values into a range appropriate for
|
||||
// display, taking into account the user's adaptation level,
|
||||
// white point, and selected value for for middle gray.
|
||||
if ( g_fEnableToneMapping > 0.0f )
|
||||
{
|
||||
float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( sample.rgb );
|
||||
//float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp );
|
||||
float toneScalar = Lp;
|
||||
sample.rgb = lerp( sample.rgb, sample.rgb * toneScalar, g_fEnableToneMapping );
|
||||
}
|
||||
|
||||
// Apply the color correction.
|
||||
sample.r = TORQUE_TEX1D( colorCorrectionTex, sample.r ).r;
|
||||
sample.g = TORQUE_TEX1D( colorCorrectionTex, sample.g ).g;
|
||||
sample.b = TORQUE_TEX1D( colorCorrectionTex, sample.b ).b;
|
||||
|
||||
// Apply contrast
|
||||
sample.rgb = ((sample.rgb - 0.5f) * Contrast) + 0.5f;
|
||||
|
||||
// Apply brightness
|
||||
//sample.rgb += Brightness;
|
||||
|
||||
//tonemapping - TODO fix up eye adaptation
|
||||
if ( g_fEnableToneMapping > 0.0f )
|
||||
{
|
||||
sample.rgb = tonemap(sample.rgb);
|
||||
}
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,29 @@ uniform float Contrast;
|
|||
|
||||
out vec4 OUT_col;
|
||||
|
||||
// uncharted 2 tonemapper see: http://filmicgames.com/archives/75
|
||||
vec3 Uncharted2Tonemap(vec3 x)
|
||||
{
|
||||
const float A = 0.15;
|
||||
const float B = 0.50;
|
||||
const float C = 0.10;
|
||||
const float D = 0.20;
|
||||
const float E = 0.02;
|
||||
const float F = 0.30;
|
||||
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
|
||||
}
|
||||
|
||||
vec3 tonemap(vec3 c)
|
||||
{
|
||||
const float W = 11.2;
|
||||
float ExposureBias = 2.0f;
|
||||
float ExposureAdjust = 1.5f;
|
||||
c *= ExposureAdjust;
|
||||
vec3 curr = Uncharted2Tonemap(ExposureBias*c);
|
||||
vec3 whiteScale = 1.0f / Uncharted2Tonemap(vec3(W,W,W));
|
||||
return curr*whiteScale;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 _sample = hdrDecode( texture( sceneTex, IN_uv0 ) );
|
||||
|
|
@ -76,22 +99,23 @@ void main()
|
|||
|
||||
// Add the bloom effect.
|
||||
_sample += g_fBloomScale * bloom;
|
||||
|
||||
// Map the high range of color values into a range appropriate for
|
||||
// display, taking into account the user's adaptation level,
|
||||
// white point, and selected value for for middle gray.
|
||||
if ( g_fEnableToneMapping > 0.0f )
|
||||
{
|
||||
float Lp = (g_fMiddleGray / (adaptedLum + 0.0001)) * hdrLuminance( _sample.rgb );
|
||||
//float toneScalar = ( Lp * ( 1.0 + ( Lp / ( g_fWhiteCutoff ) ) ) ) / ( 1.0 + Lp );
|
||||
float toneScalar = Lp;
|
||||
_sample.rgb = mix( _sample.rgb, _sample.rgb * toneScalar, g_fEnableToneMapping );
|
||||
}
|
||||
|
||||
// Apply the color correction.
|
||||
_sample.r = texture( colorCorrectionTex, _sample.r ).r;
|
||||
_sample.g = texture( colorCorrectionTex, _sample.g ).g;
|
||||
_sample.b = texture( colorCorrectionTex, _sample.b ).b;
|
||||
|
||||
// Apply contrast
|
||||
_sample.rgb = ((_sample.rgb - 0.5f) * Contrast) + 0.5f;
|
||||
|
||||
// Apply brightness
|
||||
//_sample.rgb += Brightness;
|
||||
|
||||
//tonemapping - TODO fix up eye adaptation
|
||||
if ( g_fEnableToneMapping > 0.0f )
|
||||
{
|
||||
_sample.rgb = tonemap(_sample.rgb);
|
||||
}
|
||||
|
||||
OUT_col = _sample;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,74 +24,50 @@
|
|||
#define _TORQUE_SHADERMODEL_
|
||||
|
||||
// Portability helpers for different shader models
|
||||
//Shader model 1.0 - 3.0
|
||||
#if (TORQUE_SM >= 10 && TORQUE_SM <=30)
|
||||
// Semantics
|
||||
#define TORQUE_POSITION POSITION
|
||||
#define TORQUE_DEPTH DEPTH
|
||||
#define TORQUE_TARGET0 COLOR0
|
||||
#define TORQUE_TARGET1 COLOR1
|
||||
#define TORQUE_TARGET2 COLOR2
|
||||
#define TORQUE_TARGET3 COLOR3
|
||||
|
||||
// Sampler uniforms
|
||||
#define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform sampler1D tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform sampler2D tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLER3D(tex,regist) uniform sampler3D tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLERCUBE(tex,regist) uniform samplerCUBE tex : register(S##regist)
|
||||
// Sampling functions
|
||||
#define TORQUE_TEX1D(tex,coords) tex1D(tex,coords)
|
||||
#define TORQUE_TEX2D(tex,coords) tex2D(tex,coords)
|
||||
#define TORQUE_TEX2DPROJ(tex,coords) tex2Dproj(tex,coords) //this really is sm 2 or later
|
||||
#define TORQUE_TEX3D(tex,coords) tex3D(tex,coords)
|
||||
#define TORQUE_TEXCUBE(tex,coords) texCUBE(tex,coords)
|
||||
|
||||
//Shader model 3.0 only
|
||||
#if TORQUE_SM == 30
|
||||
#define TORQUE_VPOS VPOS // This is a float2
|
||||
// The mipmap LOD is specified in coord.w
|
||||
#define TORQUE_TEX2DLOD(tex,coords) tex2Dlod(tex,coords)
|
||||
#endif
|
||||
#define TORQUE_POSITION SV_Position
|
||||
#define TORQUE_DEPTH SV_Depth
|
||||
#define TORQUE_VPOS SV_Position //note float4 compared to SM 3 where it is a float2
|
||||
#define TORQUE_TARGET0 SV_Target0
|
||||
#define TORQUE_TARGET1 SV_Target1
|
||||
#define TORQUE_TARGET2 SV_Target2
|
||||
#define TORQUE_TARGET3 SV_Target3
|
||||
#define TORQUE_TARGET4 SV_Target4
|
||||
#define TORQUE_TARGET5 SV_Target5
|
||||
// Sampler uniforms
|
||||
//1D is emulated to a 2D for now
|
||||
#define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
|
||||
#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)
|
||||
#define TORQUE_TEXCUBEARRAYLOD(tex,coords,id,lod) texture_##tex.SampleLevel(tex,float4(coords.xyz,id),lod)
|
||||
// Tex2d comparison
|
||||
#define TORQUE_TEX2DCMP(tex,coords,compare) texture_##tex.SampleCmpLevelZero(tex,coords,compare)
|
||||
|
||||
//helper if you want to pass sampler/texture in a function
|
||||
//2D
|
||||
#define TORQUE_SAMPLER2D(tex) sampler2D tex
|
||||
#define TORQUE_SAMPLER2D_MAKEARG(tex) tex
|
||||
//Cube
|
||||
#define TORQUE_SAMPLERCUBE(tex) samplerCUBE tex
|
||||
#define TORQUE_SAMPLERCUBE_MAKEARG(tex) tex
|
||||
// Shader model 4.0+
|
||||
#elif TORQUE_SM >= 40
|
||||
#define TORQUE_POSITION SV_Position
|
||||
#define TORQUE_DEPTH SV_Depth
|
||||
#define TORQUE_VPOS SV_Position //note float4 compared to SM 3 where it is a float2
|
||||
#define TORQUE_TARGET0 SV_Target0
|
||||
#define TORQUE_TARGET1 SV_Target1
|
||||
#define TORQUE_TARGET2 SV_Target2
|
||||
#define TORQUE_TARGET3 SV_Target3
|
||||
// Sampler uniforms
|
||||
//1D is emulated to a 2D for now
|
||||
#define TORQUE_UNIFORM_SAMPLER1D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState tex : register(S##regist)
|
||||
#define TORQUE_UNIFORM_SAMPLER2D(tex,regist) uniform Texture2D texture_##tex : register(T##regist); uniform SamplerState 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)
|
||||
// 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)
|
||||
// The mipmap LOD is specified in coord.w
|
||||
#define TORQUE_TEX2DLOD(tex,coords) texture_##tex.SampleLevel(tex,coords.xy,coords.w)
|
||||
#define TORQUE_TEX2DGATHER(tex,coords,compare,offset) texture_##tex.GatherCmp(tex,coords,compare,offset)
|
||||
|
||||
//helper if you want to pass sampler/texture in a function
|
||||
//2D
|
||||
#define TORQUE_SAMPLER2D(tex) Texture2D texture_##tex, SamplerState tex
|
||||
#define TORQUE_SAMPLER2D_MAKEARG(tex) texture_##tex, tex
|
||||
//Cube
|
||||
#define TORQUE_SAMPLERCUBE(tex) TextureCube texture_##tex, SamplerState tex
|
||||
#define TORQUE_SAMPLERCUBE_MAKEARG(tex) texture_##tex, tex
|
||||
#endif
|
||||
//helper if you want to pass sampler/texture in a function
|
||||
//2D
|
||||
#define TORQUE_SAMPLER2D(tex) Texture2D texture_##tex, SamplerState tex
|
||||
#define TORQUE_SAMPLER2D_MAKEARG(tex) texture_##tex, tex
|
||||
// Sampler comparison state - use above MAKEARG with this
|
||||
#define TORQUE_SAMPLER2DCMP(tex) Texture2D texture_##tex, SamplerComparisonState tex
|
||||
//Cube
|
||||
#define TORQUE_SAMPLERCUBE(tex) TextureCube texture_##tex, SamplerState tex
|
||||
#define TORQUE_SAMPLERCUBE_MAKEARG(tex) texture_##tex, tex
|
||||
#define TORQUE_SAMPLERCUBEARRAY(tex) TextureCubeArray texture_##tex, SamplerState tex
|
||||
#define TORQUE_SAMPLERCUBEARRAY_MAKEARG(tex) texture_##tex, tex
|
||||
|
||||
#endif // _TORQUE_SHADERMODEL_
|
||||
|
||||
|
|
|
|||
|
|
@ -24,12 +24,10 @@
|
|||
#define _TORQUE_SHADERMODEL_AUTOGEN_
|
||||
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "./shaderModel.hlsl"
|
||||
|
||||
// Portability helpers for autogenConditioners
|
||||
#if (TORQUE_SM >= 10 && TORQUE_SM <=30)
|
||||
#define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, coords)
|
||||
#elif TORQUE_SM >= 40
|
||||
#define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, texture_##tex, coords)
|
||||
#endif
|
||||
|
||||
#define TORQUE_DEFERRED_UNCONDITION(tex, coords) deferredUncondition(tex, texture_##tex, coords)
|
||||
|
||||
#endif //_TORQUE_SHADERMODEL_AUTOGEN_
|
||||
|
|
|
|||
|
|
@ -167,22 +167,13 @@ float2 parallaxOffsetDxtnm(TORQUE_SAMPLER2D(texMap), float2 texCoord, float3 neg
|
|||
return offset;
|
||||
}
|
||||
|
||||
|
||||
/// The maximum value for 16bit per component integer HDR encoding.
|
||||
static const float HDR_RGB16_MAX = 100.0;
|
||||
|
||||
/// The maximum value for 10bit per component integer HDR encoding.
|
||||
static const float HDR_RGB10_MAX = 4.0;
|
||||
|
||||
/// Encodes an HDR color for storage into a target.
|
||||
float3 hdrEncode( float3 sample )
|
||||
{
|
||||
#if defined( TORQUE_HDR_RGB16 )
|
||||
|
||||
return sample / HDR_RGB16_MAX;
|
||||
|
||||
#elif defined( TORQUE_HDR_RGB10 )
|
||||
|
||||
#if defined( TORQUE_HDR_RGB10 )
|
||||
return sample / HDR_RGB10_MAX;
|
||||
|
||||
#else
|
||||
|
|
@ -202,12 +193,7 @@ float4 hdrEncode( float4 sample )
|
|||
/// Decodes an HDR color from a target.
|
||||
float3 hdrDecode( float3 sample )
|
||||
{
|
||||
#if defined( TORQUE_HDR_RGB16 )
|
||||
|
||||
return sample * HDR_RGB16_MAX;
|
||||
|
||||
#elif defined( TORQUE_HDR_RGB10 )
|
||||
|
||||
#if defined( TORQUE_HDR_RGB10 )
|
||||
return sample * HDR_RGB10_MAX;
|
||||
|
||||
#else
|
||||
|
|
@ -286,37 +272,6 @@ bool getFlag(float flags, int num)
|
|||
return (fmod(process, pow(2, squareNum)) >= squareNum);
|
||||
}
|
||||
|
||||
// #define TORQUE_STOCK_GAMMA
|
||||
#ifdef TORQUE_STOCK_GAMMA
|
||||
// Sample in linear space. Decodes gamma.
|
||||
float4 toLinear(float4 tex)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
// Encodes gamma.
|
||||
float4 toGamma(float4 tex)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
float3 toLinear(float3 tex)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
// Encodes gamma.
|
||||
float3 toGamma(float3 tex)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
float3 toLinear(float3 tex)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
// Encodes gamma.
|
||||
float3 toLinear(float3 tex)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
#else
|
||||
// Sample in linear space. Decodes gamma.
|
||||
float4 toLinear(float4 tex)
|
||||
{
|
||||
|
|
@ -337,6 +292,58 @@ float3 toGamma(float3 tex)
|
|||
{
|
||||
return pow(abs(tex.rgb), 1.0/2.2);
|
||||
}
|
||||
#endif //
|
||||
|
||||
//
|
||||
float3 PBRFresnel(float3 albedo, float3 indirect, float metalness, float fresnel)
|
||||
{
|
||||
float3 diffuseColor = albedo - (albedo * metalness);
|
||||
float3 reflectColor = lerp(indirect*albedo, indirect, fresnel);
|
||||
|
||||
return diffuseColor + reflectColor;
|
||||
}
|
||||
|
||||
float3 simpleFresnel(float3 diffuseColor, float3 reflectColor, float metalness, float angle, float bias, float power)
|
||||
{
|
||||
float fresnelTerm = bias + (1.0 - bias) * pow(abs(1.0 - max(angle, 0)), power);
|
||||
|
||||
fresnelTerm *= metalness;
|
||||
|
||||
return lerp(diffuseColor, reflectColor, fresnelTerm);
|
||||
}
|
||||
|
||||
//hlsl version of the glsl funcion mod - note hlsl fmod is different
|
||||
#define mod(x,y) (x-y*floor(x/y))
|
||||
|
||||
//get direction for a cube face
|
||||
float3 getCubeDir(int face, float2 uv)
|
||||
{
|
||||
float2 debiased = uv * 2.0f - 1.0f;
|
||||
|
||||
float3 dir = 0;
|
||||
|
||||
switch (face)
|
||||
{
|
||||
case 0: dir = float3(1, -debiased.y, -debiased.x);
|
||||
break;
|
||||
|
||||
case 1: dir = float3(-1, -debiased.y, debiased.x);
|
||||
break;
|
||||
|
||||
case 2: dir = float3(debiased.x, 1, debiased.y);
|
||||
break;
|
||||
|
||||
case 3: dir = float3(debiased.x, -1, -debiased.y);
|
||||
break;
|
||||
|
||||
case 4: dir = float3(debiased.x, -debiased.y, 1);
|
||||
break;
|
||||
|
||||
case 5: dir = float3(-debiased.x, -debiased.y, -1);
|
||||
break;
|
||||
};
|
||||
|
||||
return normalize(dir);
|
||||
}
|
||||
|
||||
#define sqr(a) ((a)*(a))
|
||||
#endif // _TORQUE_HLSL_
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 6.1 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<ImageAsset
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="Grid_512_orange_ALBEDO"
|
||||
imageFile="@assetFile=Grid_512_orange.png"
|
||||
useMips="true"
|
||||
isHDRImage="false"
|
||||
originalFilePath="E:/Gamedev/T3DMIT/clangtest/Templates/Full/game/core/art/grids/Grid_512_orange.png"
|
||||
VersionId="1" />
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<ShapeAsset
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="Cube"
|
||||
fileName="@assetFile=Cube.fbx"
|
||||
isNewShape="1"
|
||||
materialSlot0="@Asset=StaticShapeTest:Grid_512_orange"
|
||||
originalFilePath="E:/Gamedev/T3DMIT/clangtest/My Projects/T3DPreview4_0/art/StarterContent/Cube.fbx"
|
||||
VersionId="1" />
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
singleton TSShapeConstructor(CubeFbx)
|
||||
{
|
||||
baseShape = "./Cube.fbx";
|
||||
};
|
||||
BIN
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cube.fbx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<ShapeAsset
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="Cylinder"
|
||||
fileName="@assetFile=Cylinder.fbx"
|
||||
isNewShape="1"
|
||||
originalFilePath="E:/Gamedev/T3DMIT/clangtest/My Projects/T3DPreview4_0/art/StarterContent/Cylinder.fbx"
|
||||
VersionId="1" />
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
singleton TSShapeConstructor(CylinderFbx)
|
||||
{
|
||||
baseShape = "./Cylinder.fbx";
|
||||
};
|
||||
BIN
Templates/BaseGame/game/data/StaticShapeTest/Shapes/Cylinder.fbx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
singleton Material(Grid_512_Orange)
|
||||
{
|
||||
mapTo = "Grid_512_orange";
|
||||
diffuseColor[0] = "0.8 0.8 0.8 1";
|
||||
diffuseMap[0] = "E:/Gamedev/T3DMIT/clangtest/Templates/Full/game/core/art/grids/Grid_512_orange.png";
|
||||
specular[0] = "0.8 0.8 0.8 1";
|
||||
specularPower[0] = "0.25";
|
||||
specularStrength[0] = "25";
|
||||
translucentBlendOp = "None";
|
||||
};
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
function StaticShapeTest::onCreate(%this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function StaticShapeTest::onDestroy(%this)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<ModuleDefinition
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
ModuleId="StaticShapeTest"
|
||||
VersionId="1"
|
||||
Group="Game"
|
||||
scriptFile="StaticShapeTest.cs"
|
||||
CreateFunction="onCreate"
|
||||
DestroyFunction="onDestroy">
|
||||
<DeclaredAssets
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
Extension="asset.taml"
|
||||
Recurse="true" />
|
||||
<AutoloadAssets
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetType="ComponentAsset"
|
||||
Recurse="true" />
|
||||
<AutoloadAssets
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetType="GUIAsset"
|
||||
Recurse="true" />
|
||||
</ModuleDefinition>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<MaterialAsset
|
||||
canSave="true"
|
||||
canSaveDynamicFields="true"
|
||||
AssetName="Grid_512_Orange"
|
||||
scriptFile="@assetFile=data/StaticShapeTest/materials/Grid_512_orange.cs"
|
||||
materialDefinitionName="Grid_512_Orange"
|
||||
originalFilePath="E:/Gamedev/T3DMIT/clangtest/Templates/Full/game/core/art/grids/Grid_512_orange.png"
|
||||
shaderGraph="data/StaticShapeTest/materials/Grid_512_orange.sgf"
|
||||
VersionId="1" />
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
//--- OBJECT WRITE BEGIN ---
|
||||
singleton Material(Grid_512_orange) {
|
||||
mapTo = "Grid_512_orange";
|
||||
DiffuseMap[0] = "data/StaticShapeTest/Images/Grid_512_orange.png";
|
||||
DiffuseMapAsset[0] = "StaticShapeTest:Grid_512_orange_ALBEDO";
|
||||
};
|
||||
//--- OBJECT WRITE END ---
|
||||
BIN
Templates/BaseGame/game/data/pbr/cubemaps/hdrSky.dds
Normal file
32
Templates/BaseGame/game/data/pbr/cubemaps/materials.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
singleton CubemapData( HdrSkyCubemap )
|
||||
{
|
||||
cubeMap = "./hdrSky.dds";
|
||||
};
|
||||
|
||||
singleton Material( HdrSky )
|
||||
{
|
||||
cubemap = HdrSkyCubemap;
|
||||
materialTag0 = "Skies";
|
||||
};
|
||||
|
|
@ -0,0 +1 @@
|
|||
These texture files were created by FreePBR.com and may be used freely in your video games and 3d work at no cost. They may not however be redistributed on other websites or anywhere else other than FreePBR.com. We think that is more than fair. :) We also would greatly appreciate it if some sorrt of credit was given if you do indeed use these textures in a published game. Other than that, keep on creating and have fun. :)
|
||||
BIN
Templates/BaseGame/game/data/pbr/images/FloorEbony_ao.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
Templates/BaseGame/game/data/pbr/images/FloorEbony_basecolor.png
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/FloorEbony_metal.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
Templates/BaseGame/game/data/pbr/images/FloorEbony_normal.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/FloorEbony_rough.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/ao.png
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/gold_albedo.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
Templates/BaseGame/game/data/pbr/images/gold_metallic.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
Templates/BaseGame/game/data/pbr/images/gold_normal.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Templates/BaseGame/game/data/pbr/images/gold_roughness.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/greasy-pan-2-albedo.png
Normal file
|
After Width: | Height: | Size: 8.8 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/greasy-pan-2-metal.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/greasy-pan-2-normal.png
Normal file
|
After Width: | Height: | Size: 7.2 MiB |
|
After Width: | Height: | Size: 3.3 MiB |
|
After Width: | Height: | Size: 4.7 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 5 MiB |
|
After Width: | Height: | Size: 4.5 MiB |
BIN
Templates/BaseGame/game/data/pbr/images/plastic_A.dds
Normal file
BIN
Templates/BaseGame/game/data/pbr/images/plastic_N.dds
Normal file
BIN
Templates/BaseGame/game/data/pbr/images/plastic_metallic.png
Normal file
|
After Width: | Height: | Size: 23 KiB |