Direct3D纹理映射

2023-09-12 11:33:51

借助纹理映射技术,我们可将图像数据映射到三角形单元中,这种功能可以显著地增加所绘制场景的细节和真实感,例如创建一个立方体然后为其每个面映射一个板条纹理,从而将该立方体变为一个板条箱,在Direct3D中纹理用接口IDirect3DTexture9来表示,纹理是类似于表面的一个像素矩阵,与表面不同的是它可被映射到三角形单元中。

纹理坐标

Direct3D锁使用的纹理坐标系由沿水平方向的u轴和沿垂直方向的v轴构成,用坐标对(u,v)标识的纹理元素称为纹理元,注意v轴的正方向是竖直向下的

为了能够处理不同尺度的纹理,Direct3D将纹理坐标做了规范化处理,使之限定在区间[0,1]内,对于每个3D三角形单元,我们都可以在纹理中定义一个相应的三角形区域,然后将该三角形区域内的纹理映射到该3D三角形单元中,为了实现该映射,需要再次修改顶点结构,为之添加一个纹理坐标对以标识纹理中的顶点

struct TextureVertex
{
	TextureVertex(){}
	TextureVertex()
	{

	}
	float _x, _y, _z;
	float _nx, _ny, _nz;
	float _u, _v;			//纹理坐标
	static const DWORD FVF;
};
const DWORD TextureVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; //D3DFVF_TEX1表示顶点结构中包含了一对纹理坐标

现在由3个顶点对象构成的每个三角形都在该纹理坐标系中定义了一个相应的纹理三角形,虽然指定了,但直到光栅化时,即该3D三角形已被变换至屏幕坐标系时,纹理映射才会进行

创建并启用纹理

纹理数据通常从磁盘中的图像文件读入,然后再加载到IDirect3DTexture9对象中,可使用D3DXCreateTextureFromFile函数来实现,该函数可以加载下列格式的图像:BMP、DDS、DIB、JPG、PNG和TGA

HRESULT D3DXCreateTextureFromFile(
	LPDIRECT3DDEVICE9         pDevice,
	LPCSTR                    pSrcFile,
	LPDIRECT3DTEXTURE9*       ppTexture
);
IDirect3DTexture9* _stonewall;
D3DXCreateTextureFromFile(Device, "stonewall.bmp", &_stonewall);

HRESULT IDirect3DDevice9::SetTexture(
	DWORD Stage,	//纹理层
	IDirect3DBaseTexture9* pTexture
);

//禁用某一纹理层,可将pTexture参数设为0,绘制物体时若不想使用纹理可以这样做
Device->SetTexture(0, 0);
renderObjectWithoutTexture();

//如果场景中的各个三角形所使用的纹理均不相同
Device->SetTexture(0, tex0);
drawTrisUsingTex0();

Device->SetTexture(0, tex1);
drawTrisUsingTex1();

在Direct3D中,最多可设置8层纹理,可以对这些纹理进行组合以创建一幅更细致的图像,这称为多重纹理

纹理过滤器

通常纹理三角形与屏幕三角形的的大小并不一致,当纹理三角形与屏幕三角形大小不一致时,为适应后者,纹理三角形需要被放大或者缩小,这俩种情况都有畸变发生,为了从某种程度克服这类畸变,Direct采用了一项称为纹理过滤的技术。

Direct3D提供了3种类型的纹理过滤器,过滤器的质量越高,运算开销越大,处理速度越慢。纹理过滤方式可用方法SetSamplerState来设置。

最近点采样:Direct3D默认使用的过滤方式,该方式的处理速度最快,但效果最差,下面代码分别表示将最近点采样方式设置为放大过滤器和缩小过滤器

线性纹理过滤器:该类型的过滤方式可以产生相当好的结果,而且以目前的硬件配置水平也可获得较快的处理速度

各向异性纹理过滤:该类型的过滤方式可以产生最好的结果,但是处理速度也是最慢的,使用该过滤时,必须对D3DSAMP_MAXANISOTROPIC水平值进行设定,该值决定了各向异性过滤的质量水平。该值越大图像效果越好,请调用IDirect3DDevice::GetDeviceCaps函数检查返回的D3DCAPS9结构参数,以获得硬件支持的值的合法取值范围。

//设置最近点采样纹理过滤
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);

//设置线性纹理过滤
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

//设置各向异性纹理过滤
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);

//将各向异性过滤的质量水平设置为4
Device->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);

多级渐进纹理

屏幕上的三角形通常与纹理三角形大小不一致,为了尽量消除由二者尺寸差异带来的影响,我们可为纹理创建一个多级渐进纹理链,方法是由某一个纹理创建一系列分辨率逐渐减小的纹理图像并且每种分辨率下的纹理所采用的过滤房还是进行定制,以便保留那些较重要的细节,在Direct3D中使用多级渐进纹理十分容易,如果硬件支持多级渐进纹理D3DXCreateTextureFromFile函数将创建一个多级渐进纹理链,此外Direct3D还将自动从纹理链中选择与屏幕三角形最匹配的那个一级纹理,所以由于可被Direct3D自动设置,而且处理时的时间和空间代价都比较低,多级渐进纹理得到了广泛应用。

多级渐进纹理过滤器

多级渐进纹理过滤器主要用于控制Direct3D使用多级渐进纹理的方式,可这样对多级渐进纹理过滤器进行如下设置

Device->SetSamplerState(0, D3DSAMP_MIPFILTER, Filter);

Filter可取以下值

D3DTEXF_NONE:禁用多级渐进纹理过滤器
D3DTEXF_POINT:通过使用该过滤器,Direct3D将选择尺寸与屏幕三角形最接近的那一级纹理,一旦选择了某一级纹理,Direct3D就会用指定的放大过滤器和缩小过滤器对该级纹理进行过滤
D3DTEXF_LINEAR:通过使用该过滤器,Direct3D将取与屏幕三角形尺寸最接近的俩个纹理级,用指定的放大过滤器和缩小过滤器对每级纹理进行过滤,然后再将这俩级纹理进行线性组合,从而形成最终的颜色值。

寻址模式

前面部分中,我们说过纹理坐标必须限制在区间[0,1]内,从技术角度讲是有问题的,因为有时坐标可能超出该范围,Direct3D定义了4种用来处理纹理坐标值超出[0,1]区间的纹理映射模式。分别是重复寻址模式(wrap)、边界颜色寻址模式(border color)、箝位寻址模式(clamp)、镜像寻址模式(mirror)。

//set wrap address mode
if (::GetAsyncKeyState('W') & 0x8000f)
{
	//表示对纹理的u方向或v方向设置纹理寻址模式
	Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); 
	//D3DTADDRESS_CLAMP、D3DTADDRESS_MIRROR
}

//set border color address mode
if (::GetAsyncKeyState('B') & 0x8000f)
{
	//表示对纹理的u方向或v方向设置纹理寻址模式
	Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
	Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
	Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x000000ff);
}

纹理四边形例程

1.构造组成物体的顶点,并为其指定纹理坐标
2.用函数D3DXCreateTextureFromFile为IDirect3DTexture9接口加载一种纹理
3.设置缩小/放大过滤器、和多级渐进纹理过滤器
4.绘制物体前,用函数IDirect3DDevice9::SetTexture来设定与该物体关联的纹理

bool SetUpTextureQuad()
{
	Device->CreateVertexBuffer(6 * sizeof(TextureVertex), D3DUSAGE_WRITEONLY, TextureVertex::FVF, D3DPOOL_MANAGED, &Quad, 0);
	TextureVertex* v;
	Quad->Lock(0, 0, (void**)&v, 0);
	v[0] = TextureVertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
	v[1] = TextureVertex(-1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[2] = TextureVertex(1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);

	v[3] = TextureVertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
	v[4] = TextureVertex(1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);
	v[5] = TextureVertex(1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 3.0f);
	Quad->Unlock();
	
	D3DXCreateTextureFromFile(Device, "dx5_logo.bmp", &Tex);
	//启用纹理
	Device->SetTexture(0, Tex);
	//设置放大/缩小过滤器
	Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	//设置渐进纹理过滤器
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

	//不使用光照
	Device->SetRenderState(D3DRS_LIGHTING, false);

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f, (float)Width / (float)Height, 1.0f, 1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);
	return true;
}

bool DisplayTextureQuad(float timeDelta)
{
	if (Device)
	{
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();
		Device->SetStreamSource(0, Quad, 0, sizeof(TextureVertex));
		Device->SetFVF(TextureVertex::FVF);
		Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}
更多推荐

设计模式七大原则

设计模式七大原则什么是设计模式呢?简单理解就是我们在开发软件的期间面临着各种各样的问题,对这种普遍存在(反复出现)的问题提出的解决方案。设计模式分为三种类型,共23种1)创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式。2)结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理

微服务: xxl-job的安装(docker),使用及springboot整合[完整版详解]

全文目录,一篇结束1.前言简介1.1xxl-job的作用及优势1.1.1xxl-job作用1.1.2xxl-job优势1.2资源位置及使用说明1.2.1文档说明1.2.2docker镜像位置2.安装配置使用xxl-job(两种)2.0公共操作:sql脚本(2.2免下载也用)2.1方法一:源码搭建方式2.1.1源码下载位

华为云云耀云服务器L实例评测|Python Selenium加Chrome Driver构建UI自动化测试实践

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。🏆数年电商行业从业经验,AWS/阿里云资深使用用户,历任核心研发工程师,项目技术负责人。🎉欢迎👍点赞✍评论⭐收藏文章目录🚀一、前言🚀二、Chrome浏览器环境搭建🔎

网络安全(黑客)自学

自学网络安全必须注意的问题:(1)打好基础初学者一定要注意打好基础,我之所以只学了6个月就能拿到12K的薪资,就是因为我基础牢固。其实一个初学者在开始的时候能培养出好的基础很难,这源于在整个学习过程中有大佬带我的原因。(2)交流沟通切记不要认为自己可以摸索自学成功,能达到一定高度的水平,一定离不开很多专业人的指导,所以

计算机竞赛 机器视觉目标检测 - opencv 深度学习

文章目录0前言2目标检测概念3目标分类、定位、检测示例4传统目标检测5两类目标检测算法5.1相关研究5.1.1选择性搜索5.1.2OverFeat5.2基于区域提名的方法5.2.1R-CNN5.2.2SPP-net5.2.3FastR-CNN5.3端到端的方法YOLOSSD6人体检测结果7最后0前言🔥优质竞赛项目系列

POLARDB IMCI 白皮书 云原生HTAP 数据库系统 一 数据压缩打更新 (本篇有数据到列节点异步但不延迟的解释)...

开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系liuaustin3,在新加的朋友会分到2群(共1300人左右1+2+3+4)3群即将突破400会关闭自由申请,新人会进4群这

计算机视觉与深度学习-全连接神经网络-激活函数- [北邮鲁鹏]

文章目录基础知识为什么需要非线性操作(激活函数)?激活函数vs数据预处理常用的激活函数Sigmoid函数(Logistic函数)双曲正切函数(Tanh函数)线性整流函数(ReLU函数)LeakyReLU函数Softmax函数基础知识激活函数是神经网络中的一种非线性函数,它作为神经元的输出函数,将输入信号进行转换并引入非

x86架构基础汇编知识

​通用寄存器EAX32位函数返回值AX低16位AH高八位AL低八位EBX32位ECX32位循环次数,this指针EDX32位EBP32位栈底寄存器ESP32位栈顶寄存器ESI源索引寄存器EDI目标索引寄存器EIP无法直接通过汇编操作例子moval,0xffaddal,1产生截断moval,0xffaddax,1产生进位

【C# Programming】继承、接口

一、继承1、派生继承在相似而又不同的概念之间建立了类层次概念。更一般的类称为基类,更具体的类称为派生类。派生类继承了基类的所有性质。定义派生类要在类标识符后面添加一个冒号,接着添加基类名。publicclassPdaItem{publicstringName{get;set;}publicDateTimeLastUpd

《计算机视觉中的多视图几何》笔记(2)

2ProjectiveGeometryandTransformationsof2D本章主要介绍本书必要的几何知识与符号。文章目录2ProjectiveGeometryandTransformationsof2D2.1Planargeometry2.2The2Dprojectiveplane2.2.1Pointsandl

无人机倾斜摄影测量技术标准及关键技术研究

无人机倾斜摄影测量技术在应用过程中,存在模型分辨率不一致、精度不可靠、格式不匹配的问题,但没有现行的标准对任务质量进行评价,这在一定程度上限制了无人机倾斜摄影测量技术进一步发展。《无人机航空摄影测量精品教程》:无人机航测外业作业流程(像控点布设、航线规划、仿地飞行、航拍)和内业数据处理软件(Pix4d、CC、EPS、P

热文推荐