该文章转载自Genesis-3D官网,
自定制水
这是一个自定制水的实例,本实例通过定制shader和脚本,展现出一个自定义的水面,帮助用户熟悉在Genesis-3D中定制水效的流程,并且了解shader的编写与使用和在脚本中使用RenderTexture,设置shader参数等渲染相关的技巧。
1. 创建一个面片,把工程资源中提供的waterplane拖入场景:
2. 创建一个材质文件,将其命名为water:
3. 创建一个文本文件命名为FX_Water.shader
在shader里用户可以自定义水面效果,在本实例中实现的大致思路如下,以供参考,完整代码请参阅工程资源内的FX_Water.shader。
02 | float3
offsets = GerstnerOffset4(worldpos.xz,Steepness,Amplitude,Frequency,Speed,DirectionAB,DirectionCD); |
03 | float3
nrml = GerstnerNormal4(worldpos.xz + offsets.xz,Amplitude,Frequency,Speed,DirectionAB,DirectionCD); |
06 | float4
projTex = p.input_ClipSpacePos; |
07 | projTex.xy
/= projTex.w; |
08 | projTex.x
= 0.5 * projTex.x + 0.5; |
09 | projTex.y
= -0.5 * projTex.y + 0.5; |
10 | projTex.xy
+= g_ScreenSize.zw; |
12 | float4
reflectCoord = p.input_ClipSpacePos; |
13 | reflectCoord.xy
/= reflectCoord.w; |
14 | reflectCoord.x
*= -1.0f; |
15 | reflectCoord.x
= 0.5 * reflectCoord.x + 0.5; |
16 | reflectCoord.y
= -0.5 * reflectCoord.y + 0.5; |
17 | reflectCoord.xy
+= g_ScreenSize.zw; |
20 | float4
reflectCol = tex2D(_reflectionMap,reflectCoord.xy+perturbVec); |
21 | loat4
refractCol = tex2D(_refractionMap,projTex.xy-perturbVec); |
24 | refractCol
*= 1 + depth.y * CausticPower; |
25 | refractCol
= lerp(WaterColor,refractCol,depth.x); |
26 | float refractWt
= saturate(RefractBias + pow(max(dot(viewdir,normalW),0.0f),RefractPower)); |
27 | float4
lerp_color = lerp(reflectCol,refractCol,refractWt); |
29 | float4 spec = t * WaterSpecColor; |
30 | float4
diffuse = (lerp_color * g_LightDiffuse[0] * WaterDiffuseColor); |
31 | o.Diffuse
= diffuse + spec; |
4. 设置waterplane的材质为water,设置water的shader为FX_Water.shader:
5. 创建一个脚本文件,命名为WaterRender.cs
在脚本文件中用户可以自由创建相机,绘制RT,设置shader参数用以完善效果,制作更加真实高级的水面效果 在本实例中实现的大致思路如下,以供参考,完整代码请参阅工程资源内的WaterRender.cs
02 | private Matrix44
Reflect(Vector4 plane) |
04 | Matrix44
matout = new Matrix44(); |
05 | matout[0,
0] = -2.0f * plane.X * plane.X + 1.0f; |
06 | matout[0,
1] = -2.0f * plane.X * plane.Y; |
07 | matout[0,
2] = -2.0f * plane.X * plane.Z; |
08 | matout[0,
3] = -2.0f * plane.X * plane.W; |
10 | matout[1,
0] = -2.0f * plane.Y * plane.X; |
11 | matout[1,
1] = -2.0f * plane.Y * plane.Y + 1.0f; |
12 | matout[1,
2] = -2.0f * plane.Y * plane.Z; |
13 | matout[1,
3] = -2.0f * plane.Y * plane.W; |
15 | matout[2,
0] = -2.0f * plane.Z * plane.X; |
16 | matout[2,
1] = -2.0f * plane.Z * plane.Y; |
17 | matout[2,
2] = -2.0f * plane.Z * plane.Z + 1.0f; |
18 | matout[2,
3] = -2.0f * plane.Z * plane.W; |
19 | matout[3,
0] = 0.0f; matout[3,1] = 0.0f; matout[3,2] = 0.0f; matout[3,3] = 1.0f; |
25 | private void CreateReflect() |
27 | int width
= GraphicSystem.GetWidth(); |
28 | int height
= GraphicSystem.GetHeight(); |
29 | Vector4
color = new Vector4(0.25f,0.25f,0.25f,1.0f); |
32 | reflectRtt
= new RenderToTexture(); |
33 | reflectRtt.Setup(width
/ 2,height / 2,PixelFormat.X8R8G8B8,ClearFlag.ClearAll, ref color, true ); |
37 | reflectCam
= new Camera(); |
38 | reflectCam.SetupPerspectiveFovRH(0.75f,
width / height,1.0f,10000.0f); |
39 | reflectCam.SetRenderTarget(reflectRtt); |
40 | reflectCam.SetLightLitTexture(lightlit); |
41 | reflectCam.RenderDepth
= false ; |
42 | reflectCam.RenderNormal
= true ; |
43 | reflectCam.RenderCustomised
= true ; |
44 | reflectCam.CullMask
= RenderLayer.eRLDefault; |
45 | reflectCam.UseBeforeDrawEvent
= false ; |
46 | reflectCam.RenderShadowMap
= false ; |
49 | private void CreateRefract() |
51 | int width
= GraphicSystem.GetWidth(); |
52 | int height
= GraphicSystem.GetHeight(); |
53 | Vector4
color = new Vector4(0.25f,0.25f,0.25f,1.0f); |
54 | refractRtt
= new RenderToTexture(); |
55 | refractRtt.Setup(width
/ 2,height / 2,PixelFormat.A16B16G16R16F,ClearFlag.ClearAll, ref color, true ); |
57 | refractCam
= new Camera(); |
58 | refractCam.SetupPerspectiveFovRH(0.75f,
width / height,1.0f,10000.0f); |
59 | refractCam.SetRenderTarget(refractRtt); |
60 | refractCam.SetLightLitTexture(lightlit); |
61 | refractCam.RenderDepth
= false ; |
62 | refractCam.RenderNormal
= true ; |
63 | refractCam.RenderCustomised
= true ; |
64 | refractCam.CullMask
= RenderLayer.eRLDefault; |
65 | refractCam.UseBeforeDrawEvent
= false ; |
66 | refractCam.RenderShadowMap
= false ; |
72 | meshRenderCom.SetTexture(0, "_waveMap" , "asset:Media/Waterbump.dds" ,
0); |
73 | meshRenderCom.SetTexture(0, "_fresnelMap" , "asset:Media/WaterFresnel.dds" ,
0); |
74 | meshRenderCom.SetTexture(0, "_reflectionMap" ,
reflectRtt); |
75 | meshRenderCom.SetTexture(0, "_refractionMap" ,
refractRtt); |
78 | public override void OnWillRenderObject(RenderComponent
sender) |
83 | lightlit
= new RenderToTexture(); |
84 | Vector4
lightlitColor = Vector4.One; |
85 | lightlit.Setup(1, 1,PixelFormat.X8R8G8B8,ClearFlag.ClearAll, ref lightlitColor, false ); |
94 | //---------------------uv
offest-----------------------// |
97 | GraphicSystem.RenderCamera(reflectCam); |
98 | GraphicSystem.RenderCamera(refractCam); |
6. 将脚本挂接在waterplane上:
7. 导入实例资源内提供的wave0.dds、wave1.dds、Waterbump.dds、WaterFresnel.dds 将wave1和wave2设置给材质中的_waveMap1和_waveMap2两个参数,两外张图是脚本中设置的材质资源。
8. 调整shader反射的参数,定制出属于自己的水面效果: