简体   繁体   English

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

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

Some 3d meshes that get exported to the Wavefront .obj format usually come with a .mtl file that has additional data to the texture it uses and it's materials, when exported from Blender they always come with Ambient, Diffuse, Specular and Emissive RGB data as part of it's material, but I'm not sure how I can use this data in the pixel shader and get the right color output.一些导出为 Wavefront .obj 格式的 3d 网格通常带有一个 .mtl 文件,该文件具有附加数据到它使用的纹理及其材料,当从 Blender 导出时,它们总是带有环境、漫反射、镜面反射和自发光 RGB 数据作为它的一部分是材料,但我不确定如何在像素着色器中使用这些数据并获得正确的颜色输出。

I would appreciate if anyone can explain to me how to use these materials and any code sample would be very welcome.如果有人能向我解释如何使用这些材料,我将不胜感激,并且非常欢迎任何代码示例。

Traditional materials and lighting models use "Ambient", "Diffuse", "Specular", and "Emissive" colors which is why you find those in Wavefront OBJ files.传统材料和照明模型使用“环境”、“漫反射”、“镜面反射”和“自发光”颜色,这就是您在 Wavefront OBJ 文件中找到这些颜色的原因。 These can often be replaced or used in multiplicative conjunction with texture colors.这些通常可以替换或与纹理颜色相乘结合使用。

The (now defunct) XNA Game Studio product did a good job of providing simple 'classic' shaders in the BasicEffect "Stock Shaders". (现已不存在的) XNA Game Studio产品在 BasicEffect “Stock Shaders”中提供简单的“经典”着色器方面做得很好。 I use them in the DirectX Tool Kit for DX11 and DX12 .我在DirectX Tool Kit for DX11DX12 中使用它们。

Take a look at BasicEffect.fx for a traditional material pixel shader.查看BasicEffect.fx了解传统材质像素着色器。 If you are looking mostly for pixel-shader handling, that's "per-pixel lighting" as opposed to "vertex lighting" which was more common back when we had less powerful GPUs.如果您主要寻找像素着色器处理,那就是“每像素照明”而不是“顶点照明”,当我们的 GPU 功能较弱时,后者更为常见。

Here's a 'inlined' version so you can follow it all in one place:这是一个“内联”版本,因此您可以在一个地方关注所有内容:

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;
}

Here is the helper function ComputeLights which implements a Blinn-Phong reflection model for the specular highlight.这是辅助函数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;
}

These BasicEffect shaders don't make use of ambient color, but you could modify them to do so if you wanted.这些 BasicEffect 着色器不使用环境色,但您可以根据需要对其进行修改。 All ambient color does is provide a 'minimum color value' that's independent of dynamic lights.所有环境颜色都提供了一个独立于动态灯光的“最小颜色值”。

Note that there also some unofficial Physically-Based Rendering (PBR) materials extension in some Wavefront OBJ files.请注意,某些 Wavefront OBJ 文件中还有一些非官方的基于物理的渲染 (PBR) 材料扩展。 See Extending Wavefront MTL for Physically-Based请参阅扩展基于物理的波前 MTL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM