How can i make gradient sphere on glsl?

ぃ、小莉子 提交于 2020-01-10 05:40:13

问题


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.

So I made a prototype using Blender node editor and that's how I did.

Now I am trying to do this in glsl.
Maybe i can use gl_Normal to replace "normal on Geometry" on Blender.
(Though it's removed after version 140, my final goal is just "make" it, so ignore that.)
And there are also dot function to calculate "dot product on vector math" on glsl.

Now i need is "View vector of camera data" and "ColorRamp".
I think "ColorRamp" can be done with mix and sin functions,
but have no idea how to get "View vector of camera data".
I already read this, and understand what it is, but don't know how to get.

So How can I get "View vector of camera data"?


回答1:


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


来源:https://stackoverflow.com/questions/41405498/how-can-i-make-gradient-sphere-on-glsl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!