Full Template for ticket #1

This commit is contained in:
DavidWyand-GG 2012-09-19 11:54:25 -04:00
parent 74f265b3b3
commit f439dc8dcd
2150 changed files with 286240 additions and 0 deletions

View file

@ -0,0 +1,197 @@
//-----------------------------------------------------------------------------
// 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"
#include "../../gl/hlslCompat.glsl"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
// miscParams
#define FRESNEL_BIAS miscParams[0]
#define FRESNEL_POWER miscParams[1]
#define CLARITY miscParams[2]
#define ISRIVER miscParams[3]
// reflectParams
#define REFLECT_PLANE_Z reflectParams[0]
#define REFLECT_MIN_DIST reflectParams[1]
#define REFLECT_MAX_DIST reflectParams[2]
#define NO_REFLECT reflectParams[3]
// distortionParams
#define DISTORT_START_DIST distortionParams[0]
#define DISTORT_END_DIST distortionParams[1]
#define DISTORT_FULL_DEPTH distortionParams[2]
// ConnectData.misc
#define LIGHT_VEC misc.xyz
#define WORLD_Z objPos.w
// specularParams
#define SPEC_POWER specularParams[3]
#define SPEC_COLOR specularParams.xyz
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
varying vec4 rippleTexCoord01;
// TexCoord 2 for ripple texture lookup
varying vec2 rippleTexCoord2;
// Screenspace vert position BEFORE wave transformation
varying vec4 posPreWave;
// Screenspace vert position AFTER wave transformation
varying vec4 posPostWave;
// Worldspace unit distance/depth of this vertex/pixel
varying float pixelDist;
// Objectspace vert position BEFORE wave transformation
// w coord is world space z position.
varying vec4 objPos;
varying vec3 misc;
//-----------------------------------------------------------------------------
// approximate Fresnel function
//-----------------------------------------------------------------------------
float fresnel(float NdotV, float bias, float power)
{
return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0.0)), power);
}
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform sampler2D bumpMap;
//uniform sampler2D prepassTex;
uniform sampler2D reflectMap;
uniform sampler2D refractBuff;
uniform samplerCube skyMap;
//uniform sampler foamMap;
uniform vec4 baseColor;
uniform vec4 miscParams;
uniform vec4 reflectParams;
uniform vec3 ambientColor;
uniform vec3 eyePos;
uniform vec3 distortionParams;
uniform vec3 fogData;
uniform vec4 fogColor;
uniform vec3 rippleMagnitude;
uniform vec4 specularParams;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
void main()
{
// Modulate baseColor by the ambientColor.
vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1.0 );
// Get the bumpNorm...
vec3 bumpNorm = ( texture2D( bumpMap, rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x;
bumpNorm += ( texture2D( bumpMap, rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y;
bumpNorm += ( texture2D( bumpMap, rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z;
// We subtract a little from it so that we don't
// distort where the water surface intersects the
// camera near plane.
float distortAmt = saturate( pixelDist / 1.0 ) * 0.8;
vec4 distortPos = posPostWave;
distortPos.xy += bumpNorm.xy * distortAmt;
#ifdef UNDERWATER
gl_FragColor = texture2DProj( refractBuff, distortPos.xyz );
#else
vec3 eyeVec = objPos.xyz - eyePos;
vec3 reflectionVec = reflect( eyeVec, normalize(bumpNorm) );
// Color that replaces the reflection color when we do not
// have one that is appropriate.
vec4 fakeColor = vec4(ambientColor,1.0);
// Use fakeColor for ripple-normals that are angled towards the camera
eyeVec = -eyeVec;
eyeVec = normalize( eyeVec );
float ang = saturate( dot( eyeVec, bumpNorm ) );
float fakeColorAmt = ang;
// Get reflection map color
vec4 refMapColor = texture2DProj( reflectMap, distortPos );
// If we do not have a reflection texture then we use the cubemap.
refMapColor = mix( refMapColor, textureCube( skyMap, -reflectionVec ), NO_REFLECT );
// Combine reflection color and fakeColor.
vec4 reflectColor = mix( refMapColor, fakeColor, fakeColorAmt );
//return refMapColor;
// Get refract color
vec4 refractColor = texture2DProj( refractBuff, distortPos.xyz );
// calc "diffuse" color by lerping from the water color
// to refraction image based on the water clarity.
vec4 diffuseColor = mix( refractColor, waterBaseColor, 1.0 - CLARITY );
// fresnel calculation
float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER );
// Also scale the frensel by our distance to the
// water surface. This removes the hard reflection
// when really close to the water surface.
fresnelTerm *= saturate( pixelDist - 0.1 );
// Combine the diffuse color and reflection image via the
// fresnel term and set out output color.
gl_FragColor = mix( diffuseColor, reflectColor, fresnelTerm );
#ifdef WATER_SPEC
// Get some specular reflection.
vec3 newbump = bumpNorm;
newbump.xy *= 3.5;
newbump = normalize( bumpNorm );
vec3 halfAng = normalize( eyeVec + -LIGHT_VEC );
float specular = saturate( dot( newbump, halfAng ) );
specular = pow( specular, SPEC_POWER );
gl_FragColor.rgb = gl_FragColor.rgb + ( SPEC_COLOR * specular.xxx );
#else // Disable fogging if spec is on because otherwise we run out of instructions.
// Fog it.
float factor = computeSceneFog( eyePos,
objPos.xyz,
WORLD_Z,
fogData.x,
fogData.y,
fogData.z );
gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor.rgb, 1.0 - saturate( factor ) );
#endif
#endif
}

View file

@ -0,0 +1,260 @@
//-----------------------------------------------------------------------------
// 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"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
varying vec4 rippleTexCoord01;
// TexCoord 2 for ripple texture lookup
varying vec2 rippleTexCoord2;
// Screenspace vert position BEFORE wave transformation
varying vec4 posPreWave;
// Screenspace vert position AFTER wave transformation
varying vec4 posPostWave;
// Worldspace unit distance/depth of this vertex/pixel
varying float pixelDist;
varying vec4 objPos;
varying vec3 misc;
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform mat4 modelMat;
uniform mat4 modelview;
uniform vec4 rippleMat[3];
uniform vec3 eyePos;
uniform vec2 waveDir[3];
uniform vec2 waveData[3];
uniform vec2 rippleDir[3];
uniform vec2 rippleTexScale[3];
uniform vec3 rippleSpeed;
uniform vec3 inLightVec;
uniform vec3 reflectNormal;
uniform float gridElementSize;
uniform float elapsedTime;
uniform float undulateMaxDist;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
void main()
{
vec4 position = gl_Vertex;
vec3 normal = gl_Normal;
vec2 undulateData = gl_MultiTexCoord0.st;
vec4 horizonFactor = gl_MultiTexCoord1;
// use projection matrix for reflection / refraction texture coords
mat4 texGen = mat4(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.5, 0.5, 0.0, 1.0);
// Move the vertex based on the horizonFactor if specified to do so for this vert.
//if ( horizonFactor.z > 0.0 )
//{
//vec2 offsetXY = eyePos.xy - mod(eyePos.xy, gridElementSize);
//position.xy += offsetXY;
//undulateData += offsetXY;
//}
vec4 worldPos = modelMat * position;
//fogPos = position.xyz;
position.z = mix( position.z, eyePos.z, horizonFactor.x );
objPos.xyz = position.xyz;
objPos.w = worldPos.z;
// Send pre-undulation screenspace position
posPreWave = modelview * position;
posPreWave = texGen * posPreWave;
// Calculate the undulation amount for this vertex.
vec2 undulatePos = (modelMat * vec4( undulateData.xy, 0, 1 )).xy;
//if ( undulatePos.x < 0.0 )
//undulatePos = position.xy;
float undulateAmt = 0.0;
undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x +
undulatePos.x * waveDir[0].x +
undulatePos.y * waveDir[0].y );
undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x +
undulatePos.x * waveDir[1].x +
undulatePos.y * waveDir[1].y );
undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x +
undulatePos.x * waveDir[2].x +
undulatePos.y * waveDir[2].y );
float undulateFade = 1.0;
// Scale down wave magnitude amount based on distance from the camera.
float dist = length( position.xyz - eyePos );
dist = clamp( dist, 1.0, undulateMaxDist );
undulateFade *= ( 1.0 - dist / undulateMaxDist );
// Also scale down wave magnitude if the camera is very very close.
undulateFade *= saturate( ( length( position.xyz - eyePos ) - 0.5 ) / 10.0 );
undulateAmt *= undulateFade;
//undulateAmt = 0;
// Apply wave undulation to the vertex.
posPostWave = position;
posPostWave.xyz += normal.xyz * undulateAmt;
// Save worldSpace position of this pixel/vert
//worldPos = posPostWave.xyz;
//worldSpaceZ = ( modelMat * vec4(fogPos,1.0) ).z;
//if ( horizonFactor.x > 0.0 )
//{
//vec3 awayVec = normalize( fogPos.xyz - eyePos );
//fogPos.xy += awayVec.xy * 1000.0;
//}
// Convert to screen
posPostWave = modelview * posPostWave;
// Setup the OUT position symantic variable
gl_Position = posPostWave;
//gl_Position.z = mix(gl_Position.z, gl_Position.w, horizonFactor.x);
// Save world space camera dist/depth of the outgoing pixel
pixelDist = gl_Position.z;
// Convert to reflection texture space
posPostWave = texGen * posPostWave;
vec2 txPos = undulatePos;
if ( horizonFactor.x > 0.0 )
txPos = normalize( txPos ) * 50000.0;
// set up tex coordinates for the 3 interacting normal maps
rippleTexCoord01.xy = txPos * rippleTexScale[0];
rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x;
mat2 texMat;
texMat[0][0] = rippleMat[0].x;
texMat[1][0] = rippleMat[0].y;
texMat[0][1] = rippleMat[0].z;
texMat[1][1] = rippleMat[0].w;
rippleTexCoord01.xy = texMat * rippleTexCoord01.xy ;
rippleTexCoord01.zw = txPos * rippleTexScale[1];
rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y;
texMat[0][0] = rippleMat[1].x;
texMat[1][0] = rippleMat[1].y;
texMat[0][1] = rippleMat[1].z;
texMat[1][1] = rippleMat[1].w;
rippleTexCoord01.zw = texMat * rippleTexCoord01.zw ;
rippleTexCoord2.xy = txPos * rippleTexScale[2];
rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z;
texMat[0][0] = rippleMat[2].x;
texMat[1][0] = rippleMat[2].y;
texMat[0][1] = rippleMat[2].z;
texMat[1][1] = rippleMat[2].w;
rippleTexCoord2.xy = texMat * rippleTexCoord2.xy ;
/*rippleTexCoord01.xy = mix( position.xy * rippleTexScale[0], txPos.xy * rippleTexScale[0], horizonFactor.x );
rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x;
rippleTexCoord01.zw = mix( position.xy * rippleTexScale[1], txPos.xy * rippleTexScale[1], horizonFactor.x );
rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y;
rippleTexCoord2.xy = mix( position.xy * rippleTexScale[2], txPos.xy * rippleTexScale[2], horizonFactor.x );
rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z; */
/*rippleTexCoord01.xy = mix( position.xy * rippleTexScale[0], txPos.xy * rippleTexScale[0], horizonFactor.x );
rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x;
mat2 texMat;
texMat[0][0] = rippleMat[0].x;
texMat[1][0] = rippleMat[0].y;
texMat[0][1] = rippleMat[0].z;
texMat[1][1] = rippleMat[0].w;
rippleTexCoord01.xy = texMat * rippleTexCoord01.xy ;
rippleTexCoord01.zw = mix( position.xy * rippleTexScale[1], txPos.xy * rippleTexScale[1], horizonFactor.x );
rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y;
texMat[0][0] = rippleMat[1].x;
texMat[1][0] = rippleMat[1].y;
texMat[0][1] = rippleMat[1].z;
texMat[1][1] = rippleMat[1].w;
rippleTexCoord01.zw = texMat * rippleTexCoord01.zw ;
rippleTexCoord2.xy = mix( position.xy * rippleTexScale[2], txPos.xy * rippleTexScale[2], horizonFactor.x );
rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z;
texMat[0][0] = rippleMat[2].x;
texMat[1][0] = rippleMat[2].y;
texMat[0][1] = rippleMat[2].z;
texMat[1][1] = rippleMat[2].w;
rippleTexCoord2.xy = texMat * rippleTexCoord2.xy ;*/
#ifdef WATER_SPEC
vec3 binormal = vec3( 1, 0, 0 );
vec3 tangent = vec3( 0, 1, 0 );
vec3 normal;
for ( int i = 0; i < 3; i++ )
{
binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulateData.x + waveDir[i].y * undulateData.y + elapsedTime * waveData[i].x );
tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulateData.x + waveDir[i].y * undulateData.y + elapsedTime * waveData[i].x );
}
binormal = normalize( binormal );
tangent = normalize( tangent );
normal = cross( binormal, tangent );
mat3 worldToTangent;
worldToTangent[0] = binormal;
worldToTangent[1] = tangent;
worldToTangent[2] = normal;
misc.xyz = inLightVec * modelMat;
misc.xyz = worldToTangent * misc.xyz;
#else
misc.xyz = inLightVec;
#endif
}

View file

@ -0,0 +1,456 @@
//-----------------------------------------------------------------------------
// 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 "shadergen:/autogenConditioners.h"
#include "../../gl/torque.glsl"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#ifdef TORQUE_BASIC_LIGHTING
#define BASIC
#endif
// miscParams
#define FRESNEL_BIAS miscParams[0]
#define FRESNEL_POWER miscParams[1]
// miscParams[2] is unused
#define ISRIVER miscParams[3]
// reflectParams
#define REFLECT_PLANE_Z reflectParams[0]
#define REFLECT_MIN_DIST reflectParams[1]
#define REFLECT_MAX_DIST reflectParams[2]
#define NO_REFLECT reflectParams[3]
// fogParams
#define FOG_DENSITY fogParams[0]
#define FOG_DENSITY_OFFSET fogParams[1]
// wetnessParams
#define WET_DEPTH wetnessParams[0]
#define WET_COLOR_FACTOR wetnessParams[1]
// distortionParams
#define DISTORT_START_DIST distortionParams[0]
#define DISTORT_END_DIST distortionParams[1]
#define DISTORT_FULL_DEPTH distortionParams[2]
// foamParams
#define FOAM_SCALE foamParams[0]
#define FOAM_MAX_DEPTH foamParams[1]
// Incoming data
// Worldspace position of this pixel
varying vec3 worldPos;
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
varying vec4 rippleTexCoord01;
// TexCoord 2 for ripple texture lookup
varying vec2 rippleTexCoord2;
// Screenspace vert position BEFORE wave transformation
varying vec4 posPreWave;
// Screenspace vert position AFTER wave transformation
varying vec4 posPostWave;
// Worldspace unit distance/depth of this vertex/pixel
varying float pixelDist;
varying vec3 fogPos;
varying float worldSpaceZ;
varying vec4 foamTexCoords;
//-----------------------------------------------------------------------------
// approximate Fresnel function
//-----------------------------------------------------------------------------
float fresnel(float NdotV, float bias, float power)
{
return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power);
}
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform sampler2D bumpMap;
uniform sampler2D prepassTex;
uniform sampler2D reflectMap;
uniform sampler2D refractBuff;
uniform samplerCUBE skyMap;
uniform sampler2D foamMap;
uniform vec4 specularColor;
uniform float specularPower;
uniform vec4 baseColor;
uniform vec4 miscParams;
uniform vec2 fogParams;
uniform vec4 reflectParams;
uniform vec3 reflectNormal;
uniform vec2 wetnessParams;
uniform float farPlaneDist;
uniform vec3 distortionParams;
//uniform vec4 renderTargetParams;
uniform vec2 foamParams;
uniform vec3 foamColorMod;
uniform vec3 ambientColor;
uniform vec3 eyePos;
uniform vec3 inLightVec;
uniform vec3 fogData;
uniform vec4 fogColor;
//uniform vec4 rtParams;
uniform vec2 rtScale;
uniform vec2 rtHalfPixel;
uniform vec4 rtOffset;
uniform vec3 rippleMagnitude;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
void main()
{
vec4 rtParams = vec4( rtOffset.x / rtOffset.z + rtHalfPixel.x,
rtOffset.y / rtOffset.w + rtHalfPixel.x,
rtScale );
// Modulate baseColor by the ambientColor.
vec4 waterBaseColor = baseColor * vec4( ambientColor.rgb, 1 );
// Get the bumpNorm...
vec3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ) * 2.0 - 1.0 ) * rippleMagnitude.x;
bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord01.zw ) * 2.0 - 1.0 ) * rippleMagnitude.y;
bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord2 ) * 2.0 - 1.0 ) * rippleMagnitude.z;
// JCF: this was here, but seems to make the dot product against the bump
// normal we use below for cubeMap fade-in to be less reliable.
//bumpNorm.xy *= 0.75;
//bumpNorm = normalize( bumpNorm );
//return vec4( bumpNorm, 1 );
// Get depth of the water surface (this pixel).
// Convert from WorldSpace to EyeSpace.
float pixelDepth = IN.pixelDist / farPlaneDist;
// Get prepass depth at the undistorted pixel.
//vec4 prepassCoord = IN.posPostWave;
//prepassCoord.xy += renderTargetParams.xy;
vec2 prepassCoord = viewportCoordToRenderTarget( IN.posPostWave, rtParams );
//vec2 prepassCoord = IN.posPostWave.xy;
float startDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w;
//return vec4( startDepth.rrr, 1 );
// The water depth in world units of the undistorted pixel.
float startDelta = ( startDepth - pixelDepth );
if ( startDelta <= 0.0 )
{
//return vec4( 1, 0, 0, 1 );
startDelta = 0;
}
startDelta *= farPlaneDist;
// Calculate the distortion amount for the water surface.
//
// We subtract a little from it so that we don't
// distort where the water surface intersects the
// camera near plane.
float distortAmt = saturate( ( IN.pixelDist - DISTORT_START_DIST ) / DISTORT_END_DIST );
// Scale down distortion in shallow water.
distortAmt *= saturate( startDelta / DISTORT_FULL_DEPTH );
//distortAmt = 0;
// Do the intial distortion... we might remove it below.
vec2 distortDelta = bumpNorm.xy * distortAmt;
vec4 distortPos = IN.posPostWave;
distortPos.xy += distortDelta;
prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams );
//prepassCoord = distortPos;
//prepassCoord.xy += renderTargetParams.xy;
// Get prepass depth at the position of this distorted pixel.
float prepassDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w;
float delta = ( prepassDepth - pixelDepth ) * farPlaneDist;
if ( delta < 0.0 )
{
// If we got a negative delta then the distorted
// sample is above the water surface. Mask it out
// by removing the distortion.
distortPos = IN.posPostWave;
delta = startDelta;
distortAmt = 0;
}
else
{
float diff = ( prepassDepth - startDepth ) * farPlaneDist;
if ( diff < 0 )
{
distortAmt = saturate( ( IN.pixelDist - DISTORT_START_DIST ) / DISTORT_END_DIST );
distortAmt *= saturate( delta / DISTORT_FULL_DEPTH );
distortDelta = bumpNorm.xy * distortAmt;
distortPos = IN.posPostWave;
distortPos.xy += distortDelta;
prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams );
//prepassCoord = distortPos;
//prepassCoord.xy += renderTargetParams.xy;
// Get prepass depth at the position of this distorted pixel.
prepassDepth = prepassUncondition( tex2D( prepassTex, prepassCoord ) ).w;
delta = ( prepassDepth - pixelDepth ) * farPlaneDist;
}
if ( delta < 0.1 )
{
// If we got a negative delta then the distorted
// sample is above the water surface. Mask it out
// by removing the distortion.
distortPos = IN.posPostWave;
delta = startDelta;
distortAmt = 0;
}
}
//return vec4( prepassDepth.rrr, 1 );
vec4 temp = IN.posPreWave;
temp.xy += bumpNorm.xy * distortAmt;
vec2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams );
vec2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams );
// Use cubemap colors instead of reflection colors in several cases...
// First lookup the CubeMap color
// JCF: which do we want to use here, the reflectNormal or the bumpNormal
// neithor of them is exactly right and how can we combine the two together?
//bumpNorm = reflectNormal;
vec3 eyeVec = IN.worldPos - eyePos;
vec3 reflectionVec = reflect( eyeVec, bumpNorm );
//vec4 cubeColor = texCUBE( skyMap, reflectionVec );
//return cubeColor;
// JCF: using ambient color instead of cubeColor for waterPlane, how do we still use the cubemap for rivers?
vec4 cubeColor = vec4(ambientColor,1);
//cubeColor.rgb = vec3( 0, 0, 1 );
// Use cubeColor for waves that are angled towards camera
eyeVec = -eyeVec;
eyeVec = normalize( eyeVec );
float ang = saturate( dot( eyeVec, bumpNorm ) );
float cubeAmt = ang;
//float rplaneDist = (reflectPlane.x * IN.pos.x + reflectPlane.y * IN.pos.y + reflectPlane.z * IN.pos.z) + reflectPlane.w;
//rplaneDist = saturate( abs( rplaneDist ) / 0.5 );
//#ifdef RIVER
// for verts far from the reflect plane z position
float rplaneDist = abs( REFLECT_PLANE_Z - IN.worldPos.z );
rplaneDist = saturate( ( rplaneDist - 1.0 ) / 2.0 );
//rplaneDist = REFLECT_PLANE_Z / eyePos.z;
rplaneDist *= ISRIVER;
cubeAmt = max( cubeAmt, rplaneDist );
//#endif
//rplaneDist = IN.worldPos.z / eyePos.z;
//return vec4( rplaneDist.rrr, 1 );
//return vec4( (reflectParams[REFLECT_PLANE_Z] / 86.0 ).rrr, 1 );
// and for verts farther from the camera
//float cubeAmt = ( eyeDist - reflectParams[REFLECT_MIN_DIST] ) / ( reflectParams[REFLECT_MAX_DIST] - reflectParams[REFLECT_MIN_DIST] );
//cubeAmt = saturate ( cubeAmt );
//float temp = ( eyeDist - reflectParams[REFLECT_MIN_DIST] ) / ( reflectParams[REFLECT_MAX_DIST] - reflectParams[REFLECT_MIN_DIST] );
//temp = saturate ( temp );
// If the camera is very very close to the reflect plane.
//float eyeToPlaneDist = eyePos.z - REFLECT_PLANE_Z; // dot( reflectNormal, eyePos ) + REFLECT_PLANE_Z;
//eyeToPlaneDist = abs( eyeToPlaneDist );
//eyeToPlaneDist = 1.0 - saturate( abs( eyeToPlaneDist ) / 1 );
//return vec4( eyeToPlaneDist.rrr, 1 );
//cubeAmt = max( cubeAmt, eyeToPlaneDist );
//cubeAmt = max( cubeAmt, rplaneDist );
//cubeAmt = max( cubeAmt, ang );
//cubeAmt = max( cubeAmt, rplaneDist );
//cubeAmt = max( cubeAmt, IN.depth.w );
// All cubemap if fullReflect is specifically user disabled
cubeAmt = max( cubeAmt, NO_REFLECT );
#ifndef UNDERWATER
// Get foam color and amount
IN.foamTexCoords.xy += distortDelta * 0.5;
IN.foamTexCoords.zw += distortDelta * 0.5;
vec4 foamColor = tex2D( foamMap, IN.foamTexCoords.xy );
foamColor += tex2D( foamMap, IN.foamTexCoords.zw );
//foamColor += tex2D( foamMap, IN.rippleTexCoord2 ) * 0.3;
foamColor = saturate( foamColor );
// Modulate foam color by ambient color so we don't have glowing white
// foam at night.
foamColor.rgb = lerp( foamColor.rgb, ambientColor.rgb, foamColorMod.rgb );
float foamDelta = saturate( delta / FOAM_MAX_DEPTH );
float foamAmt = 1.0 - foamDelta;
// Fade out the foam in very very low depth,
// this improves the shoreline a lot.
float diff = 0.8 - foamAmt;
if ( diff < 0.0 )
{
//return vec4( 1,0,0,1 );
foamAmt -= foamAmt * abs( diff ) / 0.2;
}
//return vec4( foamAmt.rrr, 1 );
foamAmt *= FOAM_SCALE * foamColor.a;
//return vec4( foamAmt.rrr, 1 );
// Get reflection map color
vec4 refMapColor = tex2D( reflectMap, reflectCoord );
//cubeAmt = 0;
// Combine cube and foam colors into reflect color
vec4 reflectColor = lerp( refMapColor, cubeColor, cubeAmt );
//return refMapColor;
// This doesn't work because REFLECT_PLANE_Z is in worldSpace
// while eyePos is actually in objectSpace!
//float eyeToPlaneDist = eyePos.z - REFLECT_PLANE_Z; // dot( reflectNormal, eyePos ) + REFLECT_PLANE_Z;
//float transitionFactor = 1.0 - saturate( ( abs( eyeToPlaneDist ) - 0.5 ) / 5 );
//reflectColor = lerp( reflectColor, waterBaseColor, transitionFactor );
//return reflectColor;
// Get refract color
vec4 refractColor = tex2D( refractBuff, refractCoord );
//return refractColor;
// We darken the refraction color a bit to make underwater
// elements look wet. We fade out this darkening near the
// surface in order to not have hard water edges.
// @param WET_DEPTH The depth in world units at which full darkening will be recieved.
// @param WET_COLOR_FACTOR The refract color is scaled down by this amount when at WET_DEPTH
refractColor.rgb *= 1.0f - ( saturate( delta / WET_DEPTH ) * WET_COLOR_FACTOR );
// Add Water fog/haze.
float fogDelta = delta - FOG_DENSITY_OFFSET;
//return vec4( fogDelta.rrr, 1 );
if ( fogDelta < 0.0 )
fogDelta = 0.0;
float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * fogDelta ) );
//return vec4( fogAmt.rrr, 1 );
// calc "diffuse" color by lerping from the water color
// to refraction image based on the water clarity.
vec4 diffuseColor = lerp( refractColor, waterBaseColor, fogAmt );
// fresnel calculation
float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER );
//return vec4( fresnelTerm.rrr, 1 );
// Scale the frensel strength by fog amount
// so that parts that are very clear get very little reflection.
fresnelTerm *= fogAmt;
//return vec4( fresnelTerm.rrr, 1 );
// Also scale the frensel by our distance to the
// water surface. This removes the hard reflection
// when really close to the water surface.
fresnelTerm *= saturate( IN.pixelDist - 0.1 );
// Combine the diffuse color and reflection image via the
// fresnel term and set out output color.
vec4 gl_FragColor = lerp( diffuseColor, reflectColor, fresnelTerm );
//float brightness = saturate( 1.0 - ( waterHeight - eyePosWorld.z - 5.0 ) / 50.0 );
//gl_FragColor.rgb *= brightness;
#else
vec4 refractColor = tex2D( refractBuff, refractCoord );
vec4 gl_FragColor = refractColor;
#endif
#ifndef UNDERWATER
gl_FragColor.rgb = lerp( gl_FragColor.rgb, foamColor.rgb, foamAmt );
#endif
gl_FragColor.a = 1.0;
// specular experiments
// 1:
/*
float fDot = dot( bumpNorm, inLightVec );
vec3 reflect = normalize( 2.0 * bumpNorm * fDot - eyeVec );
// float specular = saturate(dot( reflect, inLightVec ) );
float specular = pow( reflect, specularPower );
gl_FragColor += specularColor * specular;
*/
// 2: This almost looks good
/*
bumpNorm.xy *= 2.0;
bumpNorm = normalize( bumpNorm );
vec3 halfAng = normalize( eyeVec + inLightVec );
float specular = saturate( dot( bumpNorm, halfAng) );
specular = pow(specular, specularPower);
gl_FragColor += specularColor * specular;
*/
#ifndef UNDERWATER
float factor = computeSceneFog( eyePos,
IN.fogPos,
IN.worldSpaceZ,
fogData.x,
fogData.y,
fogData.z );
gl_FragColor.rgb = lerp( gl_FragColor.rgb, fogColor.rgb, 1.0 - saturate( factor ) );
#endif
//return vec4( refMapColor.rgb, 1 );
gl_FragColor.a = 1.0;
return gl_FragColor;
}

View file

@ -0,0 +1,177 @@
//-----------------------------------------------------------------------------
// 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 "shadergen:/autogenConditioners.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
// waveData
#define WAVE_SPEED(i) waveData[i].x
#define WAVE_MAGNITUDE(i) waveData[i].y
// Outgoing data
// Worldspace position of this pixel
varying vec3 worldPos;
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
varying vec4 rippleTexCoord01;
// TexCoord 2 for ripple texture lookup
varying vec2 rippleTexCoord2;
// Screenspace vert position BEFORE wave transformation
varying vec4 posPreWave;
// Screenspace vert position AFTER wave transformation
varying vec4 posPostWave;
// Worldspace unit distance/depth of this vertex/pixel
varying float pixelDist;
varying vec3 fogPos;
varying float worldSpaceZ;
varying vec4 foamTexCoords;
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform mat4 modelMat;
uniform mat4 modelview;
uniform mat3 cubeTrans;
uniform mat4 objTrans;
uniform vec3 cubeEyePos;
uniform vec3 eyePos;
uniform vec2 waveDir[3];
uniform vec2 waveData[3];
uniform vec2 rippleDir[3];
uniform vec2 rippleTexScale[3];
uniform vec3 rippleSpeed;
uniform vec2 reflectTexSize;
uniform vec3 inLightVec;
uniform vec3 reflectNormal;
uniform float gridElementSize;
uniform float elapsedTime;
uniform float undulateMaxDist;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
void main()
{
// Copy incoming attributes into locals so we can modify them in place.
vec4 position = gl_Vertex.xyzw;
vec3 normal = gl_Normal.xyz;
vec2 undulateData = gl_MultiTexCoord0.st;
vec4 horizonFactor = gl_MultiTexCoord1.xyzw;
// use projection matrix for reflection / refraction texture coords
mat4 texGen = { 0.5, 0.0, 0.0, 0.5, //+ 0.5 / reflectTexSize.x,
0.0, 0.5, 0.0, 0.5, //+ 1.0 / reflectTexSize.y,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
// Move the vertex based on the horizonFactor if specified to do so for this vert.
if ( horizonFactor.z > 0 )
{
vec2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize;
position.xy += offsetXY;
undulateData += offsetXY;
}
fogPos = position;
position.z = mix( position.z, eyePos.z, horizonFactor.x );
// Send pre-undulation screenspace position
posPreWave = modelview * position;
posPreWave = texGen * posPreWave;
// Calculate the undulation amount for this vertex.
vec2 undulatePos = undulateData;
float undulateAmt = 0;
for ( int i = 0; i < 3; i++ )
{
undulateAmt += WAVE_MAGNITUDE(i) * sin( elapsedTime * WAVE_SPEED(i) +
undulatePos.x * waveDir[i].x +
undulatePos.y * waveDir[i].y );
}
// Scale down wave magnitude amount based on distance from the camera.
float dist = distance( position, eyePos );
dist = clamp( dist, 1.0, undulateMaxDist );
undulateAmt *= ( 1 - dist / undulateMaxDist );
// Also scale down wave magnitude if the camera is very very close.
undulateAmt *= clamp( ( distance( IN.position, eyePos ) - 0.5 ) / 10.0, 0.0, 1.0 );
// Apply wave undulation to the vertex.
posPostWave = position;
posPostWave.xyz += normal.xyz * undulateAmt;
// Save worldSpace position of this pixel/vert
worldPos = posPostWave.xyz;
// Convert to screen
posPostWave = modelview * posPostWave;
// Setup the OUT position symantic variable
gl_Position = posPostWave;
gl_Position.z = mix(gl_Position.z, gl_Position.w, horizonFactor.x);
worldSpaceZ = modelMat * vec4(fogPos, 1.0) ).z;
if ( horizonFactor.x > 0.0 )
{
vec3 awayVec = normalize( fogPos.xyz - eyePos );
fogPos.xy += awayVec.xy * 1000.0;
}
// Save world space camera dist/depth of the outgoing pixel
pixelDist = gl_Position.z;
// Convert to reflection texture space
posPostWave = texGen * posPostWave;
float2 ripplePos = undulateData;
float2 txPos = normalize( ripplePos );
txPos *= 50000.0;
ripplePos = mix( ripplePos, txPos, IN.horizonFactor.x );
// set up tex coordinates for the 3 interacting normal maps
rippleTexCoord01.xy = mix( ripplePos * rippleTexScale[0], txPos.xy * rippleTexScale[0], IN.horizonFactor.x );
rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x;
rippleTexCoord01.zw = mix( ripplePos * rippleTexScale[1], txPos.xy * rippleTexScale[1], IN.horizonFactor.x );
rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y;
rippleTexCoord2.xy = mix( ripplePos * rippleTexScale[2], txPos.xy * rippleTexScale[2], IN.horizonFactor.x );
rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z;
foamTexCoords.xy = mix( ripplePos * 0.2, txPos.xy * rippleTexScale[0], IN.horizonFactor.x );
foamTexCoords.xy += rippleDir[0] * sin( ( elapsedTime + 500.0 ) * -0.4 ) * 0.15;
foamTexCoords.zw = mix( ripplePos * 0.3, txPos.xy * rippleTexScale[1], IN.horizonFactor.x );
foamTexCoords.zw += rippleDir[1] * sin( elapsedTime * 0.4 ) * 0.15;
}

View file

@ -0,0 +1,213 @@
//-----------------------------------------------------------------------------
// 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"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
// miscParams
#define FRESNEL_BIAS miscParams[0]
#define FRESNEL_POWER miscParams[1]
#define CLARITY miscParams[2]
#define ISRIVER miscParams[3]
// reflectParams
#define REFLECT_PLANE_Z reflectParams[0]
#define REFLECT_MIN_DIST reflectParams[1]
#define REFLECT_MAX_DIST reflectParams[2]
#define NO_REFLECT reflectParams[3]
// distortionParams
#define DISTORT_START_DIST distortionParams[0]
#define DISTORT_END_DIST distortionParams[1]
#define DISTORT_FULL_DEPTH distortionParams[2]
// ConnectData.misc
#define LIGHT_VEC IN.misc.xyz
#define WORLD_Z IN.objPos.w
// specularParams
#define SPEC_POWER specularParams[3]
#define SPEC_COLOR specularParams.xyz
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct ConnectData
{
float4 hpos : POSITION;
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
float4 rippleTexCoord01 : TEXCOORD0;
// TexCoord 2 for ripple texture lookup
float2 rippleTexCoord2 : TEXCOORD1;
// Screenspace vert position BEFORE wave transformation
float4 posPreWave : TEXCOORD2;
// Screenspace vert position AFTER wave transformation
float4 posPostWave : TEXCOORD3;
// Worldspace unit distance/depth of this vertex/pixel
float pixelDist : TEXCOORD4;
// Objectspace vert position BEFORE wave transformation
// w coord is world space z position.
float4 objPos : TEXCOORD5;
float3 misc : TEXCOORD6;
};
//-----------------------------------------------------------------------------
// approximate Fresnel function
//-----------------------------------------------------------------------------
float fresnel(float NdotV, float bias, float power)
{
return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power);
}
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform sampler bumpMap : register( S0 );
//uniform sampler2D prepassTex : register( S1 );
uniform sampler2D reflectMap : register( S2 );
uniform sampler refractBuff : register( S3 );
uniform samplerCUBE skyMap : register( S4 );
//uniform sampler foamMap : register( S5 );
uniform float4 baseColor;
uniform float4 miscParams;
uniform float4 reflectParams;
uniform float3 ambientColor;
uniform float3 eyePos;
uniform float3 distortionParams;
uniform float3 fogData;
uniform float4 fogColor;
uniform float4 rippleMagnitude;
uniform float4 specularParams;
uniform float4x4 modelMat;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
float4 main( ConnectData IN ) : COLOR
{
// Modulate baseColor by the ambientColor.
float4 waterBaseColor = baseColor * float4( ambientColor.rgb, 1 );
// Get the bumpNorm...
float3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x;
bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y;
bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord2 ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z;
bumpNorm = normalize( bumpNorm );
bumpNorm = lerp( bumpNorm, float3(0,0,1), 1.0 - rippleMagnitude.w );
// We subtract a little from it so that we don't
// distort where the water surface intersects the
// camera near plane.
float distortAmt = saturate( IN.pixelDist / 1.0 ) * 0.8;
float4 distortPos = IN.posPostWave;
distortPos.xy += bumpNorm.xy * distortAmt;
#ifdef UNDERWATER
return hdrEncode( tex2Dproj( refractBuff, distortPos ) );
#else
float3 eyeVec = IN.objPos.xyz - eyePos;
eyeVec = mul( (float3x3)modelMat, eyeVec );
float3 reflectionVec = reflect( eyeVec, bumpNorm );
// Color that replaces the reflection color when we do not
// have one that is appropriate.
float4 fakeColor = float4(ambientColor,1);
// Use fakeColor for ripple-normals that are angled towards the camera
eyeVec = -eyeVec;
eyeVec = normalize( eyeVec );
float ang = saturate( dot( eyeVec, bumpNorm ) );
float fakeColorAmt = ang;
// Get reflection map color
float4 refMapColor = hdrDecode( tex2Dproj( reflectMap, distortPos ) );
// If we do not have a reflection texture then we use the cubemap.
refMapColor = lerp( refMapColor, texCUBE( skyMap, reflectionVec ), NO_REFLECT );
// Combine reflection color and fakeColor.
float4 reflectColor = lerp( refMapColor, fakeColor, fakeColorAmt );
//return refMapColor;
// Get refract color
float4 refractColor = hdrDecode( tex2Dproj( refractBuff, distortPos ) );
// calc "diffuse" color by lerping from the water color
// to refraction image based on the water clarity.
float4 diffuseColor = lerp( refractColor, waterBaseColor, 1.0f - CLARITY );
// fresnel calculation
float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER );
//return float4( fresnelTerm.rrr, 1 );
// Also scale the frensel by our distance to the
// water surface. This removes the hard reflection
// when really close to the water surface.
fresnelTerm *= saturate( IN.pixelDist - 0.1 );
// Combine the diffuse color and reflection image via the
// fresnel term and set out output color.
float4 OUT = lerp( diffuseColor, reflectColor, fresnelTerm );
#ifdef WATER_SPEC
// Get some specular reflection.
float3 newbump = bumpNorm;
newbump.xy *= 3.5;
newbump = normalize( bumpNorm );
half3 halfAng = normalize( eyeVec + -LIGHT_VEC );
float specular = saturate( dot( newbump, halfAng ) );
specular = pow( specular, SPEC_POWER );
OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx );
#else // Disable fogging if spec is on because otherwise we run out of instructions.
// Fog it.
float factor = computeSceneFog( eyePos,
IN.objPos,
WORLD_Z,
fogData.x,
fogData.y,
fogData.z );
//OUT.rgb = lerp( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) );
#endif
return hdrEncode( OUT );
#endif
}

View file

@ -0,0 +1,236 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct VertData
{
float4 position : POSITION;
float3 normal : NORMAL;
float2 undulateData : TEXCOORD0;
float4 horizonFactor : TEXCOORD1;
};
struct ConnectData
{
float4 hpos : POSITION;
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
float4 rippleTexCoord01 : TEXCOORD0;
// TexCoord 2 for ripple texture lookup
float2 rippleTexCoord2 : TEXCOORD1;
// Screenspace vert position BEFORE wave transformation
float4 posPreWave : TEXCOORD2;
// Screenspace vert position AFTER wave transformation
float4 posPostWave : TEXCOORD3;
// Worldspace unit distance/depth of this vertex/pixel
float pixelDist : TEXCOORD4;
// Objectspace vert position BEFORE wave transformation
// w coord is world space z position.
float4 objPos : TEXCOORD5;
float3 misc : TEXCOORD6;
};
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform float4x4 modelMat;
uniform float4x4 modelview;
uniform float4 rippleMat[3];
uniform float3 eyePos;
uniform float2 waveDir[3];
uniform float2 waveData[3];
uniform float2 rippleDir[3];
uniform float2 rippleTexScale[3];
uniform float3 rippleSpeed;
uniform float3 inLightVec;
uniform float3 reflectNormal;
uniform float gridElementSize;
uniform float elapsedTime;
uniform float undulateMaxDist;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
ConnectData main( VertData IN )
{
ConnectData OUT;
// use projection matrix for reflection / refraction texture coords
float4x4 texGen = { 0.5, 0.0, 0.0, 0.5,
0.0, -0.5, 0.0, 0.5,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
// Move the vertex based on the horizonFactor if specified to do so for this vert.
// if ( IN.horizonFactor.z > 0 )
// {
// float2 offsetXY = eyePos.xy - eyePos.xy % gridElementSize;
// IN.position.xy += offsetXY;
// IN.undulateData += offsetXY;
// }
float4 worldPos = mul( modelMat, IN.position );
IN.position.z = lerp( IN.position.z, eyePos.z, IN.horizonFactor.x );
//OUT.objPos = worldPos;
OUT.objPos.xyz = IN.position.xyz;
OUT.objPos.w = worldPos.z;
// Send pre-undulation screenspace position
OUT.posPreWave = mul( modelview, IN.position );
OUT.posPreWave = mul( texGen, OUT.posPreWave );
// Calculate the undulation amount for this vertex.
float2 undulatePos = mul( modelMat, float4( IN.undulateData.xy, 0, 1 ) );
//if ( undulatePos.x < 0 )
// undulatePos = IN.position.xy;
float undulateAmt = 0.0;
undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x +
undulatePos.x * waveDir[0].x +
undulatePos.y * waveDir[0].y );
undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x +
undulatePos.x * waveDir[1].x +
undulatePos.y * waveDir[1].y );
undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x +
undulatePos.x * waveDir[2].x +
undulatePos.y * waveDir[2].y );
float undulateFade = 1;
// Scale down wave magnitude amount based on distance from the camera.
float dist = distance( IN.position.xyz, eyePos );
dist = clamp( dist, 1.0, undulateMaxDist );
undulateFade *= ( 1 - dist / undulateMaxDist );
// Also scale down wave magnitude if the camera is very very close.
undulateFade *= saturate( ( distance( IN.position.xyz, eyePos ) - 0.5 ) / 10.0 );
undulateAmt *= undulateFade;
//#endif
//undulateAmt = 0;
// Apply wave undulation to the vertex.
OUT.posPostWave = IN.position;
OUT.posPostWave.xyz += IN.normal.xyz * undulateAmt;
// Save worldSpace position of this pixel/vert
//OUT.worldPos = OUT.posPostWave.xyz;
//OUT.worldPos = mul( modelMat, OUT.posPostWave.xyz );
//OUT.worldPos.z += objTrans[2][2]; //91.16;
// OUT.misc.w = mul( modelMat, OUT.fogPos ).z;
// if ( IN.horizonFactor.x > 0 )
// {
// float3 awayVec = normalize( OUT.fogPos.xyz - eyePos );
// OUT.fogPos.xy += awayVec.xy * 1000.0;
// }
// Convert to screen
OUT.posPostWave = mul( modelview, OUT.posPostWave ); // mul( modelview, float4( OUT.posPostWave.xyz, 1 ) );
// Setup the OUT position symantic variable
OUT.hpos = OUT.posPostWave; // mul( modelview, float4( IN.position.xyz, 1 ) ); //float4( OUT.posPostWave.xyz, 1 );
//OUT.hpos.z = lerp( OUT.hpos.z, OUT.hpos.w, IN.horizonFactor.x );
// Save world space camera dist/depth of the outgoing pixel
OUT.pixelDist = OUT.hpos.z;
// Convert to reflection texture space
OUT.posPostWave = mul( texGen, OUT.posPostWave );
float2 txPos = undulatePos;
if ( IN.horizonFactor.x )
txPos = normalize( txPos ) * 50000.0;
// set up tex coordinates for the 3 interacting normal maps
OUT.rippleTexCoord01.xy = txPos * rippleTexScale[0];
OUT.rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x;
float2x2 texMat;
texMat[0][0] = rippleMat[0].x;
texMat[0][1] = rippleMat[0].y;
texMat[1][0] = rippleMat[0].z;
texMat[1][1] = rippleMat[0].w;
OUT.rippleTexCoord01.xy = mul( texMat, OUT.rippleTexCoord01.xy );
OUT.rippleTexCoord01.zw = txPos * rippleTexScale[1];
OUT.rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y;
texMat[0][0] = rippleMat[1].x;
texMat[0][1] = rippleMat[1].y;
texMat[1][0] = rippleMat[1].z;
texMat[1][1] = rippleMat[1].w;
OUT.rippleTexCoord01.zw = mul( texMat, OUT.rippleTexCoord01.zw );
OUT.rippleTexCoord2.xy = txPos * rippleTexScale[2];
OUT.rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z;
texMat[0][0] = rippleMat[2].x;
texMat[0][1] = rippleMat[2].y;
texMat[1][0] = rippleMat[2].z;
texMat[1][1] = rippleMat[2].w;
OUT.rippleTexCoord2.xy = mul( texMat, OUT.rippleTexCoord2.xy );
#ifdef WATER_SPEC
float3 binormal = float3( 1, 0, 0 );
float3 tangent = float3( 0, 1, 0 );
float3 normal;
for ( int i = 0; i < 3; i++ )
{
binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * IN.undulateData.x + waveDir[i].y * IN.undulateData.y + elapsedTime * waveData[i].x );
tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * IN.undulateData.x + waveDir[i].y * IN.undulateData.y + elapsedTime * waveData[i].x );
}
binormal = normalize( binormal );
tangent = normalize( tangent );
normal = cross( binormal, tangent );
float3x3 worldToTangent;
worldToTangent[0] = binormal;
worldToTangent[1] = tangent;
worldToTangent[2] = normal;
OUT.misc.xyz = mul( inLightVec, modelMat );
OUT.misc.xyz = mul( worldToTangent, OUT.misc.xyz );
#else
OUT.misc.xyz = inLightVec;
#endif
return OUT;
}

View file

@ -0,0 +1,383 @@
//-----------------------------------------------------------------------------
// 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 "shadergen:/autogenConditioners.h"
#include "../torque.hlsl"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#define PIXEL_DIST IN.rippleTexCoord2.z
// miscParams
#define FRESNEL_BIAS miscParams[0]
#define FRESNEL_POWER miscParams[1]
// miscParams[2] is unused
#define ISRIVER miscParams[3]
// reflectParams
#define REFLECT_PLANE_Z reflectParams[0]
#define REFLECT_MIN_DIST reflectParams[1]
#define REFLECT_MAX_DIST reflectParams[2]
#define NO_REFLECT reflectParams[3]
// fogParams
#define FOG_DENSITY fogParams[0]
#define FOG_DENSITY_OFFSET fogParams[1]
// wetnessParams
#define WET_DEPTH wetnessParams[0]
#define WET_COLOR_FACTOR wetnessParams[1]
// distortionParams
#define DISTORT_START_DIST distortionParams[0]
#define DISTORT_END_DIST distortionParams[1]
#define DISTORT_FULL_DEPTH distortionParams[2]
// foamParams
#define FOAM_OPACITY foamParams[0]
#define FOAM_MAX_DEPTH foamParams[1]
#define FOAM_AMBIENT_LERP foamParams[2]
#define FOAM_RIPPLE_INFLUENCE foamParams[3]
// specularParams
#define SPEC_POWER specularParams[3]
#define SPEC_COLOR specularParams.xyz
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct ConnectData
{
float4 hpos : POSITION;
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
float4 rippleTexCoord01 : TEXCOORD0;
// xy is TexCoord 2 for ripple texture lookup
// z is the Worldspace unit distance/depth of this vertex/pixel
// w is amount of the crestFoam ( more at crest of waves ).
float4 rippleTexCoord2 : TEXCOORD1;
// Screenspace vert position BEFORE wave transformation
float4 posPreWave : TEXCOORD2;
// Screenspace vert position AFTER wave transformation
float4 posPostWave : TEXCOORD3;
// Objectspace vert position BEFORE wave transformation
// w coord is world space z position.
float4 objPos : TEXCOORD4;
float4 foamTexCoords : TEXCOORD5;
float3x3 tangentMat : TEXCOORD6;
};
//-----------------------------------------------------------------------------
// approximate Fresnel function
//-----------------------------------------------------------------------------
float fresnel(float NdotV, float bias, float power)
{
return bias + (1.0-bias)*pow(abs(1.0 - max(NdotV, 0)), power);
}
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform sampler bumpMap : register( S0 );
uniform sampler2D prepassTex : register( S1 );
uniform sampler2D reflectMap : register( S2 );
uniform sampler refractBuff : register( S3 );
uniform samplerCUBE skyMap : register( S4 );
uniform sampler foamMap : register( S5 );
uniform sampler1D depthGradMap : register( S6 );
uniform float4 specularParams;
uniform float4 baseColor;
uniform float4 miscParams;
uniform float2 fogParams;
uniform float4 reflectParams;
uniform float3 reflectNormal;
uniform float2 wetnessParams;
uniform float farPlaneDist;
uniform float3 distortionParams;
uniform float4 foamParams;
uniform float3 ambientColor;
uniform float3 eyePos; // This is in object space!
uniform float3 fogData;
uniform float4 fogColor;
uniform float4 rippleMagnitude;
uniform float4 rtParams1;
uniform float depthGradMax;
uniform float3 inLightVec;
uniform float4x4 modelMat;
uniform float4 sunColor;
uniform float sunBrightness;
uniform float reflectivity;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
float4 main( ConnectData IN ) : COLOR
{
// Get the bumpNorm...
float3 bumpNorm = ( tex2D( bumpMap, IN.rippleTexCoord01.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.x;
bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord01.zw ).rgb * 2.0 - 1.0 ) * rippleMagnitude.y;
bumpNorm += ( tex2D( bumpMap, IN.rippleTexCoord2.xy ).rgb * 2.0 - 1.0 ) * rippleMagnitude.z;
bumpNorm = normalize( bumpNorm );
bumpNorm = lerp( bumpNorm, float3(0,0,1), 1.0 - rippleMagnitude.w );
bumpNorm = mul( bumpNorm, IN.tangentMat );
// Get depth of the water surface (this pixel).
// Convert from WorldSpace to EyeSpace.
float pixelDepth = PIXEL_DIST / farPlaneDist;
float2 prepassCoord = viewportCoordToRenderTarget( IN.posPostWave, rtParams1 );
float startDepth = prepassUncondition( prepassTex, prepassCoord ).w;
// The water depth in world units of the undistorted pixel.
float startDelta = ( startDepth - pixelDepth );
startDelta = max( startDelta, 0.0 );
startDelta *= farPlaneDist;
// Calculate the distortion amount for the water surface.
//
// We subtract a little from it so that we don't
// distort where the water surface intersects the
// camera near plane.
float distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST );
// Scale down distortion in shallow water.
distortAmt *= saturate( startDelta / DISTORT_FULL_DEPTH );
// Do the intial distortion... we might remove it below.
float2 distortDelta = bumpNorm.xy * distortAmt;
float4 distortPos = IN.posPostWave;
distortPos.xy += distortDelta;
prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams1 );
// Get prepass depth at the position of this distorted pixel.
float prepassDepth = prepassUncondition( prepassTex, prepassCoord ).w;
if ( prepassDepth > 0.99 )
prepassDepth = 5.0;
float delta = ( prepassDepth - pixelDepth ) * farPlaneDist;
if ( delta < 0.0 )
{
// If we got a negative delta then the distorted
// sample is above the water surface. Mask it out
// by removing the distortion.
distortPos = IN.posPostWave;
delta = startDelta;
distortAmt = 0;
}
else
{
float diff = ( prepassDepth - startDepth ) * farPlaneDist;
if ( diff < 0 )
{
distortAmt = saturate( ( PIXEL_DIST - DISTORT_START_DIST ) / DISTORT_END_DIST );
distortAmt *= saturate( delta / DISTORT_FULL_DEPTH );
distortDelta = bumpNorm.xy * distortAmt;
distortPos = IN.posPostWave;
distortPos.xy += distortDelta;
prepassCoord = viewportCoordToRenderTarget( distortPos, rtParams1 );
// Get prepass depth at the position of this distorted pixel.
prepassDepth = prepassUncondition( prepassTex, prepassCoord ).w;
if ( prepassDepth > 0.99 )
prepassDepth = 5.0;
delta = ( prepassDepth - pixelDepth ) * farPlaneDist;
}
if ( delta < 0.1 )
{
// If we got a negative delta then the distorted
// sample is above the water surface. Mask it out
// by removing the distortion.
distortPos = IN.posPostWave;
delta = startDelta;
distortAmt = 0;
}
}
float4 temp = IN.posPreWave;
temp.xy += bumpNorm.xy * distortAmt;
float2 reflectCoord = viewportCoordToRenderTarget( temp, rtParams1 );
float2 refractCoord = viewportCoordToRenderTarget( distortPos, rtParams1 );
float4 fakeColor = float4(ambientColor,1);
float3 eyeVec = IN.objPos.xyz - eyePos;
eyeVec = mul( (float3x3)modelMat, eyeVec );
eyeVec = mul( IN.tangentMat, eyeVec );
float3 reflectionVec = reflect( eyeVec, bumpNorm );
// Use fakeColor for ripple-normals that are angled towards the camera
eyeVec = -eyeVec;
eyeVec = normalize( eyeVec );
float ang = saturate( dot( eyeVec, bumpNorm ) );
float fakeColorAmt = ang;
// for verts far from the reflect plane z position
float rplaneDist = abs( REFLECT_PLANE_Z - IN.objPos.w );
rplaneDist = saturate( ( rplaneDist - 1.0 ) / 2.0 );
rplaneDist *= ISRIVER;
fakeColorAmt = max( fakeColorAmt, rplaneDist );
#ifndef UNDERWATER
// Get foam color and amount
float2 foamRippleOffset = bumpNorm.xy * FOAM_RIPPLE_INFLUENCE;
IN.foamTexCoords.xy += foamRippleOffset;
IN.foamTexCoords.zw += foamRippleOffset;
float4 foamColor = tex2D( foamMap, IN.foamTexCoords.xy );
foamColor += tex2D( foamMap, IN.foamTexCoords.zw );
foamColor = saturate( foamColor );
// Modulate foam color by ambient color
// so we don't have glowing white foam at night.
foamColor.rgb = lerp( foamColor.rgb, ambientColor.rgb, FOAM_AMBIENT_LERP );
float foamDelta = saturate( delta / FOAM_MAX_DEPTH );
float foamAmt = 1 - pow( foamDelta, 2 );
// Fade out the foam in very very low depth,
// this improves the shoreline a lot.
float diff = 0.8 - foamAmt;
if ( diff < 0.0 )
foamAmt -= foamAmt * abs( diff ) / 0.2;
foamAmt *= FOAM_OPACITY * foamColor.a;
foamColor.rgb *= FOAM_OPACITY * foamAmt * foamColor.a;
// Get reflection map color.
float4 refMapColor = hdrDecode( tex2D( reflectMap, reflectCoord ) );
// If we do not have a reflection texture then we use the cubemap.
refMapColor = lerp( refMapColor, texCUBE( skyMap, reflectionVec ), NO_REFLECT );
fakeColor = ( texCUBE( skyMap, reflectionVec ) );
fakeColor.a = 1;
// Combine reflection color and fakeColor.
float4 reflectColor = lerp( refMapColor, fakeColor, fakeColorAmt );
// Get refract color
float4 refractColor = hdrDecode( tex2D( refractBuff, refractCoord ) );
// We darken the refraction color a bit to make underwater
// elements look wet. We fade out this darkening near the
// surface in order to not have hard water edges.
// @param WET_DEPTH The depth in world units at which full darkening will be recieved.
// @param WET_COLOR_FACTOR The refract color is scaled down by this amount when at WET_DEPTH
refractColor.rgb *= 1.0f - ( saturate( delta / WET_DEPTH ) * WET_COLOR_FACTOR );
// Add Water fog/haze.
float fogDelta = delta - FOG_DENSITY_OFFSET;
if ( fogDelta < 0.0 )
fogDelta = 0.0;
float fogAmt = 1.0 - saturate( exp( -FOG_DENSITY * fogDelta ) );
// Calculate the water "base" color based on depth.
float4 waterBaseColor = baseColor * tex1D( depthGradMap, saturate( delta / depthGradMax ) );
// Modulate baseColor by the ambientColor.
waterBaseColor *= float4( ambientColor.rgb, 1 );
// calc "diffuse" color by lerping from the water color
// to refraction image based on the water clarity.
float4 diffuseColor = lerp( refractColor, waterBaseColor, fogAmt );
// fresnel calculation
float fresnelTerm = fresnel( ang, FRESNEL_BIAS, FRESNEL_POWER );
// Scale the frensel strength by fog amount
// so that parts that are very clear get very little reflection.
fresnelTerm *= fogAmt;
// Also scale the frensel by our distance to the
// water surface. This removes the hard reflection
// when really close to the water surface.
fresnelTerm *= saturate( PIXEL_DIST - 0.1 );
fresnelTerm *= reflectivity;
// Combine the diffuse color and reflection image via the
// fresnel term and set out output color.
float4 OUT = lerp( diffuseColor, reflectColor, fresnelTerm );
float3 lightVec = inLightVec;
// Get some specular reflection.
float3 newbump = bumpNorm;
newbump.xy *= 3.5;
newbump = normalize( bumpNorm );
float3 halfAng = normalize( eyeVec + -lightVec );
float specular = saturate( dot( newbump, halfAng ) );
specular = pow( specular, SPEC_POWER );
// Scale down specularity in very shallow water to improve the transparency of the shoreline.
specular *= saturate( delta / 2 );
OUT.rgb = OUT.rgb + ( SPEC_COLOR * specular.xxx );
#else
float4 refractColor = hdrDecode( tex2D( refractBuff, refractCoord ) );
float4 OUT = refractColor;
#endif
#ifndef UNDERWATER
OUT.rgb = OUT.rgb + foamColor.rgb;
float factor = computeSceneFog( eyePos,
IN.objPos.xyz,
IN.objPos.w,
fogData.x,
fogData.y,
fogData.z );
OUT.rgb = lerp( OUT.rgb, fogColor.rgb, 1.0 - saturate( factor ) );
//OUT.rgb = fogColor.rgb;
#endif
OUT.a = 1.0;
//return OUT;
return hdrEncode( OUT );
}

View file

@ -0,0 +1,216 @@
//-----------------------------------------------------------------------------
// 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 "shadergen:/autogenConditioners.h"
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct VertData
{
float4 position : POSITION;
float3 normal : NORMAL;
float2 undulateData : TEXCOORD0;
float4 horizonFactor : TEXCOORD1;
};
struct ConnectData
{
float4 hpos : POSITION;
// TexCoord 0 and 1 (xy,zw) for ripple texture lookup
float4 rippleTexCoord01 : TEXCOORD0;
// xy is TexCoord 2 for ripple texture lookup
// z is the Worldspace unit distance/depth of this vertex/pixel
// w is amount of the crestFoam ( more at crest of waves ).
float4 rippleTexCoord2 : TEXCOORD1;
// Screenspace vert position BEFORE wave transformation
float4 posPreWave : TEXCOORD2;
// Screenspace vert position AFTER wave transformation
float4 posPostWave : TEXCOORD3;
// Objectspace vert position BEFORE wave transformation
// w coord is world space z position.
float4 objPos : TEXCOORD4;
float4 foamTexCoords : TEXCOORD5;
float3x3 tangentMat : TEXCOORD6;
};
//-----------------------------------------------------------------------------
// Uniforms
//-----------------------------------------------------------------------------
uniform float4x4 modelMat;
uniform float4x4 modelview;
uniform float4 rippleMat[3];
uniform float3 eyePos;
uniform float2 waveDir[3];
uniform float2 waveData[3];
uniform float2 rippleDir[3];
uniform float2 rippleTexScale[3];
uniform float3 rippleSpeed;
uniform float4 foamDir;
uniform float4 foamTexScale;
uniform float2 foamSpeed;
uniform float3 inLightVec;
uniform float gridElementSize;
uniform float elapsedTime;
uniform float undulateMaxDist;
//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------
ConnectData main( VertData IN )
{
ConnectData OUT;
// use projection matrix for reflection / refraction texture coords
float4x4 texGen = { 0.5, 0.0, 0.0, 0.5,
0.0, -0.5, 0.0, 0.5,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
IN.position.z = lerp( IN.position.z, eyePos.z, IN.horizonFactor.x );
OUT.objPos = IN.position;
OUT.objPos.w = mul( modelMat, IN.position ).z;
// Send pre-undulation screenspace position
OUT.posPreWave = mul( modelview, IN.position );
OUT.posPreWave = mul( texGen, OUT.posPreWave );
// Calculate the undulation amount for this vertex.
float2 undulatePos = mul( modelMat, float4( IN.undulateData.xy, 0, 1 ) ).xy;
float undulateAmt = 0.0;
undulateAmt += waveData[0].y * sin( elapsedTime * waveData[0].x +
undulatePos.x * waveDir[0].x +
undulatePos.y * waveDir[0].y );
undulateAmt += waveData[1].y * sin( elapsedTime * waveData[1].x +
undulatePos.x * waveDir[1].x +
undulatePos.y * waveDir[1].y );
undulateAmt += waveData[2].y * sin( elapsedTime * waveData[2].x +
undulatePos.x * waveDir[2].x +
undulatePos.y * waveDir[2].y );
float undulateFade = 1;
// Scale down wave magnitude amount based on distance from the camera.
float dist = distance( IN.position.xyz, eyePos );
dist = clamp( dist, 1.0, undulateMaxDist );
undulateFade *= ( 1 - dist / undulateMaxDist );
// Also scale down wave magnitude if the camera is very very close.
undulateFade *= saturate( ( distance( IN.position.xyz, eyePos ) - 0.5 ) / 10.0 );
undulateAmt *= undulateFade;
OUT.rippleTexCoord2.w = undulateAmt / ( waveData[0].y + waveData[1].y + waveData[2].y );
OUT.rippleTexCoord2.w = saturate( OUT.rippleTexCoord2.w - 0.2 ) / 0.8;
// Apply wave undulation to the vertex.
OUT.posPostWave = IN.position;
OUT.posPostWave.xyz += IN.normal.xyz * undulateAmt;
// Convert to screen
OUT.posPostWave = mul( modelview, OUT.posPostWave );
// Setup the OUT position symantic variable
OUT.hpos = OUT.posPostWave;
//OUT.hpos.z = lerp( OUT.hpos.z, OUT.hpos.w, IN.horizonFactor.x );
// if ( IN.horizonFactor.x > 0 )
// {
// float3 awayVec = normalize( OUT.objPos.xyz - eyePos );
// OUT.objPos.xy += awayVec.xy * 1000.0;
// }
// Save world space camera dist/depth of the outgoing pixel
OUT.rippleTexCoord2.z = OUT.hpos.z;
// Convert to reflection texture space
OUT.posPostWave = mul( texGen, OUT.posPostWave );
float2 txPos = undulatePos;
if ( IN.horizonFactor.x )
txPos = normalize( txPos ) * 50000.0;
// set up tex coordinates for the 3 interacting normal maps
OUT.rippleTexCoord01.xy = txPos * rippleTexScale[0];
OUT.rippleTexCoord01.xy += rippleDir[0] * elapsedTime * rippleSpeed.x;
float2x2 texMat;
texMat[0][0] = rippleMat[0].x;
texMat[0][1] = rippleMat[0].y;
texMat[1][0] = rippleMat[0].z;
texMat[1][1] = rippleMat[0].w;
OUT.rippleTexCoord01.xy = mul( texMat, OUT.rippleTexCoord01.xy );
OUT.rippleTexCoord01.zw = txPos * rippleTexScale[1];
OUT.rippleTexCoord01.zw += rippleDir[1] * elapsedTime * rippleSpeed.y;
texMat[0][0] = rippleMat[1].x;
texMat[0][1] = rippleMat[1].y;
texMat[1][0] = rippleMat[1].z;
texMat[1][1] = rippleMat[1].w;
OUT.rippleTexCoord01.zw = mul( texMat, OUT.rippleTexCoord01.zw );
OUT.rippleTexCoord2.xy = txPos * rippleTexScale[2];
OUT.rippleTexCoord2.xy += rippleDir[2] * elapsedTime * rippleSpeed.z;
texMat[0][0] = rippleMat[2].x;
texMat[0][1] = rippleMat[2].y;
texMat[1][0] = rippleMat[2].z;
texMat[1][1] = rippleMat[2].w;
OUT.rippleTexCoord2.xy = mul( texMat, OUT.rippleTexCoord2.xy );
OUT.foamTexCoords.xy = txPos * foamTexScale.xy + foamDir.xy * foamSpeed.x * elapsedTime;
OUT.foamTexCoords.zw = txPos * foamTexScale.zw + foamDir.zw * foamSpeed.y * elapsedTime;
float3 binormal = float3( 1, 0, 0 );
float3 tangent = float3( 0, 1, 0 );
float3 normal;
for ( int i = 0; i < 3; i++ )
{
binormal.z += undulateFade * waveDir[i].x * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x );
tangent.z += undulateFade * waveDir[i].y * waveData[i].y * cos( waveDir[i].x * undulatePos.x + waveDir[i].y * undulatePos.y + elapsedTime * waveData[i].x );
}
binormal = binormal;
tangent = tangent;
normal = cross( binormal, tangent );
float3x3 worldToTangent;
worldToTangent[0] = binormal;
worldToTangent[1] = tangent;
worldToTangent[2] = normal;
OUT.tangentMat = worldToTangent;
return OUT;
}