NeHe OpenGL Lesson26 – Clipping & Reflections Using The Stencil Buffer

screen_shot8-300x211 This sample shows us how to display a reflection effect with stencil buffer and plane clipping in OpenGL. The stencil buffer usually goes with the depth buffer in the display card, and also called mask buffer. The stencil buffer filled along with the normal render process. That means when you want to render something to the frame buffer, you could mask some area in the stencil buffer with some stencil operation settings. Later, you could do some further process (usually render something) aim to those masked area with correct stencil testing functions.

 

Render Processing

For this sample, let go into it’s main draw scene function, and check how the scene will be rendered. In summary, the main scene rendering process could be divided into four part as following:
1) draw the floor only into the stencil buffer, color buffer writable disabled. And you need to set the correct depth testing here, stencil testing goes with depth testing. The code as following:

复制代码
// step (1)
// Disable the color buffer writable
glColorMask(0,0,0,0);
// set up how the stencil buffer will be filled    
glEnable(GL_STENCIL_TEST);                            
glStencilFunc(GL_ALWAYS, 1, 1);                        
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);            
 
// z-test always sccuss
glDisable(GL_DEPTH_TEST);
// draw floor into the stencil buffer.
// The area that floor will render to in the stencil buffer will be 1.
DrawFloor();                                        
 
// restore the render state settings
glEnable(GL_DEPTH_TEST);
复制代码

 

2) Enable the color buffer writable, set up the stencil buffer & plane clipping limitation, draw the reflected sphere object.  Mirror the object against XZ plane using glScale(1,-1,1) is a very good idea. The code as following:

复制代码
// step (2)
// Enable the color buffer writable
glColorMask(1,1,1,1);
// Only the area that stencil buffer filled with 1 could be render into.
glStencilFunc(GL_EQUAL, 1, 1);                        
// Do not need to write stencil, just keep everything there
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);                
 
// With clip plane to limit the reflect object display do not beyond the plane
glEnable(GL_CLIP_PLANE0);                            
glClipPlane(GL_CLIP_PLANE0, eqr);                    
 
glPushMatrix();    
    // mirror the object against the XZ plane
    glScalef(1.0f, -1.0f, 1.0f);                    
    glLightfv(GL_LIGHT0, GL_POSITION, LightPos);    
    glTranslatef(0.0f, height, 0.0f);                
    glRotatef(xrot, 1.0f, 0.0f, 0.0f);                
    glRotatef(yrot, 0.0f, 1.0f, 0.0f);
    // draw the reflected object    
    DrawObject();                                    
glPopMatrix();                                        
glDisable(GL_CLIP_PLANE0);
// stencil only used for limit the reflected object display on the floor.
// We do not need it now, so shut it down.
glDisable(GL_STENCIL_TEST);
复制代码

glClipPlane used to define the clip plane, and this plane will be defined in the world space. Here are some details about this function, “glClipPlane specifies a half-space using a four-component plane equation. When glClipPlane is called, equation is transformed by the inverse of the modelview matrix and stored in the resulting eye coordinates. Subsequent changes to the modelview matrix have no effect on the stored plane-equation components.” This will make our clipping plane set up job more easy, what we need to do is find the correct plane in the local space of the clipped object. Of course, you need to make both of them in the same space when rendering. It is a bit similar to that if you want to see though a window, you just need to find the frame of the window.

3) Disable the stencil test, draw the floor with alpah blend operation. The code as following:

复制代码
// step (3)
// draw the floor with alpha blend
glLightfv(GL_LIGHT0, GL_POSITION, LightPos);        
glEnable(GL_BLEND);                                    
glDisable(GL_LIGHTING);                                
glColor4f(1.0f, 1.0f, 1.0f, 0.8f);                    
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);    
DrawFloor();
复制代码

 

4) Draw the sphere with lighting. The code as following:

复制代码
// step (4)
// draw the sphere with lighting
glEnable(GL_LIGHTING);                                
glDisable(GL_BLEND);                                
glTranslatef(0.0f, height, 0.0f);                    
glRotatef(xrot, 1.0f, 0.0f, 0.0f);                    
glRotatef(yrot, 0.0f, 1.0f, 0.0f);                    
DrawObject();
复制代码

 

Something More

In addition to the reflection effect, here something more that you could explore.
1) The second texture used for the sphere specular map, with glBlendFunc(GL_SRC_ALPHA, GL_ONE) and another blend process, one diffuse texture blend with one specular texture:
2) What will happen, if you switch on the auto-texture coordinates generate feature and also provide them with glTexCoord2f? The answer is that auto-generates one will override other ones, that means the auto-generate one will always be used. The specular map for the sphere will use the auto-generate one, but one already there.

 

The full source code for windows version could be downloaded from here.

posted @   opencoder  阅读(857)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示