2013-11-03 31 views
3

經過幾天的大量研究和測試,我終於能夠實現所顯示的片段着色器是本書(可以說是一本很好的書):http://arcsynthesis.org/gltut/Basics/Tutorial%2002.html適用於Android的OpenGL ES 2.0 - gl_FragCoord和gl_FragColor

它只是教會如何渲染一個簡單的三角形與使用「gl_FragCoord.y」的片段着色器。

但是在這些工作日裏,我經歷了一些我希望更好地理解他們爲什麼發生的問題。

- 在我的片段着色器,如果我使用的代碼: gl_FragColor = vec4(gl_FragCoord.x/500.0, 0.0, 1.0, 1.0); 三角形渲染。

但如果我使用: gl_FragColor = vec4(gl_FragCoord.x/500, 0.0, 1.0, 1.0); 它不會呈現(我有一個黑色的屏幕,或任何顏色的GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);定義

這導致了一個問題:在GLSL號碼必須有小數?規範 需要注意的是,在代碼更改的唯一東西就是500.0數量爲500

第二 - 我怎樣才能找回屬於Fragmen裏面的變量值t着色器代碼在Toast中顯示它們?讓我解釋一下這個問題。

下面這三個代碼行:

float colorTwo[] = { 1.0f, 1.0f, 1.0f, 0.0f };

int mColorHandleTwo = GLES20.glGetUniformLocation(mProgram, "vColorTwo");

GLES20.glUniform4fv(mColorHandleTwo, 1, colorTwo, 0);

我能夠得到這個 「colorTwo」 陣列,並用它片段着色器代碼中。 在另一方面,我若假設片段着色器代碼內statment,如:

float whatThisNumber = gl_FragCoord.y

我怎樣才能得到這個漂浮在舉杯顯示呢?

下面的代碼實際上是一個我工作:

public class TheShape { 

    ByteBuffer myByteBuffer; 
    FloatBuffer positionBufferObject;  

    int mProgram; 

    public TheShape() { 

     float vertexPositions[] = { 

       0.75f, 0.75f, 0.0f, 1.0f, 
       0.75f, -0.75f, 0.0f, 1.0f, 
       -0.75f, -0.75f, 0.0f, 1.0f 

     }; 

     myByteBuffer = ByteBuffer.allocateDirect(vertexPositions.length * 4); 
     myByteBuffer.order(ByteOrder.nativeOrder()); 

     positionBufferObject = myByteBuffer.asFloatBuffer(); 
     positionBufferObject.put(vertexPositions); 
     positionBufferObject.position(0); 

     String vertexShaderCode = 
       "attribute vec4 vPosition;" + 
       "void main() {" + 
       " gl_Position = vPosition;" + 
       "}"; 

     String fragmentShaderCode = 
       "precision mediump float;" + 
       "uniform vec4 vColor;" + 
       "uniform vec4 vColorTwo;" + 
       "void main() {" + 
       "gl_FragColor = vec4(gl_FragCoord.x/500.0, 0.0, 1.0, 1.0);" + 
     //ok "gl_FragColor = mix(vColorTwo, vColor, (gl_FragCoord.y)/500.0);" + 
     //ok "gl_FragColor = vec4((gl_FragCoord.x)/500.0, (gl_FragCoord.y)/500.0, 0.0, 1.0);" + 
       "}"; 

     int myVertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 
     GLES20.glShaderSource(myVertexShader, vertexShaderCode); 
     GLES20.glCompileShader(myVertexShader); 

     int myFragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 
     GLES20.glShaderSource(myFragmentShader, fragmentShaderCode); 
     GLES20.glCompileShader(myFragmentShader); 

     mProgram = GLES20.glCreateProgram(); 

     GLES20.glAttachShader(mProgram, myVertexShader);   
     GLES20.glAttachShader(mProgram, myFragmentShader); 

     GLES20.glLinkProgram(mProgram);   

    } 

    public void draw() { 

     GLES20.glUseProgram(mProgram); 

     GLES20.glEnableVertexAttribArray(0); 
     GLES20.glVertexAttribPointer(0, 4, GLES20.GL_FLOAT, false, 0, positionBufferObject); 



     float color[] = { 0.0f, 0.0f, 0.0f, 1.0f }; 
     int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); 
     GLES20.glUniform4fv(mColorHandle, 1, color, 0); 


     float colorTwo[] = { 1.0f, 1.0f, 1.0f, 0.0f }; 
     int mColorHandleTwo = GLES20.glGetUniformLocation(mProgram, "vColorTwo"); 
     GLES20.glUniform4fv(mColorHandleTwo, 1, colorTwo, 0); 



     GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); 

    } 

} 

我希望我在我的問題說清楚。

回答

0

你的第一個問題是關於java是如何工作的,與OpenGL沒有關係。

如果用整數除整數,則會得到一個整數。所以我的猜測是,gl_FragCoord.x/500的結果是0.3的值,然後舍入爲零。

如果你用float(或double)分隔一個整數,你會得到一個float(或double)。因此,當您除以500.0時,您會得到您期望的非零浮點結果。你也可以通過使用500f來達到同樣的效果。無論哪種方式,您都要讓編譯器知道您正在使用浮點值,這在這裏顯然很重要。

至於你的第二個問題,我不相信你可以,儘管我很樂意被別人糾正。

+0

這與Java實際上沒有任何關係。 GLSL由OpenGL實現(通常是顯示驅動程序)編譯,'gl_FragCoord'是一個浮點3分量向量。如果您將這個向量(x)的單個元素混合起來,您將得到一個浮點標量。當表達式中的一個操作數是fp時,GLSL定義整型類型到浮點型的隱式轉換,所以這不應該成爲問題。我能想到的唯一情況是整數和fp之間的精度差異 - 如果整數大於尾數支持,則在升級到fp期間將發生精度損失。 –

+0

通常,在將整數500轉換爲浮點時,這不是主要問題,但OpenGL ES 2.0提供了三級浮點精度(兩個在片段着色器中是必需的,一個是可選的)。例如,lowp浮點變量只能表示範圍內的值:+/- 2.0。 –

1
  1. 在glsl語言中沒有從整數到浮點數的自動轉換,因此代碼行gl_FragColor = vec4(gl_FragCoord.x/500, 0.0, 1.0, 1.0);會導致編譯器錯誤。
  2. 您無法從java代碼(或C++代碼)中獲取着色器變量的值。 Java代碼從CPU執行,着色器從GPU執行。

希望它有幫助。