本章讨论:立方体贴图 cube map,即以特殊的方式来运用这种由6个纹理所构成的基本数组。我们可以利用这项技术方便地映射天空纹理或模拟反射

1.什么是立方体贴图 -- Cube Map

立方体贴图的主要思想是:存储6个纹理,将它们分别看作立方体的6个面。此立方体的中心点位于某坐标系的原点,且该立方体对齐于该坐标系的主轴。由于立方体纹理是轴对齐的,它的每个面对应于坐标系某个方向的主轴,因此我们可以根据与面相交的坐标轴方向(±X,±Y,±Z)来引用立方体图的特定面。

在Direct3D中,立方体图被表示为一个由6个元素所构成的纹理数组

  1. 索引0援引的是与+X轴相交的面
  2. 索引1援引的是与-X轴相交的面
  3. 索引2援引的是与+Y轴相交的面
  4. 索引3援引的是与-Y轴相交的面
  5. 索引4援引的是与+Z轴相交的面
  6. 索引5援引的是与-Z轴相交的面

寻找立方体图中纹素的方法与普通的2D纹理并不相同,此时需要使用3D纹理坐标:它定义了一个起点位于原点的查找向量v,从原点出发沿着向量v方向的射线打到立方体贴图的交点,即为对应的纹素。可以看出,查找向量v的大小并不重要,两个方向相同大小不同的查找向量会得到相同的纹素。

在HLSL中,立方体纹理用TextureCube类型来表示:

TextureCube gCubeMap;
SampleState gsamLinearWrap : register(s2);...// 在PS中:
float3 v = float3(x,y,z); // 某查找向量
float4 color = gCubeMap.Sample(gsamLinearWrap, v);

查找向量与立方体图应该位于同一空间中。

2.环境贴图 -- Environment Mapping

立方体贴图的主要应用是环境贴图。其思路是:使视场角为90°(垂直视场角与水平视场角)的摄像机位于场景中某物体的中心点O处。让摄像机朝着x、y、z轴的正负总共6个方向进行观察,以这6个视角来截取场景中的图像,将6张周围环境图像存于立方体贴图的6个面中,这就是环境图的由来。

根据上面的描述,我们为每一个采用环境贴图的物体来创建一个环境图[用于反射],这些纹理耗费较多内存。折中的实现办法:①仅在场景中的关键处截取少量环境图,为每个物体采集场景中离它们最近的环境图,因为不精确反射很难被注意到②采集环境图时,忽略部分物体,比如不考虑近处物体,只考虑远处山脉天空的环境贴图。

由于立方体图仅存储纹理数据,所以我们无须实时渲染,我们可以让美工预先制作出纹理的内容。我们可以在3D场景编辑器中绘制场景,然后预先渲染立方体图的6个面上的图像。对于户外环境图来说,Terragen程序是一种普遍的选择,它免费且能够创建具有照片级真实感的室外场景来。

应用程序中,加载dds还是使用DDSTextureLoader.h/.cpp的CreateDDSTextureFromFile12()函数:

auto skyTex = std::make_unique<Texture>();
skyTex->Name = "skyTex";
skyTex->Filename = L"Textures/grasscube1024.dds";
ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(), mCommandList.Get(), skyTex->Filename.c_str(), skyTex->Resource, skyTex->UploadHeap));// 为立方体贴图创建SRV
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; // 维度
srvDesc.TextureCube.MostDetailedMip = 0;
srvDesc.TextureCube.MipLevels = skyTex->GetDesc().MipLevels;
srvDesc.TextureCube.ResourceMinLODClamp = 0.f;
srvDesc.Format = skyTex->GetDesc().Format;
md3dDevice->CreateShaderResourceView(skyTex.Get(), &srvDesc, hDescriptor);

3.绘制天空纹理

利用环境图绘制天空纹理:创建一个巨大的球体围绕整个场景,再为其绘制纹理。具体实现:可以将天空球的中心置于摄像机上,且天空球随着摄像机的移动而移动

实现天穹效果的着色器文件如下:

// Sky.hlsl -- 处理球体并为其贴图
#include "Common.hlsl"struct VertexIn
{float3 PosL    : POSITION;float3 NormalL : NORMAL;float2 TexC    : TEXCOORD;
};struct VertexOut
{float4 PosH : SV_POSITION;float3 PosL : POSITION;
};VertexOut VS(VertexIn vin)
{VertexOut vout;// 用局部顶点的未知作为立方体图的查找向量vout.PosL = vin.PosL;// 把顶点转换到世界空间float4 posW = mul(float4(vin.PosL, 1.0f), gWorld);// 总是以摄像机作为天空球的中心posW.xyz += gEyePosW;// 设置z=w,从而使z/w=1(即令球面总是位于远平面)vout.PosH = mul(posW, gViewProj).xyww; // 让透视除法后z始终等于1,也就是位于远平面return vout;
}float4 PS(VertexOut pin) : SV_Target
{return gCubeMap.Sample(gsamLinearWrap, pin.PosL);
}

渲染天空的着色器程序与绘制普通物体的着色器程序(Default.hlsl)有着明显的区别,但由于它们的根签名是相同的,所以不必在绘制过程中改变根签名了。这两个hlsl文件所共用的代码已经移入Common.hlsl文件中。

// Common.hlsl部分内容												

dx12 龙书第十八章学习笔记 -- 立方体贴图相关推荐

  1. dx12 龙书第三章学习笔记 -- 变换

    1.线性变换:   函数的输入和输出都是3D向量,我们称为线性变换 矩阵表示法: ⭐所以已知一个线性变换,只要将i,j,z也就是标准基向量代入线性变换,就能构造一个变换矩阵 A:线性变换的矩阵表示法 ...

  2. dx12 龙书第四章学习笔记 -- Direct3D的初始化

    1.预备知识: ①Direct3D 12概述: 通过Direct3D这种底层图形应用程序编程接口(Application Programming Interface, API),即可在应用程序中对图形 ...

  3. dx12 龙书第七章学习笔记 -- 利用Direct3D绘制几何体(续)

    1.帧资源 之前,我们在处理CPU和GPU的同步问题时,采取以下方法:在每帧绘制的结尾调用D3DApp::FlushCommandQueue函数,以确保GPU在每一帧都能正确完成所有命令的执行 这样做 ...

  4. dx12 龙书第二十一章学习笔记 -- 环境光遮蔽

    hd之前我们在光照模型中模拟间接光的公式为:.我们利用一个相同的光量将场景中的所有元素稍微照亮一点.这里有改良的余地,这章将就流行于改善环境光项的环境光遮蔽技术展开讨论. 1.通过投射光线实现环境光遮 ...

  5. dx12 龙书第十一章学习笔记 -- 模板

    模板缓冲区是一种"离屏"(off-screen)缓冲区,我们可以用它来实现一些特殊的效果.模板缓冲区.后台缓冲区以及深度缓冲区都有着相同的分辨率,所以三者相同位置上的像素就能一一对 ...

  6. LearnOpenGL学习笔记——立方体贴图

    立方体贴图 在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map).简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的 ...

  7. dx12 龙书第十二章学习笔记 -- 几何着色器

    如果不启用曲面细分(tessellation)这一环节,那么几何着色器(geometry shader)这个可选阶段便会位于顶点着色器与像素着色器之间.顶点着色器以顶点作为输入数据,而几何着色器的输入 ...

  8. dx12 龙书第十九章学习笔记 -- 法线贴图

    本章需要掌握的内容:①法线贴图②TBN坐标系 1.使用法线贴图的动机 左图是使用法线贴图后的结果,右图是没有使用法线贴图(使用法线插值)的结果.可以明显感知到,高光在右图中是分布在一条直线上的,并没有 ...

  9. 第十八课,立方体贴图(加载天空盒)

    原理我在这里不再过多叙述,主要从代码的运行方向来解读立方体贴图 添加天空盒顶点 float skyboxVertices[] = {// positions -1.0f, 1.0f, -1.0f,-1 ...

最新文章

  1. Python3.2 --- Print函数用法
  2. numpy 深复制 切片创建视图
  3. 2022-01-23
  4. 计算机是怎样知道屏幕位置的,如何看自己的电脑显示器是多少寸
  5. MPU和CPU有什么区别?
  6. 你跟最伟大领导的距离,或许只差这一点
  7. 关于maven面试的哪些事儿~
  8. 大屏监控系统实战(7)-后端整合MybatisPlus并暴露服务
  9. 案例详解:Linux文件系统异常导致数据库文件无法访问
  10. 20190501-整数翻转
  11. linux下scrapy安装教程,linux centos7安装scrapy
  12. vue中的render函数介绍
  13. azure 入门_Azure Cosmos DB中的子文档入门
  14. php 进行http请求,php模拟http请求的两种方式
  15. servlet笔试题java,Java推荐!Servlet面试题和答案汇集
  16. 谷歌开源缓存框架Guava Cache
  17. 世界首款前置前驱混动8挡自动变速器山东潍坊问世
  18. tekla钢筋组弯钩方向
  19. 人工智能机器学习入门资料免费送
  20. 友盟推送_java后台集成和使用

热门文章

  1. gif.GifImageView 动态加载gif图片不动
  2. 模拟登录丁香园获取全部回复
  3. 四层高速dsp开发板制作5——预布局与精确布局
  4. s15.一键安装java脚本
  5. 5G为人工智能与工业互联网赋能|79页高清PPT
  6. 成都旅游攻略 —— 拜水都江堰 问道青城山
  7. VHDL语言基本单元及其构成——EDA学习笔记(一)
  8. win2000:ntoskrnl.exe 文件丢失解决一例
  9. cakephp oracle,CakePHP入门(8)-创建Model
  10. 在线问答未来会朝什么趋势发展?