我正在尝试创建两个 FBO 并实现乒乓渲染。但是,我只能让第一帧正常工作。我正在尝试模拟人生游戏,在第一帧之后,我只得到一个黑屏。你能帮我检查一下吗?我在这个问题上花了几个小时。
编辑
可能我没有描述清楚。其实我想用textureB作为纹理渲染到textureA,然后用textureA渲染到屏幕,反之亦然。
编辑 我可以看到第一帧,这是纹理B。在它通过片段着色器后,它变成黑色。起初,我怀疑片段着色器,我将其更改为仅将黑色恢复为白色,将白色恢复为黑色。它仍然变得全黑。
设置 fbo 和纹理
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textureA);
glBindTexture(GL_TEXTURE_2D, textureA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA,
GL_UNSIGNED_BYTE, NULL);
glGenTextures(1, &textureB);
glBindTexture(GL_TEXTURE_2D, textureB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
data=(GLubyte*)malloc(256*256*4*sizeof(GLubyte));
GLubyte val;
for (int i = 0; i < 256 * 256 * 4; i+=4) {
if (rand()%10 ==1)
{ val = 0; }
else
{ val = 255; }
data[i] = data[i+1] = data[i+2] = val;
data[i+3] = 255;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenFramebuffers(1, &fboA);
glBindFramebuffer(GL_FRAMEBUFFER, fboA);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureA, 0);
glGenFramebuffers(1, &fboB);
glBindFramebuffer(GL_FRAMEBUFFER, fboB);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureB, 0);
渲染循环
if ([context API] == kEAGLRenderingAPIOpenGLES2) {
if(counter%2==0)
{
glUseProgram(automateProg);
glBindFramebuffer(GL_FRAMEBUFFER, fboA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureB);
glUniform1i(AUTOMATE_TEXT, 0);
glUniform1f(DU, 1.0/256);
glUniform1f(DV, 1.0/256);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX_2, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX_2);
glVertexAttribPointer(ATTRIB_TEXCOORD_2, 2, GL_FLOAT, GL_FALSE, 0, texCoord);
//glEnableVertexAttribArray(ATTRIB_TEXCOORD_2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (![self validateProgram:automateProg]) {
NSLog(@"Failed to validate program: %d", automateProg);
return;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
}
else
{
glUseProgram(automateProg);
glBindFramebuffer(GL_FRAMEBUFFER, fboB);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureA);
glUniform1i(AUTOMATE_TEXT, 0);
glUniform1f(DU, 1.0/256);
glUniform1f(DV, 1.0/256);
// Update attribute values.
glVertexAttribPointer(ATTRIB_VERTEX_2, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX_2);
glVertexAttribPointer(ATTRIB_TEXCOORD_2, 2, GL_FLOAT, GL_FALSE, 0, texCoord);
//glEnableVertexAttribArray(ATTRIB_TEXCOORD_2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (![self validateProgram:automateProg]) {
NSLog(@"Failed to validate program: %d", automateProg);
return;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
}
[(EAGLView *)self.view setFramebuffer];
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
if (counter % 2 == 0) {
glUseProgram(normalProg);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureB);
glUniform1i(NORMAL_TEXT, 0);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoord);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (![self validateProgram:normalProg]) {
NSLog(@"Failed to validate program: %d", normalProg);
return;
}
glUseProgram(0);
} else {
glUseProgram(normalProg);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureA);
glUniform1i(NORMAL_TEXT, 0);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoord);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (![self validateProgram:normalProg]) {
NSLog(@"Failed to validate program: %d", normalProg);
return;
}
glUseProgram(0);
}
counter++;
[(EAGLView *)self.view presentFramebuffer];
片段着色器
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D tex; //the input texture
uniform float du; //the width of the cells
uniform float dv; //the height of the cells
void main() {
int count = 0;
vec4 C = texture2D( tex, v_texCoord );
vec4 E = texture2D( tex, vec2(v_texCoord.x + du, v_texCoord.y) );
vec4 N = texture2D( tex, vec2(v_texCoord.x, v_texCoord.y + dv) );
vec4 W = texture2D( tex, vec2(v_texCoord.x - du, v_texCoord.y) );
vec4 S = texture2D( tex, vec2(v_texCoord.x, v_texCoord.y - dv) );
vec4 NE = texture2D( tex, vec2(v_texCoord.x + du, v_texCoord.y + dv) );
vec4 NW = texture2D( tex, vec2(v_texCoord.x - du, v_texCoord.y + dv) );
vec4 SE = texture2D( tex, vec2(v_texCoord.x + du, v_texCoord.y - dv) );
vec4 SW = texture2D( tex, vec2(v_texCoord.x - du, v_texCoord.y - dv) );
if (E.r == 1.0) { count++; }
if (N.r == 1.0) { count++; }
if (W.r == 1.0) { count++; }
if (S.r == 1.0) { count++; }
if (NE.r == 1.0) { count++; }
if (NW.r == 1.0) { count++; }
if (SE.r == 1.0) { count++; }
if (SW.r == 1.0) { count++; }
if ( (count == 2 || count == 3)) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); //cell lives...
} else {
gl_FragColor = vec4(0.0,0.0,0.0, 1.0); //cell dies...
}
}