注:本系列进阶教程仅针对引擎编辑器:v1.2.2及以下版本
自定制水
素材资源 工程文件
这是一个自定制水的实例,本实例通过定制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, refcolor, 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) |
81 | if (reflectCam == null) |
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反射的参数,定制出属于自己的水面效果:
引擎官方网站:http://www.genesis-3d.com.cn/
官方论坛:http://bbs.9tech.cn/genesis-3d/
官方千人大群:59113309 135439306
YY频道-游戏开发大讲堂(完全免费,定期开课):51735288
Genesis-3D开源游戏引擎:游戏起源,皆因有我!!!