const int nParticles = 150;const float size = 0.001;const float softness = 150.0;const vec4 bgColor = vec4(0.0,0.0,0.0,1.0); float random (int i){ return fract(sin(float(i)*43.0)*4790.234); } float softEdge(float edge, float amt){ return clamp(1.0 / (clamp(edge, 1.0/amt, 1.0)*amt), 0.,1.);} void mainImage( out vec4 fragColor, in vec2 fragCoord ){ vec2 uv = fragCoord/iResolution.xy; vec2 tc = uv; float aspect = iResolution.x / iResolution.y; uv.x *= aspect; fragColor = bgColor; //vec4 tex = texture(iChannel0, tc); float np = float(nParticles); for(int i = 0; i vec2 tc = uv; float r = random(i); float r2 = random(i+nParticles); float r3 = random(i+nParticles*2); tc.x -= sin(iTime*1.125 + r*30.0)*r; tc.y -= cos(iTime*1.125 + r*40.0)*r2*0.5; float l = length(tc - vec2(aspect*0.5, 0.5));// - r*size; tc -= vec2(aspect*0.5, 0.5)*1.0; tc = tc * 2.0 - 1.0; tc *= 1.0; tc = tc * 0.5 + 0.5; vec4 orb = vec4(r, r2, r3, softEdge(l, softness)); orb.rgb *= 1.5; // boost it fragColor = mix(fragColor, orb, orb.a); } //fragColor = mix(tex, fragColor, fragColor.a);}
1.const int nParticles = 150;: 定义了粒子数量为150。
2.const float size = 0.001;: 定义了粒子大小为0.001。
3.const float softness = 150.0;: 定义了软边缘的强度为150.0。
4.const vec4 bgColor = vec4(0.0,0.0,0.0,1.0);: 定义了背景颜色为黑色。
5.float random(int i): 定义了一个生成伪随机数的函数,通过输入参数i生成不同的随机数。
6.float softEdge(float edge, float amt): 定义了一个函数,用于计算软边缘效果的强度。
7.void mainImage(out vec4 fragColor, in vec2 fragCoord): 主函数,负责计算每个像素的颜色。
8.vec2 uv = fragCoord / iResolution.xy;: 计算了当前像素的归一化坐标。
9.vec2 tc = uv;: 将uv坐标赋值给tc。
10.float aspect = iResolution.x / iResolution.y; uv.x *= aspect;: 计算了屏幕的宽高比,以便在水平方向上拉伸或挤压纹理。
11.fragColor = bgColor;: 将背景颜色赋给fragColor。
12.for(int i = 0; i < nParticles; i++) { ... }: 循环迭代nParticles次,生成粒子效果。
13.vec4 tex = texture(iChannel0, tc);: 这行代码被注释掉了,原本可能是用于从外部纹理中获取颜色信息的。
14.在循环中,通过调用random函数生成随机数r、r2和r3,用于控制粒子的位置和外观。
15.float l = length(tc - vec2(aspect*0.5, 0.5));: 计算了粒子距离屏幕中心的距离。
16.tc -= vec2(aspect*0.5, 0.5)*1.0; tc = tc * 2.0 - 1.0; tc *= 1.0; tc = tc * 0.5 + 0.5;: 对tc进行了一系列归一化操作,将其范围限制在0到1之间。
17.vec4 orb = vec4(r, r2, r3, softEdge(l, softness));: 创建了一个包含粒子颜色和透明度的vec4,透明度由softEdge函数计算得到。
18.orb.rgb *= 1.5;: 增强了粒子的颜色。
19.fragColor = mix(fragColor, orb, orb.a);: 使用混合函数将当前像素的颜色与粒子颜色进行混合。
20.//fragColor = mix(tex, fragColor, fragColor.a);: 这行代码被注释掉了,原本应该是用于将外部纹理与粒子效果混合。
由于unreal材质使用hlsl,而shadertoy使用glsl,所以需要将上面代码转化为hlsl。
针对当前案例中的代码主要的转化点为:
数据类型转换:GLSL中的vec2、vec4、float等类型需要转换为HLSL中的float2、float4、float等类型。
内置变量的转换:GLSL中的内置变量如iResolution、iTime等需要转换为HLSL中对应的内置变量。
函数定义与调用:GLSL中的函数定义和调用与HLSL中稍有不同,比如GLSL中的mix需要转化为HLSL中的lerp。
所以经过转化以后的代码如下:
//也可以继续用const来定义常量#define nParticles 150#define size 0.001#define softness 150.0 #define bgColor float4(0.0, 0.0, 0.0, 1.0) float random(int i) { return frac(sin(float(i) * 43.0) * 4790.234);} float softEdge(float edge, float amt) { return clamp(1.0 / (clamp(edge, 1.0 / amt, 1.0) * amt), 0.0, 1.0);} void mainImage(out float4 fragColor : SV_Target, in float2 fragCoord : VPos) { float2 uv = fragCoord / iResolution.xy; float2 tc = uv; float aspect = iResolution.x / iResolution.y; uv.x *= aspect; fragColor = bgColor; //float4 tex = tex2D(iChannel0, tc); float np = nParticles; for(int i = 0; i float2 tc = uv; float r = random(i); float r2 = random(i + nParticles); float r3 = random(i + nParticles * 2); tc.x -= sin(iTime * 1.125 + r * 30.0) * r; tc.y -= cos(iTime * 1.125 + r * 40.0) * r2 * 0.5; float l = length(tc - float2(aspect * 0.5, 0.5));// - r * size; tc -= float2(aspect * 0.5, 0.5) * 1.0; tc = tc * 2.0 - 1.0; tc *= 1.0; tc = tc * 0.5 + 0.5; float4 orb = float4(r, r2, r3, softEdge(l, softness)); orb.rgb *= 1.5; // boost it fragColor = lerp(fragColor, orb, orb.a); } //fragColor = lerp(tex, fragColor, fragColor.a);}
要把上面代码写进unreal材质编辑器,就需要了解custom节点的一些使用方法。比如这里面除了主函数以外,还调用了一个随机数函数和一个软边函数,而一个custom本身就是一个函数,所以需要把调用的函数放在另外一个custom节点中。具体如下:
return 0;}float random(int i) { return frac(sin(float(i) * 43.0) * 4790.234);} float softEdge(float edge, float amt) {return clamp(1.0 / (clamp(edge, 1.0/amt, 1.0)*amt), 0.,1.);另起一个custom节点,放入主函数,并将常量等相关参数暴露在外方便设置for(int i = 0; i nParticles; i++) { float2 tc = uv; float r = random(i); float r2 = random(i + nParticles); float r3 = random(i + nParticles * 2); tc.x -= sin(iTime * 1.125 + r * 30.0) * r;//时间暴露方便做速度调整 tc.y -= cos(iTime * 1.125 + r * 40.0) * r2 * 0.5; float l = length(tc - float2( 0.5, 0.5));// - r * size; tc -= float2( 0.5, 0.5) * 1.0; tc = tc * 2.0 - 1.0; tc *= 1.0; tc = tc * 0.5 + 0.5; float4 orb = float4(r, r2, r3, softEdge(l, softness)); orb.rgb *= 1.5; // boost it fragColor = lerp(fragColor, orb, orb.a); }return fragColor;
实际放到custom的时候,用引擎uv进行了替换并暴露,相应的aspect 给到数值1,并且把下面的常量等作为参数进行暴露。
文章转载自
Thepoly