// 创建 // frame buffer object glGenFramebuffers(1, &fboId); glBindFramebuffer(GL_FRAMEBUFFER, fboId); // color buffer with texture object glGenTextures(1, &color_rboId); glBindTexture(GL_TEXTURE_2D, color_rboId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, targetWidth, targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // depth buffer with render buffer object glGenRenderbuffers(1, &depth_rboId); glBindRenderbuffer(GL_RENDERBUFFER, depth_rboId); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, targetWidth, targetHeight); // Attach color buffer to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_rboId, 0); //Attach depth buffer to FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rboId); //Also attach as a stencil glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depth_stencil_rb); // 删除 if (fboId != 0) { glDeleteFramebuffers(1, &fboId); fboId = 0; } if (depth_rboId != 0) { glDeleteRenderbuffers(1, &depth_rboId); depth_rboId = 0; } if (color_rboId) { glDeleteTextures(1, &color_rboId); color_rboId = 0; }
// 创建stencil buffer以RBO形式 glGenRenderbuffers(1, &stencil_rboId); glBindRenderbuffer(GL_RENDERBUFFER, stencil_rboId); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, targetWidth, targetHeight); // 关联stencil buffer 和FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil_rboId); // 删除stencil buffer glDeleteRenderbuffers(1, &stencil_rboId);
void stencilRenderTest() { GLdouble dRadius = 0.1; // Initial radius of spiral GLdouble dAngle; // Looping variable float x = 100; float y = 100; float rsize = 25; // Clear blue window glClearColor(0.0f, 0.0f, 1.0f, 0.0f); // Use 0 for clear stencil, enable stencil test glClearStencil(0.0f); glEnable(GL_STENCIL_TEST); // Clear color and stencil buffer glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // All drawing commands fail the stencil test, and are not // drawn, but increment the value in the stencil buffer. glStencilFunc(GL_NEVER, 0x0, 0x0); glStencilOp(GL_INCR, GL_INCR, GL_INCR); // Spiral pattern will create stencil pattern // Draw the spiral pattern with white lines. We // make the lines white to demonstrate that the // stencil function prevents them from being drawn glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINE_STRIP); for(dAngle = 0; dAngle < 400.0; dAngle += 0.1) { glVertex2d(dRadius * cos(dAngle), dRadius * sin(dAngle)); dRadius *= 1.002; } glEnd(); // Now, allow drawing, except where the stencil pattern is 0x1 // and do not make any further changes to the stencil buffer glStencilFunc(GL_NOTEQUAL, 0x1, 0x1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Now draw red bouncing square // (x and y) are modified by a timer function glColor3f(1.0f, 0.0f, 0.0f); glRectf(x, y, x + rsize, y - rsize); }stencil正确时,结果显示是一个蓝色背景,红色小矩形块,矩形内部可以看到圆弧,下图右。
EVER EVER MAKE A STENCIL buffer. All GPUs and all drivers do not support an independent stencil buffer. If you need a stencil buffer, then you need to make a Depth=24, Stencil=8 buffer, also called D24S8. Please search for the example about GL_EXT_packed_depth_stencil on this page.
翻译过来就是:永远不要单独创建一个模板缓冲区,所有的gpu和驱动都不支持单独的模板缓冲区。如果需要创建模板缓冲时 需要深度、模板共用一个缓冲区,格式是DEPTH_24_STENCIL_8。
具体code如下:
// 创建 // frame buffer object glGenFramebuffers(1, &fboId); glBindFramebuffer(GL_FRAMEBUFFER, fboId); // color buffer with texture object glGenTextures(1, &color_rboId); glBindTexture(GL_TEXTURE_2D, color_rboId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, targetWidth, targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // depth buffer and stencil buffer glGenRenderbuffers(1, &depth_stencil_rb); glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, targetWidth, targetHeight); // not GL_DEPTH_COMPONENT24 but GL_DEPTH24_STENCIL8 // Attach color buffer to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_rboId, 0); //Attach depth buffer to FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_stencil_rb); //Also attach as a stencil glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depth_stencil_rb); // 删除 if (fboId != 0) { glDeleteFramebuffers(1, &fboId); fboId = 0; } if (depth_stencil_rb != 0) { glDeleteRenderbuffers(1, &depth_stencil_rb); depth_stencil_rb = 0; } if (color_rboId) { glDeleteTextures(1, &color_rboId); color_rboId = 0; }
opengl 官方wiki:https://www.opengl.org/wiki/Framebuffer_Object_Examples
1. 2013/8/14 fix 正确创建fbo帧缓冲区的bug,renderbuffer格式应该是GL_DEPTH24_STENCIL8而不是 GL_DEPTH_COMPONENT24。