How can i make gradient sphere on glsl?

前端 未结 1 695
南方客
南方客 2020-12-22 04:26

I\'m just a noob to GLSL and don\'t know how to do this in GLSL.
What I trying to do is making alpha value to 1 on center of sphere and drop gradually on outer.

相关标签:
1条回答
  • 2020-12-22 04:40

    Well without depth the shaders are simple enough:

    // Vertex
    varying vec2 pos;       // fragment position in world space
    void main()
        {
        pos=gl_Vertex.xy;
        gl_Position=ftransform();
        }
    
    // Fragment
    varying vec2 pos;
    uniform vec4 sphere;    // sphere center and radius (x,y,z,r)
    void main()
        {
        float r,z;
        r=length(pos-sphere.xy);    // radius = 2D distance to center (ignoring z)
        if (r>sphere.a) discard;    // throw away fragments outside sphere
        r=0.2*(1.0-(r/sphere[3]));  // color gradient from 2D radius ...
        gl_FragColor=vec4(r,r,r,1.0);
        }
    

    Yes you can also use gl_ModelViewProjectionMatrix * gl_Vertex; instead of the ftransform(). As you can see I used world coordinates so I do not need to play with radius scaling... If you want also the gl_FragDepth to make this 3D then you have to work in screen space which is much more complicated and I am too lazy to try it. Anyway change the gradient color to whatever you like.

    The rendering in C++ is done like this:

    void gl_draw()
        {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        GLint id;
    
        float aspect=float(xs)/float(ys);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60.0/aspect,aspect,0.1,100.0);
        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glRotatef(15.0,0.0,1.0,0.0);
        glTranslatef(1.0,1.0,-10.0);
    
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_TEXTURE_2D);
    
        float xyzr[4]={ 0.7,0.3,-5.0,1.5 };
    
        // GL 1.0 circle for debug
        int e; float a,x,y,z;
        glBegin(GL_LINE_STRIP);
        for (a=0.0,e=1;e;a+=0.01*M_PI)
            {
            if (a>=2.0*M_PI) { e=0; a=2.0*M_PI; }
            x=xyzr[0]+(xyzr[3]*cos(a));
            y=xyzr[1]+(xyzr[3]*sin(a));
            z=xyzr[2];
            glVertex3f(x,y,z);
            }
        glEnd();
    
        // GLSL sphere
        glUseProgram(prog_id);
        id=glGetUniformLocation(prog_id,"sphere"); glUniform4fv(id,1,xyzr);
        glBegin(GL_QUADS);
        glColor3f(1,1,1);
        glVertex3f(xyzr[0]-xyzr[3],xyzr[1]-xyzr[3],xyzr[2]);
        glVertex3f(xyzr[0]+xyzr[3],xyzr[1]-xyzr[3],xyzr[2]);
        glVertex3f(xyzr[0]+xyzr[3],xyzr[1]+xyzr[3],xyzr[2]);
        glVertex3f(xyzr[0]-xyzr[3],xyzr[1]+xyzr[3],xyzr[2]);
        glEnd();
        glUseProgram(0);
    
        glFlush();
        SwapBuffers(hdc);
        }
    

    And result:

    In white is the debug GL 1.0 circle to see if the two are placed in the same place. Change the gradient to match your needs. I did not use transparency so if you need it change the alpha component and enable/set BLENDing.

    The xs,ys is resolution of my GL window. and xyzr is your sphere { x,y,z,r } definition. Hope I did not forget to copy something. This code and answer take advantage of (so look there for more info in case I miss something):

    • GLSL render Disc pattern
    • complete GL+GLSL+VAO/VBO C++ example
    0 讨论(0)
提交回复
热议问题