游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2505|回复: 8

再读模版Stencil Mirror,问题多多,思考多多,难道真的和

[复制链接]

36

主题

107

帖子

107

积分

注册会员

Rank: 2

积分
107
发表于 2007-9-13 19:19:00 | 显示全部楼层 |阅读模式
void RenderScene()
{
     。。。。。。//省略了// draw the floor,// draw the walls
// draw the mirror
Device->SetMaterial(&MirrorMtrl);
Device->SetTexture(0, MirrorTex);
Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);
}
void RenderMirror()
{
        //
        // Draw Mirror quad to stencil buffer ONLY.  In this way
        // only the stencil bits that correspond to the mirror will
        // be on.  Therefore, the reflected teapot can only be rendered
        // where the stencil bits are turned on, and thus on the mirror
        // only.
        //

    HRESULT hr = NOERROR;
    hr = Device->SetRenderState(D3DRS_STENCILENABLE,    true);
    hr = Device->SetRenderState(D3DRS_STENCILFUNC,      D3DCMP_ALWAYS);
    hr = Device->SetRenderState(D3DRS_STENCILREF,       0x1);
    hr = Device->SetRenderState(D3DRS_STENCILMASK,      0xffffffff);
    hr = Device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
    hr = Device->SetRenderState(D3DRS_STENCILZFAIL,     D3DSTENCILOP_KEEP);
    hr= Device->SetRenderState(D3DRS_STENCILFAIL,      D3DSTENCILOP_KEEP);
    hr = Device->SetRenderState(D3DRS_STENCILPASS,      D3DSTENCILOP_REPLACE);

        // disable writes to the depth and back buffers
    Device->SetRenderState(D3DRS_ZWRITEENABLE, false);
    Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);
    Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

    // draw the mirror to the stencil buffer
        Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
        Device->SetFVF(Vertex::FVF);
        Device->SetMaterial(&MirrorMtrl);
        Device->SetTexture(0, MirrorTex);
        D3DXMATRIX I;
        D3DXMatrixIdentity(&I);
        Device->SetTransform(D3DTS_WORLD, &I);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);

        // re-enable depth writes
        Device->SetRenderState( D3DRS_ZWRITEENABLE, true );

        // only draw reflected teapot to the pixels where the mirror
        // was drawn to.
        Device->SetRenderState(D3DRS_STENCILFUNC,  D3DCMP_EQUAL);
    Device->SetRenderState(D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP);

        // position reflection
        D3DXMATRIX W, T, R;
        D3DXPLANE plane(0.0f, 0.0f, 1.0f, 0.0f); // xy plane
        D3DXMatrixReflect(&R, &plane);

        D3DXMatrixTranslation(&T,
                TeapotPosition.x,
                TeapotPosition.y,
                TeapotPosition.z);

        W = T * R;

        // clear depth buffer and blend the reflected teapot with the mirror
        Device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
        Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_DESTCOLOR);
   Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);

        // Finally, draw the reflected teapot
        Device->SetTransform(D3DTS_WORLD, &W);
        Device->SetMaterial(&TeapotMtrl);
        Device->SetTexture(0, 0);

        Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
        Teapot->DrawSubset(0);
       
        // Restore render states.
   Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
        Device->SetRenderState( D3DRS_STENCILENABLE, false);
   Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
}
第一次的在RenderScene()draw the mirror是绘制到Back buffer.
第二次的draw the mirror,由于Device->SetRenderState(D3DRS_STENCILENABLE,    true);
所以导致第二次的draw the mirror绘制到了stencil buffer。(这个理解时咱论坛的一个大哥指导后想到的
也不知对不对)

经过一系列的设置后,我们没有必要更新depth and back buffers,我们只想要 模版buffers.所以就有了下面的
设置
// disable writes to the depth and back buffers
    Device->SetRenderState(D3DRS_ZWRITEENABLE, false);
    Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
    Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ZERO);
    Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

之后,我们要画反射茶壶了,但是我们要
// re-enable depth writes
        Device->SetRenderState( D3DRS_ZWRITEENABLE, true );
否则反射茶壶和茶壶将得到一样的 Z buffer(我想是这个样子的,虽然还不是很理解)

在下面这几句话中Clear是最最重要的,我想它仅仅Clear 反射茶壶的Z buffer,使它和镜子获得相同的 Z buffer
(这个是我猜想,请高手指正),要不怎么会Blend 啊?
// clear depth buffer and blend the reflected teapot with the mirror
        Device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
        Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_DESTCOLOR);
   Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);

上面都好了,下面的三句话句话,决定了最后成败的关键,但是想不通为什么请高手指点
        // Restore render states.
        Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
        Device->SetRenderState( D3DRS_STENCILENABLE, false);
        Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

还有就是上面分析都是我的猜想,请高手指正!

sf_2007913191839.rar

444.89 KB, 下载次数:

2

主题

429

帖子

435

积分

中级会员

Rank: 3Rank: 3

积分
435
发表于 2007-9-14 02:28:00 | 显示全部楼层

Re: 再读模版Stencil Mirror,问题多多,思考多多,难道真的

怎么又开个贴。。。

第一次的在RenderScene()draw the mirror是绘制到Back buffer.
第二次的draw the mirror,由于Device->SetRenderState(D3DRS_STENCILENABLE,    true);
所以导致第二次的draw the mirror绘制到了stencil buffer。
==================
补充一下:Z buffer,Stencil buffer都是同时存在的,你只是控制是否写入而已。也就是你可以同时写入,所以下面才有关闭depth and back buffers。


之后,我们要画反射茶壶了,但是我们要
// re-enable depth writes
Device->SetRenderState( D3DRS_ZWRITEENABLE, true );
否则反射茶壶和茶壶将得到一样的 Z buffer(我想是这个样子的,虽然还不是很理解)
==================
和本来绘制的茶壶没关系,这里开启深度缓冲是因为你要绘制反射的茶壶,要正确显示,那么自然需要开启深度缓冲,否则会按照绘制的逆顺序显示。


在下面这几句话中Clear是最最重要的,我想它仅仅Clear 反射茶壶的Z buffer,使它和镜子获得相同的 Z buffer
(这个是我猜想,请高手指正),要不怎么会Blend 啊?
==================
清空深度缓冲是因为你现在绘制的反射茶壶,它在镜子后面,由于开启了深度缓冲,显然不清除之前的深度信息,它是不会显示出来。

上面都好了,下面的三句话句话,决定了最后成败的关键,但是想不通为什么请高手指点
====================
这三句不是关键,只是"善后",你前面开启了这些状态,自然得关掉,不然会影响到其它的。

36

主题

107

帖子

107

积分

注册会员

Rank: 2

积分
107
 楼主| 发表于 2007-9-14 13:01:00 | 显示全部楼层

Re:再读模版Stencil Mirror,问题多多,思考多多,难道真的

Enigmaya 你的指导使我受益颇多,但是我还是有个问题想请教一下

第一次的在RenderScene()draw the mirror是绘制到Back buffer.
第二次的draw the mirror,由于Device->SetRenderState(D3DRS_STENCILENABLE,    true);
所以导致第二次的draw the mirror绘制到了stencil buffer。
==================
补充一下:Z buffer,Stencil buffer都是同时存在的,你只是控制是否写入而已。也就是你可以同时写入,所以下面才有关闭depth and back buffers。
==================
????应该是 所有的Stencil buffer都更新吧,如茶壶,镜子的等等。

之后,我们要画反射茶壶了,但是我们要
// re-enable depth writes
Device->SetRenderState( D3DRS_ZWRITEENABLE, true );
否则反射茶壶和茶壶将得到一样的 Z buffer(我想是这个样子的,虽然还不是很理解)
==================
和本来绘制的茶壶没关系,这里开启深度缓冲是因为你要绘制反射的茶壶,要正确显示,那么自然需要开启深度缓冲,否则会按照绘制的逆顺序显示。
======================================
????绘制的逆顺序是什么意思啊?


在下面这几句话中Clear是最最重要的,我想它仅仅Clear 反射茶壶的Z buffer,使它和镜子获得相同的 Z buffer
(这个是我猜想,请高手指正),要不怎么会Blend 啊?
==================
清空深度缓冲是因为你现在绘制的反射茶壶,它在镜子后面,由于开启了深度缓冲,显然不清除之前的深度信息,它是不会显示出来。
======================================
????虽然我清空了深度缓冲(应该是所有的深度缓冲吧,包括镜子,墙,茶壶等),但是我back buffer的
东西没有变,所以它们还是可以绘制的,但是由于我也情况了反射茶壶的缓冲,这个就难了,我是绘制在精子的
前面,还是后面?Device->SetRenderState(D3DRS_STENCILFUNC,  D3DCMP_EQUAL);
    Device->SetRenderState(D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP);这两句话决定了我更新那部分back
buffer吧?
Device->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_DESTCOLOR);
   Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);决定了混合的结果

上面都好了,下面的三句话句话,决定了最后成败的关键,但是想不通为什么请高手指点
====================
这三句不是关键,只是"善后",你前面开启了这些状态,自然得关掉,不然会影响到其它的
========================================
????要是没有Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);可能第一次渲染的时候是正确的,但是第二次就可能不对了,因为这个时候(D3DRS_ALPHABLENDENABLE 是true直到(D3DRS_ALPHABLENDENABLE被置为false,The same to the Device->SetRenderState( D3DRS_STENCILENABLE, false);
但是Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);不知道哦,连猜都不行哦。

2

主题

429

帖子

435

积分

中级会员

Rank: 3Rank: 3

积分
435
发表于 2007-9-14 13:58:00 | 显示全部楼层

Re: 再读模版Stencil Mirror,问题多多,思考多多,难道真的

????应该是 所有的Stencil buffer都更新吧,如茶壶,镜子的等等。
=========================
开启模版缓冲后,记住是“后”,它不会涉及前面绘制的东西,之后绘制的东西才写入模版缓冲里。请去阅读关于模版缓冲的原理。

????绘制的逆顺序是什么意思啊?
=========================
不进行深度排序,想想在2维平面(屏幕),你在同一位置画的图形,是不是后画的会覆盖先画的。

????虽然我清空了深度缓冲(应该是所有的深度缓冲吧,包括镜子,墙,茶壶等),但是我back buffer的
东西没有变,所以它们还是可以绘制的,但是由于我也情况了反射茶壶的缓冲,这个就难了,我是绘制在精子的
前面,还是后面?
===========================
你都还没绘制反射茶壶,怎么清空了反射茶壶。清空操作是清空的已有的。


Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
这是关于背面裁减的,dx顺时针是正面,逆时针是背面。
这里恢复,是因为之前绘制反射茶壶前用了正面裁减:
Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
反射过后,反射茶壶的正反面和原本的茶壶是反的,想想真实的镜子。

36

主题

107

帖子

107

积分

注册会员

Rank: 2

积分
107
 楼主| 发表于 2007-9-14 15:08:00 | 显示全部楼层

Re:再读模版Stencil Mirror,问题多多,思考多多,难道真的

清空深度缓冲是因为你现在绘制的反射茶壶,它在镜子后面,由于开启了深度缓冲,为什么 说 不清除之前的深度信息,它是不会显示出来啊?

36

主题

107

帖子

107

积分

注册会员

Rank: 2

积分
107
 楼主| 发表于 2007-9-14 16:35:00 | 显示全部楼层

Re:再读模版Stencil Mirror,问题多多,思考多多,难道真的

之前的深度信息指的是?如果没清空反射茶壶的深度信息,它在镜子后面应该显示不出来啊?
(顺便发个感慨,看了很久了,游戏大师编程技巧也看了,讲的是3D引擎的机理)怎么还这么弱啊,我感觉我就是对它的渲染机理还是搞的很糊涂,给推荐本书吧,或文章,你已经知道我那里很弱了)

2

主题

429

帖子

435

积分

中级会员

Rank: 3Rank: 3

积分
435
发表于 2007-9-14 17:56:00 | 显示全部楼层

Re: Re:再读模版Stencil Mirror,问题多多,思考多多,难道真

vigour_lu: Re:再读模版Stencil Mirror,问题多多,思考多多,难道真的和想象中的一样吗?真的懂了吗?请

清空深度缓冲是因为你现在绘制的反射茶壶,它在镜子后面,由于开启了深度缓冲,为什么 说 不清除之前的深度信息,它是不会显示出来啊?


反射的茶壶是按照镜子所在的平面反射的,自然是在镜子的背后,如果不清除之前画的镜子,场景等等,它的z值大于之前的,当然不会显示出来。

RenderMirror之前是不是绘制了场景,这些就是之前的深度信息。
你需要弄清楚为什么需要zbuffer?它是干什么的?
记得游戏大师编程技巧里应该讲到z排序了的,好像是软件方法实现的。

至于书,你现在的这个程序本身的那本书就不错,dx的sdk里也有教程,或者找本图形学的书认真看看你不清楚的部分。

不要光看,多动手才能真正理解。
静下心来学习,你会有收获的。

36

主题

107

帖子

107

积分

注册会员

Rank: 2

积分
107
 楼主| 发表于 2007-9-14 18:42:00 | 显示全部楼层

读模版Stencil Mirror,问题多多,思考多多,难道真的和想

Enigmaya
真的非常感谢,你的指导比我陆续间隔一年多学习的收获还多,我好像现在对它才有了点感觉,但是我不知道这个
感觉对不对,请指导。
就是只要我们DrawPrimitive 或者DrawSubset 之后我们就要更新backbuffer 或 z ,stencil buffer,至于说更新那个和我的设置有关。但是更新backbuffer 和z ,stencil buffer的时候有个不同,更新z ,stencil buffer时候
是整体都更新,但是更新backbuffer时候是只更新我们可以绘制的那部分。
Enigmaya 老师,我说的对吗?还是差的很远?

2

主题

429

帖子

435

积分

中级会员

Rank: 3Rank: 3

积分
435
发表于 2007-9-15 01:54:00 | 显示全部楼层

Re:再读模版Stencil Mirror,

老师?岂敢当,我只是说说我的理解而已,我不懂的东西更多。

只要我们DrawPrimitive 或者DrawSubset 之后我们就要更新backbuffer 或 z ,stencil buffer
================
不是绘制之后才去确定是否更新,而是之前决定是否需要更新,如果需要,就开启,然后绘制时就会更新相应的区域。
所有的buffer的更新都是一样的,你绘制什么,buffer就按照一定的规则更新相应的区域。
backbuffer其实就是colorbuffer,最后显示的就是这个。

其实你可以把3个buffer想象成3个画布,只是记录的东西不同罢了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-21 17:52

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表