0

我正在使用 C#/XNA 4.0 制作游戏。

所以我有一个用 3DSMax 制作的简单盒子

http://i.imgur.com/gd65sTx.png

我缩放它

Vector3 scaleVector = new Vector3(width, 1, height); 
Matrix newMatrix = scale * translationMatrix; 

结果如下:

http://i.imgur.com/YNAIr8y.png

这是我的渲染方法:

    /// <summary>
    /// Draws an objects with the specified texture. This DOES change the current textures, so be careful!
    /// </summary>
    public static void DrawModel(GraphicsDevice gd, Model model,
        RenderTechnique technique, Vector3 cameraPosition,
        Matrix world, Matrix viewProjection, LightList lights, Texture2D texture)
    {
        SetTexture(texture, model);
        DrawModel(gd, model, technique, cameraPosition, world, viewProjection, lights);
    }

    /// <summary>
    /// Sets a texture for a model by changing the effect parameters
    /// </summary>
    public static void SetTexture(Texture2D texture, Model model)
    {
        // for each mesh in model
        foreach (ModelMesh mesh in model.Meshes)
        {
            // for each mesh part
            foreach (ModelMeshPart meshPart in mesh.MeshParts)
            {
                // if primitives to change
                if (meshPart.PrimitiveCount > 0)
                {
                    // set texture visa effect
                    Effect effect = meshPart.Effect;
                    effect.Parameters["Texture"].SetValue(texture);
                }

            }
        }
    }

    /// <summary>
    /// Main Draw method. All draw calls end up here eventually.
    /// </summary>
    public static void DrawModel(GraphicsDevice gd, Model model,
        RenderTechnique technique, Vector3 cameraPosition,
        Matrix world, Matrix viewProjection, LightList lights)
    {
        if (gd == null)
        {
            throw new ArgumentNullException("gd");
        }

        // get model bones
        model.CopyAbsoluteBoneTransformsTo(bones);

        BlendState bs = gd.BlendState;
        DepthStencilState ds = gd.DepthStencilState;

        gd.DepthStencilState = DepthStencilState.DepthRead;
        gd.BlendState = BlendState.Additive;


        // for each mesh in model
        foreach (ModelMesh mesh in model.Meshes)
        {
            // get mesh world matrix
            Matrix worldBone = bones[mesh.ParentBone.Index] * world;
            Matrix worldBoneInverse = Matrix.Invert(worldBone);

            // compute camera position in object space
            Vector3 cameraObjectSpace = cameraPosition - worldBone.Translation;
            cameraObjectSpace = Vector3.TransformNormal(cameraObjectSpace,
                                                    worldBoneInverse);

            gd.SamplerStates[0] = SamplerState.LinearWrap;

            // for each mesh part
            foreach (ModelMeshPart meshPart in mesh.MeshParts)
            {
                // if primitives to render
                if (meshPart.PrimitiveCount > 0)
                {
                    // setup vertices and indices
                    gd.SetVertexBuffer(meshPart.VertexBuffer);
                    gd.Indices = meshPart.IndexBuffer;

                    // setup effect
                    Effect effect = meshPart.Effect;
                    effect.Parameters["WorldViewProj"].SetValue(worldBone * viewProjection);
                    effect.Parameters["CameraPosition"].SetValue(cameraObjectSpace);

                    // setup technique
                    effect.CurrentTechnique =
                        meshPart.Effect.Techniques[(int)technique];


                    // if not lights specified
                    if (lights == null)
                    {
                        // begin effect
                        effect.CurrentTechnique.Passes[0].Apply();
                        // draw with plain mapping
                        gd.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                            meshPart.VertexOffset, 0, meshPart.NumVertices,
                            meshPart.StartIndex, meshPart.PrimitiveCount);
                        gd.SetVertexBuffer(null);
                        gd.Indices = null;
                    }
                    else
                    {
                        gd.DepthStencilState = DepthStencilState.Default;
                        gd.BlendState = BlendState.Opaque;

                        // get light effect parameters
                        EffectParameter effectLightPosition =
                                            effect.Parameters[1];
                        EffectParameter effectLightColor =
                                            effect.Parameters[2];
                        EffectParameter effectLightAmbient =
                                            effect.Parameters[3];

                        // ambient light
                        Vector3 ambient = lights.ambient;

                        // for each light
                        foreach (Light light in lights.lights)
                        {
                            // setup light in effect
                            effectLightAmbient.SetValue(ambient);
                            light.SetEffect(effectLightPosition,
                                effectLightColor, worldBoneInverse);

                            // begin effect
                            effect.CurrentTechnique.Passes[0].Apply();
                            // draw primitives
                            gd.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                                meshPart.VertexOffset, 0, meshPart.NumVertices,
                                meshPart.StartIndex, meshPart.PrimitiveCount);

                            // setup additive blending with no depth write
                            gd.DepthStencilState = DepthStencilState.DepthRead;
                            gd.BlendState = BlendState.Additive;

                            // clear ambinet light (applied in first pass only)
                            ambient = Vector3.Zero;
                        }

                        // clear vertices and indices
                        gd.SetVertexBuffer(null);
                        gd.Indices = null;

                    }

                }
            }
        }
        gd.DepthStencilState = ds;
        gd.BlendState = bs;
    }

这是我正在使用的着色器:

float4x4 WorldViewProj;
float4 LightPosition;
float3 LightColor;
float3 LightAmbient;
float3 CameraPosition;

texture2D Texture;
sampler2D TextureSampler = sampler_state
{
    Texture = <Texture>;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = linear;
};
sampler2D TextureSamplerClamp = sampler_state
{
    Texture = <Texture>;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = linear;
    AddressU = clamp;
    AddressV = clamp;
};

texture2D Bump0;
sampler2D NormalSampler = sampler_state
{
    Texture = <Bump0>;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = linear;
};

texture2D Specular0;
sampler2D SpecularSampler = sampler_state
{
    Texture = <Specular0>;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = linear;
};

texture2D Emissive0;
sampler2D GlowMapSampler = sampler_state
{
    Texture = <Emissive0>;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = linear;
};

textureCUBE Reflect;
samplerCUBE ReflectSampler = sampler_state
{
    Texture = <Reflect>;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = linear;
    AddressU = clamp;
    AddressV = clamp;
    AddressW = clamp;
};

void PlainMappingVS( 
     in float4 InPosition    : POSITION0,
     in float2 InTexCoord    : TEXCOORD0,
    out float4 OutPosition    : POSITION0,
    out float2 OutTexCoord    : TEXCOORD0 )
{
    OutPosition = mul(InPosition, WorldViewProj);
    OutTexCoord = InTexCoord;
}

float4 PlainMappingPS( in float2 TexCoord : TEXCOORD0 ) : COLOR0
{
    return tex2D(TextureSampler, TexCoord);
}

void NormalMappingVS( 
     in float4 InPosition    : POSITION0,
     in float2 InTexCoord    : TEXCOORD0,
     in float3 InNormal      : NORMAL0,  
     in float3 InBinormal    : BINORMAL0,
     in float3 InTangent     : TANGENT0,
    out float4 OutPosition   : POSITION0,
    out float2 OutTexCoord   : TEXCOORD0,
    out float3 OutLightDir   : TEXCOORD1,
    out float3 OutViewDir    : TEXCOORD2,
    out float3 OutReflectDir : TEXCOORD3 )
{
    OutPosition = mul(InPosition, WorldViewProj);

    OutTexCoord = InTexCoord;

    float3x3 tangent_space = float3x3(InTangent, InBinormal, InNormal);

    OutLightDir = mul(tangent_space, LightPosition.xyz - InPosition.xyz);

    OutViewDir = mul(tangent_space, CameraPosition - InPosition.xyz);

    OutReflectDir = reflect(InPosition.xyz - CameraPosition, InNormal);
}

float4 NormalMappingPS(
    in float2 TexCoord        : TEXCOORD0,
    in float3 LightDir        : TEXCOORD1,
    in float3 ViewDir         : TEXCOORD2,
    in float3 ReflectDir      : TEXCOORD3 ) : COLOR0
{
    float4 diffuse = tex2D(TextureSampler, TexCoord);
    float4 specular = tex2D(SpecularSampler, TexCoord);
    float4 normal = tex2D(NormalSampler, TexCoord);
    float3 reflect = texCUBE(ReflectSampler, ReflectDir);
    float4 glow = tex2D(GlowMapSampler, TexCoord);

    float3 n = normalize(normal.xyz - 0.5);
    float3 l = normalize(LightDir);
    float3 v = normalize(ViewDir);
    float3 h = normalize(l+v);

    float ndotl = saturate(dot(n,l));
    float ndoth = saturate(dot(n,h));
    if (ndotl == 0)    ndoth = 0;

    float3 ambient = LightAmbient * diffuse.xyz;

    specular.xyz *= LightColor * pow(ndoth, specular.w * 255);
    diffuse.xyz *= LightColor * ndotl;
    reflect *= 1 - normal.w;

    float glow_intensity = saturate(dot(glow.xyz, 1.0) + dot(specular.xyz, 1.0));

    float4 color;
    color.xyz = ambient + glow.xyz + diffuse.xyz + specular.xyz + reflect.xyz;
    color.w = glow_intensity;

    return color;
}

void ViewMappingVS( 
     in float4 InPosition   : POSITION0,
     in float3 InNormal     : NORMAL0,  
    out float4 OutPosition  : POSITION0,
    out float  OutFacing    : TEXCOORD0 )
{
    OutPosition = mul(InPosition, WorldViewProj);

    float3 view = normalize(CameraPosition - InPosition.xyz);

    OutFacing = saturate(dot(view, InNormal));
}

float4 ViewMappingPS(in float Facing : TEXCOORD0) : COLOR0
{
    Facing *= Facing;
    Facing *= Facing;

    float4 tex = tex2D(TextureSamplerClamp, float2(Facing, 0));
    tex.w = 1.0f;

    return tex;
}

Technique PlainMapping
{
    Pass
    {
        VertexShader = compile vs_1_1 PlainMappingVS();
        PixelShader = compile ps_2_0 PlainMappingPS();
    }
}

Technique NormalMapping
{
    Pass
    {
        VertexShader = compile vs_1_1 NormalMappingVS();
        PixelShader = compile ps_2_0 NormalMappingPS();
    }
}

Technique ViewMapping
{
    Pass
    {
        VertexShader = compile vs_1_1 ViewMappingVS();
        PixelShader = compile ps_2_0 ViewMappingPS();
    }
}

但是有两件事并没有像我希望的那样进行。首先,我想在盒子尺寸增加时平铺纹理。其次,它的灯光似乎很不稳定。我正在使用教育目录中 Ship Game 中的 Normal Lighting。

任何想法与照明发生了什么?或者我可以如何平铺纹理?

4

0 回答 0