Sign in to follow this  
MatsK

My vertex shader won't display! :(

Recommended Posts

I'm learning HLSL, and my VertexShader is compiling fine, but it isn't displaying anything. Why?
Here's my shader:

float4x4 BoneMatrix;
float4x4 World;
float4x4 View;
float4x4 Projection;
 
float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.1;
 
struct VertexShaderHeadInput
{
    float4 Position : POSITION0;
    float4 Normal : NORMAL0;
    float4 TexPosition : TEXCOORD0;
};
 
struct VertexShaderHeadOutput
{
    float4 Position : POSITION0;
    float4 Normal : NORMAL0;
    float4 TexPosition : TEXCOORD0;
};
 
VertexShaderHeadOutput TransformHead(VertexShaderHeadInput Input)
{
    VertexShaderHeadOutput Output;
 
    float4 WorldPosition = mul(Input.Position, World);
    float4 ViewPosition = mul(WorldPosition, View);
    Output.Position = mul(ViewPosition, Projection);
    Output.Normal = mul(ViewPosition, Projection);
    Output.TexPosition = mul(ViewPosition, Projection);
 
    Output.Position *= mul(Input.Position, BoneMatrix);
    Output.Normal *= mul(Input.Normal, BoneMatrix);
    Output.TexPosition *= Input.TexPosition;
 
    return Output;
}
 
float4 PixelShaderFunction(VertexShaderHeadOutput Input) : COLOR0
{
    return AmbientColor * AmbientIntensity;
}
 
technique TransformHeadTechnique
{
    pass Pass1
    {
        VertexShader = compile vs_3_0 TransformHead();
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}

Here's my usage code:

            m_HeadShader.Parameters["World"].SetValue(WorldMatrix);
            m_HeadShader.Parameters["View"].SetValue(ViewMatrix);
            m_HeadShader.Parameters["Projection"].SetValue(ProjectionMatrix);
            m_HeadShader.Parameters["BoneMatrix"].SetValue(Skel.Bones[16].AbsoluteMatrix);           

foreach(EffectPass Pass in m_HeadShader.CurrentTechnique.Passes)
                {
                    Pass.Apply();

                    foreach (Vector3 Fce in HeadMesh.Faces)
                    {
                        VertexPositionNormalTexture[] Vertex = new VertexPositionNormalTexture[3];
                        Vertex[0] = HeadMesh.RealVertices[(int)Fce.X];
                        Vertex[1] = HeadMesh.RealVertices[(int)Fce.Y];
                        Vertex[2] = HeadMesh.RealVertices[(int)Fce.Z];

                        Vertex[0].TextureCoordinate = HeadMesh.RealVertices[(int)Fce.X].TextureCoordinate;
                        Vertex[1].TextureCoordinate = HeadMesh.RealVertices[(int)Fce.Y].TextureCoordinate;
                        Vertex[2].TextureCoordinate = HeadMesh.RealVertices[(int)Fce.Z].TextureCoordinate;

                        Vertex[0].Normal = HeadMesh.RealVertices[(int)Fce.X].Normal;
                        Vertex[1].Normal = HeadMesh.RealVertices[(int)Fce.Y].Normal;
                        Vertex[2].Normal = HeadMesh.RealVertices[(int)Fce.Z].Normal;

                        m_Devc.DrawUserPrimitives(PrimitiveType.TriangleList, Vertex, 0, 1);
                    }
                }

My worldmatrix:

        /// <summary>
        /// This avatar's world matrix. Used for rendering.
        /// </summary>
        public Matrix WorldMatrix
        {
            get
            {
                if (m_WorldIsDirty)
                {
                    m_World = Matrix.CreateRotationX(m_RotateX) * Matrix.CreateRotationY(m_RotateY) * Matrix.CreateRotationZ(m_RotateZ) * Matrix.CreateScale(m_Scale) * Matrix.CreateTranslation(m_Position);
                    m_WorldIsDirty = false;
                }

                return m_World;
            }
        }

This is the code I've been trying to convert to HLSL (High Level Shader Language):

                case MeshType.Head:
                    for (int i = 0; i < Msh.TotalVertexCount; i++)
                    {
                        //Transform the head vertices' position by the absolute transform
                        //for the headbone (which is always bone 17) to render the head in place.
                        Msh.TransformedVertices[i].Position = Vector3.Transform(Msh.RealVertices[i].Position,
                            Skel.Bones[16].AbsoluteMatrix);

                        Msh.TransformedVertices[i].TextureCoordinate = Msh.RealVertices[i].TextureCoordinate;

                        //Transform the head normals' position by the absolute transform
                        //for the headbone (which is always bone 17) to render the head in place.
                        Msh.TransformedVertices[i].Normal = Vector3.Transform(Msh.RealVertices[i].Normal,
                            Skel.Bones[16].AbsoluteMatrix);
                    }

                    return;

I might add that I tried to debug the shader using RenderDoc, but it actually crashed as it was loading its log. :|

Share this post


Link to post
Share on other sites

Can you try to output float4(1.0f, 0.0f, 0.0f, 1.0f) from your PS? (bright red)

That way you can see if the problem is in your ambient constants or in the VS.

Another maybe useful thing, most of the time you can send World*View*Projection (WVP) from the CPU, precalculated. That way you prevent that calculation being done for each vertex.

Here's my basic VS as an example:

VertexOut VS_main(VertexIn vin)
{
	VertexOut vout;
	
	// Transform to world space space.
	vout.PosW    = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
	vout.NormalW = mul(vin.NormalL, (float3x3)gWorldInvTranspose);
		
	// Transform to homogeneous clip space.
	vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);

	return vout;
}

Edited by cozzie

Share this post


Link to post
Share on other sites

Ah!

Thanks! Changing to bright red gave me this:

6jhiwx.png

It seems like my shader is rendering exactly what it's supposed to be rendering, but in the wrong place. So what's wrong with my vertex shader calculations? :\

I don't understand your sample. What is gWorldInverseTranspose?

Share this post


Link to post
Share on other sites

Good, so you're a step closer to the solution :)

I think you first need to solve your Vertex Shader/ matrices, so that the bright red 'thingie' is rendered in the place where you expect it. When it does, you can change back the PixelShader to the Original code and see if it works (if it doesn't there might be something wrong with the ambient shader constants).

WorldInverseTranspose is the inverse transpose of the world matrix, used to multiply the normals in the shader, for lighting.

Share this post


Link to post
Share on other sites

Probably you rendering with an alpha value of 0.1f, so it is barely visible ;-)

float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.1;
return AmbientColor * AmbientIntensity;

should result in float4(0.1f,0.1f,0.1f,0.1f)

Try something like this:

float3 AmbientColor = float4(1, 1, 1);
float AmbientIntensity = 0.1;

return float4(AmbientColor * AmbientIntensity,1.0f);


Edited by Auskennfuchs

Share this post


Link to post
Share on other sites

Auskennfuchs: No, it's plainly visible :)

I found out that I could do: 

m_HeadShader.Parameters["World"].SetValue(WorldMatrix * Skel.Bones[16].AbsoluteMatrix);

in my program in order to render the model in place. That means I didn't have to do:

    Output.Position *= mul(Input.Position, BoneMatrix);
    Output.Normal *= mul(Input.Normal, BoneMatrix);
    Output.TexPosition *= Input.TexPosition;

in my shader.

Here's the result:

14mugxx.png

So how do I make sure that the model is rendered right side up? :)

Share this post


Link to post
Share on other sites

I managed to make the model render right side up. I also added a very basic pixel shader to render the texture. I extended the shader to include hands and accessories;

float4x4 World;
float4x4 View;
float4x4 Projection;

float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.1;

texture HeadTexture;

sampler HeadTextureSampler = sampler_state
{
	Texture = <HeadTexture>;
};

texture AccessoryTexture;

sampler AccessoryTextureSampler = sampler_state
{
	Texture = <AccessoryTexture>;
};

texture LeftHandTexture;

sampler LeftHandTextureSampler = sampler_state
{
	Texture = <LeftHandTexture>;
};

texture RightHandTexture;

sampler RightHandTextureSampler = sampler_state
{
	Texture = <RightHandTexture>;
};

struct VertexShaderHeadInput
{
	float4 Position : POSITION0;
	float4 Normal : NORMAL0;
	float4 TexPosition : TEXCOORD0;
};

struct VertexShaderHeadOutput
{
	float4 Position : POSITION0;
	float4 Normal : NORMAL0;
	float4 TexPosition : TEXCOORD0;
};

VertexShaderHeadOutput TransformHead(VertexShaderHeadInput Input)
{
	VertexShaderHeadOutput Output;

	float4 WorldPosition = mul(Input.Position, World);
	float4 ViewPosition = mul(WorldPosition, View);
	Output.Position = mul(ViewPosition, Projection);
	Output.Normal = mul(ViewPosition, Projection);
	Output.TexPosition = Input.TexPosition;

	return Output;
}

VertexShaderHeadOutput TransformAccessory(VertexShaderHeadInput Input)
{
	VertexShaderHeadOutput Output;

	float4 WorldPosition = mul(Input.Position, World);
	float4 ViewPosition = mul(WorldPosition, View);
	Output.Position = mul(ViewPosition, Projection);
	Output.Normal = mul(ViewPosition, Projection);
	Output.TexPosition = Input.TexPosition;

	return Output;
}

VertexShaderHeadOutput TransformLeftHand(VertexShaderHeadInput Input)
{
	VertexShaderHeadOutput Output;

	float4 WorldPosition = mul(Input.Position, World);
	float4 ViewPosition = mul(WorldPosition, View);
	Output.Position = mul(ViewPosition, Projection);
	Output.Normal = mul(ViewPosition, Projection);
	Output.TexPosition = Input.TexPosition;

	return Output;
}

VertexShaderHeadOutput TransformRightHand(VertexShaderHeadInput Input)
{
	VertexShaderHeadOutput Output;

	float4 WorldPosition = mul(Input.Position, World);
	float4 ViewPosition = mul(WorldPosition, View);
	Output.Position = mul(ViewPosition, Projection);
	Output.Normal = mul(ViewPosition, Projection);
	Output.TexPosition = Input.TexPosition;

	return Output;
}

float4 HeadPixelShaderFunction(VertexShaderHeadOutput Input) : COLOR0
{
	float4 Color = tex2D(HeadTextureSampler, Input.TexPosition);
	return Color;
}

float4 AccessoryPixelShaderFunction(VertexShaderHeadOutput Input) : COLOR0
{
	float4 Color = tex2D(AccessoryTextureSampler, Input.TexPosition);
	return Color;
}

float4 LeftHandPixelShaderFunction(VertexShaderHeadOutput Input) : COLOR0
{
	float4 Color = tex2D(LeftHandTextureSampler, Input.TexPosition);
	return Color;
}

float4 RightHandPixelShaderFunction(VertexShaderHeadOutput Input) : COLOR0
{
	float4 Color = tex2D(RightHandTextureSampler, Input.TexPosition);
	return Color;
}

technique TransformHeadTechnique
{
	pass HeadPass
	{
		VertexShader = compile vs_3_0 TransformHead();
		PixelShader = compile ps_3_0 HeadPixelShaderFunction();
	}
}

technique TransformAccessoryTechnique
{
	pass HeadPass
	{
		VertexShader = compile vs_3_0 TransformAccessory();
		PixelShader = compile ps_3_0 AccessoryPixelShaderFunction();
	}
}

technique TransformLeftHandTechnique
{
	pass HeadPass
	{
		VertexShader = compile vs_3_0 TransformLeftHand();
		PixelShader = compile ps_3_0 LeftHandPixelShaderFunction();
	}
}

technique TransformRightHandTechnique
{
	pass HeadPass
	{
		VertexShader = compile vs_3_0 TransformRightHand();
		PixelShader = compile ps_3_0 RightHandPixelShaderFunction();
	}
}

Now, the head, hands and accessory renders in place, but also seems to be bobbing up and down along the X-axis in addition to going around the Y-axis (which it is supposed to do).

Here's how I create my rotation:

        /// <summary>
        /// This avatar's world matrix. Used for rendering.
        /// </summary>
        public Matrix WorldMatrix
        {
            get
            {
                if (m_WorldIsDirty)
                {
                    m_World = Matrix.CreateRotationX(m_RotateX) * Matrix.CreateRotationY(m_RotateY) * Matrix.CreateRotationZ(m_RotateZ) * Matrix.CreateScale(m_Scale) * Matrix.CreateTranslation(m_Position);
                    m_WorldIsDirty = false;
                }

                return m_World;
            }
        }

        /// <summary>
        /// Gets or sets the angle (in degrees) of the rotation axis for this Avatar.
        /// </summary>
        public float RotationY
        {
            get { return m_RotateY; }
            set
            {
                m_RotateY = value;
                m_WorldIsDirty = true;
            }
        }
        /// <summary>
        /// Converts an angle given in degrees to radians.
        /// </summary>
        /// <param name="Angle">The angle to convert.</param>
        /// <returns>The angle in radians.</returns>
        private double DegreesToRadians(double Angle)
        {
            return (Math.PI / 180) * Angle;
        }

        /// <summary>
        /// Updates this avatar's rotation.
        /// </summary>
        /// <param name="GTime">A GameTime instance.</param>
        public void Update(GameTime GTime)
        {
            if (ShouldRotate)
            {
                float Time = GTime.TotalGameTime.Ticks;
                float Phase = (Time % RotationSpeed) / RotationSpeed;
                double Multiplier = Math.Sin((Math.PI * 2) * Phase);
                double NewAngle = RotationStartAngle + (RotationRange * Multiplier);

                RotationY = (float)DegreesToRadians(NewAngle);
            }
        }

Also, does anyone know how I can use the normals with my texture in the pixel shader??

Share this post


Link to post
Share on other sites

You should build your worldMatrix by using

mWorld = mScale * mRotation * mTranslation

Otherwise your scaling axis are not aligned with the models origin.

Also may try to build only one rotationmatrix by using quaternions. But I think this will not solve your problem.

Share this post


Link to post
Share on other sites

Doing this:

m_World = Matrix.CreateScale(m_Scale) * Matrix.CreateRotationX(m_RotateX) * Matrix.CreateRotationY(m_RotateY) * Matrix.CreateRotationZ(m_RotateZ) /** Matrix.CreateScale(m_Scale)*/ * Matrix.CreateTranslation(m_Position);

doesn't seem to have any effect. :(

Does the fact that I'm sending my world matrix to the shader as such have anything to do with it?

m_VitaboyShader.Parameters["World"].SetValue(WorldMatrix * Skel.Bones[Skel.FindBone("HEAD")].AbsoluteMatrix);

Also, how would I create a single rotation matrix by using quats?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this