粗糙度貼圖的多面向詳解

一、粗糙度貼圖的概念

粗糙度貼圖是一種用於增強3D模型表現力的技術,是指在建模過程中,通過在模型表面增加一層顏色或者灰度紋理貼圖,來模擬物體表面的微小凹凸不平,從而增加物體表面的細節和真實感。

常見的粗糙度貼圖包括:反射率貼圖、法線貼圖、置換貼圖、高光貼圖等。

二、粗糙度貼圖的種類和應用

1、反射率貼圖

反射率貼圖用於影響物體表面的反射度,比如鏡面反射。

下面是一段實現反射率貼圖的代碼示例:

float4 ReflectanceMapPS(PSInput input) : SV_Target
{
    float4 diffuse = texDiffuse.Sample(ss, input.TexCoord);
    float3 normal = texNormal.Sample(ss, input.TexCoord).rgb * 2 - 1;
    float3 specular = pow(max(dot(normal, eyeVector), 0), shininess) * texSpecular.Sample(ss, input.TexCoord).rgb;

    return float4((diffuse.rgb + emissive.rgb) * ambient.rgb + diffuse.rgb * lightColor.rgb + specular * lightColor.rgb, texDiffuse.Sample(ss, input.TexCoord).a);
}

2、法線貼圖

法線貼圖是一種用來模擬3D模型表面細節的技術,通過在模型表面以紋理的方式存儲法線向量,來增強物體表面的細節感。

下面是一段實現法線貼圖的代碼示例:

float3 NormalMapPS(PSInput input) : SV_Target
{
    float3 normal = texNormal.Sample(ss, input.TexCoord).rgb * 2 - 1;
    float3 tangent = normalize(tangentVector - input.WorldNormal * dot(tangentVector, input.WorldNormal));
    float3 bitangent = cross(input.WorldNormal, tangent) * tangent.w;

    float3x3 tbn = float3x3(tangent, bitangent, input.WorldNormal);
    normal = normalize(mul(normal, tbn));

    return normal * 0.5f + 0.5f;
}

3、置換貼圖

置換貼圖是一種用於模擬物體表面幾何細節的技術,通過將幾何信息存儲在紋理中,並在運行時將幾何信息應用到模型中,增加模型表面的凹凸感。

下面是一段實現置換貼圖的代碼示例:

float4 DisplacementMapPS(PSInput input) : SV_Target
{
    float4 pos = mul(float4(input.WorldPos, 1), viewProj);
    pos /= pos.w;

    float3 normal = texNormal.Sample(ss, input.TexCoord).rgb * 2 - 1;
    float height = texHeight.Sample(ss, input.TexCoord).r;
    float3x3 tbn = float3x3(input.WorldTangent, input.WorldBinormal, input.WorldNormal);

    float4 offset = float4(normal * height * displacementScale, 0);
    offset = mul(offset, tbn);

    pos.xyz += offset.xyz;

    return texDiffuse.Sample(ss, input.TexCoord);
}

4、高光貼圖

高光貼圖用於模擬3D模型表面的高亮反射,增加物體表面的反射感。

下面是一段實現高光貼圖的代碼示例:

float4 SpecularMapPS(PSInput input) : SV_Target
{
    float3 normal = texNormal.Sample(ss, input.TexCoord).rgb * 2 - 1;
    float3 reflection = normalize(reflect(-lightVector, normal));
    float specular = pow(saturate(dot(reflection, eyeVector)), shininess) * texSpecular.Sample(ss, input.TexCoord).r;

    return float4(specular, specular, specular, 1);
}

三、粗糙度貼圖的優化

1、壓縮紋理

在使用粗糙度貼圖的時候,可以採用壓縮紋理的方式來減小紋理資源的體積,從而節省顯存和提高載入速度。

下面是一段實現壓縮紋理的代碼示例:

D3DX11CreateTextureFromFile(device, L"texture.dds", NULL, NULL, &texture, NULL);
D3DX11CreateShaderResourceViewFromFile(device, L"texture.dds", NULL, NULL, &textureSRV, NULL);

2、使用MipMaps

MipMaps可以用來處理粗糙度貼圖的採樣問題,在遠處使用低解析度的MipMap,近處使用高解析度的MipMap,從而避免了遠處紋理變得模糊,近處紋理變得失真的問題。

下面是一段使用MipMaps的代碼示例:

D3DX11CreateTextureFromFile(device, L"texture.dds", NULL, NULL, &texture, NULL);
D3DX11CreateShaderResourceViewFromFile(device, L"texture.dds", NULL, NULL, &textureSRV, NULL);

D3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

device->CreateSamplerState(&samplerDesc, &samplerState);

context->PSSetSamplers(0, 1, &samplerState);

3、使用紋理陣列

紋理陣列可以用來存儲多個紋理,在頂點/像素著色器中使用數組下標進行訪問,從而避免了頻繁地在GPU和CPU之間切換紋理。此外,紋理陣列還可以用於實現環境貼圖等效果。

下面是一段實現紋理陣列的代碼示例:

D3DX11CreateTextureFromFile(device, L"textureArray.dds", NULL, NULL, &textureArray, NULL);
D3DX11CreateShaderResourceViewFromFile(device, L"textureArray.dds", NULL, NULL, &textureArraySRV, NULL);

context->PSSetShaderResources(0, 1, &textureArraySRV);

4、使用GPU實現採樣

使用GPU實現紋理採樣可以避免在CPU和GPU之間頻繁地拷貝紋理數據,從而提高渲染效率。

下面是一段使用GPU實現紋理採樣的代碼示例:

Texture2D tex : register(t0);
SamplerState samp : register(s0);

cbuffer ConstantBuffer : register(b0)
{
    float4x4 worldViewProj;
};

struct VS_INPUT
{
    float3 pos : POSITION;
    float3 norm : NORMAL;
    float2 texCoord : TEXCOORD;
};

struct PS_INPUT
{
    float4 pos : SV_POSITION;
    float3 norm : NORMAL;
    float2 texCoord : TEXCOORD;
};

PS_INPUT main(VS_INPUT input)
{
    PS_INPUT output;
    output.pos = mul(worldViewProj, float4(input.pos, 1.0f));
    output.norm = input.norm;
    output.texCoord = input.texCoord;

    return output;
}

float4 main(PS_INPUT input) : SV_TARGET
{
    return tex.Sample(samp, input.texCoord);
}

四、結語

粗糙度貼圖是一項非常重要的技術,可以大大增強3D模型的表現力,讓模型更真實、更細緻。希望通過這篇文章的介紹,能夠對粗糙度貼圖技術有更深入的了解,同時也希望大家在實際的開發中能夠充分應用這項技術,為遊戲的畫面質量提升做出自己的貢獻。

原創文章,作者:NNZG,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/136035.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
NNZG的頭像NNZG
上一篇 2024-10-04 00:15
下一篇 2024-10-04 00:15

相關推薦

  • Python定義兩個列表的多面探索

    Python是一種強大的編程語言,開放源代碼,易於學習和使用。通過Python語言,我們可以定義各種數據類型,如列表(list)。在Python中,列表(list)在處理數據方面起…

    編程 2025-04-29
  • Python中中括弧里數字的多面

    本文將從多個方面對Python中中括弧里數字做詳細的闡述,包括索引、切片、循環等,以及一些常見問題的解決方法。 一、索引操作 索引操作指的是通過中括弧里的數字來訪問列表(list)…

    編程 2025-04-28
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變數讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分散式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25

發表回復

登錄後才能評論