c# - HLSL/XNA 环境光纹理与多 channel 照明混合

标签 c# models xna-4.0 hlsl light

最近我在照明方面遇到了一些麻烦。我在谷歌上找到了一个在这个例子中运行得很好的来源。然而,当我尝试将它实现到我当前的项目时,我遇到了一些非常奇怪的错误。主要的一个是,当我只激活环境光时,我的纹理会“混合”,这意味着一个模型会获取另一个模型的纹理 you can see it there .

我对模型的每个网格使用相同的效果。我想这可能是问题所在,但我真的不知道如何“重置”新模型的效果。可能吗?

这是我的着色器:

float4x4 WVP;

float4x4 WVP;
float3x3 World;

float3 Ke;
float3 Ka;
float3 Kd;
float3 Ks;
float specularPower;

float3 globalAmbient;
float3 lightColor;

float3 eyePosition;
float3 lightDirection;
float3 lightPosition;
float spotPower;

texture2D Texture;
sampler2D texSampler = sampler_state
{
    Texture = <Texture>;
    MinFilter = anisotropic;
    MagFilter = anisotropic;
    MipFilter = linear;
    MaxAnisotropy = 16;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 Texture  : TEXCOORD0;
    float3 Normal   : NORMAL0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 Texture  : TEXCOORD0;
    float3 PositionO: TEXCOORD1;
    float3 Normal   : NORMAL0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    output.Position = mul(input.Position, WVP);

    output.Normal = input.Normal;

    output.PositionO = input.Position.xyz;

    output.Texture = input.Texture;

    return output;
}

float4 PSAmbient(VertexShaderOutput input) : COLOR0
{
    return float4(Ka*globalAmbient + Ke,1) * tex2D(texSampler,input.Texture);
}

float4 PSDirectionalLight(VertexShaderOutput input) : COLOR0
{
    //Difuze
    float3 L = normalize(-lightDirection);
    float diffuseLight = max(dot(input.Normal,L), 0);
    float3 diffuse = Kd*lightColor*diffuseLight;

    //Specular
    float3 V = normalize(eyePosition - input.PositionO);
    float3 H = normalize(L + V);
    float specularLight = pow(max(dot(input.Normal,H),0),specularPower);
    if(diffuseLight<=0) specularLight=0;
    float3 specular = Ks * lightColor * specularLight;

    //sum all light components
    float3 light = diffuse + specular;

    return float4(light,1) * tex2D(texSampler,input.Texture);
}

technique MultiPassLight
{
    pass Ambient
    {
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader = compile ps_3_0 PSAmbient();
    }
    pass Directional
    {
        PixelShader = compile ps_3_0 PSDirectionalLight();
    }
}

这是我实际应用效果的方法:

public void ApplyLights(ModelMesh mesh, Matrix world, 
    Texture2D modelTexture, Camera camera, Effect effect, 
    GraphicsDevice graphicsDevice)
{
    graphicsDevice.BlendState = BlendState.Opaque;

    effect.CurrentTechnique.Passes["Ambient"].Apply();

    foreach (ModelMeshPart part in mesh.MeshParts)
    {
        graphicsDevice.SetVertexBuffer(part.VertexBuffer);
        graphicsDevice.Indices = part.IndexBuffer;

        // Texturing
        graphicsDevice.BlendState = BlendState.AlphaBlend;
        if (modelTexture != null)
        {
            effect.Parameters["Texture"].SetValue(
                modelTexture
            );
        }

        graphicsDevice.DrawIndexedPrimitives(
            PrimitiveType.TriangleList,
            part.VertexOffset,
            0,
            part.NumVertices,
            part.StartIndex,
            part.PrimitiveCount
        );

        // Applying our shader to all the mesh parts
        effect.Parameters["WVP"].SetValue(
            world *
            camera.View *
            camera.Projection
        );
        effect.Parameters["World"].SetValue(world);
        effect.Parameters["eyePosition"].SetValue(
            camera.Position
        );


        graphicsDevice.BlendState = BlendState.Additive;

        // Drawing lights
        foreach (DirectionalLight light in DirectionalLights)
        {
            effect.Parameters["lightColor"].SetValue(light.Color.ToVector3());
            effect.Parameters["lightDirection"].SetValue(light.Direction);

            // Applying changes and drawing them
            effect.CurrentTechnique.Passes["Directional"].Apply();
            graphicsDevice.DrawIndexedPrimitives(
                PrimitiveType.TriangleList, 
                part.VertexOffset, 
                0, 
                part.NumVertices, 
                part.StartIndex, 
                part.PrimitiveCount
            ); 
        }
    }

我在加载效果时也应用了这个:

effect.Parameters["lightColor"].SetValue(Color.White.ToVector3());
effect.Parameters["globalAmbient"].SetValue(Color.White.ToVector3());
effect.Parameters["Ke"].SetValue(0.0f);
effect.Parameters["Ka"].SetValue(0.01f);
effect.Parameters["Kd"].SetValue(1.0f);
effect.Parameters["Ks"].SetValue(0.3f);
effect.Parameters["specularPower"].SetValue(100);

非常感谢

更新: 我尝试在绘图时为每个模型加载一个效果,但它似乎没有改变任何东西。我想这是因为 XNA 检测到该效果之前已经加载过,并且不想加载新的效果。知道为什么吗?

最佳答案

好吧,这个问题实际上非常愚蠢。我对每个网格应用了相同的效果。我只是在加载模型时添加了 Effect.Clone() 并且它起作用了!

关于c# - HLSL/XNA 环境光纹理与多 channel 照明混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19471507/

相关文章:

c# - XNA for WP7 和多点触控每帧更新

c# - 在 Xna/MonoGame 中按程序生成 Texture2D

c# - 如何使流体阻力方程不依赖于帧速率

c# - 通过套接字发送和接收图像

有很多模型的 wpf 3d

ruby-on-rails - Memcached 作为 Rails 中的对象存储

python - 在 Tensorflow 中使用迁移学习训练 Mobilnet V2

c# - 我应该在每个等待的操作上调用 ConfigureAwait(false)

c# - 如何在字符串中只保留数字和一些特殊字符?

c# - ScreenCaptureJob 类的引用或程序集