我已经使用此网站创建了一个着色器,用于显示一个雪人和一些雪花:
http://glslsandbox.com/e#54840.8
如果链接不起作用,请使用以下代码:
#ifdef GL_ES
precision mediump float;
#endif
#extension GL_OES_standard_derivatives : enable
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
uniform sampler2D backbuffer;
#define PI 3.14159265
vec2 p;
float bt;
float seed=0.1;
float rand(){
seed+=fract(sin(seed)*seed*1000.0)+.123;
return mod(seed,1.0);
}
//No I don't know why he loks so creepy
float thicc=.003;
vec3 color=vec3(1.);
vec3 border=vec3(.4);
void diff(float p){
if( (p)<thicc)
gl_FragColor.rgb=color;
}
void line(vec2 a, vec2 b){
vec2 q=p-a;
vec2 r=normalize(b-a);
if(dot(r,q)<0.){
diff(length(q));
return;
}
if(dot(r,q)>length(b-a)){
diff(length(p-b));
return;
}
vec2 rr=vec2(r.y,-r.x);
diff(abs(dot(rr,q)));
}
void circle(vec2 m,float r){
vec2 q=p-m;
vec3 c=color;
diff(length(q)-r);
color=border;
diff(abs(length(q)-r));
color=c;
}
void main() {
p=gl_FragCoord.xy/resolution.y;
bt=mod(time,4.*PI);
gl_FragColor.rgb=vec3(0.);
vec2 last;
//Body
circle(vec2(1.,.250),.230);
circle(vec2(1.,.520),.180);
circle(vec2(1.,.75),.13);
//Nose
color=vec3(1.,.4,.0);
line(vec2(1,.720),vec2(1.020,.740));
line(vec2(1,.720),vec2(.980,.740));
line(vec2(1,.720),vec2(.980,.740));
line(vec2(1.020,.740),vec2(.980,.740));
border=vec3(0);
color=vec3(1);
thicc=.006;
//Eyes
circle(vec2(.930,.800),.014);
circle(vec2(1.060,.800),.014);
color=vec3(.0);
thicc=0.;
//mouth
for(float x=0.;x<.1300;x+=.010)
circle(vec2(.930+x,.680+cos(x*40.0+.5)*.014),.005);
//buttons
for(float x=0.02;x<.450;x+=.070)
circle(vec2(1.000,.150+x),0.01);
color=vec3(0.9);
thicc=0.;
//snowflakes
for(int i=0;i<99;i++){
circle(vec2(rand()*2.0,mod(rand()-time,1.0)),0.01);
}
gl_FragColor.a=1.0;
}
它的工作方式是,对于屏幕上的每个像素,着色器检查区域内的每个元素(按钮,身体,头部,眼睛,嘴巴,胡萝卜,雪花),然后替换当前元素。使用当前绘制颜色在该位置上绘制颜色。
因此,我们的复杂度为O(pixels_width * pixels_height * elements)
,导致当自己的屏幕上有太多的雪花时,着色器速度变慢。
所以现在我想知道如何优化此代码?我已经考虑过使用边界框甚至3d Octree(我想那是四叉树)来快速丢弃某个像素(或片段)区域之外的元素。
有人有另一个想法如何优化此着色器代码吗?请记住,每个着色器执行完全独立于所有其他着色器,并且我不能使用任何总体结构。
答案 0 :(得分:0)
您需要将屏幕分成多个区域,“平铺”并计算每个图块的雪花。磁贴将具有相同数量的雪花并共享相同的种子,因此离开磁贴边界的一个粒子将具有相同的粒子进入下一个磁贴,从而使其看起来无缝。根据您的设置,图案可能仍会出现,但是您可以考虑根据最终的屏幕位置添加额外的统一变换。
顺便说一句,您可以通过删除所有条件分支(并在过程中看起来是抗锯齿的)来更有效地绘制圆形,并且可以摆脱length()生成的平方根。