经过几天的研究和测试,我终于成功实现了这本书中展示的片段着色器(一本非常好的书,我必须说):http://arcsynthesis.org/gltut/Basics/Tutorial%2002.html。
它只是教你如何使用“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。
第二 - 我如何检索片段着色器代码中的变量值,以便例如在Toast中显示它们?让我解释一下这个问题。
使用以下三行代码:
float colorTwo[] = { 1.0f, 1.0f, 1.0f, 0.0f };
int mColorHandleTwo = GLES20.glGetUniformLocation(mProgram, "vColorTwo");
GLES20.glUniform4fv(mColorHandleTwo, 1, colorTwo, 0);
我能够获取这个“colorTwo”数组,并在片段着色器代码中使用它。 另一方面,如果我在片段着色器代码中有一个语句,例如:
float whatThisNumber = gl_FragCoord.y
我该如何获取这个浮点数并在Toast中显示它?
下面的代码实际上是我正在处理的代码:
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);
}
}
我希望我的问题表达清楚了。
gl_FragCoord
是一个浮点型的三分量向量。如果你从这个向量中取出一个分量(x),你会得到一个浮点型的标量。GLSL定义了整数类型到浮点型的隐式转换,当表达式中的一个操作数是浮点型时,整数类型会被自动转换为浮点型,所以这不应该是一个问题。我唯一能想到的是整数和浮点型之间精度的差异 - 如果整数大于尾数支持的范围,升级为浮点型时会发生精度损失。 - Andon M. Colemanlowp
浮点变量只能表示范围内的值:+/- 2.0。 - Andon M. Coleman