1

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. Sphere gradient

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"?

Community
  • 1
  • 1
Lee M.U.
  • 123
  • 1
  • 12
  • Repost this on http://blender.stackexchange.com/ – Andy Ray Dec 31 '16 at 04:38
  • @AndyRay I want to do this in **GLSL** to use another project (not on Blender), and just made prototype using Blender, so I think SO is the proper place to question this :-P – Lee M.U. Dec 31 '16 at 04:44
  • you can slightly moddify this: [GLSL render Disc pattern](http://stackoverflow.com/a/35940219/2521214) just compute the color as a function of distance form mid point .... you know `Z=z0(+/-)sqrt(R^2 - (x-x0)^2 - (y-y0)^2)` ... – Spektre Dec 31 '16 at 10:47
  • @Spektre Thank you! That link helped me a lot :-) Just one more thing, that sphere should be always same appearance wherever I see, and `gl_Position=gl_Vertex;` didn't reflect model matrix, so I did `gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;`. But when I did that, only z axis becomes transparent, [like this](http://imgur.com/igxkJcy). I know that's because pos is `gl_Vertex.xy`, so I thought I have to modify gl_Position. In this situation, what should I do? – Lee M.U. Jan 01 '17 at 07:43
  • if your transparency depends on `Z` then compute it in fragment. For that you need sphere center `(x0,y0,z0)`,radius `R` and actual fragment position `(x,y)` all in the same coordinate system/space. If you use perspective and screen space then you need also scale `R` by the center distance from camera. From all this you just compute actual `z` with equation above... If outside sphere (therm under sqrt is negative) throw away fragment or set as fully transparent (If BLEND is used) if inside compute color and or transparency from your sphere relative coordinates `(x-x0,y-y0,z-z0)` – Spektre Jan 01 '17 at 10:30
  • @Spektre Actually, I couldn't fully understand yet :-( What you said is, get sphere model position, draw a wanted-size disk (and if I use perspective, set radius proportional to distance between model and camera), right? I fixed my program so that shader can get model position, so (x0,y0,z0) solved. I got actual fragment position by doing (gl_FragCoord.xy/resolution.xy). And got actual z by using your equation. But, i don't know how to join together in perspective view. What should i do? Plus, is it right to set gl_position to gl_ModelViewProjectionMatrix * gl_Vertex in this situation? – Lee M.U. Jan 02 '17 at 17:05
  • @Spektre I'm so sorry if the question above is quite stupid, but I'm too noob to here... I'm trying to understand but this thing is too new to me :-P – Lee M.U. Jan 02 '17 at 17:11

1 Answers1

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:

overview

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):

Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Thank you! Solved by modifying my program by following your instruction. :-) And Sorry for the late comment...I was in a hospital because of some accident ;-( – Lee M.U. Jan 08 '17 at 20:11