PDA

View Full Version : Frame buffers/fragment shaders - problems on ATI



jas511
06-09-2011, 02:08 PM
In my application, I have a case where I want to draw a bunch of shapes and blend them together in a frame buffer so they only blend with each other and not the rest of the scene. Then I apply a fragment shader to them, and then I take that whole shaded image and draw that to the main display. I initially draw the points to the buffer using standard gl shapes (triangle fans in this case). Then I read that buffer using glReadPixels and I redraw it back out to the frame buffer with the fragment shader applied. Finally, I read the pixels again and redraw them to the main display (I know this may be inefficient, but that isn't the issue in question here). So this works well on an nvidia card, but I've had problems on numerous ATI cards that have GLSL 1.2. I've posted my code below (it's in Java OpenGL, but hopefully still understandable). I'm completely stumped as to why it works on nvidia but not on the ATI cards. Any help would be appreciated. Thanks. I know the code is a bit long but I've tried to include anything relevant here.



public void draw() {
gl.glPushAttrib(GL.GL_ALL_ATTRIB_BITS);
try {
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_ALWAYS);
if (!init) {
initBuffers(width, height, gl);
unbindBuffers(gl);
init = true;
return;
}
bindBuffers(width, height, gl);
setColor(grayscaleColors[0], gl);
prepareGL(gl, width, height);
// this just draws a bunch of circles using GL_TRIANGLES
drawPoints(globe, gl);
ByteBuffer buff = readBuffer(width, height, gl);
unbindBuffers(gl);

// draw the points in color without blending back to the buffer
bindBuffers(width, height, gl);
prepareGL(gl, width, height);
gl.glDisable(GL.GL_BLEND);
gl.glUseProgram(colorShaderProgram);
drawPixels(width, height, gl, buff);
buff.clear();
buff = readBuffer(width, height, gl);
unbindBuffers(gl);
gl.glUseProgram(0);
gl.glWindowPos2d(0, 0);
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
drawPixels(width, height, gl, buff);
gl.glUseProgram(0);
buff.clear();
} finally {
gl.glPopAttrib();
}
}

private void initBuffers(int width, int height, GL gl)
{
colorShaderProgram = createShader(gl, createColorShaderProgram());
int[] frameBufferArray = new int[1];
IntBuffer frameBuffer = IntBuffer.wrap(frameBufferArray);
gl.glGenFramebuffersEXT(1, frameBuffer);
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferArray[0]);
frameBufferId = frameBufferArray[0];
int[] renderBufferArray = new int[1];
IntBuffer rbo = IntBuffer.wrap(renderBufferArray);
gl.glGenRenderbuffersEXT(1, rbo);
gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, renderBufferArray[0]);
gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT , GL.GL_RGBA, width, height);
gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_ EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_RENDERBUFFER_EXT, renderBufferArray[0]);
renderBufferId = renderBufferArray[0];
ensureBufferCreated(gl);
init = true;
}

private void bindBuffers(int width, int height, GL gl)
{
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferId);
gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, renderBufferId);
gl.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT , GL.GL_RGBA, width, height);
gl.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_ EXT, GL.GL_COLOR_ATTACHMENT0_EXT, GL.GL_RENDERBUFFER_EXT, renderBufferId);
}

private void drawPixels(int width, int height, GL gl, ByteBuffer buff)
{
gl.glDrawPixels(width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);
}

private void unbindBuffers(GL gl)
{
LOGGER.debug("unbinding framebuffer ext");
gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
debugLastError(gl);
LOGGER.debug("unbinding renderbuffer ext");
gl.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0);
debugLastError(gl);
}

private ByteBuffer readBuffer(int width, int height, GL gl)
{
ByteBuffer buff = ByteBuffer.allocate(width * height * 4);
gl.glReadBuffer(GL.GL_COLOR_ATTACHMENT0_EXT);
debugLastError(gl);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
gl.glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);
buff.rewind();
return buff;
}

private static void prepareGL(GL gl, int width, int height)
{
gl.glClearColor(0, 0, 0, 0);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glViewport(0, 0, width, height);
gl.glRasterPos2d(0, 0);
gl.glWindowPos2d(0, 0);
}

private void drawPixels(int width, int height, GL gl, ByteBuffer buff)
{
gl.glDrawPixels(width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);
}

Alfonse Reinheart
06-09-2011, 02:23 PM
drawPixels(width, height, gl, buff);

You didn't show what this function is.

jas511
06-09-2011, 02:57 PM
Oops, thanks. I have added that.

jas511
06-10-2011, 10:46 PM
It turns out the pixel shader wasn't being applied on certain graphics cards when using glDrawPixels. Switching to texture mapping worked just fine.