我目前正在尝试在CG着色器中创建3D单面噪声实现以实现统一。我决定使用最初用C ++编写的this实现并将其移植到CG,因为它们是相似的。
我决定提供排列和渐变矢量作为纹理,因此它们可以很容易地在代码中使用。一切都很好,除了每个单纯形边缘的地方。这导致了我想修复的不可接受的视觉伪像。
注意纹理上的虚线。我认为它可能是圆形/地板的问题,但我无法弄清楚哪个操作导致了这个问题。我试着玩地板,但没有任何帮助。
这是我的着色器代码:
Shader "Custom/PerlinNoise" {
Properties {
_Permutation ("RandomVector (RGB)", 2D) = "white" { }
_Gradient3 ("GradientVector (RGB)", 2D) = "white" { }
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
uniform sampler2D _Permutation;
uniform sampler2D _Gradient3;
//Get the i-th int3 gradient. x,y,z in range [-1, 1]
int3 grad3(int i)
{
float2 pos;
pos.x = i / 16.0;
pos.y = 0;
fixed3 tx = tex2D(_Gradient3, pos);
tx = tx * 2.0 - 1;
return tx;
}
//Get the i-th permutation. Result in range [0-255]
int p(int i)
{
float2 pos;
pos.x = i / 256.0;
pos.y = 0.5;
return tex2D(_Permutation, pos).r * 256;
}
float dt(const int3 g, float x, float y, float z)
{
return g.x*x + g.y*y + g.z*z;
}
int fastfloor(const float x)
{
return x > 0 ? (int) x : (int) x - 1;
}
//Almost a copy-paste from the original C++ code
float simplex(const float x, const float y, const float z)
{
float n0, n1, n2, n3; // Noise contributions from the four corners
// Skew the input space to determine which simplex cell we're in
float F3 = 1.0/3.0;
float s = (x+y+z)*F3; // Very nice and simple skew factor for 3D
int i = fastfloor(x+s);
int j = fastfloor(y+s);
int k = fastfloor(z+s);
float G3 = 1.0/6.0; // Very nice and simple unskew factor, too
float t = (i+j+k)*G3;
float X0 = i-t; // Unskew the cell origin back to (x,y,z) space
float Y0 = j-t;
float Z0 = k-t;
float x0 = x-X0; // The x,y,z distances from the cell origin
float y0 = y-Y0;
float z0 = z-Z0;
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
// Determine which simplex we are in.
int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
if(x0>=y0) {
if(y0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order
else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order
else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order
}
else { // x0<y0
if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order
else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order
else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order
}
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
// c = 1/6.
float x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
float y1 = y0 - j1 + G3;
float z1 = z0 - k1 + G3;
float x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
float y2 = y0 - j2 + 2.0*G3;
float z2 = z0 - k2 + 2.0*G3;
float x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
float y3 = y0 - 1.0 + 3.0*G3;
float z3 = z0 - 1.0 + 3.0*G3;
// Work out the hashed gradient indices of the four simplex corners
int ii = i & 255;
int jj = j & 255;
int kk = k & 255;
int gi0 = p(ii+p(jj+p(kk))) % 12;
int gi1 = p(ii+i1+p(jj+j1+p(kk+k1))) % 12;
int gi2 = p(ii+i2+p(jj+j2+p(kk+k2))) % 12;
int gi3 = p(ii+1+p(jj+1+p(kk+1))) % 12;
// Calculate the contribution from the four corners
float t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
if(t0<0) n0 = 0.0;
else {
t0 *= t0;
n0 = t0 * t0 * dt(grad3(gi0), x0, y0, z0);
}
float t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
if(t1<0) n1 = 0.0;
else {
t1 *= t1;
n1 = t1 * t1 * dt(grad3(gi1), x1, y1, z1);
}
float t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
if(t2<0) n2 = 0.0;
else {
t2 *= t2;
n2 = t2 * t2 * dt(grad3(gi2), x2, y2, z2);
}
float t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
if(t3<0) n3 = 0.0;
else {
t3 *= t3;
n3 = t3 * t3 * dt(grad3(gi3), x3, y3, z3);
}
// Add contributions from each corner to get the final noise value.
// The result is scaled to stay just inside [0,1)
return 16.0*(n0 + n1 + n2 + n3) + 0.5;
}
float4 frag(v2f_img i) : SV_Target
{
float v = simplex(i.uv.x * 4, i.uv.y * 4, _Time);
return fixed4(v, v, v, 1.0);
}
ENDCG
}
}
}
以下是在着色器中模仿常量数据的图像:
请记住将它们分配给着色器中的适当属性。