• Advertisement
Sign in to follow this  

[C++, DX9] Cel (Toon) Shader problem

This topic is 2781 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My shader:

Shader.fx

float4x4 gViewProj : VIEWPROJECTION;

struct VS_INPUT{
float4 Position : POSITION;
float3 BlendWeights : BLENDWEIGHT;
float4 BlendIndices : BLENDINDICES;
float3 Normal : NORMAL;
float3 Tex0 : TEXCOORD0;
};

struct VS_OUTPUT{
float4 Position : POSITION0;
float2 Texcoord : TEXCOORD0;
float3 Normal : TEXCOORD1;
float3 ViewDirection : TEXCOORD2;
float3 LightDirection : TEXCOORD3;
};

#include "cel.psh"
#include "skin.vsh"

technique Skinning{
pass p0{
VertexShader = ( vsArray20[ CurNumBones ] );
PixelShader = compile ps_2_0 Cel();
}
}

technique Toon{
pass p0{
VertexShader = compile vs_2_0 Transform();
PixelShader = compile ps_2_0 Cel();
}
}




Cel.psh

float4x4 World;
float4x4 View;
float4x4 Projection;
float3 EyePosition;
float3 LightPosition;
float LayerOneSharp;
float LayerOneRough;
float LayerOneContrib;
float LayerTwoSharp;
float LayerTwoRough;
float LayerTwoContrib;

sampler TextureSampler = sampler_state{
AddressU = WRAP;
AddressV = WRAP;
MIPFILTER = LINEAR;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
};

VS_OUTPUT Transform(VS_INPUT Input){
float4x4 WorldViewProjection = mul(World, gViewProj);
float3 ObjectPosition = mul(Input.Position, World);

VS_OUTPUT Output;
Output.Normal = mul(Input.Normal, World);
Output.Position = mul(Input.Position, WorldViewProjection);

Output.ViewDirection = EyePosition - ObjectPosition;
Output.LightDirection = LightPosition - ObjectPosition;
Output.Texcoord = Input.Tex0;

return Output;
}

struct PS_INPUT{
float3 Normal : TEXCOORD1;
float3 ViewDirection : TEXCOORD2;
float3 LightDirection : TEXCOORD3;
float2 Texcoord : TEXCOORD0;
};

float4 Cel(PS_INPUT Input) : COLOR0{
float4 baseColor = tex2D(TextureSampler, Input.Texcoord);
float3 Normal = normalize(Input.Normal);
float3 ViewDirection = normalize(Input.ViewDirection);
float3 NLightDirection = normalize(Input.LightDirection);

float oneW = 0.18f * ( 1.0f - LayerOneSharp );
float twoW = 0.18f * ( 1.0f - LayerTwoSharp );

float NDotL = dot(Normal, NLightDirection);
float3 Reflection = normalize(2.0f * NDotL * Normal - NLightDirection);

float4 layerOneColor = smoothstep(0.72f-oneW, 0.72f+oneW, pow(saturate(dot(Reflection, ViewDirection)), LayerOneRough));
float4 layerTwoColor = smoothstep(0.72f-twoW, 0.72f+twoW, pow(saturate(dot(Reflection, ViewDirection)), LayerTwoRough));

float4 color = (baseColor + LayerOneContrib*layerOneColor) + LayerTwoContrib*layerTwoColor;
color.a = 1.0;

return color;
}



Skin.vsh

#define MATRIX_PALETTE_SIZE_DEFAULT 70
const int MATRIX_PALETTE_SIZE = MATRIX_PALETTE_SIZE_DEFAULT;
float4x3 amPalette[ MATRIX_PALETTE_SIZE_DEFAULT ];

struct VS_SKIN_INPUT{
float4 vPos;
float3 vBlendWeights;
float4 vBlendIndices;
float3 vNor;
};

VS_OUTPUT VS_Skin( const VS_SKIN_INPUT vInput, int iNumBones ){
VS_OUTPUT vOutput = (VS_OUTPUT)0;

float fLastWeight = 1.0;
float fWeight;
float afBlendWeights[ 3 ] = (float[ 3 ]) vInput.vBlendWeights;
int aiIndices[ 4 ] = (int[ 4 ]) D3DCOLORtoUBYTE4( vInput.vBlendIndices );

if(iNumBones > 2){
for( int iBone = 0; (iBone < 3) && (iBone < iNumBones - 1); ++ iBone ){
fWeight = afBlendWeights[ iBone ];
fLastWeight -= fWeight;
vOutput.Position.xyz += mul( vInput.vPos, amPalette[ aiIndices[ iBone ] ] ) * fWeight;
vOutput.Normal += mul( vInput.vNor, amPalette[ aiIndices[ iBone ] ] ) * fWeight;
}
}else if(iNumBones == 2){
fWeight = afBlendWeights[ 0 ];
fLastWeight -= fWeight;
vOutput.Position.xyz += mul( vInput.vPos, amPalette[ aiIndices[ 0 ] ] ) * fWeight;
vOutput.Normal += mul( vInput.vNor, amPalette[ aiIndices[ 0 ] ] ) * fWeight;
}

vOutput.Position.xyz += mul( vInput.vPos, amPalette[ aiIndices[ iNumBones - 1 ] ] ) * fLastWeight;
vOutput.Normal += mul( vInput.vNor, amPalette[ aiIndices[ iNumBones - 1 ] ] ) * fLastWeight;

return vOutput;
}

VS_OUTPUT VertSkinning( VS_INPUT i, uniform int iNumBones ){

VS_SKIN_INPUT vsi = { i.Position, i.BlendWeights, i.BlendIndices, i.Normal };
VS_OUTPUT vso = VS_Skin( vsi, iNumBones );

vso.ViewDirection = EyePosition - vso.Position;
vso.LightDirection = LightPosition - vso.Position;
vso.Texcoord = i.Tex0;

vso.Position = mul( float4( vso.Position.xyz, 1.0f ), gViewProj );


return vso;
}


int CurNumBones = 2;

VertexShader vsArray20[ 4 ] = { compile vs_2_0 VertSkinning( 1 ),
compile vs_2_0 VertSkinning( 2 ),
compile vs_2_0 VertSkinning( 3 ),
compile vs_2_0 VertSkinning( 4 ) };



On buildings and terrain (non skinned meshes) shader looks alright, however on skinned mesh it seems to be like default lighting; triangle is light either dark. As visible on this image ( http://dl.dropbox.com/u/2637453/Capture.PNG ) Terrain gets shaded smoothly, while character on his back has weirdly shaded triangles and squares.

Terrain uses 'Toon' technique, character - 'Skinning' technique.

At first I though it's something wrong with Normals, but no matter how much I mess with them, I wasn't able to fix it.

If anymore information needed, just let me know.

Thank you.

Share this post


Link to post
Share on other sites
Advertisement
Looks like you forgot to move your normal and position into world space in your skinned shader...

Change your shader to this:


VS_OUTPUT VertSkinning( VS_INPUT i, uniform int iNumBones )
{
VS_SKIN_INPUT vsi = { i.Position, i.BlendWeights, i.BlendIndices, i.Normal };
VS_OUTPUT vso = VS_Skin( vsi, iNumBones );

vso.Position = mul( float4( vso.Position.xyz, 1.0f ), World );
vso.Normal = mul( vso.Normal, World );

vso.ViewDirection = EyePosition - vso.Position;
vso.LightDirection = LightPosition - vso.Position;
vso.Texcoord = i.Tex0;

vso.Position = mul( vso.Position.xyz, gViewProj );

return vso;
}



Share this post


Link to post
Share on other sites
I though VS_Skin function calculates world matrix, as it's root bone transformation. Also with
vso.Position = mul( vso.Position.xyz, gViewProj );
it doesn't work, must be
vso.Position = mul( float4(vso.Position.xyz, 1.0f), gViewProj );
and either way, it still remains in triangles, doesn't get smooth.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement