Direct3D 12——模板——平面阴影效果

news2024/9/21 16:24:50

平行光阴影

在这里插入图片描述
图展示了由平行光源经物体所投射岀的阴影。给定方向为L的平行光源,并用r(t)=p + tL来表 示途经顶点p的光线。光线r (t)与阴影平面(n,d)的交点为S。以此光源射出的光线照射到物体的各个顶点,用这些映射到平面上的交点集合便可以定义几何体所投射出的阴影形状。对于顶点P来说,它的阴影投影可由下列公式求岀:
在这里插入图片描述
公式也可以写作矩阵的形式
在这里插入图片描述
我们称以上的4x4矩阵为方向光阴影矩阵(directional shadow matrix,也译作平行光阴影矩阵),Sdir表示。为了证明此矩阵与公式是等价的,我们用乘法运算加以验证。首先可以看出,此矩阵改变了w分量,即Sw=n·L。这样一来,当执行透视除法时,S中的每个坐标都会除以Si其中 i∈{1,2, 3}。在透视除法完成之后,我们有:

在这里插入图片描述
此结果与公式求出的s中的第i个坐标完全相同,因此s=s’。

为了运用阴影矩阵,我们将它与世界矩阵组合在一起。但是,在世界变换之后,由于透视除法还没 有执行,因而几何体的阴影还未被投射到阴影平面上。此时便出现了一个问题:若Sw=n·L<0,则w坐标将变为负值。在透视投影的处理过程中,我们一般将 z 坐标复制到 w 坐标,若 w 坐标为负值则表明 此点位于视锥体之外而应将其裁剪掉(裁剪操作在透视除法之前的齐次空间内执行)。这对于平面阴影来 讲是个大问题,因为除了计算透视除法之外,我们还要用 w 坐标来实现阴影效果。图就展示了这样 一种n·L<0却存在阴影的情况,但此时这个阴影却无法显示出来。
在这里插入图片描述

为了纠正这个问题,我们用指向无穷远处光源的方向向量L1 = -L来取代光线方向向量L。可以看岀, r(t)=p + tLr(t)=p + tL1定义的是相同的3D直线,且该直线与平面之间的交点也是一致的(利用不同 的交点参数值ts来弥补L1与L之间的符号差异)。因此使用L1 = -L 会得到与L相同的计算结果,但是前 者会保证n·L>0,以此来绕开w坐标为负值的这个坑。

点光阴影

在这里插入图片描述
图展示了位于点 L 处的点光源所投射出的物体阴影。从点光源发出的途经任意顶点p的光线可 由r(t) = p + t(p - L)来表示。光线r(t)与阴影平面(n,d)的交点为s。以此光源发出的光线经过物体的每个 顶点,这映射在平面的交点集合便定义了几何体所投射出的阴影形状。对于顶点 p 而言,其阴影投影可以表示为:
在这里插入图片描述
公式也可以写作矩阵方程:
在这里插入图片描述

为了证明此矩阵等价于公式我们就以上面同样的办法,用矩阵进行乘法运算。观察到最后一列中并没有0项,则有:
在这里插入图片描述
这就是公式中分母部分的相反数,我们可以通过将分子与分母同时乘以T,使二者一致。

对于点光与平行光而言,L 充当着不同的角色。在使用点光时,L 定义了点光源的位置。 在使用平行光时,我们却用 L 来定义指向无穷远处光源的方向向量(即与平行光光线传 播方向相反的向量)。

通用阴影矩阵

我们可通过齐次坐标创建出一个能同时应用于点光与方向光的通用阴影矩阵。

1.如果Lw=0 ,则 L 表示指向无穷远处光源的方向向量(即与平行光光线传播方向相反的向量)。
2.如果如果Lw=1,则 L 表示点光的位置。

接下来,我们用下列阴影矩阵(shadow matrix)来表示由顶点p到其投影s的变换:
在这里插入图片描述
DirectX的数学提供了以下函数,用以构建在特定平面内投射阴影所用的相应阴影矩阵,若w = 0 表示平行光,而w=l则表示点光:
inline XMMATRIX XM_CALLCONV XMMatrixShadow(
FXMVECTOR ShadowPlane,
FXMVECTOR LightPosition);

使用模板缓冲区防止双重混合

将物体的几何形状投射到平面而形成阴影时,可能(实际上也经常岀现)会有两个甚至更多的平面 阴影三角形相互重叠。若此时用透明度这一混合技术来渲染阴影,则这些三角形的重叠部分会混合多次, 使之看起来更暗。

1.首先,保证参与渲染阴影的模板缓冲区中的阴影范围像素都已被清理为0。
2.设置模板测试,使之仅接受模板缓冲区中元素为0的像素。如果通过模板测试,则将相应模板 缓冲区值增为1。

在第一次渲染阴影像素时,由于模板缓冲区元素为0,因而模板测试会成功。渲染该像素的同时, 我们也会将对应的模板缓冲区元素增加为1。这样一来,如果试图覆写已被渲染过的区域,则模板测试 会失败。这将防止同一像素被绘制多次,继而阻止双重混合的发生。

编写阴影部分的代码
auto shadowMat = std::make_unique<Material>();
	shadowMat->Name = "shadowMat";
	shadowMat->MatCBIndex = 4;
	shadowMat->DiffuseSrvHeapIndex = 3;
	shadowMat->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.0f, 0.5f);
	shadowMat->FresnelR0 = XMFLOAT3(0.001f, 0.001f, 0.001f);
	shadowMat->Roughness = 0.0f;
	//为了防止双重混合,我们用下列的深度/模板状态来设置PSO:
	//以下列深度/模板状态来防止双重混合的发生
	// 我们要用透明度绘制阴影,所以基于透明度描述
	D3D12_DEPTH_STENCIL_DESC shadowDSS;
	shadowDSS.DepthEnable = true;
	shadowDSS.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
	shadowDSS.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
	shadowDSS.StencilEnable = true;
	shadowDSS.StencilReadMask = 0xff;
	shadowDSS.StencilWriteMask = 0xff;

	shadowDSS.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
	shadowDSS.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;
	shadowDSS.FrontFace.StencilPassOp = D3D12_STENCIL_OP_INCR;
	shadowDSS.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_EQUAL;

	// 我们不渲染背面多边形,所以这些设置无关紧要。
	shadowDSS.BackFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
	shadowDSS.BackFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;
	shadowDSS.BackFace.StencilPassOp = D3D12_STENCIL_OP_INCR;
	shadowDSS.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_EQUAL;

	D3D12_GRAPHICS_PIPELINE_STATE_DESC shadowPsoDesc = transparentPsoDesc;
	shadowPsoDesc.DepthStencilState = shadowDSS;
	ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&shadowPsoDesc, IID_PPV_ARGS(&mPSOs["shadow"])));
//绘制阴影
mCommandList->OMSetStencilRef(0);
	mCommandList->SetPipelineState(mPSOs["shadow"].Get());
	DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Shadow]);
    //更新阴影的世界矩阵
	XMVECTOR shadowPlane = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); // xz plane
	XMVECTOR toMainLight = -XMLoadFloat3(&mMainPassCB.Lights[0].Direction);
	XMMATRIX S = XMMatrixShadow(shadowPlane, toMainLight);
	XMMATRIX shadowOffsetY = XMMatrixTranslation(0.0f, 0.001f, 0.0f);
	XMStoreFloat4x4(&mShadowedSkullRitem->World, skullWorld * S * shadowOffsetY);

注意,我们将投影网格沿着y轴做了少量的偏移调整,以防发生深度冲突,所以阴影网 格不会与地板网格相交,得到的最终效果是阴影会略高于地板。如果这两种网格相交,则由于深度缓冲 区的精度限制,将导致地板与阴影的网格像素为了各自的完全显现而发生闪烁的现象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/431943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion本地搭建windows and linux(附搭建环境)

linux搭建过程以centos为例 1.使用git工具下载项目文件到本地文件夹&#xff0c;命令如下&#xff1a; git clone https://github.com/IDEA-CCNL/stable-diffusion-webui.git然后进入该文件夹&#xff1a; cd stable-diffusion-webui2.运行自动化脚本 运行webui.sh安装一些p…

2023最新接口自动化测试面试真题详解,看完轻松拿捏HR

目录 一.有接口测试工具为什么还需要开发自动化框架或自动化平台。 二.接口自动化中如果一个接口请求不通该如何排查 三.你平常做接口自动化的过程中发现过哪些bug?多吗&#xff1f; 四.你在接口自动化中是怎么校验接口返回结果是否正确&#xff1f; 五、接口自动化回归过程中…

【C生万物】 操作符篇

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; 前言&#xff1a; 我觉得学习语言&#xff0c;最直接的就是懂不懂符号&#xff0c;而符号中最突出的就是操作符&#xff0c;这期带大家认识认识C语言中的操作符及其使用。 目录 Part1:算数操作符 Part2:移…

直方图均衡化(调节图像亮度、对比度)

直方图均衡化&#xff08;调节图像亮度、对比度&#xff09; 本篇目录 &#x1f984; 一、前言 &#x1f984; 二、直方图均衡化概念 &#x1f984; 三、直方图均衡化实例 &#xff08;1&#xff09;、灰度图像的均衡处理实例 ①、卡通人物灰度图像均衡处理 ②、卡通猫头…

音频编辑开发SDK Audio DJ Studio for .NET Crack

11.7版本--Audio DJ Studio for .NET是 MultiMedia Soft 开发的 .NET Windows Forms 自定义控件&#xff0c;可以轻松地向使用Microsoft Visual Studio编写的Winform和WPF 应用程序添加声音播放和混音功能&#xff1b;由于与 DirectShow 编解码器和 BASS 库的集成&#xff0c;两…

【UITableView和UITableViewCell的常见属性 Objective-C语言】

一、UITableView和UITableViewCell的常见属性, 1.我们说,这些属性里面, 2.这些是不是都是单元格的属性, 1)这个imageView:是单元格里面的图片框,是不是指的是这个啊, 2)这个textLabel:是指的这个标题上面这个Label吧, 3)这个detailTextLabel:是指的标题下面这…

安装tomcat8,配置服务启动脚本,部署jpress应用

1. 简述静态网页和动态网页的区别。 静态网站顾名思义就是不能动的网站&#xff0c;其中的内容一旦做好就固定了。而动态网站是一种网页编程技术&#xff0c;它可以使得浏览器和服务器可以交互&#xff0c;根据服务器的不同请求动态的生成网页内容。 3. 简述 Webl.0 和 Web2.…

基于STM32的倒车雷达系统设计

目录 前言 一、绪论 1.1 设计背景 1.2 设计内容 二、系统硬件设计 2.1 硬件系统框图 2.2 主控制电路 2.3 超声波电路 2.4 OLED显示电路 2.5 键盘输入电路 2.6 声光报警模块电路 三、系统软件设计 3.1 系统主程序设计 3.2 OLED显示程序设计 3.3 键盘设定程序设计…

设计模式-结构型模式之外观模式

4. 外观模式4.1. 模式定义外观模式(Facade Pattern)&#xff1a;外部与一个子系统的通信必须通过一个统一的外观对象进行&#xff0c;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。外观模式…

C++11 make_shared函数和std::make_unique详解

make_shared的使用: shared_ptr<string> p1 make_shared<string>(10, 9); shared_ptr<string> p2 make_shared<string>("hello"); shared_ptr<string> p3 make_shared<string>(); 好处&#xff1a;减少分配次数 std::s…

大厂面试内幕:阿里内部整理出的5000页Java面试复盘指南,起飞!!!

互联网的技术岗一直是高薪的代名词&#xff0c;特别是大厂&#xff0c;应届生的年薪基本都20W起&#xff0c;比一般的公司高多了。 看下面这张网上热传的大厂应届生薪酬表就知道了&#xff0c;SP offer甚至能拿到30W以上。 技术社区也有晒出高薪offer的同学&#xff1a; 除了薪…

Unity LOD 技术

Unity LOD 技术 LOD(Level of detail) 多层次细节&#xff0c;常用的Unity 优化技术 它是根据物体在游戏画面中所占视图百分比来调用显示不同精度的模型 说白了就是 当物体距离摄像机距离较近时显示高精度模型 当物体距离摄像机距离较远时显示低精度模型 优点&#xff1a;优化…

Python深度学习实现DIY专属个人表情包

引言&#xff1a; 在现代社交媒体的时代&#xff0c;表情包已经成为了人们日常生活中不可或缺的一部分。表情包可以用来表达情感、传递信息&#xff0c;甚至成为一种文化符号。然而&#xff0c;随着表情包的日益普及&#xff0c;大量的表情包已经不能满足人们的需求&#xff0…

如何对图片批量重命名?

对于爱好摄影的朋友们来说&#xff0c;不管是手机还是相机拍摄的照片&#xff0c;在导入电脑后&#xff0c;它们的文件名通常都是一串长长的乱码。这不仅会导致桌面看起来杂乱无章&#xff0c;还会给我们查找图片带来很多不便&#xff0c;有时候丢失几张图片都发现不了。不过&a…

7、在vscode上利用cmake构建多文件C++工程

文章目录 &#xff08;1&#xff09;创建如下工程文件夹&#xff1a;其中头文件放在include文件夹中&#xff0c;源文件放在src文件夹中&#xff08;2&#xff09;在vscode上打开工程文件夹&#xff0c;在对应的文件夹内建立相应的文件1&#xff09;目录结构2&#xff09;各文件…

【C语言督学训练营 第十一天】三篇文章吃透数据结构中的线性表(二)----- 链表的增删改查与销毁

文章目录 前言一、链表1.基本介绍2.增删改查原理与实战 总结与源码 前言 谭浩强老师说过&#xff1a;“指针是c语言的灵魂”&#xff0c;今天说到的链表就是由C语言的灵魂所筑&#xff0c;学会了链表之后可以使用链表轻松实现树、图等数据结构&#xff0c;可以轻松化解考研数据…

《无线神经调节的微创技术治疗慢性顽固性疼痛:初步观察报告》

**全文概况 **&#xff1a;该文件讨论了一种新型无线和微创神经调节设备&#xff0c;用于治疗之前曾经失败的患者慢性顽固性疼痛。该设备通过经皮植入的电极远程控制&#xff0c;进行高频背根节神经刺激或周围神经刺激。该系统对于患有腰腿疼痛的患者有重要潜力&#xff0c;因为…

车载 Android开发面试习题整合~

随着车联网技术的不断发展和普及&#xff0c;越来越多的汽车厂商开始使用 Android 操作系统作为车载娱乐和信息娱乐系统的核心。在这个趋势下&#xff0c;车载 Android 应用开发程序员的需求也日益增加。 像一些车企大厂在广招这方面的技术人才。给原本处于落寞的Android 开发行…

PTA:C课程设计(7)

山东大学&#xff08;威海&#xff09;2022级大一下C习题集&#xff08;7&#xff09;函数题7-6-1 递增的整数序列链表的插入7-6-2 查找学生链表7-6-3 统计专业人数7-6-4 建立学生信息链表编程题7-7-1 查找书籍7-7-2 找出总分最高的学生函数题 7-6-1 递增的整数序列链表的插入…

五子棋透明棋盘界面设计(C语言)

五子棋透明棋盘设计&#xff0c;漂亮的界面制作。程序设置双人对奕&#xff0c;人机模式&#xff0c;对战演示三种模式。设置悔棋&#xff0c;记录功能&#xff0c;有禁手设置。另有复盘功能设置。 本文主要介绍透明的玻璃板那样的五子棋棋盘的制作。作为界面设计&#xff0c;…