2012-03-14 61 views
0

我想要一個模型(面部)在半透明模型(水晶球)內部做事的「面對水晶球」效果。我感覺我正在服用瘋狂的藥丸,因爲我無法讓這個內心的面孔出現在球的部分遮擋下。我的目標是改變球(和/或臉)的阿爾法,使臉部出現和消失。OpenGL(ES)半透明模型內的模型

下面是相關的位代碼。你會看到,我不使用着色器,只是很好的GL/GLES1。如果有人能告訴我我做錯了什麼,我會非常感激。

設置代碼...

//-- CONFIGURATION --------------- 
// Create The Depth Buffer Object 
glGenRenderbuffersOES(1, &depth_renderbuffer); 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depth_renderbuffer); 
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, 
         GL_DEPTH_COMPONENT16_OES, 
         width, 
         height); 

// Create The FrameBuffer Object 
glGenFramebuffersOES(1, &framebuffer); 
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); 
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, 
          GL_COLOR_ATTACHMENT0_OES, 
          GL_RENDERBUFFER_OES, 
          color_renderbuffer); 

glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, 
          GL_DEPTH_ATTACHMENT_OES, 
          GL_RENDERBUFFER_OES, 
          depth_renderbuffer); 

// Bind Color Buffer 
glBindRenderbufferOES(GL_RENDERBUFFER_OES, color_renderbuffer); 

glViewport(0, 0, width, height); 

//-- LIGHTING ---------------------- 
glEnable(GL_LIGHTING); 
glEnable(GL_LIGHT0); 

//-- PROJECTION --------------------- 
glMatrixMode(GL_PROJECTION); 
viewport_size = vec2((float) width,(float) height); 

//Orthographic Projection 
float max_x,max_y; 
if(width>height){ 
    max_y = 1; 
    max_x = (float)width/(float)height; 
} 
else{ 
    max_x = 1; 
    max_y = (float)height/(float) width; 
} 
const float MAX_X = max_x; 
const float MAX_Y = max_y; 
const float Z_0 = 0; 
const float MAX_Z = 1; 
glOrthof(-MAX_X, MAX_X, -MAX_Y, MAX_Y, Z_0-MAX_Z, Z_0+MAX_Z); 

world_size = vec3(2*MAX_X,2*MAX_Y,2*MAX_Z); 

//Color Depth 
glEnable(GL_DEPTH_TEST); 
glDepthMask(GL_TRUE); //Dissapears if False 
glDepthFunc(GL_LEQUAL); 
glEnable(GL_BLEND); 
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //doesn't do it 
glBlendFunc(GL_ONE, GL_ONE); //better 

這裏是渲染調用

glClearColor(world->background_color.x, 
      world->background_color.y, 
      world->background_color.z, 
      world->background_color.w); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

for(int s=0;s<surfaces.size();s++){ 
    Surface* surface = surface[s]; 

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, surface->getMatAmbient().Pointer()); 
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, surface->getMatDiffuse().Pointer()); 

    glMatrixMode(GL_MODELVIEW); 

    //If I don't put this code in here (as opposed to above), the light gets all crazy! WHY!? 
    glPushMatrix(); 
    glLoadIdentity(); 
    vec4 light_position = vec4(world->light->position,1); 
    glLightfv(GL_LIGHT0,GL_POSITION,light_position.Pointer()); 

    glPopMatrix(); 


    glPushMatrix(); 
    glMultMatrixf(surface->transform.Pointer()); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surface->index_buffer); 
    glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_buffer); 

    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_NORMAL_ARRAY); 

    glVertexPointer(3, GL_FLOAT, VERTEX_STRIDE, 0); 
    glNormalPointer(GL_FLOAT, VERTEX_STRIDE, (GLvoid*) VERTEX_NORMAL_OFFSET); 

    glDrawElements(GL_TRIANGLES, surface->indices.size(), GL_UNSIGNED_SHORT, 0); 


    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_NORMAL_ARRAY); 
    glPopMatrix(); 

} 

回答

2

爲了什麼你渲染的對象?如果您在面前畫球,那麼整個面部會被拒絕,因爲它位於z緩衝區內的球后面。如果你想做正確的透明度,你必須從後到前渲染對象。

和關於你的網線的問題: //If I don't put this code in here (as opposed to above), the light gets all crazy! WHY!?

當你調用glLightfv一個位置,該位置是由目前什麼在模型視圖矩陣堆棧轉化。你必須把它放在正確的地方,相對於你定義座標的參考框架(它是相對於視圖座標,還是世界座標,還是對象座標?)。

+0

謝謝!基本上我試圖修復世界座標中的光線。有關最佳做法的任何提示? – Brooks 2012-05-31 22:49:04

3

聽起來好像您可能正在遭受深度緩衝區概念的簡單情況,而這種情況並不適用於您的場景。深度緩衝區爲屏幕上的每個像素存儲一個深度,在具有完全不透明對象的場景中,該深度將是該像素處最近對象的深度。

問題是,當您想要將部分透明的對象添加到場景中時,最終會出現多個對象對單個像素的顏色起作用的位置。但是,您仍然可以存儲其中一個的深度。

那麼是什麼在你的情況很可能發生的事情是你第一次畫水晶球,而這把各種水晶球像素的深度進入深度緩衝。然後你試圖繪製臉部,OpenGL發現它比緩衝區中的值更遠,因此跳過這些像素。

所以快速修復解決方案就是用手重新排序場景幾何圖形,以便始終在水晶球之前繪製面部,始終在面板內部。

在一個理想的解決方案中,您可以在一個步驟中繪製所有不透明的幾何圖形(傳統上以接近前後順序的方式繪製,儘管這對於PowerVR並不重要)建立不透明的深度值,幾何回到正面,以便它按正確的順序合成。

在OpenGL中你真的想某些事情的順序是相對固定的,這樣就可以轉移到GPU推動相關的值,且不會產生通信費用。人們仍傾向於分爲透明和不透明的幾何形狀和繪製不透明第一,但往往他們就會再禁用時,他們繪製透明幾何Z緩衝寫道,在努力做到這一點的東西有點像背到前面的命令,但不要在這個問題上投入太多時間。

如果您很樂意使用純粹的添加混合,那麼一旦深度緩衝區設置了不透明的東西,顯然任何透明度順序圖都是正確的。

+0

謝謝!重新排列GPU上的幾何圖形聽起來很痛苦。我其實沒有不透明的物體,所以它們不是真正的問題。由於透明模型始終在旋轉,因此除了添加劑混合之外,聽起來並不像我有任何其他選擇? – Brooks 2012-05-31 22:53:09

+0

將所有東西推到樹葉上的BSP樹將允許幾何重新排序的次數比您預期的要少(在計算方面,無論如何) - 特別是如果很多對象都是凸起的(比如球)。否則,你可能會想要添加劑。 – Tommy 2012-05-31 23:51:19