if( GetShaderQuality() > QUALITY_LOW )
{
bumpNormal.z = 1;//sqrt(1 - dot(bumpNormal.xy, bumpNormal.xy));
bumpNormal.xyz += vVertexNormal.xyz;
}
bumpNormal.xyz = normalize( bumpNormal );
//bumpNormal.xyz += ;
//bumpNormal.xyz = normalize( vVertexNormal.xyz + float3(bumpNormal.xy, 0) );
return bumpNormal;
}
pixout WaterLowQualityPS( v2fWater IN )
{
pixout OUT = (pixout) 0;
half3 vVertexNormal = IN.normalVec.xyz;
half3 bumpNormal = BumpGen( IN );
half3 vFinalNormal = bumpNormal;//vVertexNormal.xyz ;//( vVertexNormal.xyz + float3(bumpNormal.xy, 0) ); // opt: no normalize
bumpNormal = vFinalNormal;
// Water edge softness
half3 viewVec = normalize(IN.viewVec.xyz);
float sceneDepth = DecodeSceneDepth( sceneDepthSampler, IN.screenProj );
float waterDepth = IN.screenProj.w;
float depth = ( sceneDepth - waterDepth ) * IN.normalVec.w;
half softIntersect = saturate( SoftIntersectionFactor * depth );
// Get abs( NdotI ) and fresnel term
half NdotI = 1-abs( dot( viewVec.xyz, vFinalNormal.xyz ) );
half fFresnel= saturate( 0.5 + NdotI*NdotI*0.5);// FresnelBias + GetFresnelTex( NdotI, 0).z*FresnelScale;
//half fFresnel= 0.25 + NdotI *NdotI*0.8;// FresnelBias + GetFresnelTex( NdotI, 0).z*FresnelScale;
// Get reflection color
half2 reflNewst = (IN.envTC.xy/IN.envTC.w) + vFinalNormal.xy * 0.33;
// Should do bilinear filtering, but artefacts not much visible due to bump mapping
half4 reflectColor = tex2D(envMapSamplerRefl, reflNewst);
reflectColor += saturate(tex2D(waterGlossMapSampler,IN.Wave0.xy + vFinalNormal.xy * 0.33)-0.25)*0.125;
/*
// Get refraction
float2 refrNewst = ( IN.screenProj.xy / IN.screenProj.w );
float2 refrTC = bumpNormal.xy * 0.1;
// apply refraction masking
{
float depthRefr = tex2D( sceneDepthSampler, refrNewst + refrTC.xy * 1.15 ).r;
half fRefractionMask = (IN.viewVec.w <depthRefr );
// Apply refraction mask to bump offsets
refrTC *= fRefractionMask;
}*/
// half3 refractColor = tex2D(envMapSamplerRefr, refrNewst + refrTC * 1.15 ).xyz;
#if %SUN_SHINE
// half3 mirrorEye = ( 2 * dot( viewVec, bumpNormal) * bumpNormal - viewVec );
// half dotSpec = saturate(dot( mirrorEye.xyz, g_PS_SunLightDir ) * 0.6 + 0.4);
// half3 vSunGlow = saturate(g_PS_SunLightDir.z) *( ( pow( dotSpec, SunShinePow ) ) *SunMultiplier) * g_PS_SunColor.xyz ;
#endif
fFresnel = ( fFresnel ); //* ReflectionAmount);
half3 final= reflectColor;
#if %SUN_SHINE
// Add sun specular term
//final.xyz += vSunGlow.xyz;
#endif
//final.xyz = lerp( IN.localFogColor.xyz, final, saturate( IN.localFogColor.w / softIntersect) );
#if %_RT_FOG
final.xyz = lerp( IN.localFogColor.xyz, final, saturate( IN.localFogColor.w) );
#endif
OUT.Color.xyz = final;
OUT.Color.w = saturate(fFresnel*softIntersect);
return OUT;
}
pixout WaterPS(v2fWater IN)
{
pixout OUT = (pixout) 0;
int nQuality = GetShaderQuality(); // shader quality level
#ifdef D3D10
// workaround for usual dx10 incorrect order sampler binding
half4 c0 = 0;
c0 += tex2D(envMapSamplerRefl, IN.screenProj.xy);
c0 += tex2D(envMapSamplerRefr, IN.screenProj.xy);
c0 += tex2D(oceanBumpMapSampler, IN.screenProj.xy);
c0 += tex2D(sceneDepthSampler, IN.screenProj.xy);
c0 += tex2D(foamSampler, IN.screenProj.xy);
c0 += tex2D(waterGlossMapSampler, IN.screenProj.xy);
c0 += tex2D(foamSamplerSec, IN.screenProj.xy);
#endif
// envMapSamplerRefl sampler NA NA 0 1
// envMapSamplerRefr sampler NA NA 1 1
// oceanBumpMapSampler sampler NA NA 2 1
// sceneDepthSampler sampler NA NA 3 1
// foamSampler sampler NA NA 4 1
// waterGlossMapSampler sampler NA NA 5 1
// foamSamplerSec sampler NA NA 6 1
//OUT.Color = 1;
//return OUT;
if( !nQuality )
return WaterLowQualityPS( IN );
OUT.Color = IN.cColor *4;
OUT.Color.w = 1;
//return OUT;
#if %_RT_DEBUG0 || %_RT_DEBUG1 || %_RT_DEBUG2 || %_RT_DEBUG3
DebugOutput(OUT.Color, IN.baseTC);
return OUT;
#endif
//get shadow from sun
half fShadowOccl = 1; //1.0f - tex2Dproj(shadowOccludeMapSampler, IN.screenProj.xyzw).x;
/* Begin:: Generate normal map from 4 normal map layers */
half3 vVertexNormal = IN.normalVec.xyz;
half3 bumpNormal = BumpGen( IN );
// bumpNormal = float3(0,0,1);
half3 vFinalNormal = ( vVertexNormal.xyz + float3(bumpNormal.xy, 0) ); // opt: no normalize
// opt: - 15 alu
/* End:: Generate normal map from 4 normal map layers */
/*
// Get glossy color (used for adding detail to sun specular, and fake big waves foam) = 5 alu
half fFoamGloss = tex2D(waterGlossMapSampler, IN.Wave0.wz*0.5*2 + vFinalNormal.xy*0.1).x; // 1 alu
fFoamGloss *= tex2D(waterGlossMapSampler, -IN.Wave0.xy*0.33*2 + vFinalNormal.xy*0.1).x; // 2 alu, 1 mov
fFoamGloss *= 2; // 1 alu
// Get foam = 5 alu
half fFoam = tex2D(foamSampler, IN.baseTC.xy*2 + vFinalNormal.xy*0.3).x; // 1 alu
fFoam += tex2D(foamSampler, IN.baseTC.wz*2 + vFinalNormal.xy*0.3).x; // 2 alu
*/
half fFoamGloss = tex2D(waterGlossMapSampler, IN.Wave0.wz*0.5*2 + vFinalNormal.xy*0.1).x; // 1 alu
fFoamGloss *= tex2D(waterGlossMapSampler, -IN.Wave0.xy*0.33*2 + vFinalNormal.xy*0.1).x; // 2 alu, 1 mov
fFoamGloss *= 2; // 1 alu
// Get foam = 5 alu
half fFoam = saturate(tex2D(foamSamplerSec, IN.baseTC.xy - vFinalNormal.xy*0.1).x); // 1 alu
fFoam += tex2D(foamSampler, IN.baseTC.wz + vFinalNormal.xy*0.4).x; // 2 alu
half fFoamLuminance = saturate( fFoam -0.85 ); // 1 alu
//////////////////////////////////////////////////////////////////////////////////////////////////
// Water edge and foam softness
half3 viewVec = normalize(IN.viewVec.xyz);
float sceneDepth = DecodeSceneDepth( sceneDepthSampler, IN.screenProj );
float waterDepth = IN.screenProj.w;
float depth = ( sceneDepth - waterDepth ) * IN.normalVec.w;
half softIntersect = saturate( SoftIntersectionFactor * depth );
// soften camera intersections (and foam also) - test - using alpha blending now to save some instructions
// softIntersect *= saturate( (IN.viewVec.w - PS_NearFarClipDist.x) * 1.5);
// foamSoftIntersect *= saturate( (IN.viewVec.w - PS_NearFarClipDist.x) * 0.75);
//////////////////////////////////////////////////////////////////////////////////////////////////
// Get abs( NdotI ) and fresnel term
half NdotI = (dot( viewVec.xyz, vFinalNormal.xyz ) ); // need detail textures rendering for underwater reflection
//half fInsideReflection = (1 - saturate(1000.0 * (NdotI+0.1)));
half fInsideReflection = 0;
if( nQuality >= QUALITY_HIGH )
fInsideReflection = saturate(-viewVec.z*1000);
NdotI = abs( NdotI ) ;
half fInternalRefl = 0;
//if( nQuality >= QUALITY_HIGH )
// fInternalRefl = saturate(1 - (saturate(NdotI-0.25))) * fInsideReflection;
half fFresnel= GetFresnel( NdotI , 0, 5) * FresnelScale;
//////////////////////////////////////////////////////////////////////////////////////////////////
// Get reflection color
half2 reflNewst = (IN.envTC.xy/IN.envTC.w) + bumpNormal.xy * (0.33 )*0.5;
// Should do bilinear filtering, but artefacts not much visible due to bump mapping
half4 reflectColor = tex2D(envMapSamplerRefl, reflNewst);
// OUT.Color = reflectColor;
//OUT.Color.w = 1;
// foam soft isec, also add a bit of foam nearby camera intersections
half foamSoftIntersect = saturate( (0.1 / saturate(fFoamLuminance)) * (depth) );
//////////////////////////////////////////////////////////////////////////////////////////////////
// Get refraction ( using chroma dispersion )
// Compute refraction mask
float2 refrNewst = ( IN.screenProj.xy / IN.screenProj.w );
float2 refrTC = bumpNormal.xy *(0.1+ 0.1*fInsideReflection)*saturate( softIntersect*4); // Difraction amount always 0.1
//if( nQuality == QUALITY_HIGH )
{
// only hi-specs get refraction masking
// Add small bias to avoid leaking when extremelly nearby camera/water plane
const float fRefrMaskBias = 0.0001;
IN.viewVec.w += fRefrMaskBias;
#if !%NO_REFRACTION_BUMP
#if !%_RT_SAMPLE4
float depthRefr = tex2D( sceneDepthSampler, refrNewst + refrTC.xy * 1.15 ).r;
half fRefractionMask = (IN.viewVec.w <depthRefr );
// Apply refraction mask to bump offsets
refrTC *= fRefractionMask;
#else
float3 depthRefr = tex2D( sceneDepthSampler, refrNewst + refrTC.xy * 1.15 ).r;
depthRefr.y = tex2D( sceneDepthSampler, refrNewst + refrTC.xy ).r;
depthRefr.z = tex2D( sceneDepthSampler, refrNewst + refrTC.xy * 0.85 ).r;
half3 fRefractionMask = (IN.viewVec.www < depthRefr.xyz );
// Apply refraction mask to bump offsets
refrTC *= fRefractionMask.x * fRefractionMask.y * fRefractionMask.z;
#endif
#endif
}
#ifdef OPENGL
refrNewst.y = 1.0 - refrNewst.y;
#endif
half3 refractColor = 0;
#if !%NO_REFRACTION_BUMP
// Achromatic aberration taking about 2 ms. Only enable on very high specs (>=g 0
#if %_RT_SAMPLE4
// since we need bilinear filtering in HDR anyway, use 3 lookups instead and get chroma dispersion for free
// 6 instructions extra for chroma dispersion
refractColor.x = tex2D(envMapSamplerRefr, refrNewst + refrTC * 1.15 ).x;;
refractColor.y = tex2D(envMapSamplerRefr, refrNewst + refrTC ).y;
refractColor.z = tex2D(envMapSamplerRefr, refrNewst + refrTC * 0.85 ).z;
#else
// no color dispersion for lower specs
refractColor.xyz = tex2D(envMapSamplerRefr, refrNewst + refrTC * 1.15 ).xyz;
#endif
#else
// no color dispersion for lower specs
refractColor.xyz = tex2D(envMapSamplerRefr, refrNewst ).xyz;
#endif
#if %SUN_SHINE
half3 mirrorEye = ( 2 * dot( viewVec, bumpNormal) * bumpNormal - viewVec );
half dotSpec = saturate(dot( mirrorEye.xyz, g_PS_SunLightDir ) * 0.5 + 0.5);
half3 vSunGlow = fFresnel*saturate(g_PS_SunLightDir.z) *( ( pow( dotSpec, 512 ) )*(fFoamGloss*1.8+0.2))* g_PS_SunColor.xyz ;
vSunGlow += vSunGlow *25 *saturate(fFoamGloss-0.05)* g_PS_SunColor.xyz;
#endif
fFresnel = saturate( fFresnel * ReflectionAmount*(fFoamGloss*0.2+0. );
float fA = 1;
#if !%WAVE_DECAL
half3 final= lerp(refractColor,reflectColor,saturate(fFresnel +saturate(1-NdotI*2)*fInsideReflection));
#else
half3 final= lerp(refractColor,reflectColor,saturate(fFresnel +saturate(1-NdotI*2)*fInsideReflection));
#endif
// no foam for low-specs
if( nQuality == QUALITY_HIGH )
{
// procedural foam
half foam = smoothstep(0.4, 0.8, 1-foamSoftIntersect ) *0.5* softIntersect;
half3 cFoamFinal = foam;
half fCrestFoam = 0.5 * (fFoamLuminance * fFoamGloss * (IN.cColor.z + IN.screenProj.z));
half3 cWavesFoam =fFoamGloss*0.3;
cWavesFoam *= WhiteCapsAmount; // 2 alu
cFoamFinal = (fFoamGloss*0.5+0.5) * saturate( (cFoamFinal + cWavesFoam)*fFoamLuminance +fCrestFoam *WhiteCapsAmount); // 2 alu
// Add foam
final += (g_PS_SkyColor.xyz + g_PS_SunColor.xyz ) * cFoamFinal ; // 2 alu
// 6 alu
}
#if %SUN_SHINE
// Add sun specular term
final.xyz += vSunGlow.xyz * fShadowOccl * SunMultiplier;
#endif
#if !%WAVE_DECAL
fA = 1;
// soft intersection with camera
if( nQuality == QUALITY_HIGH )
fA *= saturate((IN.screenProj.w- PS_NearFarClipDist.x) * 50);
#endif
#if %_RT_FOG
half4 localFogColor = IN.localFogColor;
if( nQuality >= QUALITY_HIGH ) // compute per-pixel instead for hi specs
localFogColor = GetVolumetricFogColor( IN.localFogColor.xyz );
final.xyz = lerp( localFogColor.xyz, final, localFogColor.w );
#endif
final.xyz = lerp( refractColor, final.xyz, softIntersect * saturate(IN.screenProj.w));
// Add global fog - make sure fog doens't affect refraction on shore
// Soften camera intersections
// maybe 4 hi-spec
#if %WAVE_DECAL
//final = fA ;
//fA =1;
//fA *= saturate( (IN.viewVec.w - PS_NearFarClipDist.x) *100);
//fA *= saturate( (IN.viewVec.w/PS_NearFarClipDist.w - PS_NearFarClipDist.x) * 100);
#endif
//fA *= IN.screenProj.z;//*IN.screenProj.z*IN.screenProj.z;
#if !%WAVE_DECAL
// fA *= IN.cColor.w;
#endif
#if WHITE_OUTPUT
final = 1;
#endif
//OUT.Color = float4(IN.cColor.xxx, 1); //;max( half4(final.xyz, fA), 0);
OUT.Color = max( half4(final.xyz, fA), 0);
return OUT;
}
//////////////////////////////// technique ////////////////
technique Water
<
string Script =
"TechniqueShadowPass=ShadowPassWater;"
>
{
pass p0
{
ZEnable = true;
ZFunc = LEqual;
ZWriteEnable = true;
CullMode = None;
SrcBlend = SRC_ALPHA;
DestBlend = ONE_MINUS_SRC_ALPHA;
AlphaBlendEnable = true;
IgnoreMaterialState = true;
#if %WAVE_DECAL
SrcBlend = SRC_ALPHA;
DestBlend = ONE_MINUS_SRC_ALPHA;
AlphaBlendEnable = true;
CullMode = None;
ZEnable = false;
ZWriteEnable = false;
#endif
VertexShader = compile vs_Auto WaterVS() GeneralVS;
PixelShader = compile ps_Auto WaterPS() GeneralPS;
}
}
technique WaterFFT
<
string Script =
"TechniqueShadowPass=ShadowPassWaterFFT;"
>
{
pass p0
{
ZEnable = true;
ZFunc = LEqual;
ZWriteEnable = true;
CullMode = None;
SrcBlend = SRC_ALPHA;
DestBlend = ONE_MINUS_SRC_ALPHA;
AlphaBlendEnable = true;
IgnoreMaterialState = true;
#if %WAVE_DECAL
SrcBlend = SRC_ALPHA;
DestBlend = ONE_MINUS_SRC_ALPHA;
AlphaBlendEnable = true;
CullMode = None;
ZEnable = false;
ZWriteEnable = false;
#endif
VertexShader = compile vs_3_0 WaterVS() GeneralVS;
PixelShader = compile ps_3_0 WaterPS() GeneralPS;
}
}
/////////////// Shadow Pass ////////////////////////
#include "ShadowCommon.cfi"
#include "CommonShadowPass.cfi"
vert2fragShadow Water_ShadowVS(a2vWater IN)
{
vert2fragShadow OUT;
#ifndef OPENGL
OUT = (vert2fragShadow)0;
#endif
// Position in screen space.
float4 vPos = IN.Position;
float4 vPosOrig = IN.Position;
float2 FlowDir = OceanParams1.yz;
float fVertexDist = 0;
#if !%WAVE_DECAL
GetGridVertexPos( vPos, fVertexDist);
#else
vPos.z = (vPos.z < OceanParams1.w)? OceanParams1.w: vPos.z;
#endif
vPosOrig.xyz = vPos.xyz;
float viewAngle = abs( normalize(g_VS_WorldViewPos.xyz-vPosOrig.xyz).z *10);
float3 vPos0 = vPosOrig.xyz;
GetWave( vPos0.xyz, FlowDir, IN);
// todo: Store previous frame position,transformation - use for interpolating. Might help hiding some artefacts
float3 vDisp = vPos0 - vPos.xyz;
float fDistToCam = length(g_VS_WorldViewPos.xyz - vPos.xyz);
float fDispLen = length( vDisp.xyz );
// Attenuate wave strength nearby camera
float fNearbyCameraAtten = (saturate( fDistToCam / 5));
vPos.xyz += vDisp.xyz * fNearbyCameraAtten;
// Add small waves nearby camera
#if !%WAVE_DECAL
float fNearCamWaves = sin( - g_VS_AnimGenParams.z * 11 + fDistToCam * 10 )*0.6;
fNearCamWaves += sin( - g_VS_AnimGenParams.z * 5 + fDistToCam * 15)*0.4;
float fDispAmount = saturate( 1 / (fDistToCam) );
vPos.z += (fNearCamWaves )* fDispAmount*0.025;
#endif
OUT.HPosition = mul(mViewProj, vPos);
OUT.RandDirTC.xy = mul(vPos.xyz, (float3x3) TexGen0).xy / 800;
// compute shadow tex coords and depth
GenShadowTC(vPos, OUT.shadowTC);
return OUT;
}
pixout_cl Water_ShadowPS(vert2fragShadow IN)
{
pixout_cl OUT;
float4 vCompare = (float4)0;
#ifndef %_RT_GSM_COMBINED
//non-combined GSM
vCompare = ShadowDepthTest(IN.shadowTC, IN.RandDirTC.xy);
#else
//GSM ATLAS
vCompare = ShadowDepthTestAtlas(IN.shadowTC, IN.RandDirTC.xy);
//GSM ATLAS
#endif
//shadow fading - is not supported currently
//vCompare *= IN.RandDirTC.z;
OUT.Color = 1 - vCompare;
return OUT;
}
technique ShadowPassWater
{
pass p0
{
VertexShader = compile vs_Auto Water_ShadowVS();
PixelShader = compile ps_Auto Water_ShadowPS();
ZEnable = true;
ZFunc = LEqual;
ZWriteEnable = false;
CullMode = None;
ZEnable = true;
ZWriteEnable = true;
CullMode = None;
}
}
technique ShadowPassWaterFFT
{
pass p0
{
VertexShader = compile vs_Auto Water_ShadowVS();
PixelShader = compile ps_Auto Water_ShadowPS();
ZEnable = true;
ZFunc = LEqual;
ZWriteEnable = false;
CullMode = None;
ZEnable = true;
ZWriteEnable = true;
CullMode = None;
}
}
/////////////////////// eof ///
Stichworte
Berechtigungen
Neue Themen erstellen: Nein
Themen beantworten: Nein
Anhänge hochladen: Nein
Beiträge bearbeiten: Nein
Foren-Regeln