DirectX 10 教程5:纹理

本教程详细介绍了如何在DirectX 10中使用纹理,包括Texel坐标系统、纹理坐标(UV)、以及如何在代码中实现纹理映射。通过创建和应用纹理,使得3D场景更加真实。教程提供了从加载纹理到绘制纹理的完整步骤,并给出了多个练习以加深理解。
摘要由CSDN通过智能技术生成

源代码下载:dx10tut05.zip

本教程介绍如何在DirectX 10中使用纹理。纹理通过在多边形表面施加一张图片让我们的场景变得更真实。本教程中使用的纹理如下图所示:

纹理

然后将这张纹理施加到上一个教程显示的三角形上,如下图所示:

施加了纹理的三角形

纹理的格式为.dds。它是DirectX 使用的Direct Draw Surface格式,生成.dds文件的工具位于DirectX SDK中,在DirectX Utilities文件夹中,叫做DirectX Texture Tool。你可以将图像粘贴到这个程序然后将它储存为.dds文件,使用起来非常简单。

在编写代码前我们需要讨论一下纹理映射的原理。要将.dds图形映射到像素我们用的是Texel坐标系统。这个系统将将整数值的像素变换到0.0f和1.0f之间的浮点数。例如,如果一张纹理宽为256个像素,那么第一个像素映射为0.0f,第256个像素映射为1.0f,中间的第128个像素映射为0.5f。

在texel坐标系统中,水平方向的值名为“U"”,垂直方向为“V”。水平方向左边为0.0,右边为1.0。竖直方向顶部为0.0,底部为1.0。例如,左上角为U 0.0、V 0.0,右下角为U 1.0、 V 1.0。下图就表示了纹理坐标系统:

纹理坐标

理解了纹理映射的基本概念后,让我们看一下更新后的框架:

更新后的框架

相对于上一个教程,框架的变化在于ModelClass下有了一个新的类TextureClass,TextureShaderClass取代了ColorShaderClass。

首先讨论新的HLSL纹理shader。

Texture.fx


// Filename: texture.fx

texture shader中的变量与上一教程的color.fx shader类似。在顶点着色器中仍有三个矩阵用于变换。新的变量是类型为Texture2D的shaderTexture,这就是纹理资源。本例中我们在ModelClass中加载了一个.dds纹理,然后将这个纹理链接到shader中的纹理资源。这样shader就可以访问这个纹理并用于绘制了。

/
// GLOBALS //
/
matrix worldMatrix;
matrix viewMatrix;
matrix projectionMatrix;
Texture2D shaderTexture;

Shader中的另一个新东西是采样状态。采样状态让我们可以调整像素写入到多边形的方式。例如,如果多边形离相机很远,在屏幕上只占8个像素,那么我们使用采样状态判断原始纹理中的哪些像素或像素的组合会实际显示在屏幕上,原始纹理可能是256像素×256 像素,因此决定哪些像素被绘制是非常重要的,它能让多边形上的纹理看起来仍是合适的。

///
// SAMPLE STATES //
///
SamplerState SampleType
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

本例中定义的采样状态只有三个元素,但都很重要。如果你想有更多的控制权,可以定义地更加详细。下面是DirectX中采样状态的描述:

//
// TYPEDEFS //
//
struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD0;
};
 
struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
};


最重要的元素是Filter。Filter决定哪些像素会被使用或进行组合创建最终的颜色。本例中我使用的是MIN_MAG_MIP_LINEAR,它需要耗费更多的资源但效果最好。它告诉采样器为缩小、放大和mip-level采样使用线性插值。本教程我不打算详细解释,你可以看一下MSDN上的D3D10_FILTER说明,看看产生不同效果的其他选项。AddressU和AddressV设置为Wrap确保纹理坐标位于0.0f和1.0f范围之内。

VertexInputType和PixelInputType需要修改,顶点着色器中不再使用颜色,取而代之的是纹理坐标。纹理坐标有U和V两个浮点数分量,因此类型为float2。TEXCOORD[N]语义让你可以定义纹理坐标的设置数字。本例中我们只使用一个纹理坐标,所以数字设为0,表示这是第一个也是唯一一个纹理坐标。



// Vertex Shader

PixelInputType TextureVertexShader(VertexInputType input)
{
    PixelInputType output;
     
     
    // Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;
 
    // Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
与上一个教程中color.fx的顶点着色器代码的唯一区别在于我们复制了纹理坐标而不是颜色。

    // Store the texture coordinates for the pixel shader.
    output.tex = input.tex;
     
    return output;
}

像素着色器也改变了。现在我们使用了sample方法,参数是前面定义的采样状态和输入的纹理坐标。处理之后返回从纹理中采样的像素进行绘制。


// Pixel Shader

float4 TexturePixelShader(PixelInputType input) : SV_Target
{
    float4 textureColor;
 
 
    // Sample the pixel color from the texture using the sampler at this texture coordinate location.
    textureColor = shaderTexture.Sample(SampleType, input.tex);
 
    return textureColor;
}

除了shader的名称,technique保持不变。

// Technique

technique10 TextureTechnique
{
    pass pass0
    {
        SetVertexShader(CompileShader(vs_4_0, TextureVertexShader()));
        SetPixelShader(CompileShader(ps_4_0, TexturePixelShader()));
        SetGeometryShader(NULL);
    }
}

Textureclass.h

TextureClass封装了加载、卸载和访问一个纹理资源的代码。每个纹理都需要这个类的实例化对象

// Filename: textureclass.h

#ifndef _TEXTURECLASS_H_
#define _TEXTURECLASS_H_
 
 
//
// INCLUDES //
//
#include <d3d10.h>
#include <d3dx10.h>
 
 

// Class name: TextureClass

class TextureClass
{
public:
    TextureClass();
    TextureClass(const TextureClass&);
    ~TextureClass();

第一个方法根据文件名加载纹理,第二个方法在纹理不使用后卸载纹理。
bool Initialize(ID3D10Device*, WCHAR*);
void Shutdown();

GetTexture返回一个指向纹理资源的指针,被shader使用。
    ID3D10ShaderResourceView* GetTexture();
 
private:

下面是私有的纹理资源变量。
    ID3D10ShaderResourceView* m_texture;
};
 
#endif

Textureclass.cpp


// Filename: textureclass.cpp

#include "textureclass.h"

构造函数中将纹理指针设置为null。
TextureClass::TextureClass()
{
    m_texture = 0;
}
 
 
TextureClass::TextureClass(const TextureClass& other)
{
}
 
 
TextureClass::~TextureClass()
{
}

Ini
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值