先修复一下,错误的场景 删除不必要的钓场资产 修复into场景 update:更新meta文件,修复报错 update:修复资源 修复第一章节建造 修复建造第三章 update:删除多余内容 update:更新README.md update:还原图标 update:更新README update:更新配置
236 lines
8.4 KiB
HLSL
236 lines
8.4 KiB
HLSL
|
|
struct SceneData
|
|
{
|
|
float4 positionNDC; //Unnormalized
|
|
float2 screenPos; //Normalized and no refraction
|
|
float3 positionWS;
|
|
float3 color;
|
|
float refractionMask;
|
|
|
|
float viewDepth;
|
|
float verticalDepth;
|
|
};
|
|
|
|
// Project from eye space to world space
|
|
#define WorldPosFromDepth(NDCw, depth, viewDir) -(depth.eye * (viewDir/NDCw) - _WorldSpaceCameraPos)
|
|
//Linear depth difference between scene and current (transparent) geometry pixel
|
|
#define SurfaceDepth(depth, positionCS) depth.eye - LinearEyeDepth(positionCS.z, _ZBufferParams)
|
|
|
|
|
|
void PopulateSceneData(inout SceneData scene, in Varyings input, in WaterSurface water)
|
|
{
|
|
const float2 screenPos = input.positionNDC.xy / input.positionNDC.w;
|
|
scene.positionNDC = input.positionNDC;
|
|
scene.screenPos = screenPos;
|
|
|
|
//Default for disabled depth texture scene.viewDepth = 1;
|
|
scene.verticalDepth = 1;
|
|
|
|
#ifdef _REFRACTION
|
|
SceneDepth depth = SampleDepth(screenPos);
|
|
float3 positionWS = WorldPosFromDepth(input.positionNDC.w, depth, water.viewDelta);
|
|
float viewDepth = SurfaceDepth(depth, input.positionCS);
|
|
|
|
const float2 refractionOffset = input.normalWS.xz * 0.5 * _RefractionStrength;
|
|
SceneDepth depthRefract = SampleDepth(screenPos + refractionOffset);
|
|
float3 positionWSRefract = WorldPosFromDepth(input.positionNDC.w, depthRefract, water.viewDelta);
|
|
float viewDepthRefract = SurfaceDepth(depthRefract, input.positionCS);
|
|
|
|
float mask = saturate(viewDepth) * saturate(viewDepthRefract);
|
|
|
|
scene.positionWS = lerp(positionWS, positionWSRefract, mask);
|
|
scene.viewDepth = lerp(viewDepth, viewDepthRefract, mask);
|
|
//Distance to opaque geometry in normal direction
|
|
scene.verticalDepth = length((water.positionWS - scene.positionWS) * water.vertexNormal);
|
|
scene.color = SampleSceneColor(screenPos + refractionOffset * mask);
|
|
scene.refractionMask = mask;
|
|
#else
|
|
SceneDepth depth = SampleDepth(screenPos);
|
|
scene.positionWS = WorldPosFromDepth(input.positionNDC.w, depth, water.viewDelta);
|
|
scene.viewDepth = SurfaceDepth(depth, input.positionCS);
|
|
scene.verticalDepth = length((water.positionWS - scene.positionWS) * water.vertexNormal);
|
|
scene.color = SampleSceneColor(screenPos);
|
|
scene.refractionMask = 0;
|
|
#endif
|
|
}
|
|
|
|
float GetWaterDensity(SceneData scene, float heightScalar, float viewDepthScalar)
|
|
{
|
|
const float viewDepth = scene.viewDepth;
|
|
const float verticalDepth = scene.verticalDepth;
|
|
|
|
const float depthAttenuation = 1.0 - exp(-viewDepth * viewDepthScalar * 0.1);
|
|
const float heightAttenuation = saturate(verticalDepth * heightScalar);
|
|
|
|
return max(depthAttenuation, heightAttenuation);
|
|
}
|
|
|
|
float4 ForwardPassFragment(Varyings input) : SV_Target
|
|
{
|
|
WaterSurface water = (WaterSurface)0;
|
|
SceneData scene = (SceneData)0;
|
|
|
|
float3 normalWS = normalize(input.normalWS.xyz);
|
|
float3 WorldTangent = input.tangent.xyz;
|
|
float3 WorldBiTangent = input.bitangent.xyz;
|
|
//wPos.x in w-component
|
|
float3 positionWS = float3(input.normalWS.w, input.tangent.w, input.bitangent.w);
|
|
|
|
water.alpha = 1.0;
|
|
water.positionWS = positionWS;
|
|
water.viewDelta = _WorldSpaceCameraPos - positionWS;
|
|
float3 viewDir = normalize(water.viewDelta);
|
|
water.viewDir = viewDir;
|
|
water.vertexNormal = normalize(input.normalWS.xyz);
|
|
|
|
//Normal
|
|
water.tangentNormal = float3(0.5, 0.5, 1);
|
|
water.tangentWorldNormal = normalWS;
|
|
|
|
half VdotN = 1.0 - saturate(dot(viewDir, normalWS));
|
|
half4 shadowMask = 1.0;
|
|
float4 shadowCoords = float4(0, 0, 0, 0);
|
|
Light mainLight = GetMainLight(shadowCoords, water.positionWS, shadowMask);
|
|
|
|
PopulateSceneData(scene, input, water);
|
|
|
|
//return float4(scene.verticalDepth.xxx, 1);
|
|
//return float4(saturate(scene.viewDepth).xxx, 1);
|
|
//return float4(scene.color, 1);
|
|
|
|
water.fog = GetWaterDensity(scene, _DepthHorizontal, _DepthVertical);
|
|
|
|
//Albedo
|
|
float4 baseColor = lerp(_ShallowColor, _BaseColor, water.fog);
|
|
|
|
water.fog *= baseColor.a;
|
|
water.alpha = baseColor.a;
|
|
|
|
float fresnel = saturate(pow(VdotN, _HorizonDistance)) * _HorizonColor.a;
|
|
|
|
water.albedo = lerp(baseColor.rgb, _HorizonColor.rgb, fresnel);
|
|
|
|
water.edgeFade = saturate(scene.verticalDepth / (_EdgeFade * 0.01));
|
|
water.alpha *= water.edgeFade;
|
|
|
|
|
|
// Wave Mesure
|
|
|
|
#if _INTERSECTION || _WAVE_FOAM
|
|
float waveMesure = (positionWS.y - _WaveMesureMin) / (_WaveMesureMax - _WaveMesureMin);
|
|
|
|
float2 nUV = positionWS.xz * _IntersectionTiling;
|
|
float foamTexNoise = SAMPLE_TEXTURE2D(_IntersectionNoise, sampler_IntersectionNoise, nUV + TIME_VERTEX/_IntersectionTiling * _IntersectionSpeed).r;
|
|
|
|
float interSecGradient = 1-saturate(exp(scene.verticalDepth) / _IntersectionLength);
|
|
#endif
|
|
|
|
|
|
#ifdef _WAVE_FOAM
|
|
// remap wave from [_WaveFoamClipping,1] to [0,1]
|
|
//float waveFoamNoise = (waveMesure - _WaveFoamClipping) / (1 - _WaveFoamClipping) * foamTexNoise;
|
|
float waveFoamNoise = smoothstep(_WaveFoamClipping.x, _WaveFoamClipping.y, waveMesure * foamTexNoise);
|
|
//return float4(waveFoamNoise.xxx, 1);
|
|
#else
|
|
float waveFoamNoise = 0;
|
|
#endif
|
|
|
|
|
|
/* ========
|
|
// Intercection
|
|
=========== */
|
|
#ifdef _INTERSECTION
|
|
float intersecMesure = waveMesure * interSecGradient;
|
|
float dist = saturate(interSecGradient / _IntersectionFalloff);
|
|
float intersecNoise = saturate(foamTexNoise + intersecMesure) * dist + dist;
|
|
intersecNoise = smoothstep(_IntersectionClipping, 1, intersecNoise);
|
|
#else
|
|
float intersecNoise = 0;
|
|
#endif
|
|
|
|
|
|
#if _INTERSECTION || _WAVE_FOAM
|
|
float noise = saturate(intersecNoise + waveFoamNoise);
|
|
water.albedo.rgb = lerp(water.albedo.rgb, _IntersectionColor.rgb, noise);
|
|
water.alpha = saturate(water.alpha + interSecGradient);
|
|
#else
|
|
float noise = 0;
|
|
#endif
|
|
|
|
/* ========
|
|
// Causitcs
|
|
=========== */
|
|
|
|
#ifdef _CAUSTICS
|
|
float2 cuv = positionWS.xz * _CausticsTiling;
|
|
float coffset = TIME_VERTEX/_CausticsTiling * _CausticsSpeed;
|
|
float3 caustics1 = SAMPLE_TEXTURE2D(_CausticsTex, sampler_CausticsTex, cuv + coffset).rgb;
|
|
float3 caustics2 = SAMPLE_TEXTURE2D(_CausticsTex, sampler_CausticsTex, cuv*0.8 - coffset).rgb;
|
|
// Limit distance from cam and verticalDepth
|
|
float3 causticsDensity = saturate((1-length(water.viewDelta) / _CausticsClipping.x) * smoothstep(_CausticsClipping.y,1, scene.verticalDepth));
|
|
float3 caustics = min(caustics1, caustics2) * _CausticsBrightness * causticsDensity;
|
|
#endif
|
|
|
|
/* ========
|
|
// Reflection Prob
|
|
=========== */
|
|
|
|
half3 reflectionVector = reflect(-viewDir, normalWS);
|
|
water.reflections = GlossyEnvironmentReflection(reflectionVector, water.positionWS, _ReflectionBlur, 1 ,scene.screenPos.xy);
|
|
|
|
//Schlick's BRDF fresnel AIR_RI = 1.000293
|
|
float cosTheta = saturate(dot(normalWS, viewDir));
|
|
water.reflectionMask = pow(max(0.0, 1.000293 - cosTheta), _ReflectionFresnel) * _ReflectionStrength;
|
|
|
|
water.albedo = lerp(water.albedo, water.reflections.rgb, water.reflectionMask - noise);
|
|
|
|
|
|
// =================== Make ApplyLight simple =========================
|
|
|
|
// =====Translucency Begin========
|
|
float3 lightDir = mainLight.direction;
|
|
float3 lightColor = mainLight.color;
|
|
float3 emission = 0;
|
|
float3 specular = 0;
|
|
|
|
float scatteringMask = saturate(water.fog + water.edgeFade);
|
|
|
|
half incident = saturate(dot(lightDir, normalWS)) * _TranslucencyStrengthDirect;
|
|
|
|
const float lightIntensity = lightColor.r * 0.3 + lightColor.g * 0.59 + lightColor.b * 0.11;
|
|
|
|
half attenuation = incident * scatteringMask * lightIntensity;
|
|
|
|
#ifdef _CAUSTICS
|
|
emission += lerp(caustics * lightIntensity, _ShallowColor.rgb, attenuation) * mainLight.distanceAttenuation;
|
|
#else
|
|
emission = lerp(0, _ShallowColor.rgb, attenuation) * mainLight.distanceAttenuation;
|
|
#endif
|
|
|
|
// =====Translucency End========
|
|
|
|
|
|
#ifdef _LIGHT_COLOR
|
|
// LightingLambert Light applied here
|
|
half3 attenuatedLightColor = lightColor * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
|
|
half3 diffuseColor = LightingLambert(attenuatedLightColor, lightDir, normalWS) + _GlossyEnvironmentColor.rgb * _AmbientStrength;
|
|
float3 finalColor = (water.albedo * diffuseColor ) + emission + specular;
|
|
#else
|
|
float3 finalColor = (water.albedo ) + emission + specular;
|
|
#endif
|
|
|
|
|
|
finalColor = lerp(finalColor, _IntersectionColor.rgb, noise);
|
|
|
|
// =================== Make ApplyLight simple end =========================
|
|
|
|
finalColor = lerp(scene.color, finalColor, water.fog + noise);
|
|
|
|
//Apply fog
|
|
|
|
half fogCoord = InitializeInputDataFog(float4(positionWS,1), input.fogFactor);
|
|
finalColor = MixFog(finalColor, fogCoord);
|
|
|
|
return float4(finalColor, water.alpha);
|
|
}
|