Direct3D 11 Tutorial 7:Texture Mapping and Constant Buffers_Direct3D 11 教程7:纹理映射和常量缓冲区
概述
在上一个教程中,我们为项目引入了照明。 现在我们将通过向我们的立方体添加纹理来构建它。 此外,我们将介绍常量缓冲区的概念,并解释如何使用缓冲区通过最小化带宽使用来加速处理。
本教程的目的是修改中心立方体以将纹理映射到其上。
资源目录
(SDK root)\Samples\C++\Direct3D11\Tutorials\Tutorial07
纹理映射
纹理映射是指2D图像在3D几何体上的投影。 我们可以把它想象成包装礼物,将装饰纸放在一个平淡无奇的盒子上。 为此,我们必须指定几何体表面上的点如何与2D图像对应。
诀窍是正确地将模型的坐标与纹理对齐。 对于复杂模型,很难手动确定纹理的坐标。 因此,3D建模包通常将导出具有相应纹理坐标的模型。 由于我们的示例是一个立方体,因此很容易确定匹配纹理所需的坐标。 纹理坐标在顶点处定义,然后针对曲面上的各个像素进行插值。
从纹理和采样器状态中创建着色器资源
纹理是从文件中检索并用于创建着色器资源视图的2D图像,以便可以从着色器中读取它。
hr = D3DX11CreateShaderResourceViewFromFile( g_pd3dDevice, L"seafloor.dds", NULL, NULL, &g_pTextureRV, NULL );
我们还需要创建一个采样器状态来控制着色器如何处理过滤,MIP和寻址。 在本教程中,我们将启用简单的采样器状态,以启用线性过滤和换行寻址。 要创建采样器状态,我们将使用ID3D11Device :: CreateSamplerState()。
// Create the sample state
D3D11_SAMPLER_DESC sampDesc;
ZeroMemory( &sampDesc, sizeof(sampDesc) );
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = g_pd3dDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear );
定义坐标
在我们将图像映射到立方体之前,我们必须首先在立方体的每个顶点上定义纹理坐标。 由于图像可以是任何大小,因此使用的坐标系已标准化为[0,1]。 纹理的左上角对应于(0,0),右下角对应于(1,1)。
在这个例子中,我们将整个纹理分布在立方体的每一侧。 这简化了坐标的定义,没有混淆。 但是,它完全可以指定要在所有六个面上拉伸的纹理,尽管定义点更加困难,并且它会显得拉伸和扭曲。
首先,我们更新了用于定义顶点的结构,以包含纹理坐标。
struct SimpleVertex
{
XMFLOAT3 Pos;
XMFLOAT2 Tex;
};
接下来,我们将更新输入布局为了让着色器包含这些坐标。
// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
由于输入布局已更改,因此还必须修改相应的顶点着色器输入以匹配添加。
struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD;
};
最后,我们准备在我们在教程4中定义的顶点中包含纹理坐标。注意第二个参数输入是包含纹理坐标的D3DXVECTOR2。 立方体上的每个顶点都对应于纹理的一角。 这将创建一个简单的映射,其中每个顶点得到(0,0)(0,1)(1,0)或(1,1)作为坐标。
// Create vertex buffer
SimpleVertex vertices[] =
{
{ XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
{ XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
{ XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
};
当我们对纹理进行采样时,我们需要使用下面几何体的材质颜色对其进行调制。
将纹理绑定为着色器资源
纹理和采样器状态是我们在前面的教程中看到的常量缓冲区之类的对象。 在着色器可以使用它们之前,需要使用ID3D11DeviceContext :: PSSetSamplers()和ID3D11DeviceContext :: PSSetShaderResources()API进行设置。
g_pImmediateContext->PSSetShaderResources( 0, 1, &g_pTextureRV );
g_pImmediateContext->PSSetSamplers( 0, 1, &g_pSamplerLinear );
好了,现在我们已准备好在着色器中使用纹理。
应用纹理
要在几何体顶部映射纹理,我们将在像素着色器中调用纹理查找功能。 函数Sample将执行2D纹理的纹理查找,然后返回采样的颜色。 下面显示的像素着色器调用此函数并将其乘以底层网格颜色(或材质颜色),然后输出最终颜色。
- 当我们将资源视图g_pTextureRV绑定到它时,txDiffuse是存储我们从上面的代码传入的纹理的对象。
- samLinear将在下面描述; 它是纹理查找的采样器规范。
- input.Tex是我们在源中指定的纹理的坐标。
// Pixel Shader
float4 PS( PS_INPUT input) : SV_Target
{
return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor;
}
还有另一件事情我们必须记住,就是要通过顶点着色器传递纹理坐标。 如果不这样做,数据在到达像素着色器时就会丢失。 在这里,我们只需将输入的坐标复制到输出中,然后让硬件处理其余部分。
// Vertex Shader
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul( input.Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Tex = input.Tex; return output;
}
常量缓冲区
在Direct3D 11中,应用程序可以使用常量缓冲区来设置着色器常量(着色器变量)。 使用类似于C风格结构的语法声明常量缓冲区。 常量缓冲区通过允许将着色器常量组合在一起并同时提交来减少更新着色器常量所需的带宽,而不是单独调用单独提交每个常量。
在前面的教程中,我们使用单个常量缓冲区来保存我们需要的所有着色器常量。 但是,有效使用常量缓冲区的最佳方法是根据更新频率将着色器变量组织到常量缓冲区中。 这允许应用程序最小化更新着色器常量所需的带宽。 例如,本教程将常量分为三个结构:一个用于更改每个帧的变量,一个用于仅在窗口大小更改时更改的变量,另一个用于设置一次然后不更改的变量。
本教程的.fx文件中定义了以下常量缓冲区。
cbuffer cbNeverChanges
{
matrix View;
}; cbuffer cbChangeOnResize
{
matrix Projection;
}; cbuffer cbChangesEveryFrame
{
matrix World;
float4 vMeshColor;
};
要使用这些常量缓冲区,您需要为每个缓冲区创建一个ID3D11Buffer对象。 然后,您可以调用ID3D11DeviceContext :: UpdateSubresource()来在需要时更新每个常量缓冲区,而不会影响其他常量缓冲区。
//
// Update variables that change once per frame
//
CBChangesEveryFrame cb;
cb.mWorld = XMMatrixTranspose( g_World );
cb.vMeshColor = g_vMeshColor;
g_pImmediateContext->UpdateSubresource( g_pCBChangesEveryFrame, 0, NULL, &cb, 0, 0 );
最终效果
Direct3D 11 Tutorial 7:Texture Mapping and Constant Buffers_Direct3D 11 教程7:纹理映射和常量缓冲区的更多相关文章
- Direct3D 11 Tutorial 5: 3D Transformation_Direct3D 11 教程5:3D转型
概述 在上一个教程中,我们从模型空间到屏幕渲染了一个立方体. 在本教程中,我们将扩展转换的概念并演示可以通过这些转换实现的简单动画. 本教程的结果将是围绕另一个轨道运行的对象. 展示转换以及如何将它们 ...
- Direct3D 11 Tutorial 4: 3D Spaces_Direct3D 11 教程4:3D空间
概述 在上一个教程中,我们在应用程序窗口的中心成功渲染了一个三角形. 我们没有太注意我们在顶点缓冲区中拾取的顶点位置. 在本教程中,我们将深入研究3D位置和转换的细节. 本教程的结果将是渲染到屏幕的3 ...
- Direct3D 11 Tutorial 2: Rendering a Triangle_Direct3D 11 教程2:渲染一个三角形
概要 在之前的教程中,我们建立了一个最小的Direct3D 11的应用程序,它用来在窗口上输出一个单一颜色.在本次教程中,我们将扩展这个应用程序,在屏幕上渲染出一个单一颜色的三角形.我们将通过设置数据 ...
- OpenCASCADE Texture Mapping
OpenCASCADE Texture Mapping eryar@163.com Abstract. 纹理贴图技术的出现和流行是图形显示技术的一个非常重要的里程碑,直接影响3D技术从工业进入娱乐领域 ...
- 投影纹理映射(Projective Texture Mapping)
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 投影纹理映射( Projective ...
- OpenGL 4.0 GLSL 实现 投影纹理映射(Projective Texture Mapping) (转)
http://blog.csdn.net/zhuyingqingfen/article/details/19331721 分类: GLSL 投影纹理映射 (projective texture ...
- Java 11 Tutorial
Java 11 Tutorial 参考 https://blog.csdn.net/sihai12345/article/details/82889827 原文 https://winterbe.co ...
- 投影纹理映射(Projective Texture Mapping) 【转】
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 投影纹理映射( Projective ...
- Method for sub-pixel texture mapping and filtering
BACKGROUND OF THE INVENTION 1. Field of the Invention The present invention relates to a method for ...
随机推荐
- php error_log() 范例
<?php// 如果无法连接到数据库,发送通知到服务器日志if (!Ora_Logon($username, $password)) { error_log("Oracle da ...
- 潭州课堂25班:Ph201805201 爬虫高级 第十三 课 代理池爬虫检测部分 (课堂笔记)
1,通过爬虫获取代理 ip ,要从多个网站获取,每个网站的前几页2,获取到代理后,开进程,一个继续解析,一个检测代理是否有用 ,引入队列数据共享3,Queue 中存放的是所有的代理,我们要分离出可用的 ...
- [洛谷P1638]逛画展
[洛谷P1638]逛画展 题目大意: 有\(n(n\le10^6)\)个格子,每个格子有一种颜色.颜色种数为\(m(m\le2000)\).求包含所有颜色的最小区间. 思路: 尺取法裸题. 思路: # ...
- 一个label两种颜色,一个label两种字体
-(void)addLabel{ UILabel *label = [[UILabel alloc]init]; label.backgroundColor = [UIColor grayColor] ...
- Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) E. DNA Evolution 树状数组
E. DNA Evolution 题目连接: http://codeforces.com/contest/828/problem/E Description Everyone knows that D ...
- 201771010134杨其菊《面向对象程序设计java》第八周学习总结
第八周学习总结 第一部分:理论知识 一.接口.lambda和内部类: Comparator与comparable接口: 1.comparable接口的方法是compareTo,只有一个参数:comp ...
- __c语言__结构体、共用体、枚举__笔记
2017-09-16 21:14:09 结构体,共用体,枚举 1.结构体 把不同的类型整合成一个有机的整体,以便于引用,这个类型就叫做结构体 1)结构体变量的定义方式(3种)和引用成员变量: 定义一个 ...
- 咏南WEB APP开发框架
咏南WEB APP开发框架 咏南WEB桌面框架演示:47.106.93.126:9999 咏南WEB手机框架本地:47.106.93.126:8077 咏南CS框架下载:https://pan.bai ...
- 用SublimeText当Unity Shader的编辑器
用Visual Studio写shader实在蛋疼,那可能就会有人要问了,为啥不用插件可视化制作shader呢?因为我是新手,新手还是老老实实敲代码,慢慢来- 所以试着在网上找找,有没有类似的插件或者 ...
- eclipse实现代码块折叠-类似于VS中的#region……#endregion
背 景 刚才在写代码的时候,写了十几行可以说是重复的代码: 如果整个方法或类中代码多了,感觉它们太TM占地方了,给读者在阅读代码上造成很大的困难,于是想到能不能把他们“浓缩”成一行,脑子里第一个闪现出 ...