簡體   English   中英

如何使用像素着色器從 Wavefront Obj 文件渲染材質?

[英]How to use pixel shader to render material from a Wavefront Obj file?

一些導出為 Wavefront .obj 格式的 3d 網格通常帶有一個 .mtl 文件,該文件具有附加數據到它使用的紋理及其材料,當從 Blender 導出時,它們總是帶有環境、漫反射、鏡面反射和自發光 RGB 數據作為它的一部分是材料,但我不確定如何在像素着色器中使用這些數據並獲得正確的顏色輸出。

如果有人能向我解釋如何使用這些材料,我將不勝感激,並且非常歡迎任何代碼示例。

傳統材料和照明模型使用“環境”、“漫反射”、“鏡面反射”和“自發光”顏色,這就是您在 Wavefront OBJ 文件中找到這些顏色的原因。 這些通常可以替換或與紋理顏色相乘結合使用。

(現已不存在的) XNA Game Studio產品在 BasicEffect “Stock Shaders”中提供簡單的“經典”着色器方面做得很好。 我在DirectX Tool Kit for DX11DX12 中使用它們。

查看BasicEffect.fx了解傳統材質像素着色器。 如果您主要尋找像素着色器處理,那就是“每像素照明”而不是“頂點照明”,當我們的 GPU 功能較弱時,后者更為常見。

這是一個“內聯”版本,因此您可以在一個地方關注所有內容:

struct VSInputNmTx
{
    float4 Position : SV_Position;
    float3 Normal   : NORMAL;
    float2 TexCoord : TEXCOORD0;
};

Texture2D<float4> Texture : register(t0);
sampler Sampler : register(s0);

cbuffer Parameters : register(b0)
{
    float4 DiffuseColor             : packoffset(c0);
    float3 EmissiveColor            : packoffset(c1);
    float3 SpecularColor            : packoffset(c2);
    float  SpecularPower            : packoffset(c2.w);

    float3 LightDirection[3]        : packoffset(c3);
    float3 LightDiffuseColor[3]     : packoffset(c6);
    float3 LightSpecularColor[3]    : packoffset(c9);

    float3 EyePosition              : packoffset(c12);

    float3 FogColor                 : packoffset(c13);
    float4 FogVector                : packoffset(c14);

    float4x4 World                  : packoffset(c15);
    float3x3 WorldInverseTranspose  : packoffset(c19);
    float4x4 WorldViewProj          : packoffset(c22);
};

struct VSOutputPixelLightingTx
{
    float2 TexCoord   : TEXCOORD0;
    float4 PositionWS : TEXCOORD1;
    float3 NormalWS   : TEXCOORD2;
    float4 Diffuse    : COLOR0;
    float4 PositionPS : SV_Position;
};

// Vertex shader: pixel lighting + texture.
VSOutputPixelLighting VSBasicPixelLightingTx(VSInputNmTx vin)
{
    VSOutputPixelLighting vout;

    vout.PositionPS = mul(vin.Position, WorldViewProj);

    vout.PositionWS.xyz = mul(vin.Position, World).xyz;

    // ComputeFogFactor
    vout.PositionWS.w = saturate(dot(vin.Position, FogVector));

    vout.NormalWS = normalize(mul(vin.Normal, WorldInverseTranspose));

    vout.Diffuse = float4(1, 1, 1, DiffuseColor.a);

    vut.TexCoord = vin.TexCoord;

    return vout;
}

struct PSInputPixelLightingTx
{
    float2 TexCoord   : TEXCOORD0;
    float4 PositionWS : TEXCOORD1;
    float3 NormalWS   : TEXCOORD2;
    float4 Diffuse    : COLOR0;
};

// Pixel shader: pixel lighting + texture.
float4 PSBasicPixelLightingTx(PSInputPixelLightingTx pin) : SV_Target0
{
    float4 color = Texture.Sample(Sampler, pin.TexCoord) * pin.Diffuse;

    float3 eyeVector = normalize(EyePosition - pin.PositionWS.xyz);

    float3 worldNormal = normalize(pin.NormalWS);

    ColorPair lightResult = ComputeLights(eyeVector, worldNormal, 3);

    color.rgb *= lightResult.Diffuse;

    // AddSpecular
    color.rgb += lightResult.Specular * color.a;

    // ApplyFog (we passed fogfactor in via PositionWS.w)
    color.rgb =  lerp(color.rgb, FogColor * color.a, pin.PositionWS.w);

    return color;
}

這是輔助函數ComputeLights ,它為鏡面高光實現了Blinn-Phong反射模型。

struct ColorPair
{
    float3 Diffuse;
    float3 Specular;
};


ColorPair ComputeLights(float3 eyeVector, float3 worldNormal, uniform int numLights)
{
    float3x3 lightDirections = 0;
    float3x3 lightDiffuse = 0;
    float3x3 lightSpecular = 0;
    float3x3 halfVectors = 0;
    
    [unroll]
    for (int i = 0; i < numLights; i++)
    {
        lightDirections[i] = LightDirection[i];
        lightDiffuse[i]    = LightDiffuseColor[i];
        lightSpecular[i]   = LightSpecularColor[i];
        
        halfVectors[i] = normalize(eyeVector - lightDirections[i]);
    }

    float3 dotL = mul(-lightDirections, worldNormal);
    float3 dotH = mul(halfVectors, worldNormal);
    
    float3 zeroL = step(0, dotL);

    float3 diffuse  = zeroL * dotL;
    float3 specular = pow(max(dotH, 0) * zeroL, SpecularPower) * dotL;

    ColorPair result;
    
    result.Diffuse  = mul(diffuse,  lightDiffuse)  * DiffuseColor.rgb + EmissiveColor;
    result.Specular = mul(specular, lightSpecular) * SpecularColor;

    return result;
}

這些 BasicEffect 着色器不使用環境色,但您可以根據需要對其進行修改。 所有環境顏色都提供了一個獨立於動態燈光的“最小顏色值”。

請注意,某些 Wavefront OBJ 文件中還有一些非官方的基於物理的渲染 (PBR) 材料擴展。 請參閱擴展基於物理的波前 MTL

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM