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

相关文章

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

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的部门名,员