我正在尝试使用sin函数在Unity 2017.1.0f3中编写一个简单的类似波形的着色器,但是它是一个未定义的一种颜色形状而没有重新定义法线,因此它可以使阴影正确。然而,尽管我的数学,我似乎无法让这些法线看起来正确,正如你在GIF中看到的那样,它们都是超级混乱。
所以这就是我正在做的事情:
void vert(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
//Just basing the height of the wave on distance from the center and time
half offsetvert = o.offsetVert = ((v.vertex.x*v.vertex.x) + (v.vertex.z * v.vertex.z))*100;//The 100 is to compensate for the massive scaling of the object
half value = _Scale * sin(-_Time.w * _Speed + offsetvert * _Frequency)/100;
v.vertex.y += value;
o.pos = v.vertex.xyz;
}
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_CBUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_CBUFFER_END
void surf (Input IN, inout SurfaceOutputStandard o)
{
//Calculate new normals
//Refer to MATH (1) for how I'm getting the y
float3 norm = (0,sqrt(1/(1+1/(-100/(_Scale*_Frequency*cos(_Time.w * _Speed + IN.offsetVert * _Frequency))))),0);
//Refer to Math (2) for how I'm getting the x and z
float derrivative = _Scale*_Frequency*cos(-_Time.w * _Speed + IN.offsetVert * _Frequency)/100;
float3 norm = (0,sqrt(1/(1+1/(-1/(derrivative)))),0);
float remaining = 1 - pow(norm.y,2);
norm.x = sqrt(remaining/(1 + IN.pos.z*IN.pos.z/(IN.pos.x*IN.pos.x)));
norm.z = sqrt(1-norm.y*norm.y-norm.x*norm.x);
//Assume this is facing away from the center
if (IN.pos.z<0)
norm.z = -norm.z;
if (IN.pos.x<0)
norm.x = -norm.x;
//Flip the direction if necessary
if (derrivative > 0){
norm.x = -norm.x;
norm.z = -norm.z;
}
norm.y = abs(norm.y);
norm = normalize(norm);//Just to be safe
o.Albedo = _Color.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
o.Normal.xyz = norm;
}
MATH 1 如果y是距离的函数
y =(scale / 100)sin(time.w * speed + distance * frequency)
然后
dy / d(距离)=(比例/ 100)*频率* cos(time.w *速度+距离*频率)
制作
法线的渐变y /(某些x和z方向)-100 /(标度*频率* cos(time.w *速度+距离*频率))。
我们也知道
(y分量)^ 2 +(某些xz分量)^ 2 = 1,
其中
(y分量)/(某些xz分量)=定义的正常梯度。
解决这两个联立方程式
y component = sqrt(1 /(1 + 1 /(gradient ^ 2)))
MATH 2 我们知道
(x分量)/(z分量)=(x位置)/(z位置)
和毕达哥拉斯,
(x分量)^ 2 +(z分量)^ 2 = 1 - (y分量)^ 2
并解决这些联立方程式
x component = sqrt((1 - (y component)^ 2)/(1 +(z position / x position)^ 2))
然后我们可以通过Pythagoras获得z组件。
如果你弄清楚出了什么问题,请告诉我。)
答案 0 :(得分:0)
为什么要计算曲面函数的法线?这是每个片段完成的,效率很低。为什么不仅仅计算顶点函数中的法线?
我要做的是与顶点偏移量相同的计算,只不过是针对从顶点在X和Y方向上偏移的另外两个点再次进行计算-然后您使用向量之间的叉积和偏移顶点以获得法线。
假设您已将偏移量移至其自己的函数,该函数将坐标作为参数。然后,您可以这样做:
float3 offsetPos = VertexOffset(v.vertex.xy)
float3 offsetPosX = offsetPos - VertexOffset(v.vertex.xy + float2(0.1, 0))
float3 offsetPosY = offsetPos - VertexOffset(v.vertex.xy + float2(0, 0.1))
v.vertex.xyz = offsetPos
v.normal.xyz = cross(normalize(offsetPosX), normalize(offsetPosY))