Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
1.1.0:water [2023/10/25 08:08] – [Water] admin1.1.0:water [2024/01/23 08:23] (current) – [Example] admin
Line 20: Line 20:
  
 The plane is a simple and opaque instance of TGorillaPlane or TPlane. It will be used as basis mesh to render water onto. The plane is a simple and opaque instance of TGorillaPlane or TPlane. It will be used as basis mesh to render water onto.
 +
 +Using a none planar object is not recommended, because reflection and refraction computation is based on plane models.
  
 ==== Refraction ==== ==== Refraction ====
Line 32: Line 34:
 FRefraction.IgnoreControl(FWaterPlane); FRefraction.IgnoreControl(FWaterPlane);
 </file> </file>
 +
 The water surface would be black, because it's image information will be computed in main render pass first. The water surface would be black, because it's image information will be computed in main render pass first.
 +
 +Because the refraction pass should render from a certain position, we have to adjust the surface position to the current water plane position everytime it changes:
 +<file pascal>
 +  // set the current position of the water plane as surface plane
 +  // this needs to be updated, if water plane moves
 +  FRefraction.SurfacePosition.Point := TPoint3D(FWaterPlane.AbsolutePosition);
 +</file>
  
 ==== Reflection ==== ==== Reflection ====
Line 52: Line 62:
   // set the current position of the water plane as mirror plane   // set the current position of the water plane as mirror plane
   // this needs to be updated, if water plane moves   // this needs to be updated, if water plane moves
-  FReflection.MirrorPosition := TPoint3D(FWaterPlane.AbsolutePosition);+  FReflection.MirrorPosition.Point := TPoint3D(FWaterPlane.AbsolutePosition);
 </file> </file>
  
 In case plane size or position changes, you have to update those values in reflection pass. In case plane size or position changes, you have to update those values in reflection pass.
  
 +==== Displacement ====
 +
 +Our water shader supports displacement mapping to render waves. This manipulates vertex position in the vertex shader.
 +To use displacement mapping, apply a tetxure to the "DisplacementMap" property and configure the intensity of waves by
 +the "DisplIntensity" property of your material source.
 +
 +When working with displacement mapping, vertices getting shifted. This leads to offsets in refraction and reflection, because
 +in those render passes we rendered with different information.
 +
 +Therefor you have to adjust the reflection mirror position and refraction surface position by the "DisplIntensity" value:
 +
 +<file pascal>
 +  FReflection.MirrorPosition.Point := TPoint3D(FWaterPlane.AbsolutePosition) + 
 +    Point3D(0, -FWaterMaterial.DisplIntensity, 0);
 +    
 +  FRefraction.SurfacePosition.Point := TPoint3D(FWaterPlane.AbsolutePosition) + 
 +    Point3D(0, -FWaterMaterial.DisplIntensity, 0);
 +</file>
 ==== Water Material ==== ==== Water Material ====
  
Line 138: Line 166:
 end; end;
 </file> </file>
 +
 +Ripple computation in the vertex shader is embedded inside our water shader program.
 +In case you'll need additional handling in the fragment shader, you could a code snippet like that.
 +
 +<file Pascal>
 +var LStr := TStringList.Create();
 +try
 +  LStr.Text := 
 + '''
 +   void SurfaceShader(inout TLocals DATA){
 + float l_TotalRippleEffect = 0.0;
 + float l_Time = abs(_TimeInfo.w);
 + vec3 l_TransfVertexPos = DATA.TransfVertPos.xyz;
 +
 + for(int i = 0; i < int(_RippleCount); i++){
 +   float l_RippleDist = distance(l_TransfVertexPos.xz, _Ripples[i].xz);
 +   float l_RippleTime = abs((_TimeInfo.x + l_Time) - _Ripples[i].w);
 +   float l_TimeLimit = clamp(1.0 / (l_RippleTime / (_RippleProximity * _RippleDecay)), 0.0, 1.0);
 +
 +   float l_RippleEffect = (-_RippleAmplification * exp(_RippleDecay * - l_RippleDist));
 +   l_RippleEffect *= cos(_RippleProximity * (l_RippleDist - l_RippleTime));
 +   l_RippleEffect *= l_TimeLimit;
 +
 +   l_TotalRippleEffect += exp(-l_RippleDist) * sin(0.5 * l_RippleDist) * l_RippleEffect;
 + }
 +
 + if(l_TotalRippleEffect > 0.01){
 +   vec4 l_BoatTrail = tex2D(_WaterShore, DATA.TexCoord0.xy);
 +   DATA.BaseColor.rgb += vec3(l_BoatTrail.rgb * l_TotalRippleEffect);
 +   DATA.SumColor.rgb += vec3(l_BoatTrail.rgb * l_TotalRippleEffect);
 + }
 +   }
 + ''';
 +
 +  FWaterMat.SurfaceShader := LStr;
 +finally
 +  LStr.Free;
 +end;
 +</file>
 +
 +This snippet will render the water shore texture onto the ripples if they have a minimum size of 0.01.
 +===== Tutorial =====
 +
 +{{youtube>bIXeUcTrd58}}
 +
 ===== Example ===== ===== Example =====