2013-04-08 108 views
2

我正在使用这个简单的函数在面向相机的3D空间中绘制四边形。现在,我想使用片段着色器来绘制内部球体的错觉。但是,问题是我是OpenGL ES的新手,所以我不知道如何?如何使用片段着色器在OpenGL ES中绘制球体错觉?

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(); 
} 

更精确地说,我要做到这一点: Enhancing Molecules using OpenGL ES 2.0

+0

您的代码示例使用仅由ES 1支持的功能,ES 2没有这些功能。但是ES 1没有着色器。那么你的目标是什么版本的OpenGL ES? – 2013-04-08 13:39:25

+0

那么,我猜OpenGL ES 2. – miller 2013-04-09 07:51:48

+0

然后你的代码示例将无法正常工作,因为它只使用OpenGL ES 2支持的单个函数。 – 2013-04-09 08:08:05

回答

5

有可能是你需要实现这个...这是你发布的最后一个图像的绘制球体了不少东西使用照明和光泽和颜色的结果。一般来说,你需要一个可以处理所有这些并且通常可以用于任何形状的着色器。

这个特定的情况(也可以用数学表示的其他一些情况)可以用一个四元组绘制,而不需要将正常坐标推送到程序。什么,你需要做的是在片段着色器创建一个正常的:如果你收到载体sphereCenterfragmentPosition和浮sphereRadius,然后sphereNormal

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

和实时球位置这样的载体:

spherePosition = sphereCenter + sphereNormal*sphereRadius; 

现在你需要做的就是添加你的照明。静态或不是最常见的使用一些环境因素,线性和平方距离因素,闪耀因子:

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

这种在片段着色器中创建灯光的模式非常多。如果你不喜欢它,或者你不能使它工作,我建议你在网上找到另一个,否则我希望你能理解它,并能够玩弄它。

+2

用于生成上述图像的确切着色器代码可以在这里找到:http://stackoverflow.com/questions/10488086/drawing-a-sphere-in-opengl-es/10506172#10506172(这是我曾经创建复制到问题中的图像)。 – 2013-04-10 22:15:12