2014-01-16 106 views
1

我想使用Android NDK將OpenGL ES 2.0中的圖像作爲紋理顯示在四邊形上。使用OpenGL ES 2.0和Android NDK繪製的紋理

我有以下簡單的頂點和片段着色器:

#define DISP_SHADER_V_SRC "\ 
attribute vec4 aPos;\ 
attribute vec2 aTexCoord;\ 
varying vec2 vTexCoord;\ 
void main() {\ 
    gl_Position = aPos;\ 
    vTexCoord = aTexCoord;\ 
}" 

#define DISP_SHADER_F_SRC "\ 
precision mediump float;\n\ 
varying vec2 vTexCoord;\n\ 
uniform sampler2D sTexture;\n\ 
void main() {\n\ 
    gl_FragColor = texture2D(sTexture, vTexCoord);\n\ 
}" 

首先,創建GLSurfaceView當本地的「創建」方法被調用。它設置了清晰的顏色,構建了着色器並使用glGenTextures爲我提供了一個紋理ID。 「調整大小」方法設置當前視圖大小。另一種方法如下設置紋理數據:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 

我不相信那裏有什麼問題。重要的事情應該是「抽獎」的方法。 glClear,glViewport和glUseProgram後,我做到以下幾點:

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, texId); 

glEnableVertexAttribArray(shAPos); 
glVertexAttribPointer(shAPos, 3, GL_FLOAT, false, 0, quadVertices); 

glVertexAttribPointer(shATexCoord, 2, GL_FLOAT, false, 0, quadTexCoordsStd); 
glEnableVertexAttribArray(shATexCoord); 

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 
// now glDisableVertex... 

我可以證實的是,着色器基本工作原理,因爲gl_FragColor=vec4(1.0);導致白屏。當我加載紋理時,它不起作用。我嘗試使用memset將像素數據設置爲「全白」,以確認問題與我的圖像數據無關,但仍保持黑屏。我錯過了什麼?

+0

由於您可以使用修改的着色器進行繪製,因此聽起來像採樣器僅在紋理圖像中找到了零。你可以確認你在'glTexImage2D'調用之前調用'glBindTexture(GL_TEXTURE_2D,texId)'嗎?紋理是否使用兩種尺寸的冪次? – fadden

+0

我可以證實。我打電話給'glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,texId);',然後我設置'GL_CLAMP_TO_EDGE'並生成mipmap。我還通過設置'gl_FragColor = vec4(vTexCoord.s,vTexCoord.t,1.0,1.0)'來檢查'vTexCoord'是否有效。這一切都做它應該,除了繪製該死的質地:( – IsaacKleiner

+1

哇,這需要一些時間......嗯,我不*完全*確定問題是什麼,但我解決了這樣的問題:我注意到繪製當我通過JNI直接在'onSurfaceCreated'中調用紋理加載函數時,紋理起作用了,但是當我觸摸視圖時,我希望紋理髮生了變化,我猜想它與調用線程有關係,所以我移動了代碼來調用從OnClickListener直接到實現'GLSurfaceView.Renderer'的類的紋理加載函數,現在它的工作原理雖然很棘手,因爲沒有錯誤拋出:( – IsaacKleiner

回答

1

IsaacKleiner自己的評論是正確的,我遇到了同樣的問題,我用C++開發了一個使用NDK的OpenGL ES 2.0的android應用程序。加載紋理的函數最初是在C++部分。出於某種原因,這沒有奏效。只有在後,我將加載紋理代碼移動到java部分,它是否正常工作。 我將紋理加載到java部分,按正常方式綁定,然後將紋理ID傳遞給C++ JNI代碼。我不知道爲什麼會有這樣的問題。我可以提供a link,其中有一個使用OpenGL ES 1.0和NDK顯示多維數據集的示例。雖然它是中文的,但代碼可以解釋自己。請注意紋理是如何生成的以及紋理標識在Java和C++之間傳遞的方式。

+0

是的,再次說明這個問題:問題的根源在於不能使用來自兩個不同線程的OpenGL函數。無論它們是在Java還是在應用程序的C++ JNI部分,都應該始終從同一個線程(創建EGL上下文的線程)調用OpenGL函數。在我的情況下,我從UI線程調用一個GL函數(正如@fadden解釋的),這不起作用。將它移動到GLSurfaceView渲染線程後,它就可以工作。 – IsaacKleiner