D3D12渲染技术之纹理案例

2023-10-11 16:59

本文主要是介绍D3D12渲染技术之纹理案例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们现在回顾一下将纹理添加到箱子模型上面,就跟以前的博客中提到的那样。下面我们详细介绍如何实现?

指定纹理坐标

GeometryGenerator :: CreateBox生成箱子的纹理坐标,以便将整个纹理图像映射到箱子的每个面上。 为简洁起见,我们仅显示正面,背面和顶面的顶点定义。 另请注意,我们省略了顶点构造函数中法线和切线向量的坐标(纹理坐标以粗体显示)。

GeometryGenerator::MeshData GeometryGenerator::CreateBox(float width, float height, float depth, uint32 numSubdivisions)
{MeshData meshData;Vertex v[24];float w2 = 0.5f*width;float h2 = 0.5f*height;float d2 = 0.5f*depth;// Fill in the front face vertex data.v[0] = Vertex(-w2, -h2, -d2, …, 0.0f, 1.0f);v[1] = Vertex(-w2, +h2, -d2, …, 0.0f, 0.0f);v[2] = Vertex(+w2, +h2, -d2, …, 1.0f, 0.0f);v[3] = Vertex(+w2, -h2, -d2, …, 1.0f, 1.0f);// Fill in the back face vertex data.v[4] = Vertex(-w2, -h2, +d2, …, 1.0f, 1.0f);v[5] = Vertex(+w2, -h2, +d2, …, 0.0f, 1.0f);v[6] = Vertex(+w2, +h2, +d2, …, 0.0f, 0.0f);v[7] = Vertex(-w2, +h2, +d2, …, 1.0f, 0.0f);// Fill in the top face vertex data.v[8] = Vertex(-w2, +h2, -d2, …, 0.0f, 1.0f);v[9] = Vertex(-w2, +h2, +d2, …, 0.0f, 0.0f);v[10] = Vertex(+w2, +h2, +d2, …, 1.0f, 0.0f);v[11] = Vertex(+w2, +h2, -d2, …, 1.0f, 1.0f);

创建纹理

我们在初始化时从文件创建纹理,如下所示:

// Helper structure to group data related to the texture.
struct Texture
{// Unique material name for lookup.std::string Name;std::wstring Filename;Microsoft::WRL::ComPtr<ID3D12Resource> Resource = nullptr;Microsoft::WRL::ComPtr<ID3D12Resource> UploadHeap = nullptr;};std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;void CrateApp::LoadTextures()
{auto woodCrateTex = std::make_unique<Texture>();woodCrateTex->Name = "woodCrateTex";woodCrateTex->Filename = L"Textures/WoodCrate01.dds";ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),mCommandList.Get(), woodCrateTex->Filename.c_str(),woodCrateTex->Resource, woodCrateTex->UploadHeap));mTextures[woodCrateTex->Name] = std::move(woodCrateTex);
}

我们将所有独特纹理存储在无序地图中,以便我们可以按名称查找它们。 在代码中,在加载纹理之前,需要检查纹理数据是否已经加载(即,它是否已经包含在无序映射中),以便它不会多次加载。

设置纹理

一旦创建了纹理并在描述符堆中为它创建了SRV,将纹理绑定到管道以便可以在着色器程序中使用它只需将其设置为需要纹理的根签名参数:

// Get SRV to texture we want to bind.
CD3DX12_GPU_DESCRIPTOR_HANDLE tex(
mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
tex.Offset(ri->Mat->DiffuseSrvHeapIndex, mCbvSrvDescriptorSize);…// Bind to root parameter 0. The root parameter description specifies which 
// shader register slot this corresponds to.
cmdList->SetGraphicsRootDescriptorTable(0, tex);

纹理转换

我们没有讨论过的两个常量缓冲区变量是gTexTransform和gMatTransform。 这些变量在顶点着色器中用于变换输入纹理坐标:

在这里插入代码片// Output vertex attributes for interpolation across triangle.
float4 texC = mul(float4(vin.TexC, 0.0f, 1.0f), gTexTransform);
vout.TexC = mul(texC, gMatTransform).xy;

纹理坐标表示纹理平面中的2D点, 因此,我们可以像任何其他点一样平移,旋转和缩放它们, 以下是转换纹理的一些示例用法:
1、砖纹理沿墙壁被拉伸, 墙顶点当前具有范围[0,1]中的纹理坐标。 我们将纹理坐标放大4倍,以将它们放大到范围[0,4],这样纹理将在墙上重复四到四次。
2、天空飘动的云层, 通过将纹理坐标转换为时间的函数,云在天空上就可以飘动了。
3、纹理旋转有时对粒子效果非常有用,例如,我们会随着时间的推移旋转火球纹理。

在本篇博客提供的案例中,我们使用单位矩阵变换,以便输入纹理坐标保持不变,但在下篇博客中,我们将解释使用纹理变换的演示。

请注意,要将2D纹理坐标转换为4×4矩阵,我们将其扩展为4D矢量:

vin.TexC ---> float4(vin.Tex, 0.0f, 1.0f)

在乘法完成之后,通过丢弃z分量和w分量将得到的4D矢量转回到2D矢量。

vout.TexC = mul(float4(vin.TexC, 0.0f, 1.0f), gTexTransform).xy;

我们使用两个单独的纹理变换矩阵gTexTransform和gMatTransform,因为有时它对材质转换纹理(对于像水这样的动画材料)更有意义,但有时它使纹理变换更有意义成为对象的属性。
因为我们正在处理2D纹理坐标,所以我们只关心对前两个坐标进行的转换。 例如,如果纹理矩阵转换了z坐标,则它对结果纹理坐标没有影响。最后给大家看一下实现的Demo:
在这里插入图片描述

Demo下载地址:链接:https://pan.baidu.com/s/1X0Vikf6qGYGPKU-Nwf-wYA 密码:h79q

这篇关于D3D12渲染技术之纹理案例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/189516

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固 通俗易懂版)

《MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固通俗易懂版)》本文主要讲解了MySQL中的多表查询,包括子查询、笛卡尔积、自连接、多表查询的实现方法以及多列子查询等,通过实际例子和操... 目录复合查询1. 回顾查询基本操作group by 分组having1. 显示部门号为10的部门名,员

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck