mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
343 lines
9.5 KiB
HLSL
343 lines
9.5 KiB
HLSL
//-----------------------------------------------------------------------------
|
|
// 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.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef _TORQUE_HLSL_
|
|
#define _TORQUE_HLSL_
|
|
|
|
#include "./shaderModel.hlsl"
|
|
|
|
static float M_HALFPI_F = 1.57079632679489661923f;
|
|
static float M_PI_F = 3.14159265358979323846f;
|
|
static float M_2PI_F = 6.28318530717958647692f;
|
|
|
|
|
|
/// Calculate fog based on a start and end positions in worldSpace.
|
|
float computeSceneFog( float3 startPos,
|
|
float3 endPos,
|
|
float fogDensity,
|
|
float fogDensityOffset,
|
|
float fogHeightFalloff )
|
|
{
|
|
float f = length( startPos - endPos ) - fogDensityOffset;
|
|
float h = 1.0 - ( endPos.z * fogHeightFalloff );
|
|
return exp( -fogDensity * f * h );
|
|
}
|
|
|
|
|
|
/// Calculate fog based on a start and end position and a height.
|
|
/// Positions do not need to be in worldSpace but height does.
|
|
float computeSceneFog( float3 startPos,
|
|
float3 endPos,
|
|
float height,
|
|
float fogDensity,
|
|
float fogDensityOffset,
|
|
float fogHeightFalloff )
|
|
{
|
|
float f = length( startPos - endPos ) - fogDensityOffset;
|
|
float h = 1.0 - ( height * fogHeightFalloff );
|
|
return exp( -fogDensity * f * h );
|
|
}
|
|
|
|
|
|
/// Calculate fog based on a distance, height is not used.
|
|
float computeSceneFog( float dist, float fogDensity, float fogDensityOffset )
|
|
{
|
|
float f = dist - fogDensityOffset;
|
|
return exp( -fogDensity * f );
|
|
}
|
|
|
|
|
|
/// Convert a float4 uv in viewport space to render target space.
|
|
float2 viewportCoordToRenderTarget( float4 inCoord, float4 rtParams )
|
|
{
|
|
float2 outCoord = inCoord.xy / inCoord.w;
|
|
outCoord = ( outCoord * rtParams.zw ) + rtParams.xy;
|
|
return outCoord;
|
|
}
|
|
|
|
|
|
/// Convert a float2 uv in viewport space to render target space.
|
|
float2 viewportCoordToRenderTarget( float2 inCoord, float4 rtParams )
|
|
{
|
|
float2 outCoord = ( inCoord * rtParams.zw ) + rtParams.xy;
|
|
return outCoord;
|
|
}
|
|
|
|
|
|
/// Convert a float4 quaternion into a 3x3 matrix.
|
|
float3x3 quatToMat( float4 quat )
|
|
{
|
|
float xs = quat.x * 2.0f;
|
|
float ys = quat.y * 2.0f;
|
|
float zs = quat.z * 2.0f;
|
|
|
|
float wx = quat.w * xs;
|
|
float wy = quat.w * ys;
|
|
float wz = quat.w * zs;
|
|
|
|
float xx = quat.x * xs;
|
|
float xy = quat.x * ys;
|
|
float xz = quat.x * zs;
|
|
|
|
float yy = quat.y * ys;
|
|
float yz = quat.y * zs;
|
|
float zz = quat.z * zs;
|
|
|
|
float3x3 mat;
|
|
|
|
mat[0][0] = 1.0f - (yy + zz);
|
|
mat[0][1] = xy - wz;
|
|
mat[0][2] = xz + wy;
|
|
|
|
mat[1][0] = xy + wz;
|
|
mat[1][1] = 1.0f - (xx + zz);
|
|
mat[1][2] = yz - wx;
|
|
|
|
mat[2][0] = xz - wy;
|
|
mat[2][1] = yz + wx;
|
|
mat[2][2] = 1.0f - (xx + yy);
|
|
|
|
return mat;
|
|
}
|
|
|
|
|
|
/// The number of additional substeps we take when refining
|
|
/// the results of the offset parallax mapping function below.
|
|
///
|
|
/// You should turn down the number of steps if your needing
|
|
/// more performance out of your parallax surfaces. Increasing
|
|
/// the number doesn't yeild much better results and is rarely
|
|
/// worth the additional cost.
|
|
///
|
|
#define PARALLAX_REFINE_STEPS 3
|
|
|
|
/// Performs fast parallax offset mapping using
|
|
/// multiple refinement steps.
|
|
///
|
|
/// @param texMap The texture map whos alpha channel we sample the parallax depth.
|
|
/// @param texCoord The incoming texture coordinate for sampling the parallax depth.
|
|
/// @param negViewTS The negative view vector in tangent space.
|
|
/// @param depthScale The parallax factor used to scale the depth result.
|
|
///
|
|
float2 parallaxOffset(TORQUE_SAMPLER2D(texMap), float2 texCoord, float3 negViewTS, float depthScale)
|
|
{
|
|
float depth = TORQUE_TEX2D(texMap, texCoord).a/(PARALLAX_REFINE_STEPS*2);
|
|
float2 offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS);
|
|
|
|
for (int i = 0; i < PARALLAX_REFINE_STEPS; i++)
|
|
{
|
|
depth = (depth + TORQUE_TEX2D(texMap, texCoord + offset).a)/(PARALLAX_REFINE_STEPS*2);
|
|
offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS);
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
/// Same as parallaxOffset but for dxtnm where depth is stored in the red channel instead of the alpha
|
|
float2 parallaxOffsetDxtnm(TORQUE_SAMPLER2D(texMap), float2 texCoord, float3 negViewTS, float depthScale)
|
|
{
|
|
float depth = TORQUE_TEX2D(texMap, texCoord).r/(PARALLAX_REFINE_STEPS*2);
|
|
float2 offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS*2);
|
|
|
|
for (int i = 0; i < PARALLAX_REFINE_STEPS; i++)
|
|
{
|
|
depth = (depth + TORQUE_TEX2D(texMap, texCoord + offset).r)/(PARALLAX_REFINE_STEPS*2);
|
|
offset = negViewTS.xy * (depth * depthScale)/(PARALLAX_REFINE_STEPS*2);
|
|
}
|
|
|
|
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 )
|
|
|
|
return sample / HDR_RGB10_MAX;
|
|
|
|
#else
|
|
|
|
// No encoding.
|
|
return sample;
|
|
|
|
#endif
|
|
}
|
|
|
|
/// Encodes an HDR color for storage into a target.
|
|
float4 hdrEncode( float4 sample )
|
|
{
|
|
return float4( hdrEncode( sample.rgb ), sample.a );
|
|
}
|
|
|
|
/// 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 )
|
|
|
|
return sample * HDR_RGB10_MAX;
|
|
|
|
#else
|
|
|
|
// No encoding.
|
|
return sample;
|
|
|
|
#endif
|
|
}
|
|
|
|
/// Decodes an HDR color from a target.
|
|
float4 hdrDecode( float4 sample )
|
|
{
|
|
return float4( hdrDecode( sample.rgb ), sample.a );
|
|
}
|
|
|
|
/// Returns the luminance for an HDR pixel.
|
|
float hdrLuminance( float3 sample )
|
|
{
|
|
// There are quite a few different ways to
|
|
// calculate luminance from an rgb value.
|
|
//
|
|
// If you want to use a different technique
|
|
// then plug it in here.
|
|
//
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Max component luminance.
|
|
//
|
|
//float lum = max( sample.r, max( sample.g, sample.b ) );
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
// The perceptual relative luminance.
|
|
//
|
|
// See http://en.wikipedia.org/wiki/Luminance_(relative)
|
|
//
|
|
const float3 RELATIVE_LUMINANCE = float3( 0.2126, 0.7152, 0.0722 );
|
|
float lum = dot( sample, RELATIVE_LUMINANCE );
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// The average component luminance.
|
|
//
|
|
//const float3 AVERAGE_LUMINANCE = float3( 0.3333, 0.3333, 0.3333 );
|
|
//float lum = dot( sample, AVERAGE_LUMINANCE );
|
|
|
|
return lum;
|
|
}
|
|
|
|
/// Called from the visibility feature to do screen
|
|
/// door transparency for fading of objects.
|
|
void fizzle(float2 vpos, float visibility)
|
|
{
|
|
// NOTE: The magic values below are what give us
|
|
// the nice even pattern during the fizzle.
|
|
//
|
|
// These values can be changed to get different
|
|
// patterns... some better than others.
|
|
//
|
|
// Horizontal Blinds - { vpos.x, 0.916, vpos.y, 0 }
|
|
// Vertical Lines - { vpos.x, 12.9898, vpos.y, 78.233 }
|
|
//
|
|
// I'm sure there are many more patterns here to
|
|
// discover for different effects.
|
|
|
|
float2x2 m = { vpos.x, 0.916, vpos.y, 0.350 };
|
|
clip( visibility - frac( determinant( m ) ) );
|
|
}
|
|
|
|
// Deferred Shading: Material Info Flag Check
|
|
bool getFlag(float flags, int num)
|
|
{
|
|
int process = round(flags * 255);
|
|
int squareNum = pow(2, 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)
|
|
{
|
|
return float4(pow(abs(tex.rgb), 2.2), tex.a);
|
|
}
|
|
// Encodes gamma.
|
|
float4 toGamma(float4 tex)
|
|
{
|
|
return float4(pow(abs(tex.rgb), 1.0/2.2), tex.a);
|
|
}
|
|
// Sample in linear space. Decodes gamma.
|
|
float3 toLinear(float3 tex)
|
|
{
|
|
return pow(abs(tex.rgb), 2.2);
|
|
}
|
|
// Encodes gamma.
|
|
float3 toGamma(float3 tex)
|
|
{
|
|
return pow(abs(tex.rgb), 1.0/2.2);
|
|
}
|
|
#endif //
|
|
|
|
#endif // _TORQUE_HLSL_
|