一、粗糙度貼圖的概念
粗糙度貼圖是一種用於增強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