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.

转载于:https://www.cnblogs.com/open-coder/archive/2012/08/23/2653267.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值