平面剪切(clip mirror )-----做一个镜面效果
2005-03-22 17:09
811 查看
使用平面剪切功能,我们可以屏蔽一些我们不想看到的东西,它就像一块挡光板,挡住了我们的视线.这样我们就可以创建一个镜子。
一、首先我们必需先构造一个平面。在3D中,我们有两种方法来构造一个平面
1、通过平面上的一个点和这个平面的法线,我们就可以确定一个平面。
D3DXVECTOR3 vPosition, vNormal;
D3DXPLANE plane;
D3DXPlaneFromPointNormal( &plane, vPosition, vNormal );
2、通过平面上的任意三点,也可以确定一个平面
D3DXVECTOR3 v1, v2, v3;
D3DXPLANE plane;
D3DXPlaneFromPoints( &plane, &v1, &v2, &v3 );
二、在确定平面之后,我们就要得到相对于这个平面的世界变换,并改变当前世界变换。当然我们得保存现有的世界变换,好在使用完平面之后恢复世界变换。
D3DXMATRIX matSaveWorld , matReflectMirror;
pd3dDevice->GetTransfrom( D3DTS_WORLD, &matSaveWorld );
D3DXMatrixReflect( &matReflectMirror, &plane );
pd3dDevice->SetTransfrom( D3DTS_WORLD, &matReflectMirror );
三、设置D3DRS_CULLMODE 为反面模式 D3DCULL_CW,
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
四、设置平面剪切方法
pd3dDevice->SetClipPlane( 0, &plane ); // 当要从多面剪切时,设置多个。
// 然后在后面的渲染状态里面加以设置
pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 /*| D3DCLIPPLANE1*/ );
// 在上面的函数里面,当要设置多个剪切平面时,可以给第二个参数传多个
// D3DCLIPPLANE0 | D3DCLIPPLANE1| D3DCLIPPLANE2| D3DCLIPPLANE3
五、画出要看到的东西(即是把其渲染到剪切中)
RenderScene();
六、把刚刚渲染的输出
pd3dDevice->SetTransform( D3DTS_WORLD, &matSaveWorld );
pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00); // 清除平面剪切
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ) ;
pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// 在这里渲染出刚刚经过平面剪切后的内容
RenderClip();
pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
D3D中的代码示例
RenderMirror()
{
D3DXMATRIXA16 matWorldSaved;
D3DXMATRIXA16 matReflectInMirror;
D3DXPLANE plane;
// Save the world matrix so it can be restored
m_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorldSaved );
// Get the four corners of the mirror. (This should be dynamic rather than
// hardcoded.)
D3DXVECTOR3 a(-1.5f, 1.5f, 3.0f );
D3DXVECTOR3 b( 1.5f, 1.5f, 3.0f );
D3DXVECTOR3 c( -1.5f,-1.5f, 3.0f );
D3DXVECTOR3 d( 1.5f,-1.5f, 3.0f );
// Construct the reflection matrix
D3DXPlaneFromPoints( &plane, &a, &b, &c );
D3DXMatrixReflect( &matReflectInMirror, &plane );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matReflectInMirror );
// Reverse the cull mode (since normals will be reflected)
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
// Set the custom clip planes (so geometry is clipped by mirror edges).
// This is the heart of this sample. The mirror has 4 edges, so there are
// 4 clip planes, each defined by two mirror vertices and the eye point.
m_pd3dDevice->SetClipPlane( 0, *D3DXPlaneFromPoints( &plane, &b, &a, &m_vEyePt ) );
m_pd3dDevice->SetClipPlane( 1, *D3DXPlaneFromPoints( &plane, &d, &b, &m_vEyePt ) );
m_pd3dDevice->SetClipPlane( 2, *D3DXPlaneFromPoints( &plane, &c, &d, &m_vEyePt ) );
m_pd3dDevice->SetClipPlane( 3, *D3DXPlaneFromPoints( &plane, &a, &c, &m_vEyePt ) );
m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE,
D3DCLIPPLANE0 | D3DCLIPPLANE1 | D3DCLIPPLANE2 | D3DCLIPPLANE3 );
// Render the scene
RenderScene();
// Restore the modified render states
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorldSaved );
m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00 );
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
// Finally, render the mirror itself (as an alpha-blended quad)
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_pd3dDevice->SetStreamSource( 0, m_pMirrorVB, 0, sizeof(MIRRORVERTEX) );
m_pd3dDevice->SetFVF( MIRRORVERTEX::FVF );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
}
一、首先我们必需先构造一个平面。在3D中,我们有两种方法来构造一个平面
1、通过平面上的一个点和这个平面的法线,我们就可以确定一个平面。
D3DXVECTOR3 vPosition, vNormal;
D3DXPLANE plane;
D3DXPlaneFromPointNormal( &plane, vPosition, vNormal );
2、通过平面上的任意三点,也可以确定一个平面
D3DXVECTOR3 v1, v2, v3;
D3DXPLANE plane;
D3DXPlaneFromPoints( &plane, &v1, &v2, &v3 );
二、在确定平面之后,我们就要得到相对于这个平面的世界变换,并改变当前世界变换。当然我们得保存现有的世界变换,好在使用完平面之后恢复世界变换。
D3DXMATRIX matSaveWorld , matReflectMirror;
pd3dDevice->GetTransfrom( D3DTS_WORLD, &matSaveWorld );
D3DXMatrixReflect( &matReflectMirror, &plane );
pd3dDevice->SetTransfrom( D3DTS_WORLD, &matReflectMirror );
三、设置D3DRS_CULLMODE 为反面模式 D3DCULL_CW,
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
四、设置平面剪切方法
pd3dDevice->SetClipPlane( 0, &plane ); // 当要从多面剪切时,设置多个。
// 然后在后面的渲染状态里面加以设置
pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0 /*| D3DCLIPPLANE1*/ );
// 在上面的函数里面,当要设置多个剪切平面时,可以给第二个参数传多个
// D3DCLIPPLANE0 | D3DCLIPPLANE1| D3DCLIPPLANE2| D3DCLIPPLANE3
五、画出要看到的东西(即是把其渲染到剪切中)
RenderScene();
六、把刚刚渲染的输出
pd3dDevice->SetTransform( D3DTS_WORLD, &matSaveWorld );
pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00); // 清除平面剪切
pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ) ;
pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// 在这里渲染出刚刚经过平面剪切后的内容
RenderClip();
pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
D3D中的代码示例
RenderMirror()
{
D3DXMATRIXA16 matWorldSaved;
D3DXMATRIXA16 matReflectInMirror;
D3DXPLANE plane;
// Save the world matrix so it can be restored
m_pd3dDevice->GetTransform( D3DTS_WORLD, &matWorldSaved );
// Get the four corners of the mirror. (This should be dynamic rather than
// hardcoded.)
D3DXVECTOR3 a(-1.5f, 1.5f, 3.0f );
D3DXVECTOR3 b( 1.5f, 1.5f, 3.0f );
D3DXVECTOR3 c( -1.5f,-1.5f, 3.0f );
D3DXVECTOR3 d( 1.5f,-1.5f, 3.0f );
// Construct the reflection matrix
D3DXPlaneFromPoints( &plane, &a, &b, &c );
D3DXMatrixReflect( &matReflectInMirror, &plane );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matReflectInMirror );
// Reverse the cull mode (since normals will be reflected)
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
// Set the custom clip planes (so geometry is clipped by mirror edges).
// This is the heart of this sample. The mirror has 4 edges, so there are
// 4 clip planes, each defined by two mirror vertices and the eye point.
m_pd3dDevice->SetClipPlane( 0, *D3DXPlaneFromPoints( &plane, &b, &a, &m_vEyePt ) );
m_pd3dDevice->SetClipPlane( 1, *D3DXPlaneFromPoints( &plane, &d, &b, &m_vEyePt ) );
m_pd3dDevice->SetClipPlane( 2, *D3DXPlaneFromPoints( &plane, &c, &d, &m_vEyePt ) );
m_pd3dDevice->SetClipPlane( 3, *D3DXPlaneFromPoints( &plane, &a, &c, &m_vEyePt ) );
m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE,
D3DCLIPPLANE0 | D3DCLIPPLANE1 | D3DCLIPPLANE2 | D3DCLIPPLANE3 );
// Render the scene
RenderScene();
// Restore the modified render states
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorldSaved );
m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0x00 );
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
// Finally, render the mirror itself (as an alpha-blended quad)
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_pd3dDevice->SetStreamSource( 0, m_pMirrorVB, 0, sizeof(MIRRORVERTEX) );
m_pd3dDevice->SetFVF( MIRRORVERTEX::FVF );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
}
相关文章推荐
- osg通过glsl实现一个平面的水效果(法线贴图) 【转】
- ViewFlow,一个滑动效果库
- Android: 让一个EditText失去焦点,setFocusableInTouchMode与setFocusable 效果不一样
- 基于Bootstrap实现下图所示效果的页面,一个白底的带有两个菜单项、一个下拉菜单和一个登录表单的基本导航条
- 一个基于jquery的页面预载入效果(loading)
- 一个基于jquery的页面预载入效果(loading)
- 一个简单的tab选项效果
- 帖一个简单css效果
- 一个菜单效果 http://www.51js.com/viewthread.php?tid=1560&highlight=%CA%F7
- JS中关于 一个关于计时器功能效果的实现
- 一个流行的弹出层的效果
- 一个非常好的抽屉效果实例
- 一个效果非常不错的JAVA数据库连接池
- 一个焦点图切换效果的制作
- 实现一个垂直跑马灯的效果(垂直公告)
- WPF中splashScreen启动程序之前出现一个过程动画的效果
- .定义两个数组,首先把两个数组合并成一个新数组,然后把新数组中的所有元素逆序排列,需要实现的效果如图-2所示。
- 用ajax jquery设计一个上传的效果
- 一个带动画效果的颜色选择对话框控件AnimatedColorPickerDialog
- 单一用户登录,即当前用户登录后要踢出前一个登录,即做出踢人效果,如何实现?