我有任务要做。我需要为每个波浪创建挥舞的水着色器脚本,以使其具有随机大小。我试图通过创建C#脚本以将随机值传递给着色器脚本,然后将顶点输入乘以该值来创建它,但是当我这样做时,正如预期的那样,Y的所有值都被相乘,而这并不是我想要的结果。我需要将正弦波的一个特定波(一个pi)乘以仅增加一个波,而不是全部y点。同样,随机值变化太快,但我可以自行解决。
我是着色器脚本的新手,就我所知:
Shader "Custom/Waves"
{
Properties{
_Color("Color", Color) = (0, 0, 0, 1)
_Strength("Strength", Range(0, 2)) = 1.0
_Speed("Speed", Range(-200,200)) = 100
}
SubShader{
Tags{
"RenderType" = "transparent"
}
Pass{
Cull Off
CGPROGRAM
#pragma vertex vertexFunc
#pragma fragment fragFunc
float4 _Color;
float _Strength;
float _Speed;
struct vertexInput {
float4 vertex : POSITION;
};
struct vertexOutput {
float4 pos : SV_POSITION;
};
vertexOutput vertexFunc(vertexInput v) {
vertexOutput o;
float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
float a = 1;
float displacement = (cos(worldPos.y) + cos(worldPos.x + _Speed * _Time.y));
worldPos.y = worldPos.y + (displacement * _Strength);
o.pos = mul(UNITY_MATRIX_VP, worldPos);
return o;
}
float4 fragFunc(vertexOutput IN) : COLOR{
return _Color;
}
ENDCG
}
}
}
随机值的C#脚本:
public class RandomValue: MonoBehaviour
{
public Material material;
public float Max = 2.0f;
// Start is called before the first frame update
// Update is called once per frame
void Update()
{
float number = Random.Range(0.0f, Max);
material.SetFloat("_Strength", number);
}
}
有人可以解释我如何将随机值应用于在x顶点中移动的正弦波的特定部分。
更改单个波的幅度非常困难,需要您创建某种功能以使您可以对单个波峰进行操作。当您的波依赖于一个坐标时,这很容易,但是当峰也依赖于Y值的余弦时,这将变得更加复杂(您要使用Z表示吗?Y在Unity中是向上的!)。我认为通常情况下,您最好在总体上为波浪添加一些额外级别的随机性,以使其看起来更加多样化和动态。
[一种选择是使用程序噪声场,并将顶点X / Z位置用作UV坐标。您可以将其乘以正弦值以获得一些变化,甚至可以按时间抵消UV噪声,以获得更大的运动尺寸。这里有一个很好的梯度噪声实现:
https://www.shadertoy.com/view/XdXGW8
但是,当要模拟海洋中的多个波时,最常见的方法是使用快速傅立叶变换以较低的计算成本来模拟数千个波的频率和振幅之和。这就是大多数AAA游戏所使用的。有一些工程师级的数学知识,但是有一些资源和GitHub项目可以在线查看。通常,您可以在计算着色器中或在GPU上进行傅立叶变换,然后将它们以纹理的形式发送到顶点/片段着色器。
https://arm-software.github.io/opengl-es-sdk-for-android/ocean_f_f_t.html
https://www.keithlantz.net/2011/11/ocean-simulation-part-two-using-the-fast-fourier-transform/