Unity怎么样在一个面片上实现真实水体渲染

 查看数: 75 | 7 天前
提问:黄小厨

马上注册成为元素者,获取海量元素资源,结识各路大神级人物

您需要 登录 才可以下载或查看,没有帐号?注册

x
image.png
7 天前  

使用道具 登录

2个回答,把该问题分享到群,邀请大神一起回答。
首先采样法线贴图扰动来做波纹效果:

//采样法线贴图的uv坐标,和时间相加
o.bumpUv1.xy = v.uv + float2(_SinTime.x * _WaveSpeed.x, _SinTime.x * _WaveSpeed.y);
o.bumpUv1.zw = v.uv + float2(_CosTime.y * 1.2 * _WaveSpeed.z, _SinTime.y*0.5* _WaveSpeed.w);

//法线贴图  
half4 bump10 = (tex2D(_DumpTex, v.bumpUv1.xy / _NormalsScale) * 2) + (tex2D(_DumpTex, v.bumpUv1.zw / _NormalsScale) * 2) - 2;  
half3 oriOffset = UnpackNormal(bump10);  
oriOffset.xy = oriOffset.xy * _NormalsStrength;
bump = normalize(oriOffset);  
half2 offset = oriOffset.xy;
//采样折射贴图(地面) float4 refraCol = tex2D(_MainTexture, v.uv.xy + offset );
注意上面使用了不同的uv坐标采样两次法线贴图的数据,并各自乘以2后相加的结果减去2。

这样的目的是为了使得波纹有交叉扰动的感觉。

接着采样深度贴图,做出水浅,水深过渡的效果。

//深度贴图 float zdepth = tex2D(_DepthTexture, v.oriuv).r;
//把深度强的地方增强,弱的地方变化不大,这步可做可不做,具体看效果  zdepth = pow(zdepth, 1.3);
float depthDifference = zdepth * _FoamDeP; float waterDepthDifference01 = saturate(depthDifference);  
waterDepthDifference01 = pow(waterDepthDifference01, 0.8);  
//根据深度值插值颜色
float4 lightColor = lerp(float4(1, 1, 1, 1),_DepthGradientShallow , smoothstep(0,0.5, waterDepthDifference01));
float4 waterColor = lerp(lightColor, _DepthGradientDeep, waterDepthDifference01); float alpha = smoothstep(0, 0.1, zdepth);
再接着做实线的浪花

//浪花贴图  float4 FoamCol = tex2D(_FoamTexture, v.foamuv);
//根据深度值来显示透明度  float FoamAlpha = (FoamCol.r + (FoamCol.g * cSecondWeight));
FoamCol.a = FoamAlpha;  
half waveFaInner = _waveFaMax - _Time.y * _WaveSpeed.x * _waveFaSpeed % (_waveFaMax);  
waveFaInner = clamp(waveFaInner, _waveFaMin, _waveFaMax);
//是否显示浪花  half borderFlag = step(zdepth.r, waveFaInner) * step(waveFaInner - _line, zdepth.r);   
half4 border1 = FoamCol.a * borderFlag * _specularColor * (alpha);
然后就可以得出水体的颜色了:

float4 finalCol = float4(refraCol.rgb * waterColor.rgb, alpha);
half4 cc =  finalCol+ border1;
最后加上高光,

刚开始高光是想用blin-phong做的,效果不太好,感觉是一片片的生硬的色块,不仅有锯齿,还没过渡的感觉。

而海岛纪元的高光真的过渡很柔和,很真实。难道是PBR的高光渲染?

试了一下,果然是真的。

所以这里我用到了PBR的高光,也就是BRDF高光公式

//高光,PBR的高光
float roughness = 1.0 - _Smoothness;
roughness = max(roughness, 0.002);
float roughness2 = roughness * roughness;
//d项
half dCol = BRDF_DTerm(NdotH, roughness2);  
////G项
half gTerm = BRDF_GTerm(NdotL, NdotV, roughness2);  
////F项 菲涅尔  
half3 frenCol = BRDF_FresnelTerm(_specularColor.rgb, LdotH);
float specularPBL = dCol * gTerm * UNITY_PI * frenCol;
//不会为负数
specularPBL = max(0, specularPBL * NdotL);  
//any 参数里的任意一个元素不为零   
specularPBL *= any(_specularColor.rgb) ? 1.0 : 0.0;
//加上高光,得到最终的颜色  
float4 outCol = cc + float4(specularPBL * mainLight.color, 1) * alpha;  
outCol.r = clamp(outCol.r, 0, 1);  
outCol.g = clamp(outCol.g, 0, 1);  
outCol.b = clamp(outCol.b, 0, 1);  
return outCol;
回复 收起回复
B Color Smilies
还可输入 200 个字符
7 天前  
 赞 赞 1

使用道具 登录

可以直接去找个写实水的shader。。网上很多的。
回复 收起回复
B Color Smilies
还可输入 200 个字符
7 天前  
 赞 赞 1

使用道具 登录

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表