问题在于FBO副本的结果填充了源纹理的纹理坐标0,0处的任何像素。
如果我编辑着色器以根据纹理坐标位置渲染渐变,则片段着色器会填充整个结果,就好像它有纹理坐标0,0一样。
如果我编辑三角形条带顶点,事情就像预期的那样,所以我认为相机和几何体设置正确。当它应该反映我的输入纹理或者至少我的位置渐变着色器时,2-tri四边形都是相同的颜色!
我已经将这段代码移植到了一个有效的iOS示例中。
这与Unity3D一起运行,因此不要假设任何GL设置是默认设置,因为引擎可能在我的代码启动之前摆弄它们。
这是FBO复制操作
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer);
checkGlError("glBindFramebuffer");
GLES20.glViewport(0, 0, TEXTURE_WIDTH*4, TEXTURE_HEIGHT*4);
checkGlError("glViewport");
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(false);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glPolygonOffset(0.0f, 0.0f);
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
checkGlError("fbo setup");
// Load the shaders if we have not done so
if (mProgram <= 0) {
createProgram();
Log.i(TAG, "InitializeTexture created program with ID: " + mProgram);
if (mProgram <= 0)
Log.e(TAG, "Failed to initialize shaders!");
}
// Set up the program
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glUniform1i(mUniforms[UNIFORM_TEXTURE], 0);
checkGlError("glUniform1i");
// clear the scene
GLES20.glClearColor(0.0f,0.0f, 0.1f, 1.0f);
checkGlError("glClearColor");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Bind out source texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
checkGlError("glActiveTexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mSourceTexture);
checkGlError("glBindTexture");
GLES20.glFrontFace( GLES20.GL_CW );
// Our object to render
ByteBuffer imageVerticesBB = ByteBuffer.allocateDirect(8 * 4);
imageVerticesBB.order(ByteOrder.nativeOrder());
FloatBuffer imageVertices = imageVerticesBB.asFloatBuffer();
imageVertices.put(new float[]{
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f}
);
imageVertices.position(0);
// The object's texture coordinates
ByteBuffer textureCoordinatesBB = ByteBuffer.allocateDirect(8 * 4);
imageVerticesBB.order(ByteOrder.nativeOrder());
FloatBuffer textureCoordinates = textureCoordinatesBB.asFloatBuffer();
textureCoordinates.put(new float[]{
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f}
);
textureCoordinates.position(0);
// Update attribute values.
GLES20.glEnableVertexAttribArray(ATTRIB_VERTEX);
GLES20.glVertexAttribPointer(ATTRIB_VERTEX, 2, GLES20.GL_FLOAT, false, 0, imageVertices);
GLES20.glEnableVertexAttribArray(ATTRIB_TEXTUREPOSITON);
GLES20.glVertexAttribPointer(ATTRIB_TEXTUREPOSITON, 2, GLES20.GL_FLOAT, false, 0, textureCoordinates);
// Draw the quad
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
如果你想深入了解,我在这里提出了更新循环,设置和着色器的好主意:https://gist.github.com/acgourley/7783624
我正在检查这个结果作为UnityFBO(MIT许可证)的Android端口,因此所有帮助都受到赞赏,并将更广泛地分享。
答案 0 :(得分:1)
顶点着色器 输出 和片段着色器 输入 的声明不会因纹理坐标变化而变化(不同的精度限定符)。通常情况下这不是一个问题,但由于我将在下面使用highp
在你的片段着色器中讨论的原因,可能会回来咬你的屁股。
attribute vec4 position;
attribute mediump vec4 textureCoordinate;
varying mediump vec2 coordinate;
void main()
{
gl_Position = position;
coordinate = textureCoordinate.xy;
}
varying highp vec2 coordinate;
uniform sampler2D texture;
void main()
{
gl_FragColor = texture2D(texture, coordinate);
}
<小时/> 在OpenGL ES 2.0中,
highp
是片段着色器中的可选功能。除非预处理器定义highp
,否则不应在片段着色器中声明任何GL_FRAGMENT_PRECISION_HIGH
。
内置宏 GL_FRAGMENT_PRECISION_HIGH 定义为支持片段语言 highp 精度的系统
#define GL_FRAGMENT_PRECISION_HIGH 1
并且未在不支持片段语言中的highp精度的系统上定义。定义时,此宏在顶点和片段语言中都可用。 highp 限定符是片段语言中的可选功能,未通过 #extension 启用。
最重要的是,您需要在声明某些内容highp
之前检查片段着色器是否支持highp
精度,或者在片段着色器中重新编写声明以使用mediump
。我无法看到在片段着色器中任意增加顶点着色器坐标精度的太多理由,老实说,我希望在 中将其写为highp
顶点着色器和片段着色器或保留mediump
。