这是一道在《Introduction to 3D Game Programming with DirectX 11》上的练习题。

要求把某个像素点上的Depth Complexity(深度复杂度?)可视化输出。Depth Complexity即某个点上有多少次depth test。

根据题目中的提示,我们可以用stencil buffer完成。

简要步骤如下:

  1. 绘制场景,设置DepthStencilState为stencil test永远通过,通过后stencil buffer中的值+1。这样每个点绘制后在stencil buffer中的点就会+1。

  2. 根据stencil buffer中的值绘制深度信息。

    要做到这一点,我们只需要置StencilFunc为D3D11_COMPARISON_EQUAL,此时只有在stencil buffer中的值和stencilRef中的值相同的像素点会通过测试。接着对所有的可能的深度值(比如0~5),把整个屏幕用设定的颜色重新绘制一遍即可。这里的绘制不需要具体的顶点信息,只需要覆盖整个屏幕即可(我们会绘制一个覆盖屏幕的四边形,在接下来的shader中可以看到我们是如何做到这一点的)

综上所述,我们需要创建两个depth stencil state,第一个用来绘制场景,同时给stencil buffer中对应的点+1。注意,这个depth stencil state应该设置为在不通过或者通过depth test时都为stencil buffer +1。

建立一个名为DepthCounterDSS的depth stencil state

	D3D11_DEPTH_STENCIL_DESC dsdesc = { 0 };
dsdesc.DepthEnable = true; //深度测试无所谓
dsdesc.DepthFunc = D3D11_COMPARISON_LESS;
dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsdesc.StencilEnable = true;
dsdesc.StencilReadMask = 0xff;
dsdesc.StencilWriteMask = 0xff;
dsdesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; //Stencil test永远通过
dsdesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; //depth fail失败了也+1
dsdesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_INCR;
dsdesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; //不会失败,这项无意义。
//背面被剔除了,下面这些设置无意义。
dsdesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
dsdesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsdesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsdesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_INCR; HR(device->CreateDepthStencilState(&dsdesc, &DepthCounterDSS));

第二个depth stencil state用于绘制深度信息。需要做的工作就是让stencil buffer中的值和stencilRef相等时通过stencil test,否则不通过即可。

注意,此时我们要绘制的图形只有一个覆盖整个屏幕的四边形(两个三角形组成)。

建立一个名为DepthVisualDSS的depth stencil state

	D3D11_DEPTH_STENCIL_DESC dvdesc = { 0 };
dvdesc.DepthEnable = false; //深度测试无所谓
dvdesc.DepthFunc = D3D11_COMPARISON_LESS;
dvdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dvdesc.StencilEnable = true;
dvdesc.StencilReadMask = 0xff;
dvdesc.StencilWriteMask = 0xff;
dvdesc.FrontFace.StencilFunc = D3D11_COMPARISON_EQUAL; //相等时才通过
dvdesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; //不管成功失败都不修改stencil buffer
dvdesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dvdesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
//背面无所谓。
dvdesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
dvdesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dvdesc.BackFace.StencilFunc = D3D11_COMPARISON_EQUAL;
dvdesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
HR(device->CreateDepthStencilState(&dvdesc, &DepthVisualDSS));

接下来我们修改DrawScene()函数,使其在绘制场景前设置stencil depth state为我们的DepthCounterDSS,然后照常绘制即可。(注意在绘制中途stencil depth state有无改变)

void BlendApp::DrawScene()
{
md3dImmediateContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::Silver));
md3dImmediateContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0);
md3dImmediateContext->OMSetDepthStencilState(RenderStates::DepthCounterDSS, 0); //StencilRef没有用
//普通绘制
//……
//绘制结束,此时stencil buffer中存的就是每个像素的深度复杂度 DrawComplexity();
}

再实现DrawComplexity函数

void BlendApp::DrawComplexity()
{ ID3DX11EffectTechnique* quadTech = Effects::BasicFX->DepthVisual;
D3DX11_TECHNIQUE_DESC techDesc;
quadTech->GetDesc(&techDesc);
for (UINT p = 0; p<techDesc.Passes; ++p)
{
for (int i = 0; i<10; ++i) //假设最多有10层深度
{
md3dImmediateContext->OMSetDepthStencilState(RenderStates::DepthVisualDSS, i); //设置stencilref=i Effects::BasicFX->SetDVColor(Colors::White/10*i); //设置绘制颜色,i越大白色越浓 quadTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext); md3dImmediateContext->Draw(3, 0); //绘制一个四边形,具体的顶点信息由vertex shader自己给出
}
}
}

以上代码中的DepthVisual是一个简单的对全屏幕进行一次指定颜色绘制的technique,shader代码如下。


cbuffer quadColor
{
float4 gDVColor;
} VertexOut VSfullscreenQuad(uint id : SV_VERTEXID) //SV_VERTEXID由gpu给出,指定当前顶点序号
{
VertexOut output; // 计算齐次坐标
output.PosH.x = (float) (id / 2) * 4.0 - 1.0f;
output.PosH.y = (float) (id % 2) * 4.0 - 1.0f;
output.PosH.z = 0.0f;
output.PosH.w = 1.0f; return output;
} float4 PScolorOnly(VertexOut pin) : SV_Target
{
return gDVColor;
} technique11 DepthVisual
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VSfullscreenQuad()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_5_0, PScolorOnly()));
}
}

完成效果如下

在DirectX11下用Stencil Buffer绘制可视化Depth Complexity的更多相关文章

  1. windows API下的模板缓冲(stencil buffer)

    在windows API搭建的OpenGL窗口中使用模板缓冲,需要在像素格式描述表中设置stencil buffer位宽为8,这样窗口会自动生成stencil buffer,然后可以在opengl环境 ...

  2. Directx11教程(50) 输出depth/stencil buffer的内容

    原文:Directx11教程(50) 输出depth/stencil buffer的内容      有时候,我们需要查看depth/stencil buffer的内容,比如上一章中,我们要查看sten ...

  3. Directx11教程(48) depth/stencil buffer的作用

    原文:Directx11教程(48) depth/stencil buffer的作用      在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所 ...

  4. Stencil Buffer

    刚在草稿箱里发现了这篇充满特色的好日志.发表之. ------------------吃货的分割线---------------------------------------- Stencil Bu ...

  5. UnityShader实例09:Stencil Buffer&Stencil Test

    http://blog.csdn.net/u011047171/article/details/46928463 Stencil Buffer&Stencil Test 在开始前先吐槽下uni ...

  6. pytorch下可采用visidom作为可视化工具

    2018/9/18更新  感觉tensorboardX插件更好用,已转用https://github.com/lanpa/tensorboardX 更新:新版visdom0.1.7安装方式为:cond ...

  7. Directx11教程(49) stencil的应用-镜面反射

    原文:Directx11教程(49) stencil的应用-镜面反射      本教程中,我们利用stencil来实现一个镜面反射效果. 1.首先我们要在D3DClass中增加几个成员变量及函数. I ...

  8. UnityShader学习笔记- Stencil Buffer

    模板测试(Stencil Test)是现代渲染流水线的一环,其中涉及到的就是模板缓冲(Stencil Buffer),模板缓冲可以用来制作物体的遮罩.轮廓描边.阴影.遮挡显示等等效果 目录 Stenc ...

  9. depth/stencil buffer的作用 ----------理解模板缓存 opengl

    在D3D11中,有depth/stencil buffer,它们和framebuffer相对应,如下图所示,framebuffer中一个像素,有相对应的depth buffer和stencil buf ...

随机推荐

  1. ThreadPool线程池的几种姿势比较

    from multiprocessing.pool import ThreadPool #from multiprocessing.dummy import Pool as ThreadPool #这 ...

  2. picker组件,mode=date,苹果机年份从1开始

    由于在IOS上复制图片不方便, 所以用了张别的网站的图 这是在没有设置value和start的情况下出现的,安卓机上显示是好的.尝试完网上相关说法, 发现都不中! 通过各种挣扎啊!~ 心里苦啊~ 复制 ...

  3. SQLAlchemy 学习笔记(一):Engine 与 SQL 表达式语言

    个人笔记,如有错误烦请指正. SQLAlchemy 是一个用 Python 实现的 ORM (Object Relational Mapping)框架,它由多个组件构成,这些组件可以单独使用,也能独立 ...

  4. java csv list cant not repeat

    require: /** * before: * file A1.csv {1,2,3,4,5} * file A2.csv {2,3,9,10,11} * file B1.csv {5,12,13, ...

  5. PE文件格式介绍

    Useful Tools: 1. WDK安装目录下搜下depends.exe,这个工具可以查看.exe文件依赖的.dll,以及用到的dll中的api. 2.PE文件格式分析器: 有很多的PE格式分析器 ...

  6. AndroidStudio3.0 注解报错Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor.

    体验最新版AndroidStudio3.0 Canary 8的时候,发现之前项目的butter knife报错,用到注解的应该都会报错 Error:Execution failed for task ...

  7. Java 利用枚举实现单例模式

    引言 单例模式比较常见的实现方法有懒汉模式,DCL模式公有静态成员等,从Java 1.5版本起,单元素枚举实现单例模式成为最佳的方法. Java枚举 基本用法 枚举的用法比较多,本文主要旨在介绍利用枚 ...

  8. mac 倍速播放

    Mac的倍速播放,使用工具播放是quick time player,使用方式是,按住 “option” + “>>” 即可调整倍数:

  9. 【转】The test form is only available for requests from the local machine 解决方法

    描述:在内网可以访问 WebServer     ,在外部网站无法通过IP调用 webserver 转自:http://www.cnblogs.com/xiaogelove/p/3447283.htm ...

  10. 【题解】NOI2015寿司晚宴

    想好久啊+不敢写啊……但果然人还是应当勇敢自信,只有坚定地去尝试,才会知道最后的结果.1A真的太开心啦,不过好像我的做法还是比较复杂的样子……理解起来应该算是比较容易好懂的类型,大家可以参考一下思路~ ...