OpenG:Reflection-Stencil Buffer

发布时间:2016-12-11 14:10:53 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"OpenG:Reflection-Stencil Buffer",主要涉及到OpenG:Reflection-Stencil Buffer方面的内容,对于OpenG:Reflection-Stencil Buffer感兴趣的同学可以参考一下。

转自:http://www.cppblog.com/biao/archive/2010/12/17/136762.html 每个像素都有自己对应的 Buffer,其实就是一个 32bit 的数,如 Color Buffer, Depth Buffer, Stencil Buffer. Stencil Buffer 与 Depth Buffer 有点特别,因为他们共用同一个 Buffer, Depth Buffer 占用 Buffer 前面的 24Bit, Stencil Buffer 占用后面的 8Bit. Stencil Buffer 可以使用从 1Bit-8Bit. 如在绘制反射时,就像照镜子一样,因为只需要在反射平面上绘制物体的镜像,即要么在反射平面上绘制,要不就不绘制,所以只需要用到 1Bit 的 Stencil Buffer.   什么叫 Stencil Buffer ? 即是一个模板,也就是说,他可以是一个平面,也可以是一个立体几何图形,如一个四边形,一个Teapot. 在模板所占据的空间中,他的值为 1(values stored in the stencil buffer), 在启用 Stencil Buffer 时,我们所画的图形只有在这个空间中的部分才能显示出来,所以我们可以创建一个模板,他是一个字,然后以后画的图形最多只能把这个字给显示出来,这个图形有其他部分都没有被写进 Color Buffer.   Stencil Buffer 最简单的运用,用来生成镜面反射。 1. 先要使编程环境支持 Stencil Buffer         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);   2. 设置清除 Stencil Buffer 使用的函数         glClearStencil(0);   3. 在我们创建模板的时候,要先关掉 Depth Test und Color Mask,         因为我们并不想把模板画到屏幕上         glDisable(GL_DEPTH_TEST);         glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);         // 为了把我们的模板图形不显示到屏幕上,但又要写入 Stencil Buffer 中。           我们什么时候创建模板的?就是在启用模板缓存后进行的第一次进绘制的图形就是模板。         OpenGL会根据我们所设定的 glStencilFunc 的值和 glStencilOp 来比较,         然后在 plane 中(即视口所对应的那个二维数组)写入比较的结果值。   4. 开始创建模板         glEnable(GL_STENCIL_TEST);         glStencilFunc(GL_ALWAYS, 0x1, 0x1);         // 把模板图形所在的区域的 Buffer 值设置成 1, 其余的还是 0.         // 这时用的就是给 glStencilFunc 指定的 ref 的值,现在是 1         // 当然可以有其他的操作,如 GL_INCR, GL_INVERT(bitwise invert)         glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);                 // 开始创建模板的图形         drawFloor();                 // 模板创建好后,我们就要设置下一次进行绘制时的模板函数         // 只有通过条件的像素才能被显示到屏幕上,否则就被丢弃         // 但要注意,现在我们要进行绘制的就是镜像了,所以是要被显示到屏幕上的,         // 所以在绘制之前,要把颜色屏蔽关掉和启用深度测试         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);         glEnable(GL_DEPTH_TEST);           // Stencil buffer 值等于 1 的地方才绘制到屏幕上                glStencilFunc(GL_EQUAL, 0x1, 0x1);         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);   5. 绘制镜像图像         // 现在绘制我们的镜像图像         // 镜像是跟原来的物体对称的, 所以用 glScalef 来进行反转,实现对称         // 在绘制镜像物体的时候,灯光也要相应的反转         glPushMatrix();                 glScalef(1, -1, 1);                 glutSolidTeapot(1.0f);         glPopMatrix();   6. 在模板中显示的镜像图像已经创建好,不再需要模板了,所以我们关掉 stencil buffer         glDisable(GL_STENCIL_TEST);   7. 绘制镜像所在的平面,就如镜子         // 使用 Blend 与镜像图像混合起来         glEnable(GL_BLEND);         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);         drawFloor();         glDisable(GL_BLEND);   8. 绘制产生镜像的物体         glutSolidTeapot(1.0f);   至此,真正的镜面反射已经创建完成。 非真正的反射可以如下实现: 先画对称物体,画出镜面(使用 Blend), 然后画出原物体,但这时如果旋转Camera,就会发现,那个对称的物体并不是平面的,还是原来的空间立体物体。但用 Stencil Buffer 实现的镜面反射是真正的镜面反射,镜像是只在镜面上显示,即是平面的。   下面的代码可以很好的工作  //****************************************************************//  if (useStencil) {           glClearStencil(0);           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);  } else {           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  }  if (useStencil) {           glDisable(GL_DEPTH_TEST);           glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);           /* Draw 1 into the stencil buffer. */           glEnable(GL_STENCIL_TEST);           glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);           glStencilFunc(GL_ALWAYS, 1, 0xffffffff);           /* Now render floor; floor pixels just get their stencil set to 1. */           drawFloor();           /* Re-enable update of color and depth. */           glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);           glEnable(GL_DEPTH_TEST);           /* Now, only render where stencil is set to 1. */           glStencilFunc(GL_EQUAL, 1, 0xffffffff); /* draw if ==1 */           glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);  }  glPushMatrix();           glScalef(1, -1, 1);           glTranslatef(0.0, 0.8, 0);           glColor3f(0, 1, 0);           glutSolidTeapot(1);  glPopMatrix();    if (useStencil) {           glDisable(GL_STENCIL_TEST);  }  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  glColor4f(0.7, 0.0, 0.0, 0.3);  drawFloor();  glDisable(GL_BLEND);    glTranslatef(0, -0.0001, 0);  glFrontFace(GL_CW);  glColor3f(1, 1, 1);  drawFloor();    glTranslatef(0.0, 0.8, 0);  glColor3f(0, 1, 0);  glutSolidTeapot(1);  //****************************************************************//  

上一篇:IOS开发基础资料
下一篇:[置顶] Flume-0.9.4和Hbase-0.96整合(2)

相关文章

相关评论