[英]How to use fragment shader to draw sphere ilusion in OpenGL ES?
我正在使用此簡單功能在面向相機的3D空間中繪制四邊形。 現在,我想使用片段着色器在內部繪制一個球體的錯覺。 但是,問題是我是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();
}
更確切地說,我想實現以下目標:
要實現此目標,可能需要做很多事情...在您發布的最后一張圖像上繪制的球體是使用照明,光澤和顏色的結果。 通常,您需要一個可以處理所有內容並且通常可以適用於任何形狀的着色器。
可以用單個四邊形繪制此特定情況(也可以用數學方式表示其他一些情況),而無需將法向坐標推送到程序。 您需要做的是在片段着色器中創建一個法線:如果接收到向量sphereCenter
, fragmentPosition
和float 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)
}
在片段着色器中創建光的這種模式是很多模式之一。 如果您不喜歡它或無法使其正常運行,我建議您在網絡上找到另一個,否則,我希望您能理解並能夠試用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.