Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- struct S_VSOutputWater2
- {
- float4 Pos : POSITION;
- float4 WorldPosAndDepth : TEXCOORD0;
- float3 Normal : TEXCOORD1;
- float3 NormalSmooth : TEXCOORD2;
- float4 UVScreenProj : TEXCOORD3;
- float3 ToViewer : TEXCOORD4;
- float4 UV0UV1 : TEXCOORD5;
- float4 UV2UV3 : TEXCOORD6;
- float Foam : TEXCOORD7;
- };
- struct S_VSOutputTerrainDynWater
- {
- float4 Pos : POSITION;
- float4 WorldPosAndDepth : TEXCOORD0;
- float3 Normal : TEXCOORD1;
- float3 ToViewer : TEXCOORD2;
- float4 UVScreenProj : TEXCOORD3;
- float4 UV0 : TEXCOORD4;
- float4 UV1 : TEXCOORD5;
- // xy - terrain surface tex UV
- float4 UVTerrain : TEXCOORD6;
- // x - layer0 flow blend param
- // y - layer1 flow blend param
- // z - water height
- // w - noise
- float4 Params : TEXCOORD7;
- // xy - water velocity
- float4 Params2 : TEXCOORD8;
- };
- struct S_WavesEvalCtx
- {
- float3 PosOffs;
- float3 Normal;
- float3 NormalSmooth;
- float3 Tangent;
- float3 Binormal;
- float FoamAmount;
- };
- struct S_WaterShadingParams
- {
- float4 WorldPosAndDepth;
- half3 Normal;
- half3 NormalBump;
- float3 ToViewer;
- float WaterDepth;
- float2 UVScreen;
- half4 RefrColorFlat;
- half4 RefrColorBump;
- half Opacity;
- };
- //
- // ResetWavesEvalCtx()
- //
- //
- //*********************************************************************************************
- void ResetWavesEvalCtx(in out S_WavesEvalCtx ctx)
- {
- ctx.PosOffs = 0;
- ctx.Binormal = float3(0,0,1);
- ctx.Tangent = float3(1,0,0);
- ctx.Normal = float3(0,1,0);
- ctx.NormalSmooth= float3(0,1,0);
- ctx.FoamAmount = 0;
- }
- //*********************************************************************************************
- //
- // RemapVelocityToAngularSeg()
- //
- //
- //*******************************************************************************************
- float2 RemapVelocityToAngularSeg(float2 vel,float segSizeRad,float offs)
- {
- const float coeff_1 = PI / 4;
- const float coeff_2 = 3 * coeff_1;
- float x = vel.x;
- float y = vel.y;
- float abs_y = abs(y) + 1e-10f; // kludge to prevent 0/0 condition
- float angle;
- if (x >= 0)
- {
- angle = coeff_1 - coeff_1 * (x - abs_y) / (x + abs_y);
- }
- else
- {
- angle = coeff_2 - coeff_1 * (x + abs_y) / (abs_y - x);
- }
- angle = y < 0 ? 2 * PI - angle : angle;
- float2 res;
- angle = (angle + offs) / segSizeRad;
- res.x = floor(angle);
- res.y = angle - res.x;
- return res;
- }
- //*******************************************************************************************
- //
- // EvalOceanWaves()
- //
- //
- //*********************************************************************************************
- void EvalOceanWaves(float2 pos,
- float time,
- float4 waveSteepness,
- float4 waveDirX,
- float4 waveDirY,
- float4 wavePhases,
- float4 waveLengths,
- float4 waveSpeeds,
- float4 waveAmps,
- in out S_WavesEvalCtx ctx)
- {
- float4 dirAngleSin = waveDirY;
- float4 dirAngleCos = waveDirX;
- float4 wavePos = pos.xxxx * dirAngleCos + pos.yyyy * dirAngleSin;
- float4 waveFreqs = 2 * PI / waveLengths;
- float4 waveInputs = waveFreqs * (wavePos + waveSpeeds * time);
- float4 sinWaves;
- float4 cosWaves;
- sincos(wavePhases + waveInputs,sinWaves,cosWaves);
- sinWaves *= waveAmps;
- cosWaves *= waveAmps;
- float4 gerstnerOffs = waveSteepness * cosWaves;
- float3 posDiff = float3( dot(gerstnerOffs * dirAngleCos,1),
- dot(sinWaves,1),
- dot(gerstnerOffs * dirAngleSin,1));
- ctx.PosOffs += posDiff;
- float dNx = -dot(dirAngleCos * cosWaves * waveFreqs,1);
- float dNz = -dot(dirAngleSin * cosWaves * waveFreqs,1);
- ctx.Normal.x += dNx;
- ctx.Normal.y -= dot(waveSteepness * waveFreqs * sinWaves,1);
- ctx.Normal.z += dNz;
- ctx.NormalSmooth.x += dNx;
- ctx.NormalSmooth.z += dNz;
- ctx.Binormal.x -= dot(waveSteepness * dirAngleCos * dirAngleSin * waveFreqs * sinWaves,1);
- ctx.Binormal.y += dot(dirAngleSin * waveFreqs * cosWaves,1);
- ctx.Binormal.z -= dot(waveSteepness * dirAngleSin * dirAngleSin * waveFreqs * sinWaves,1);
- ctx.Tangent.x -= dot(waveSteepness * dirAngleCos * dirAngleCos * waveFreqs * sinWaves,1);
- ctx.Tangent.y += dot(dirAngleCos * waveFreqs * cosWaves,1);
- ctx.Tangent.z -= dot(waveSteepness * dirAngleCos * dirAngleSin * waveFreqs * sinWaves,1);
- }
- //*********************************************************************************************
- //
- // CalcLayerUV()
- //
- //
- //*********************************************************************************************
- float2 CalcLayerUV(float3 worldPos,float4 layerParams,float time)
- {
- float2 uvDirU;
- float2 uvDirV;
- sincos(layerParams.x,uvDirU.y,uvDirU.x);
- uvDirV = uvDirU.yx * float2(-1,1);
- return float2( dot(worldPos.xz,uvDirU) * layerParams.z,
- dot(worldPos.xz,uvDirV) * layerParams.z + layerParams.y * time);
- }
- //*********************************************************************************************
- //
- // EvalWavesByVelocity()
- //
- //
- //*********************************************************************************************
- void EvalWavesByVelocity(float3 worldPos,float2 waterVelocity,float waterHeight,float time,float noise,float minWaveLength,in out S_WavesEvalCtx ctx)
- {
- const float ANGULAR_SEGMENT_SIZE = PI / 24;
- const float G = 9.81f;
- const float WAVELENGTH_TO_AMP = 1.0f / 300;
- #if 0
- float2 waveInputPos = worldPos.xz - GPU_PARAM_ID_WRLD_CAM_OFFS.xz;
- float4 waveDirX = 1;
- float4 waveDirY = 0;
- float4 waveSteepness = 2;//1.5;
- float4 waveLengths = float4(1,1,1,1) * 8;
- float4 waveSpeeds = sqrt((waveLengths * G) / (2 * PI));
- float4 waveAmplitudes = float4(1,1,1,1) * 0.15f;
- float4 phaseOffs = 0;
- float4 dirAngles = float4(0,PI / 4, 2 * PI / 4, 3 * PI / 4);
- sincos(dirAngles,waveDirY,waveDirX);
- EvalOceanWaves(waveInputPos,time,waveSteepness,waveDirX,waveDirY,phaseOffs,waveLengths,waveSpeeds,waveAmplitudes,ctx);
- #else
- float xxNoise = (0.8f + 0.4f * noise);
- float2 angRange = RemapVelocityToAngularSeg(waterVelocity,ANGULAR_SEGMENT_SIZE,(noise * 2 - 1) * PI / 10);
- // float2 angRange = RemapVelocityToAngularSeg(waterVelocity,ANGULAR_SEGMENT_SIZE,0);
- float waveLengthsScaler = 60;
- float minWaveLengthInv = rcp(2 * minWaveLength);
- const float4 angJitter0 = float4(-0.2,0.2,-0.4,0.4) * 2;
- const float4 waveSpeedsJitter = float4(1,1.4f,0.8f,1.2f);
- float4 phaseOffs0 = float4(23.488591f,67.153645f,87.654664f,73.334413f);// + noise * PI;//(PI / 10);
- float4 waveLengths0 = float4(1,1.15f,1.2f,1.25f) * waveLengthsScaler;
- float dirBlend = SmoothStep(angRange.y);
- float4 waveAmpsBase = waveLengths0 * WAVELENGTH_TO_AMP * xxNoise;
- float4 waveAmplitudes0 = waveAmpsBase * (1 - dirBlend);
- float4 waveAmplitudes1 = waveAmpsBase * dirBlend;
- float4 waveSpeeds = sqrt((waveLengths0 * G) / (2 * PI)) * waveSpeedsJitter;
- // float4 waveSpeeds = sqrt(G * waterHeight);
- float4 dirAngles0 = (angRange.xxxx + angJitter0) * ANGULAR_SEGMENT_SIZE;
- float4 dirAngles1 = dirAngles0 + ANGULAR_SEGMENT_SIZE;
- float4 waveSteepness = 1;
- float2 waveInputPos = worldPos.xz - GPU_PARAM_ID_WRLD_CAM_OFFS.xz;
- float4 waveDirX0;
- float4 waveDirY0;
- float4 waveDirX1;
- float4 waveDirY1;
- sincos(dirAngles0,waveDirY0,waveDirX0);
- sincos(dirAngles1,waveDirY1,waveDirX1);
- NX_HINT_LOOP
- for (int i = 0; i < 1; i++)
- {
- float4 waveAmpsFadeout = 1;// saturate(waveLengths0 * minWaveLengthInv);
- waveAmpsFadeout *= waveAmpsFadeout;
- waveAmpsFadeout *= waveAmpsFadeout;
- waveAmpsFadeout *= waveAmpsFadeout;
- EvalOceanWaves(waveInputPos,time,waveSteepness,waveDirX0,waveDirY0,phaseOffs0,waveLengths0,waveSpeeds,waveAmplitudes0 * waveAmpsFadeout,ctx);
- EvalOceanWaves(waveInputPos,time,waveSteepness,waveDirX1,waveDirY1,phaseOffs0,waveLengths0,waveSpeeds,waveAmplitudes1 * waveAmpsFadeout,ctx);
- float scale = 1.35424f;
- waveLengths0 *= scale;
- waveSpeeds *= SQRT2;
- waveAmplitudes0 *= scale;
- waveAmplitudes1 *= scale;
- phaseOffs0 *= PI / 2;
- }
- #endif
- }
- //*********************************************************************************************
- //
- // WaterSampleScreenSpaceRefl()
- //
- //
- //*******************************************************************************************
- half4 WaterSampleScreenSpaceRefl(float3 wpos,float3 dir,const S_SSRParams params)
- {
- float zf = params.m_CamNearFar.w;
- float maxSearchDist = 10000;
- // return SampleScreenSpaceRefl2(wpos,dir * maxSearchDist,GPU_PARAM_ID_VIEW_PROJ_TM,GPU_PARAM_ID_VIEW_TM,GPU_SAMPLER_ID_AUX_SCREENSPACE_COLOR,GPU_SAMPLER_ID_SCENE_DEPTH,GPU_PARAM_ID_RTARGET_SIZE,GPU_PARAM_ID_CAM_NEAR_FAR.w);
- return SampleScreenSpaceRefl2(wpos,dir * maxSearchDist,params.m_ViewProjTM,params.m_ViewTM,GPU_SAMPLER_ID_SSR_COLOR,GPU_SAMPLER_ID_SSR_DEPTH,params.m_RTSize,zf);
- }
- //*******************************************************************************************
- //
- // EvalWaterShading()
- //
- //
- //*********************************************************************************************
- half3 EvalWaterShading(in S_WaterShadingParams params)
- {
- half3 normViewerDir = normalize(params.ToViewer.xyz);
- float sceneDepth = DecodeTexDepth(NXTex2DLod(GPU_SAMPLER_ID_SCENE_DEPTH,params.UVScreen.xyyy)) * GPU_PARAM_ID_CAM_NEAR_FAR.w;
- // half3 normal = params.Normal;
- half3 normalBump = params.NormalBump;
- float waterDepth = params.WaterDepth;
- float accWaterDepth = max(sceneDepth - params.WorldPosAndDepth.w * GPU_PARAM_ID_CAM_NEAR_FAR.w,0);
- float horizAttScale = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams2.y;
- float vertAttScale = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams2.z;
- half3 extinction = exp(-GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ColorAtt.xyz * (accWaterDepth * horizAttScale + waterDepth * vertAttScale));
- half invInScatter = exp(-GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ColorAtt.w * accWaterDepth);
- half edgeSoftFactor = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams2.x;
- float edgeSoftening = Sqr(saturate(waterDepth * edgeSoftFactor));
- float time = GPU_PARAM_ID_TIME;
- half3 R = ReflectLeaving(normViewerDir,normalBump);
- half4 refr = params.RefrColorBump;
- half4 refrFlat = params.RefrColorFlat;
- half4 reflSS = WaterSampleScreenSpaceRefl(params.WorldPosAndDepth.xyz,R,GPU_PARAM_ID_SSR_PARAMS);
- half3 reflSky = EvalSkyColor(R);
- half3 refl = lerp(reflSky,reflSS,reflSS.a);
- half specPower = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams.z;
- half facing = saturate(dot(normViewerDir,normalBump));
- half fresnelPower = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams.x;
- half fresnelBias = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams.y;
- half fresnel = Fresnel(facing,fresnelBias,fresnelPower);
- half sunShadowMask = 1;
- S_LightAccumCtx lightAccCtx;
- S_ShadingParams shadingParams = (S_ShadingParams)0;
- S_MaterialParams materialParams;
- shadingParams.m_Normal = normalBump;
- shadingParams.m_ToViewer = normViewerDir;
- shadingParams.m_Refl = R;
- shadingParams.m_WorldPos = params.WorldPosAndDepth.xyz;
- shadingParams.m_WorldDist = length(params.ToViewer);
- shadingParams.m_BloomEmissivity = 0;
- materialParams.m_MatDiff = 1;
- materialParams.m_MatParams = half4(specPower,1,1,0);
- BeginLightingAccumulation(lightAccCtx,shadingParams,materialParams,GPU_PARAM_ID_GLOBAL_LIGHTING);
- lightAccCtx.m_ShadowMask = sunShadowMask;
- AccumulateGlobalLighting(lightAccCtx,GPU_PARAM_ID_GLOBAL_LIGHTING,shadingParams,materialParams);
- EndLightingAccumulation(lightAccCtx,shadingParams,materialParams,GPU_PARAM_ID_GLOBAL_LIGHTING);
- // return saturate(dot(normViewerDir,normalBump));
- half3 litColor = lightAccCtx.m_Diff;
- half3 finalRefr = lerp(GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ScatterColor.xyz,refr * extinction,invInScatter);
- // half3 finalRefr = lerp(GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ScatterColor.xyz * sunShadowMask,refr * extinction,invInScatter);
- litColor = lerp(finalRefr,refl,fresnel);// + lightAccCtx.m_Spec;
- half3 result = FinalizeColorOutput(litColor,0,shadingParams,lightAccCtx,GPU_PARAM_ID_GLOBAL_LIGHTING);
- return lerp(refrFlat,result,edgeSoftening * params.Opacity);
- }
- //*********************************************************************************************
- //
- // VS_WaterProjGrid()
- //
- //
- //*******************************************************************************************
- S_VSOutputWater2 VS_WaterProjGrid(float2 pos: POSITION)
- {
- S_VSOutputWater2 res = (S_VSOutputWater2)0;
- float zn = GPU_PARAM_ID_CAM_NEAR_FAR.z;
- float4 waterPlane = GPU_PARAM_ID_WATER_PARAMS.m_ProjectorSpaceWaterPlane;
- float3 bckOffs = float3(0,0,-GPU_PARAM_ID_WATER_PARAMS.m_MiscParams.z);
- float depth = zn - bckOffs.z;
- float3 vpos = GetViewSpacePosFromDepth(pos.xy,depth,GPU_PARAM_ID_WATER_PARAMS.m_ProjGridProjInfo);
- float isecT = PlaneRayIntersection(bckOffs,vpos,waterPlane);
- [branch]
- if (isecT >= 0)
- {
- vpos = bckOffs + vpos * isecT;
- //
- // calc frequency fadeouts to avoid aliasing
- //
- float3 vposC = GetViewSpacePosFromDepth(pos.xy,zn,GPU_PARAM_ID_WATER_PARAMS.m_ProjGridProjInfo);
- float3 vposHN = GetViewSpacePosFromDepth(pos.xy + float2(GPU_PARAM_ID_WATER_PARAMS.m_ProjGridParams.z,0),zn,GPU_PARAM_ID_WATER_PARAMS.m_ProjGridProjInfo);
- float3 vposVN = GetViewSpacePosFromDepth(pos.xy + float2(0,GPU_PARAM_ID_WATER_PARAMS.m_ProjGridParams.w),zn,GPU_PARAM_ID_WATER_PARAMS.m_ProjGridProjInfo);
- vposC = vposC * PlaneRayIntersectionUnchecked(0,vposC,waterPlane);
- vposHN = vposHN * PlaneRayIntersectionUnchecked(0,vposHN,waterPlane);
- vposVN = vposVN * PlaneRayIntersectionUnchecked(0,vposVN,waterPlane);
- float2 stepXY = float2(distance(vposC,vposHN),distance(vposC,vposVN));
- float minWaveLength = max(stepXY.x,stepXY.y);
- float3 wpos = mul(float4(vpos,1),GPU_PARAM_ID_VIEW_TM_INV);
- S_WavesEvalCtx evalCtx;
- ResetWavesEvalCtx(evalCtx);
- NX_HINT_LOOP
- for (int i = 0; i < GPU_MAX_WATER_WAVES / 4; i++)
- {
- float4 waveLengths = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesLengths[i];
- float4 waveAmpsFadeout = saturate(pow((waveLengths * 0.5) / minWaveLength,10));
- float4 waveAmplitudes = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesAmplitudes[i] * waveAmpsFadeout;
- float4 waveSpeeds = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesSpeeds[i];
- float4 wavePhases = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesPhases[i];
- float4 waveDirX = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesDirX[i];
- float4 waveDirY = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesDirY[i];
- float4 waveSteepness = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesSteepness[i];
- float2 waveInputPos = wpos.xz - GPU_PARAM_ID_WRLD_CAM_OFFS.xz;
- EvalOceanWaves(waveInputPos,GPU_PARAM_ID_TIME,waveSteepness,waveDirX,waveDirY,wavePhases,waveLengths,waveSpeeds,waveAmplitudes,evalCtx);
- }
- res.Foam = 0;
- //
- // UVs are calculated before actual position displacement to get nice stretching of normalmaps over waves
- //
- float time = GPU_PARAM_ID_TIME;
- res.UV0UV1.xy = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer0Params,time);
- res.UV0UV1.zw = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer1Params,time);
- res.UV2UV3.xy = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer2Params,time);
- res.UV2UV3.zw = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer3Params,time);
- res.UV0UV1 += GPU_PARAM_ID_WATER_PARAMS.m_Layer01UVoffs;
- res.UV2UV3 += GPU_PARAM_ID_WATER_PARAMS.m_Layer23UVoffs;
- wpos += evalCtx.PosOffs;
- res.Normal = evalCtx.Normal;
- res.NormalSmooth = evalCtx.NormalSmooth;
- res.Pos = mul(float4(wpos,1),GPU_PARAM_ID_VIEW_PROJ_TM);
- res.WorldPosAndDepth = float4(wpos,res.Pos.w);
- res.UVScreenProj = HPosToScreenUV(res.Pos);
- res.ToViewer = GPU_PARAM_ID_CAM_POS - wpos;
- }
- else
- {
- res.Pos = float4(pos.xy * float2(2,-2) + float2(-1,1),2,1);
- }
- return res;
- }
- //*******************************************************************************************
- //
- // VS_DynamicSimWater()
- //
- //
- //*******************************************************************************************
- S_VSOutputTerrainDynWater VS_DynamicSimWater(float3 pos : POSITION,int4 normalX16Y16: BLENDINDICES,float3 vel2DAndHeight : TEXCOORD0)
- {
- S_VSOutputTerrainDynWater res = (S_VSOutputTerrainDynWater)0;
- #if 1
- float3 wpos = mul(float4(pos,1),GPU_PARAM_ID_WORLD_TM);
- float2 nrm2 = float2(dot(normalX16Y16.xy,float2(1,256)) / 65535,dot(normalX16Y16.zw,float2(1,256)) / 65535) * 2 - 1;
- float3 normal = float3(nrm2.x,sqrt(1 - nrm2.x * nrm2.x - nrm2.y * nrm2.y),nrm2.y);
- float time = GPU_PARAM_ID_TIME;
- float layer0UVScale = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexNormalsLayer0Params.z;
- float layer1UVScale = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexNormalsLayer1Params.z;
- float noise = Perlin2D((wpos.xz - GPU_PARAM_ID_WRLD_CAM_OFFS.xz) * 0.025f + time * 0.1f) * 0.5f + 0.5f;
- #if 0
- S_WavesEvalCtx wavesEvalCtx;
- ResetWavesEvalCtx(wavesEvalCtx);
- EvalWavesByVelocity(wpos,-vel2DAndHeight.xy,vel2DAndHeight.z,time,0,wavesEvalCtx);
- wpos += wavesEvalCtx.PosOffs;
- normal = wavesEvalCtx.Normal;
- #endif
- float4 hpos = mul(float4(wpos,1),GPU_PARAM_ID_VIEW_PROJ_TM);
- res.Pos = VSOutputFinalPos(hpos);
- res.WorldPosAndDepth = float4(wpos,LinWorldDepthFromHPos(hpos));
- res.Normal = normal;
- res.ToViewer = GPU_PARAM_ID_CAM_POS - wpos;
- res.UVScreenProj = HPosToScreenUV(res.Pos);
- res.UV0 = (wpos.xz * layer0UVScale + GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexNormalsLayer0Params.xy).xyxy * float2(1,-1).xyxy;
- res.UV1 = (wpos.xz * layer1UVScale + GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexNormalsLayer1Params.xy).xyxy * float2(1,-1).xyxy;
- res.UVTerrain.xy = wpos.xz * GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_WrldToTerrainTexUVScaleBias.xy + GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_WrldToTerrainTexUVScaleBias.zw;
- res.Params.z = vel2DAndHeight.z;// + wavesEvalCtx.PosOffs.y;
- res.Params.w = noise;
- //
- // adjust UVs to follow flow field
- //
- {
- float2 nrmVel = normalize(vel2DAndHeight.xy);
- float2 flowVel = nrmVel * min(length(vel2DAndHeight.xy),0.25f) * float2(1,-1);
- float4 uvRndOffs = float4(0.182764f,0.8766731f,0.564621f,0.427134f);
- float4 flowFollowAmps = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexLayersFlowFollowAmp;
- float2 flowSpeedScaleLayer = float2( GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexNormalsLayer0Params.w,
- GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_TexNormalsLayer1Params.w);
- float flowOffs = noise * 0.25f;
- float4 toffs = frac(frac(time.xxxx * flowSpeedScaleLayer.xxyy + float2(0,0.5f).xyxy) + flowOffs);
- res.UV0 = res.UV0 - (flowVel.xyxy * toffs.xxyy * flowFollowAmps.x) + uvRndOffs.xyzw;
- res.UV1 = res.UV1 - (flowVel.xyxy * toffs.zzww * flowFollowAmps.y) + uvRndOffs.zwyx;
- res.Params.xy = 2 * abs(toffs.xz - 0.5f);
- res.Params2.xy = vel2DAndHeight.xy;
- }
- #endif
- return res;
- }
- //*******************************************************************************************
- //
- // VS_Water()
- //
- //
- //*******************************************************************************************
- S_VSOutputWater2 VS_Water(int4 input: BLENDINDICES)
- {
- S_VSOutputWater2 res = (S_VSOutputWater2)0;
- float span = GPU_PARAM_ID_WATER_TILE_PARAMS.x;
- float tileSize = GPU_PARAM_ID_WATER_TILE_PARAMS.z;
- float waterHeight = GPU_PARAM_ID_WATER_PARAMS.m_Params.w;
- float2 gridPos = input.xy;
- float3 wrldPos;
- gridPos.y = tileSize - 1 - gridPos.y;
- wrldPos.xz = gridPos.xy * span - (tileSize - 1) * 0.5 * span;
- wrldPos.y = waterHeight + GPU_PARAM_ID_WRLD_CAM_OFFS.y;
- S_WavesEvalCtx evalCtx;
- float3 wpos = wrldPos;
- evalCtx.PosOffs = 0;
- evalCtx.Binormal = float3(0,0,1);
- evalCtx.Tangent = float3(1,0,0);
- evalCtx.Normal = float3(0,1,0);
- evalCtx.NormalSmooth= float3(0,1,0);
- evalCtx.FoamAmount = 0;
- NX_HINT_LOOP
- for (int i = 0; i < GPU_MAX_WATER_WAVES / 4; i++)
- {
- float4 waveLengths = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesLengths[i];
- float4 waveAmplitudes = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesAmplitudes[i];
- float4 waveSpeeds = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesSpeeds[i];
- float4 wavePhases = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesPhases[i];
- float4 waveDirX = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesDirX[i];
- float4 waveDirY = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesDirY[i];
- float4 waveSteepness = GPU_PARAM_ID_WATER_GERSTNER_WAVES.m_GeomWavesSteepness[i];
- EvalOceanWaves(wpos.xz - GPU_PARAM_ID_WRLD_CAM_OFFS.xz,GPU_PARAM_ID_TIME,waveSteepness,waveDirX,waveDirY,wavePhases,waveLengths,waveSpeeds,waveAmplitudes,evalCtx);
- }
- //
- // UVs are calculated before actual position displacement to get nice stretching of normalmaps over waves
- //
- float time = GPU_PARAM_ID_TIME;
- res.UV0UV1.xy = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer0Params,time);
- res.UV0UV1.zw = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer1Params,time);
- res.UV2UV3.xy = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer2Params,time);
- res.UV2UV3.zw = CalcLayerUV(wpos,GPU_PARAM_ID_WATER_PARAMS.m_Layer3Params,time);
- res.UV0UV1 += GPU_PARAM_ID_WATER_PARAMS.m_Layer01UVoffs;
- res.UV2UV3 += GPU_PARAM_ID_WATER_PARAMS.m_Layer23UVoffs;
- wpos += evalCtx.PosOffs;
- float4 hpos = mul(float4(wpos,1),GPU_PARAM_ID_VIEW_PROJ_TM);
- res.Normal = evalCtx.Normal;
- res.NormalSmooth = evalCtx.NormalSmooth;
- res.Pos = VSOutputFinalPos(hpos);
- res.WorldPosAndDepth = float4(wpos,LinWorldDepthFromHPos(hpos));
- res.UVScreenProj = HPosToScreenUV(res.Pos);
- res.ToViewer = GPU_PARAM_ID_CAM_POS - wpos;
- res.Foam = evalCtx.FoamAmount;
- #if 0
- sincos(GPU_PARAM_ID_WATER_PARAMS.m_Layer0Params.x,res.RotL0L1.y,res.RotL0L1.x);
- sincos(GPU_PARAM_ID_WATER_PARAMS.m_Layer1Params.x,res.RotL0L1.w,res.RotL0L1.z);
- sincos(GPU_PARAM_ID_WATER_PARAMS.m_Layer2Params.x,res.RotL2L3.y,res.RotL2L3.x);
- sincos(GPU_PARAM_ID_WATER_PARAMS.m_Layer3Params.x,res.RotL2L3.w,res.RotL2L3.z);
- #endif
- return res;
- }
- //*******************************************************************************************
- //
- // PS_Water()
- //
- //
- //*******************************************************************************************
- half4 PS_Water(S_VSOutputWater2 input) : COLOR0
- {
- half3 normViewerDir = normalize(input.ToViewer.xyz);
- float sceneDepth = DecodeTexDepth(NXTex2Dproj(GPU_SAMPLER_ID_SCENE_DEPTH,input.UVScreenProj)) * GPU_PARAM_ID_CAM_NEAR_FAR.w;
- float3 sceneViewPos = GetViewSpacePosFromDepth(input.UVScreenProj.xy / input.UVScreenProj.w,sceneDepth);
- float3 sceneWrldPos = mul(float4(sceneViewPos,1),GPU_PARAM_ID_VIEW_TM_INV);
- half sunShadowMask = 1;
- half edgeSoftening = saturate((sceneDepth - input.UVScreenProj.w) * GPU_PARAM_ID_WATER_PARAMS.m_MiscParams.w);
- half3 normalSmooth = normalize(input.NormalSmooth);
- half3 normal = normalize(input.Normal);
- float waterDepth = max(input.WorldPosAndDepth.y - sceneWrldPos.y,0);
- float accWaterDepth = max(sceneDepth - input.WorldPosAndDepth.w,0);
- float viewDist = length(input.ToViewer.xyz);
- float L = viewDist * waterDepth / (GPU_PARAM_ID_CAM_POS.y - sceneWrldPos.y);
- half3 extinction = exp(-GPU_PARAM_ID_WATER_PARAMS.m_ColorAtt.xyz * 2 * L);
- // half3 extinction = exp(-GPU_PARAM_ID_WATER_PARAMS.m_ColorAtt.xyz * (accWaterDepth + waterDepth));
- half invInScatter = exp(-GPU_PARAM_ID_WATER_PARAMS.m_ColorAtt.w * accWaterDepth);
- half3 fnormal = normalize(cross(ddx(input.WorldPosAndDepth.xyz),ddy(input.WorldPosAndDepth.xyz)));
- //
- // calc bumpmapped normal
- //
- #if 1
- float3x3 TNB0 = CotangentFrame(normal,-normViewerDir,input.UV0UV1.xy);
- float3x3 TNB1 = CotangentFrame(normal,-normViewerDir,input.UV0UV1.zw);
- float3x3 TNB2 = CotangentFrame(normal,-normViewerDir,input.UV2UV3.xy);
- float3x3 TNB3 = CotangentFrame(normal,-normViewerDir,input.UV2UV3.zw);
- half3 texNrm0 = mul(UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER0,input.UV0UV1.xy)),TNB0);
- half3 texNrm1 = mul(UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER1,input.UV0UV1.zw)),TNB1);
- half3 texNrm2 = mul(UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER2,input.UV2UV3.xy)),TNB2);
- half3 texNrm3 = mul(UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER3,input.UV2UV3.zw)),TNB3);
- half3 texNrm;
- texNrm.xz = texNrm0.xz + texNrm1.xz + texNrm2.xz + texNrm3.xz;
- texNrm.y = texNrm0.y * texNrm1.y * texNrm2.y * texNrm3.y;
- normal = normalize(texNrm);
- #else
- // This is incorrect because of gerstner-waves introduced non-uniform UV stretching
- half3 texNrm0 = UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER0,input.UV0UV1.xy));
- half3 texNrm1 = UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER1,input.UV0UV1.zw));
- half3 texNrm2 = UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER2,input.UV2UV3.xy));
- half3 texNrm3 = UnpackTexNormal(NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER3,input.UV2UV3.zw));
- half3 texNrm;
- texNrm.x = dot(texNrm0.xy,input.RotL0L1.xy);
- texNrm.y = dot(texNrm0.xy,input.RotL0L1.yx * float2(1,-1));
- texNrm.x += dot(texNrm1.xy,input.RotL0L1.zw);
- texNrm.y += dot(texNrm1.xy,input.RotL0L1.wz * float2(1,-1));
- texNrm.x += dot(texNrm2.xy,input.RotL2L3.xy);
- texNrm.y += dot(texNrm2.xy,input.RotL2L3.yx * float2(1,-1));
- texNrm.x += dot(texNrm3.xy,input.RotL2L3.zw);
- texNrm.y += dot(texNrm3.xy,input.RotL2L3.wz * float2(1,-1));
- texNrm.z = texNrm0.z * texNrm1.z * texNrm2.z * texNrm3.z;
- texNrm = normalize(texNrm);
- normal = normalize( texNrm.x * tangent +
- texNrm.y * binormal +
- texNrm.z * normal);
- #endif
- // return saturate(dot(normViewerDir,normalSmooth));
- // return saturate(dot(normViewerDir,normal));
- //
- // reflection vector
- //
- half3 R = ReflectLeaving(normViewerDir,normal);
- //
- // sample refraction
- //
- half2 bumpScale = half2(GPU_PARAM_ID_WATER_PARAMS.m_Params.xy);// * input.UVScreenProj.w;
- half4 bumpUVOffs = half4(normal.xzxz) * bumpScale.xxyy;
- float4 uvRefr = input.UVScreenProj;
- float4 uvRefl = input.UVScreenProj;
- uvRefl.xy += bumpUVOffs.xy;
- uvRefr.xy += bumpUVOffs.zw;
- half4 refrBump = NXTex2Dproj(GPU_SAMPLER_ID_AUX_SCREENSPACE_COLOR,uvRefr);
- half4 refrFlat = NXTex2Dproj(GPU_SAMPLER_ID_AUX_SCREENSPACE_COLOR,input.UVScreenProj);
- half4 refr = lerp(refrFlat,refrBump,edgeSoftening);
- half3 Rsmooth = ReflectLeaving(normViewerDir,normalize(normalSmooth));
- float4 projR = mul(float4(Rsmooth,0),GPU_PARAM_ID_WATER_PARAMS.m_ReflViewProjTM);
- float2 reflUV = (projR.xy / projR.z) * float2(0.5,-0.5) + float2(0.5,0.5);
- half4 refl = NXTex2D(GPU_SAMPLER_ID_REFLECTION,reflUV);
- //
- // Fresnel term approximation
- //
- #if 0
- half facing = saturate(dot(normViewerDir,normal));
- #else
- half facing = saturate(dot(normViewerDir,normalSmooth));
- #endif
- half fresnel = Fresnel(facing,GPU_PARAM_ID_WATER_PARAMS.m_MiscParams.x,GPU_PARAM_ID_WATER_PARAMS.m_MiscParams.y);
- S_LightAccumCtx lightAccCtx;
- S_ShadingParams shadingParams = (S_ShadingParams)0;
- S_MaterialParams materialParams;
- shadingParams.m_Normal = normal;//Smooth;
- shadingParams.m_ToViewer = normViewerDir;
- shadingParams.m_Refl = R;
- shadingParams.m_WorldPos = input.WorldPosAndDepth.xyz;
- shadingParams.m_WorldDist = length(input.ToViewer);
- shadingParams.m_BloomEmissivity = 0;
- materialParams.m_MatDiff = 1;
- materialParams.m_MatParams = half4(45,1,1,0);
- // spec power
- materialParams.m_MatParams.x = GPU_PARAM_ID_WATER_PARAMS.m_Params.z;
- BeginLightingAccumulation(lightAccCtx,shadingParams,materialParams,GPU_PARAM_ID_GLOBAL_LIGHTING);
- lightAccCtx.m_ShadowMask = sunShadowMask;
- AccumulateGlobalLighting(lightAccCtx,GPU_PARAM_ID_GLOBAL_LIGHTING,shadingParams,materialParams);
- EndLightingAccumulation(lightAccCtx,shadingParams,materialParams,GPU_PARAM_ID_GLOBAL_LIGHTING);
- half3 litColor = lightAccCtx.m_Diff;
- half3 finalRefr = lerp(GPU_PARAM_ID_WATER_PARAMS.m_ScatterColor.xyz,refr * extinction,invInScatter);
- half fakeLight = 0.5 + 0.5 * saturate(dot(normalSmooth,GPU_PARAM_ID_GLOBAL_LIGHTING.m_LightDir));
- half4 foamTex = NXTex2D(GPU_SAMPLER_ID_DIFFUSE,input.UV0UV1.xy * 20);
- half3 foamLit = foamTex.xyz * (lightAccCtx.m_Diff + lightAccCtx.m_Amb);
- litColor = lerp(finalRefr,refl,fresnel) + lightAccCtx.m_Spec;
- litColor = lerp(litColor,foamLit,input.Foam);
- half3 result = FinalizeColorOutput(litColor,0,shadingParams,lightAccCtx,GPU_PARAM_ID_GLOBAL_LIGHTING);
- result = lerp(refrFlat,result,edgeSoftening);
- return half4(result,0);
- }
- //*******************************************************************************************
- //
- // PS_TerrainDynWater()
- //
- //
- //*******************************************************************************************
- half4 PS_TerrainDynWater(S_VSOutputTerrainDynWater input NX_IMPORT_VPOS) : COLOR0
- {
- S_WaterShadingParams params;
- float3 normal = normalize(input.Normal);
- #if 0
- {
- S_WavesEvalCtx wavesEvalCtx;
- float3 waveSamplePos = input.WorldPosAndDepth.xyz;
- float time = GPU_PARAM_ID_TIME;
- ResetWavesEvalCtx(wavesEvalCtx);
- wavesEvalCtx.Normal = normal;
- // waveSamplePos.xz += -input.Params2.xy * fmod(time,20) * 10;
- // EvalWavesByVelocity(input.WorldPosAndDepth.xyz,-input.Params2.xy,input.Params.z,time,input.Params.w,5,wavesEvalCtx);
- EvalWavesByVelocity(waveSamplePos,-input.Params2.xy,input.Params.z,time,input.Params.w,15,wavesEvalCtx);
- half3 wnormal = normalize(wavesEvalCtx.Normal);
- half3 toViewer = normalize(input.ToViewer);
- normal = wnormal;
- // return wnormal.xyzz;
- // return saturate(dot(wnormal,toViewer));
- }
- #endif
- float2 UVScreen = input.UVScreenProj.xy / input.UVScreenProj.w;
- float3 binormal = normalize(cross(float3(1,0,0),normal));
- float3 tangent = normalize(cross(normal,binormal));
- float distance = length(input.ToViewer.xyz);
- half nrmMapStrength = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_MiscParams.w;
- half3 layer0nrmA = NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER0,input.UV0.xy);
- half3 layer0nrmB = NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER0,input.UV0.zw);
- half3 layer0nrm = UnpackTexNormal(lerp(layer0nrmA,layer0nrmB,input.Params.x).xyz);
- half3 layer1nrmA = NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER1,input.UV1.xy);
- half3 layer1nrmB = NXTex2D(GPU_SAMPLER_ID_NORMALS_LAYER1,input.UV1.zw);
- half3 layer1nrm = UnpackTexNormal(lerp(layer1nrmA,layer1nrmB,input.Params.y).xyz);
- half3 finalNrm = MixSignedNormals(layer0nrm,layer1nrm);
- half3 normalBump = normalize(finalNrm.x * tangent + finalNrm.y * binormal + finalNrm.z * normal * nrmMapStrength);
- float refrBumpScale = GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_ShadingParams.w * (1 - saturate(distance / 200));
- half2 refrBumpUVOffs = normalBump.xz * refrBumpScale;
- params.WorldPosAndDepth = input.WorldPosAndDepth;
- params.Normal = normal;
- params.NormalBump = normalBump;
- params.ToViewer = input.ToViewer.xyz;
- params.WaterDepth = input.Params.z;
- params.UVScreen = UVScreen;
- params.RefrColorFlat = NXTex2DLod(GPU_SAMPLER_ID_AUX_SCREENSPACE_COLOR,UVScreen.xyyy);
- params.RefrColorBump = NXTex2DLod(GPU_SAMPLER_ID_AUX_SCREENSPACE_COLOR,(UVScreen + refrBumpUVOffs).xyyy);
- //
- // calc opacity for LOD cross-fading
- //
- #if 1
- half LODDistFade = saturate(max(length(input.ToViewer.xyz) - GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_MiscParams.x,0) * GPU_PARAM_ID_TERRAIN_WATER_PARAMS.m_MiscParams.z);
- #else
- half LODDistFade = params.RefrColorFlat.a;
- #endif
- params.Opacity = step(LODDistFade,NXTex2D(GPU_SAMPLER_ID_DITHER_MASK,NX_GET_VPOS(input) * (1.0f / DITHER_TEX_SIZE)).a * (255.0 / 64));
- // params.Opacity = 1;
- return half4(EvalWaterShading(params),0);
- }
- //*******************************************************************************************
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement