XNA Skinned Model Cel-Shading全黑

时间:2011-12-14 14:45:48

标签: c# xna shader models xna-4.0

我实际上正在利用我在Apphub上找到的其他人的解决方案(我会在那里问过,但显然我必须支付他们的订阅才能提出问题)。无论如何,这个人将Skinned Model效果与Cel-Shading效果合并。他们发布了效果代码但不是如何使用它的片段,所以我不确定我是否正确实现它。我可以在屏幕上绘制模型(即使是使用cel-shader创建的彩色轮廓),但模型是纯黑色。我想我可能没有正确设置模型的纹理。

这是一种细胞阴影效果,未经其他人修改。

//--------------------------- BASIC PROPERTIES------------------------------  
#define MaxBones 60
float4x3 Bones[MaxBones];
// The world transformation
float4x4 World;     // The view transformation 
float4x4 View;     // The projection transformation  float4x4
Projection;     // The transpose of the inverse of the world
transformation,  // used for transforming the vertex's normal 
float4x4 WorldInverseTranspose;

//---------------------------DIFFUSE LIGHT PROPERTIES ------------------------------
// The direction of the diffuse light
float3 DiffuseLightDirection = float3(0, 0.5, 0.5);
// The color of the diffuse light
float4 DiffuseColor = float4(1, 1, 1, 1);
// The intensity of the diffuse light
float DiffuseIntensity = 5.7;

//---------------------------TOON SHADER PROPERTIES ------------------------------
// The color to draw the lines in.  Black is a good default.
float4 LineColor = float4(0, 0, 0, 1);
// The thickness of the lines.  This may need to change, depending on the scale of
// the objects you are drawing. 
float4 LineThickness = 0.12;

//--------------------------- TEXTURE PROPERTIES ------------------------------
// The texture being used for the object
texture Texture;
// The texture sampler, which will get the texture color
sampler2D textureSampler = sampler_state  
{
    Texture = (Texture); 
    MinFilter = Linear; 
    MagFilter = Linear; 
    AddressU = Clamp; 
    AddressV = Clamp;
};

//--------------------------- DATA STRUCTURES -----------------------------
// The structure used to store information between the application and the
// vertex shader
struct AppToVertex  { 
    float4 Position : SV_Position; 
    float3 Normal   : NORMAL; 
    float2 TexCoord : TEXCOORD0; 
    int4   Indices  : BLENDINDICES0; 
    float4 Weights  : BLENDWEIGHT0;
};

// The structure used to store information between the vertex shader and the
// pixel shader 
struct VertexToPixel  { 
    float4 Position : POSITION0; 
    float2 TextureCoordinate : TEXCOORD0; 
    float3 Normal : TEXCOORD1;
};

//SKIN Metod
void Skin(inout AppToVertex vin, uniform int boneCount) 
{ 
    float4x3 skinning = 0;

    [unroll] 
    for (int i = 0; i < boneCount; i++) 
    { 
        skinning += Bones[vin.Indices[i]] * vin.Weights[i]; 
    } 

    vin.Position.xyz = mul(vin.Position, skinning); 
    vin.Normal = mul(vin.Normal, (float3x3)skinning);
}

//--------------------------- SHADERS ------------------------------ 
// The vertex shader that does cel shading.
// It really only does the basic transformation of the vertex location,
// and normal, and copies the texture coordinate over.
VertexToPixel CelVertexShader(AppToVertex input)
{ 
    VertexToPixel output; 
    Skin(input, 4); 

    // Transform the position 
    float4 worldPosition = mul(input.Position, World); 
    float4 viewPosition = mul(worldPosition, View); 
    output.Position = mul(viewPosition, Projection); 

    // Transform the normal
    output.Normal = normalize(mul(input.Normal, WorldInverseTranspose)); 

    // Copy over the texture coordinate 
    output.TextureCoordinate = input.TexCoord; 

    return output;
}

// The pixel shader that does cel shading.  Basically, it calculates
// the color like is should, and then it discretizes the color into
// one of four colors.
float4 CelPixelShader(VertexToPixel input) : COLOR0
{ 
    // Calculate diffuse light amount 
    float intensity = dot(normalize(DiffuseLightDirection), input.Normal); 
    if(intensity < 0) 
        intensity = 0; 

    // Calculate what would normally be the final color, including texturing and diffuse lighting 
    float4 color = tex2D(textureSampler, input.TextureCoordinate) * DiffuseColor * DiffuseIntensity; 
    color.a = 1; 

    // Discretize the intensity, based on a few cutoff points 
    if (intensity > 0.95) 
        color = float4(1.0,1,1,1.0) * color; 
    else if (intensity > 0.5) 
        color = float4(0.7,0.7,0.7,1.0) * color; 
    else if (intensity > 0.05) 
        color = float4(0.35,0.35,0.35,1.0) * color; 
    else 
        color = float4(0.1,0.1,0.1,1.0) * color; 

    return color;
}

// The vertex shader that does the outlines
VertexToPixel OutlineVertexShader(AppToVertex input)
{ 
    VertexToPixel output = (VertexToPixel)0; 
    Skin(input, 4); 

    // Calculate where the vertex ought to be.  This line is equivalent 
    // to the transformations in the CelVertexShader. 
    float4 original = mul(mul(mul(input.Position, World), View), Projection); 

    // Calculates the normal of the vertex like it ought to be. 
    float4 normal = mul(mul(mul(input.Normal, World), View), Projection); 

    // Take the correct "original" location and translate the vertex a little 
    // bit in the direction of the normal to draw a slightly expanded object. 
    // Later, we will draw over most of this with the right color, except the expanded 
    // part, which will leave the outline that we want. 
    output.Position    = original + (mul(LineThickness, normal)); 

    return output;
}

// The pixel shader for the outline.  It is pretty simple:  draw everything with the
// correct line color. 
float4 OutlinePixelShader(VertexToPixel input) : COLOR0
{ 
    return LineColor;
}

// The entire technique for doing toon shading
technique Toon
{ 
    // The first pass will go through and draw the back-facing triangles with the outline shader,
    // which will draw a slightly larger version of the model with the outline color.  Later, the 
    // model will get drawn normally, and draw over the top most of this, leaving only an outline. 
    pass Pass1 
    { 
        VertexShader = compile vs_1_1 OutlineVertexShader(); 
        PixelShader = compile ps_2_0 OutlinePixelShader(); 
        CullMode = CW; 
    } 

    // The second pass will draw the model like normal, but with the cel pixel shader, which will 
    // color the model with certain colors, giving us the cel/toon effect that we are looking for. 
    pass Pass2 
    { 
        VertexShader = compile vs_1_1 CelVertexShader(); 
        PixelShader = compile ps_2_0 CelPixelShader(); 
        CullMode = CCW; 
    }
}

以下是我的绘画方式

public void Draw(Matrix viewMatrix, Matrix projectionMatrix)
    {
        Matrix[] boneTransforms = AnimPlayer.GetSkinTransforms(); //new Matrix[model.Bones.Count];
        Matrix worldMatrix = Orientation * Matrix.CreateTranslation(Position);

        foreach (ModelMesh mesh in Model.Meshes)
        {
            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                part.Effect = celshader;
                part.Effect.CurrentTechnique = part.Effect.Techniques["Toon"];
                part.Effect.Parameters["Bones"].SetValue(boneTransforms);
                part.Effect.Parameters["World"].SetValue(worldMatrix);
                part.Effect.Parameters["View"].SetValue(viewMatrix);
                part.Effect.Parameters["Projection"].SetValue(projectionMatrix);
                part.Effect.Parameters["WorldInverseTranspose"].SetValue(Matrix.Transpose(Matrix.Invert(worldMatrix)));
                part.Effect.Parameters["DiffuseLightDirection"].SetValue(new Vector3(.5f));
                part.Effect.Parameters["DiffuseColor"].SetValue(Color.White.ToVector4());
                part.Effect.Parameters["DiffuseIntensity"].SetValue(1);
                part.Effect.Parameters["LineColor"].SetValue(Color.Black.ToVector4());
                part.Effect.Parameters["LineThickness"].SetValue(new Vector4(.1f));
                part.Effect.Parameters["Texture"].SetValue(Texture);

                foreach (EffectPass pass in part.Effect.CurrentTechnique.Passes)
                {
                    part.Effect.CurrentTechnique.Passes[0].Apply();
                }
            }
            mesh.Draw();
        } 
    }

celshader是Cel-Shading效果,而Texture是模型的加载纹理。 有线索吗?

2 个答案:

答案 0 :(得分:0)

我认为你应该看看这个:

http://msdn.microsoft.com/en-us/library/bb975391(v=xnagamestudio.31).aspx

你不应该在每次Draw调用时分配效果;在加载时间内这样做(通常在LoadContent中放置,但我不会假设你如何设置它)。

此外,在Draw期间,您通常应该为每个效果调用mesh.Draw(),就像它们在文章中一样,而不仅仅是每个网格。

答案 1 :(得分:0)

我有这个错误,有一个类似的CelShader:)

我做的第一件事就是创建一个效果并在CelConder中加载cel着色器。

现在,当您绘制模型时,您不希望将模型的不同部分设置为使用着色器(可能有效,但我还没有尝试过),而是像这样设置着色器参数(在foreach内部(在mesh.MeshParts中的ModelMeshPart部分)循环)

celShader.Parameters["Texture"].SetValue(texture);
celShader.Parameters["World"].SetValue(world);
celShader.Parameters["TintColor"].SetValue(Color.DarkBlue.ToVector4());
celShader.CurrentTechnique = celShader.Techniques["Toon"];

还设置模型的索引并将vertexbuffer填充到graphicsdevice

graphicsDevice.SetVertexBuffer(meshPart.VertexBuffer,meshPart.VertexOffset);
graphicsDevice.Indices = meshPart.IndexBuffer;

然后我们可以将着色器应用于模型并绘制它!

foreach (EffectPass pass in celShader.CurrentTechnique.Passes)
{
    pass.Apply();
    graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
    meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
}

应该可以解决模型为黑色的任何错误。 希望这有帮助

我的整个绘图代码:

public void Draw(GraphicsDevice graphicsDevice, Effect theEffect)
    {
        Matrix[] bones = animationManager.GetBones();

        celShader.Parameters["Projection"].SetValue(Camera.Proj);
        celShader.Parameters["View"].SetValue(Camera.View);

        // for each model in the mesh
        foreach (ModelMesh mesh in test.Meshes)
        {
            // for each mesh part
            foreach (ModelMeshPart meshPart in mesh.MeshParts)
            {
                graphicsDevice.SetVertexBuffer(meshPart.VertexBuffer,
                        meshPart.VertexOffset);
                graphicsDevice.Indices = meshPart.IndexBuffer;

                //here i load the texture!!!!!!!!!
                Texture2D texture = ((SkinnedEffect)meshPart.Effect).Texture;


                Matrix world = Matrix.Identity;

                celShader.Parameters["Texture"].SetValue(texture);
                celShader.Parameters["World"].SetValue(world);

                celShader.Parameters["Bones"].SetValue(bones);
                celShader.Parameters["TintColor"].SetValue(Color.DarkBlue.ToVector4());

                celShader.CurrentTechnique = celShader.Techniques["Toon"];
                // for each effect pass in the cell shader
                foreach (EffectPass pass in celShader.CurrentTechnique.Passes)
                {
                    pass.Apply();

                    graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
                        meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
                }
            }
        }
}