2012-04-07 21 views
0

我遇到了一些意想不到的與Stage3D一起工作的問題。我爲我的對象製作了兩個不同的着色器程序。其中一個程序是使用紋理位圖和UV數據。另一個只是使用顏色數據。這兩個對象是非常不同的,因爲最終,我會用純色和簡單的渲染邏輯顯示一些東西(如方向線,高光等),而其他東西(如實際對象,背景等)將用mipmaps等渲染向前。問題是,當我使用這兩個非常不同的着色器程序時,只有一個或另一個工作。因此,無論是我的所有僅用於顏色的對象還是所有僅用於紋理的對象都會出現。顯然,我希望兩者都出現。混合不同的Program3D會導致一些對象無法渲染

下面是紋理對象我的AGAL代碼:

頂點着色器:

//4x4 matrix multiply to get camera angle 
"m44 op, va0, vc0\n" + 
//tell fragment shader about xyz 
"mov v0, va0\n" + 
//tell frament shader about uv 
"mov v1, va1\n" + 
//tell fragment shader about RGBA 
"mov v2, va2\n" 

片段着色器:

//grab the texture color from texture 0 and 
//the uv coordinates from varying register 1 and 
//store the interpolated value in ft0 
"tex ft0, v1, fs0 <2d,linear,repeat,miplinear>\n" + 
//move this value to the output color 
"mov oc, ft0\n" 

這些對象的繪製代碼如下所示:

context3D.setProgram(_renderProgram); 
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, renderMatrix, true); 
context3D.setTextureAt(0, texture); 

// vertex position to attribute register 0 
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 
context3D.setVertexBufferAt(1, uvBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); 
context3D.setVertexBufferAt(2, colorsBuffer, 0, Context3DVertexBufferFormat.FLOAT_4); 

這裏是清楚的彩色物體我AGAL代碼(即無紋理):

頂點着色器:

"m44 op, va0, vc0\n" + // pos to clipspace 
"mov v0, va1" // copy color 

片段着色器:

"mov oc, v0 " 

這些對象的繪製代碼如下所示:

context3D.setProgram(_renderProgram); 
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, renderMatrix, true); 
// vertex position to attribute register 0 
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); 
// color to attribute register 1 
context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3); 

由於某些原因,我不明白,我是這樣的事實將不同的數據分配給不同的變化的寄存器索引(va)導致渲染過程之一失敗。如果我在紋理循環中首先渲染紋理對象,則所有顏色對象消失,反之亦然。對象將在第一幀中正確顯示。但只要渲染循環第二次播放,就會發生這種意外行爲。

我發現,如果我通過增加,修改顏色對象的渲染代碼如下:

context3D.setTextureAt(0, null); 
context3D.setVertexBufferAt(2, null); 

它的工作原理。但這真的不是一個好的解決方案。我不想知道在我的程序中的某個地方,另一個對象正在渲染n個不同的寄存器,所以如果另一個program3D實例需要少於n個,我必須將所有這些未使用的va設置爲null。此外,如果我爲某個對象(例如發光對象)創建了一個新的着色器程序,現在需要第四個VA,現在我必須返回並修改其他所有着色器程序,以將VA4設置爲空,以便渲染所有內容。這是真的嗎?當然,我在這裏錯過了一些東西。同樣的事情去設置我所有的紋理寄存器(英尺)。

我可以提供更多的信息.​​.....

+0

不會將此作爲答案添加,但我在以下鏈接中發現了一些有趣的內容:http://en.nicoptere.net/?p=2119#more-2119:「問題在於此頂點緩衝區將在drawTriangles()調用之後保留在內存中,並且當你繪製下一個對象時,GPU會期望着色器使用它,如果沒有,則會崩潰。因此,在渲染任何東西之前,明智地實施3個步驟呈現邏輯「。 – jpwrunyan 2012-04-11 02:04:39

+0

然後他繼續說,在每次調用drawTriangles()之後,他將從GPU中取消分配資源。例如:context.setVertexBufferAt(0,null); // - > va0 = null; context.setVertexBufferAt(1,null); // - > va1 = null; context.setTextureAt(0,null); // - > fs0 = null – jpwrunyan 2012-04-11 02:06:39

+0

你是否有任何實際的錯誤,或者你的代碼不工作?你能提供更多的源代碼嗎?很高興看到您設置程序和drawTriangles()的順序。 – bwroga 2012-12-05 20:22:35

回答

0

這裏挖了一個老帖子。我注意到你的意見和想法我會提到(主要是爲了未來的讀者),你發現的事實上是糾正解決方案。當準備繪製一個三維物體在屏幕上,典型的過程是這樣的:

  • 定義/編譯/上傳程序
  • 上傳頂點和紋理
  • 開始渲染循環
    • 開始對象循環
      • 組節目
      • 組常數
      • 組輸入緩衝器和叔extures
      • 呼叫drawTriangles()
      • 組輸入緩衝器和紋理爲null
    • 結束對象環路
    • 呼叫本()
  • 端呈現循環
0

不幸的是,看起來你是對的 - 至少這是我找到並實施的解決方案。先前通過的紋理必須「清除」...

context3D.setTextureAt(<n>, null); 

......否則,您的無紋理着色器仍然會期望紋理並且不會呈現。