2

I am using this simple function to draw quad in 3D space that is facing camera. Now, I want to use fragment shader to draw illusion of a sphere inside. But, the problem is I'm new to OpenGL ES, so I don't know how?

void draw_sphere(view_t view) {

    set_gl_options(COURSE);

    glPushMatrix();
    {
        glTranslatef(view.plyr_pos.x, view.plyr_pos.y, view.plyr_pos.z - 1.9);
#ifdef __APPLE__
#undef  glEnableClientState
#undef  glDisableClientState
#undef  glVertexPointer
#undef  glTexCoordPointer
#undef  glDrawArrays

        static const GLfloat vertices []=
        {
            0, 0, 0,
            1, 0, 0,
            1, 1, 0,
            0, 1, 0,
            0, 0, 0,
            1, 1, 0
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, 0, vertices);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
        glDisableClientState(GL_VERTEX_ARRAY);
#else
#endif
    }
    glPopMatrix();
}

More exactly, I want to achieve this: Enhancing Molecules using OpenGL ES 2.0

miller
  • 1,636
  • 3
  • 26
  • 55
  • You code example uses functions that are only supported by ES 1, ES 2 doesn't have these. But then ES 1 doesn't have shaders. So what version of OpenGL ES are you targetting? – Christian Rau Apr 08 '13 at 13:39
  • Well, I guess OpenGL ES 2. – miller Apr 09 '13 at 07:51
  • Then your code example won't work, since it uses only a single function that is supported by OpenGL ES 2. – Christian Rau Apr 09 '13 at 08:08
  • 2
    You should probably point to my answer: http://stackoverflow.com/questions/10488086/drawing-a-sphere-in-opengl-es/10506172#10506172 which is where you copied that image from. I describe the exact shader code used to achieve that effect, and you can even download the code for the application I built around that. The rest is simply drawing a two-triangle quad, passing in the four impostor space coordinates shown in the image, and running this shader against that. – Brad Larson Apr 10 '13 at 22:13

1 Answers1

6

There might be quite a few thing you need to to achieve this... The sphere that is drawn on the last image you posted is a result in using lighting and shine and color. In general you need a shader that can process all that and can normally work for any shape.

This specific case (also some others that can be mathematically presented) can be drawn with a single quad without even needing to push normal coordinates to the program. What you need to do is create a normal in a fragment shader: If you receive vectors sphereCenter, fragmentPosition and float sphereRadius, then sphereNormal is a vector such as

sphereNormal = (fragmentPosition-sphereCenter)/radius; //taking into account all have .z = .0
sphereNormal.z = -sqrt(1.0 - length(sphereNormal)); //only if(length(spherePosition) < sphereRadius)

and real sphere position:

spherePosition = sphereCenter + sphereNormal*sphereRadius;

Now all you need to do is add your lighting.. Static or not it is most common to use some ambient factor, linear and square distance factors, shine factor:

color = ambient*materialColor; //apply ambient

vector fragmentToLight = lightPosition-spherePosition;
float lightDistance = length(fragmentToLight);
fragmentToLight = normalize(fragmentToLight); //can also just divide with light distance
float dotFactor = dot(sphereNormal, fragmentToLight); //dot factor is used to take int account the angle between light and surface normal
if(dotFactor > .0) {
   color += (materialColor*dotFactor)/(1.0 + lightDistance*linearFactor + lightDistance*lightDistance*squareFactor); //apply dot factor and distance factors (in many cases the distance factors are 0)
}

vector shineVector = (sphereNormal*(2.0*dotFactor)) - fragmentToLight; //this is a vector that is mirrored through the normal, it is a reflection vector
float shineFactor = dot(shineVector, normalize(cameraPosition-spherePosition)); //factor represents how strong is the light reflection towards the viewer
if(shineFactor > .0) {
   color += materialColor*(shineFactor*shineFactor * shine); //or some other power then 2 (shineFactor*shineFactor)
}

This pattern to create lights in fragment shader is one of very many. If you don't like it or you cant make it work I suggest you find another one on the web, otherwise I hope you will understand it and be able to play around with it.

Matic Oblak
  • 16,318
  • 3
  • 24
  • 43
  • 4
    The exact shader code used to generate the above image can be found here: http://stackoverflow.com/questions/10488086/drawing-a-sphere-in-opengl-es/10506172#10506172 (it was what I used to create the image that was copied into the question here). – Brad Larson Apr 10 '13 at 22:15