Graphics 如何在着色器中高效地绘制直线和圆

Graphics 如何在着色器中高效地绘制直线和圆,graphics,glsl,webgl,shader,Graphics,Glsl,Webgl,Shader,我使用此网站创建了一个着色器,显示一个雪人和一些雪花: 如果链接不起作用,代码如下: #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.141

我使用此网站创建了一个着色器,显示一个雪人和一些雪花: 如果链接不起作用,代码如下:

#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;



}
它的工作方式是,对于屏幕上的每个像素,着色器会检查每个elment按钮、主体、头部、眼睛、嘴巴、胡萝卜、雪花是否在某个区域内,在这种情况下,它会使用当前绘制颜色替换该位置的当前颜色

因此,我们有一个复杂的阿片素_宽度*像素_高度*元素,当屏幕上有太多雪花时,这会导致着色器变慢。 所以现在我想知道,如何优化这段代码?我已经考虑过使用边界框,甚至是3d八叉树,我想这将是一个四叉树,用于快速丢弃某个像素或片段区域之外的元素


有人知道如何优化此着色器代码吗?请记住,每个着色器的执行都完全独立于所有其他着色器,我不能使用任何总体结构。

您需要将屏幕分为多个区域、分片,并计算每个分片的雪花数。瓷砖将具有相同数量的雪花并共享相同的种子,因此离开瓷砖边界的一个粒子将有相同的粒子进入下一个瓷砖,使其看起来无缝。该模式可能仍然取决于您的设置,但您可以考虑添加一个额外的统一转换,可能基于最终屏幕位置。


另一方面,通过删除所有条件分支和消除过程中的锯齿,可以更有效地绘制圆,并且可以消除由长度生成的平方根。

为形状创建简单的几何图形并使用纹理?该网站不支持纹理,我认为它可以伸缩,但圆包含通常是通过半径平方检查,而不是长度检查,这通常需要一个sqrt和其他乐趣。但老实说,如果系统无法向您报告它在哪里花费时间,那么您就是在猜测减速的实际位置。您可以通过使用三角形和多边形(而不是使用单个GLSL着色器)以正常方式进行优化。在单个GLSL着色器中进行操作的唯一一点是,作为一个难题,如何在一个着色器中绘制对象。这不是实现绩效的方式。性能是通过使用传统技术实现的,大多数高性能应用程序使用ie,通过使用许多着色器和多边形绘制游戏。否则,根据gpu的不同,通过添加分层检查,您可能可以节省一些时间。如果InGroup ABCD{groupABCD…}或者{groupEFGH…}groupABCD。。。{if inGroupAB{groupAB}else{groupCD}groupAB..{if inA{doA..}else{doB..}等等…谢谢,像这样的事情是我最终做的,我只是不知道如何移动雪花:。