2012-03-14 27 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バッファのボールの後ろにあるため、顔全体が拒否されます。正しい透明性を実現するには、オブジェクトを前後にレンダリングする必要があります。

そして、あなたのインライン質問について:あなたが位置してglLightfvを呼び出すと //If I don't put this code in here (as opposed to above), the light gets all crazy! WHY!?

、位置はモデルビュー行列スタックに現在何によって変換されます。座標を定義している参照フレームの相対的な位置に適切な位置に配置する必要があります(ビューの座標、ワールドの座標、オブジェクトの座標かどうか)。

+0

ありがとうございます!基本的には、世界の座標にライトを固定しようとしています。ベストプラクティスのヒント – Brooks

3

シーンに実際には適用されないデプスバッファの概念の単純なケースに苦しんでいるようです。深度バッファは、画面上の各ピクセルの1つの深度を格納します。完全に不透明なオブジェクトを持つシーンでは、そのピクセルで最も近いオブジェクトの深度になります。

部分的に透明なオブジェクトをシーンに追加すると、いくつかのオブジェクトが個々のピクセルの色に寄与する位置に終わることに問題があります。しかし、あなたはまだそれらの1つだけの深さを保存することができます。

あなたのケースでおそらく起こっているのは、まずクリスタルボールを描いていることです。これは、さまざまなクリスタルボールピクセルの深度を深度バッファに入れていることです。あなたは顔を描こうとしていますが、OpenGLはバッファ内の値よりも遠いので、それらのピクセルをスキップしています。

クイックフィックスの解決策は、水晶球の前に常に顔を描くようにシーンジオメトリを手作業で並べ替えることです。

理想的な解決策では、不透明な奥行き値を設定するために、すべての不透明なジオメトリを伝統的に(一番前から後ろの順に近いもので、PowerVRではそれほど重要ではありませんが)ジオメトリが正しい順番で合成されるように前後にジオメトリを配置します。

OpenGLでは、特定のものの順序を比較的固定して、関連する値をGPUにプッシュして通信コストをかけないようにしたいと考えています。人々はまだ不透明で透明なジオメトリに分割して不透明なものを描く傾向がありますが、透明なジオメトリを描画するときにzバッファ書き込みを無効にすることがよくあります。問題にあまりにも多くの時間を費やすことはありません。デプスバッファが不透明なものが設定されたら

あなたは純粋に添加剤ブレンドを使用して満足している場合

は明らかに透明度のために描画任意の順序が正しいです。

+0

ありがとう! GPUからジオメトリを並べ替えると苦労します。私は実際に不透明なオブジェクトを持っていないので、本当に心配していません。透明のモデルはすべての時間を回転しているので、私は、添加剤の配合以外の他のオプションを持っているようにそれが聞こえませんか?あなたのオブジェクトの多くは、凸状の場合は特に、とにかく(ボールのような) - すべてと – Brooks

+0

BSPツリーはジオメトリが(まあ、計算上、とにかく)あなたが期待するかもしれないより少ない痛みで並べ替えが可能になる葉にプッシュダウン。それ以外の場合は、おそらく追加したいと思うでしょう。 – Tommy

関連する問題