文章目录
简单的模拟水的效果(3A游戏效果请绕开哦)
- 制作步骤
- 准备好水体网格
- 扰动水体网格
- 添加水体网格色调,纹理
- 放置海上放哨点(一些随便放的立方体)
- 添加水的深浅透视效果
- 添加水光效
- 重构水顶点法线
- 正交的相机的深度需要注意
- 改进
- Project
- References
效果:
- 准备好水体网格(网格脚本生成的,参考:Unity Shader - Noise 噪点图 - 实现简单山脉)
- 扰动水体网格顶点(参考:Unity Shader - 使用Noise噪点图生成简单山脉(使用tex2Dlod控制顶点高度))
- 添加水体网格色调,纹理
- 放置海上放哨点(一些随便放的立方体)
- 添加水的深浅透视效果
- 添加水光效
- 重构水顶点法线(参考:Unity Shader - 简单山脉 - 顶点着色器重构法线)
网格脚本生成的,参考:Unity Shader - Noise 噪点图 - 实现简单山脉
参考:Unity Shader - 使用Noise噪点图生成简单山脉(使用tex2Dlod控制顶点高度)
我使用了:大波浪与小波浪的叠加
float centerH = sin(_Time.y * _BigWaveLen + v.uv.x + v.uv.y) * _BigWaveAmplitude;
centerH += tex2Dlod(_MainTex, float4(v.uv + float2(_Time.x * _SmallWaveSpeedX, _Time.x * _SmallWaveSpeedY), 0, 0)).r * _SmallWaveAmplitude;
v.vertex.y = centerH;
着了个色调,并对uv滚动动画
fixed4 col = tex2D(_MainTex, i.uv + float2(_Time.y * _BigWaveLen * _UVSpeed, 0));
col.rgb *= _MainColor.rgb;
这个参考了unity内置的shader中,处理软粒子的思路:。
- 获取深度纹理的view space的
buffViewZ
。 - 获取当前片段的view space的
fragViewZ
。 - 将
delta = buffViewZ - fragViewZ
的深度插值,来控制水体的alpha透视,或lerp的颜色过渡。 - 还可以使用我们下面实现代码中的fade来控制浅水到深度的效果,我这里就控制海水原来的颜色(
combined.rgb + _ShallowColor.rgb * (_ShallowColor.a * 2)
)到浅水着色变量的颜色来过渡(combined.rgb
)。combined.rgb = lerp(combined.rgb + _ShallowColor.rgb * (_ShallowColor.a * 2), combined.rgb, fade);
如果需要你可以创建一个用个纹理:_ShallowToDeepTex
的纹理然后:
var shallowToDeepCol = tex2D(_ShallowToDeepTex, i.uv);
combined.rgb = lerp(combined.rgb + shallowToDeepCol.rgb * (shallowToDeepCol.a * 2), combined.rgb, fade);
下面是参考的:unity内置的shader软粒子代码:
// Soft particles fragment function
#if defined(SOFTPARTICLES_ON) && defined(_FADING_ON)
#define fragSoftParticles(i) \
if (SOFT_PARTICLE_NEAR_FADE > 0.0 || SOFT_PARTICLE_INV_FADE_DISTANCE > 0.0) \
{ \
float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projectedPosition))); \
float fade = saturate (SOFT_PARTICLE_INV_FADE_DISTANCE * ((sceneZ - SOFT_PARTICLE_NEAR_FADE) - i.projectedPosition.z)); \
ALBEDO_MUL *= fade; \
}
#else
#define fragSoftParticles(i)
#endif
参考我手绘的一张图:
下面我们的实现代码
// vert
#if DEEP_EFF
o.projPos = ComputeScreenPos (o.pos);
COMPUTE_EYEDEPTH(o.projPos.z);
#endif
// frag
#if DEEP_EFF // 水深效果
// 深度效果
// 这里参考unity内置的shader中,实现软例子:Soft particle的写法
// 与背景深度远时,alpha比较高,里的近则alha低
// 先是获取深度图的view space下的z值: buffViewZ
float buffViewZ = LinearEyeD、epth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
// 再是获取片段的view space的z值:fragViewZ
float fragViewZ = i.projPos.z;
// 然后去他们之间的距离值做alpha的控制,与颜色lerp的变化
float fade = saturate ((buffViewZ-fragViewZ) * _DeepFactor);
combined.rgb = lerp(combined.rgb + _ShallowColor.rgb * (_ShallowColor.a * 2), combined.rgb, fade);
combined.a *= fade;
#endif
材质中暴露了一个DeepFactor
参数,可以用于控制水深的系数。如下:
也暴露了一个浅水的颜色色调着色:
这个就是传统的经验光照模型:ambient + diffuse(HalfLambert) + specular(blinn phong)
// frag
#if LIGHTING_ON // 光照效果
// ambient
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
// diffuse
half3 L = normalize(_WorldSpaceLightPos0.xyz);
half3 N = normalize(i.normal);
half LdotN = dot(L, N) * 0.5 + 0.5;
fixed3 diffuse = col.rgb * LdotN;
// specular
half3 specular = 0;
half3 V = normalize(_WorldSpaceCameraPos.xyz - i.wPos);
half3 H = normalize(L + V);
half HdotN = max(0, dot(H, N)); // blinn-phone
specular = _LightColor0.rgb * pow(HdotN, _SpecularGlossy * 100) * _SpecularIntensity;
// combined color
fixed4 combined = fixed4(ambient + diffuse + specular, col.a);
#else // LIGHTING_OFF
fixed4 combined = col;
#endif
参考:Unity Shader - 简单山脉 - 顶点着色器重构法线,这里不说了,参考的文章说得很清楚的。
#if REBUILD_NORMAL // 重构法线,参考:https://blog.csdn.net/linjf520/article/details/104859710
// reconstruct normals
// 这个4x4数据也可以通过外部传入,可以节省顶点着色器ALU的计算量与L1 caches缓存量。
const float4x4 offset_xz = {
{+1,+0, /* gap **/ +1,-1}, // 右下
{+0,-1, /* gap **/ -1,-1}, // 左下
{-1,+0, /* gap **/ -1,+1}, // 左上
{+0,+1, /* gap **/ +1,+1} // 右上
};
// 默认向量也可以外部传入,因为上面的默认法线是可以调整的
// 下面我讲默认法线初始化为:up
float3 sumNormal = float3(0, 1, 0);
float4 uv4 = 0;
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?