Hi,
I am not an expert on HLSL. Hope someone can help me rewrite this Shader, so it can work on Shader Model 2 (vs_4_0_level_9_3). I have an engine running on Windows 8.1 (App Store), which uses DirectX 11.2 (feature level 11_1). I am trying to rewrite this engine, so it runs on Windows Phone 8.1. In order to accomplish that, I had to decrease the DirectX feature level to 9_3, which only uses Shader Model 2 (unlike feature level 11_1, which supports Shader Model 5).
I am having difficulties to rewrite my vertex shader (originally written for vs_5_0), so that it's now for vs_4_0_level_9_3. Here are my shaders written for vs_5_0 profile:
Common.hlsl:
// Constant buffer to be updated by application per object
cbuffer PerObject : register(b0)
{
// WorldViewProjection matrix
float4x4 WorldViewProjection;
// We need the world matrix so that we can
// calculate the lighting in world space
float4x4 World;
// Inverse transpose of world, used for
// bringing normals into world space, especially
// necessary where non-uniform scaling has been applied
float4x4 WorldInverseTranspose;
};
// A simple directional light (e.g. the sun)
struct DirectionalLight
{
float4 Color;
float3 Direction;
};
// Constant buffer - updated once per frame
// Note: HLSL data is packed in such a
// way that it does not cross a 16-byte boundary
cbuffer PerFrame: register (b1)
{
DirectionalLight Light;
float3 CameraPosition;
};
// Constant buffer to hold our material configuration
// Note: HLSL data is packed in such a
// way that it does not cross a 16-bytes boundary
cbuffer PerMaterial : register (b2)
{
float4 MaterialAmbient;
float4 MaterialDiffuse;
float4 MaterialSpecular;
float MaterialSpecularPower;
bool HasTexture;
float4 MaterialEmissive;
float4x4 UVTransform;
};
// Constant buffer to hold our skin matrices for each bone.
// Note: 1024*64 = maximum bytes for a constant buffer in SM5
cbuffer PerArmature : register(b3)
{
float4x4 Bones[63];
};
// Vertex Shader input structure (from Application)
struct VertexShaderInput
{
float4 Position : SV_Position;// Position - xyzw
float3 Normal : NORMAL; // Normal - for lighting and mapping operations
float4 Color : COLOR0; // Color - vertex color, used to generate a diffuse color
float2 TextureUV: TEXCOORD0; // UV - texture coordinate
uint4 SkinIndices : BLENDINDICES0; // blend indices
float4 SkinWeights : BLENDWEIGHT0; // blend weights
};
// Pixel Shader input structure (from Vertex Shader)
struct PixelShaderInput
{
float4 Position : SV_Position;
// Interpolation of combined vertex and material diffuse
float4 Diffuse : COLOR;
// Interpolation of vertex UV texture coordinate
float2 TextureUV: TEXCOORD0;
// We need the World Position and normal for light calculations
float3 WorldNormal : NORMAL;
float3 WorldPosition : WORLDPOS;
};
float3 Lambert(float4 pixelDiffuse, float3 normal, float3 toLight)
{
// Calculate diffuse color (using Lambert's Cosine Law - dot product of
// light and normal) Saturate to clamp the value within 0 to 1.
float3 diffuseAmount = saturate(dot(normal, toLight));
return pixelDiffuse.rgb * diffuseAmount;
}
float3 SpecularPhong(float3 normal, float3 toLight, float3 toEye)
{
// R = reflect(i,n) => R = i - 2 * n * dot(i,n)
float3 reflection = reflect(-toLight, normal);
// Calculate the specular amount (smaller specular power = larger specular highlight)
// Cannot allow a power of 0 otherwise the model will appear black and white
float specularAmount = pow(saturate(dot(reflection,toEye)), max(MaterialSpecularPower,0.00001f));
return MaterialSpecular.rgb * specularAmount;
}
float3 SpecularBlinnPhong(float3 normal, float3 toLight, float3 toEye)
{
// Calculate the half vector
float3 halfway = normalize(toLight + toEye);
// Saturate is used to prevent backface light reflection
// Calculate specular (smaller specular power = larger specular highlight)
float specularAmount = pow(saturate(dot(normal, halfway)), max(MaterialSpecularPower,0.00001f));
return MaterialSpecular.rgb * specularAmount;
}
VS.hlsl:
#include "Common.hlsl"
void SkinVertex(float4 weights, uint4 bones, inout float4 position, inout float3 normal)
{
// If there are skin weights apply vertex skinning
if (weights.x != 0)
{
// Calculate the skin transform from up to four bones and weights
float4x4 skinTransform = Bones[bones.x] * weights.x +
Bones[bones.y] * weights.y +
Bones[bones.z] * weights.z +
Bones[bones.w] * weights.w;
// Apply skinning to vertex and normal
position = mul(position, skinTransform);
// We assume here that the skin transform includes only uniform scaling (if any)
normal = mul(normal, (float3x3)skinTransform);
}
}
// Vertex shader main function
PixelShaderInput VSMain(VertexShaderInput vertex)
{
PixelShaderInput result = (PixelShaderInput)0;
// Apply vertex skinning if any
SkinVertex(vertex.SkinWeights, vertex.SkinIndices, vertex.Position, vertex.Normal);
result.Position = mul(vertex.Position, WorldViewProjection);
result.Diffuse = vertex.Color * MaterialDiffuse;
// Apply material UV transformation
result.TextureUV = mul(float4(vertex.TextureUV.x, vertex.TextureUV.y, 0, 1), (float4x2)UVTransform).xy;
// We use the inverse transpose of the world so that if there is non uniform
// scaling the normal is transformed correctly. We also use a 3x3 so that
// the normal is not affected by translation (i.e. a vector has the same direction
// and magnitude regardless of translation)
result.WorldNormal = mul(vertex.Normal, (float3x3)WorldInverseTranspose);
result.WorldPosition = mul(vertex.Position, World).xyz;
return result;
}
When I try to compile this vertex shader with vs_4_0_level_9_3 profile, I get this error:
Common.hlsl(76,14-18): error X4507: maximum vs_4_0_level_9_3 constant register index (256) exceeded - Try reducing number of constants referenced
I see the error refers to the line "float4x4 Bones[1024];" in Common.hlsl. I tried to decrease it to "float4x4 Bones[63];", but I got another error:
Common.hlsl(30,14-32): error X4507: maximum vs_4_0_level_9_3 constant register index (256) exceeded - Try reducing number of constants referenced
... the line "float4x4 WorldViewProjection;"
I really don't know what now.. :/ any help would be appreciated.
Thank you in advance for any pointers and advices.