目录
程序化生成星点图
主要思路是伪随机生成,随机因子是晶格化后的晶格坐标。生成星点后再添加一些动态效果。
随机生成
参考了这篇文章。对扩大了某个倍数的三角函数取小数部分,可以得到混乱的效果。
float random(float x, float factor){
return abs(frac(sin(x) * factor));
}
为每个晶格生成一个星点
首先要划分晶格,直接将uv扩大就可以。扩大的倍数直接决定了晶格的数量。
这里要根据晶格坐标的整数部分划分晶格,作为每个晶格独特的ID。之后,需要用这个ID来作为随机因子,为每个晶格生成一个星点坐标。这样,在片元着色器中便可以求得当前像素到星点坐标的距离,从而求得其亮度。
fixed4 galaxy(float2 uv, int tessFactor, int luminPower,fixed4 color , float rad){
uv *= tessFactor;
float u = floor(uv.x);
float v = floor(uv.y);
u = random(u,134.56);
v= random(v,56.546);
float2 xy = random2(float2(u,v));
u = xy.x;
v= xy.y;
float x = frac(uv.x);
float y = frac(uv.y);
float distance = pow(u - x,2) + pow(v - y,2);
distance = sqrt(distance);
float radians = rad*saturate(u/v);
radians = pow(radians,1);
fixed lumin = pow(saturate((radians - distance)),luminPower);
fixed4 randomColor = color *saturate(v/u);
fixed4 col = lumin * randomColor * (saturate(sin(_Time.y + 5 * u/v)) + 0.5);
return fixed4(col.rgb, 1);
}
不仅星点的坐标需要随机生成,每个星点的亮度、半径也需要一个随机值。
float radians = rad*saturate(u/v);
fixed4 randomColor = color *saturate(v/u);
实际上,需要对一维随机函数升级,使其能生成二维的随机数,才能正确生成随机的星点坐标
float2 random2(float2 xy){
return frac(sin(float2(dot(xy,float2(23423.1,54544.7)), sin(dot(xy,float2(33332.5,18563.3))))) *323434.34344);
}
一些动态效果
闪烁
首先是使其随时间闪烁,使用sin函数即可。要注意的是不同晶格的闪烁周期要错开。
fixed4 col = lumin * randomColor * (saturate(sin(_Time.y + 5 * u/v)) + 0.5);
偏移
星空是一个经典的样式,因此它有许多不同的动态样式。在做效果之前要把目标明确。我这次是为一个卡牌卡面做背景,考虑到没有视角反转,且大概率只有平移效果,我用世界坐标系下的xy坐标作为其偏移的基准,且做了两层。
fixed4 frag (v2f i) : SV_Target
{
float2 uv = i.vertex.xy/1000;
float3 clipPos = UnityWorldToClipPos(_WorldPos);
float exchange = (_WorldPos.x+ _WorldPos.y)/2;
exchange = (sin(exchange) + 1)/2;
float2 uv2 = uv + float2(1 * (2*_WorldPos.x/2000 - 1), 1* (2*_WorldPos.y/4000 -1));
float2 uv1 = uv + float2(1 * (2*_WorldPos.x/8000 - 1), 1* (2*_WorldPos.y/8000 -1));
fixed4 col = galaxy(uv1, _TessFactor, _Power, _Color, _Radians);
fixed4 col2 = galaxy(uv2,_TessFactor2, _Power2, _Color2, _Radians2);
fixed distanceFromSpec = sqrt(pow(uv.x - _SpecCenter.x, 2) +pow(uv.y - _SpecCenter.y,2));
distanceFromSpec = pow(distanceFromSpec, _SpecPower);
fixed4 specColor= saturate(lerp(0,1,_SpecRadius - distanceFromSpec)) * _SpecColor;
return col + col2 + lerp(0,col, exchange) + lerp(0,col2, 1 - exchange) + specColor;
}
接下来再做程序化生成星云噪声的效果。