Ive been trying all sorts of stuff for 2 days and i still cant figure this out. Need some help.
Here is my shader code.
cbuffer cbPerFrame
{
DirectionalLight gDirLights[3];
float3 gEyePosW;
float gFogStart;
float gFogRange;
float4 gFogColor;
};
cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWorldInvTranspose;
float4x4 gWorldViewProj;
float4x4 gTexTransform;
Material gMaterial;
};
struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
};
struct VertexOut
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
};
struct GeoOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
};
SamplerState samAnisotropic
{
Filter = ANISOTROPIC;
MaxAnisotropy = 4;
AddressU = WRAP;
AddressV = WRAP;
};
Texture2D gDiffuseMap;
VertexOut VS(VertexIn vin)
{
VertexOut vout;
// Transform to world space space.
vout.PosL = mul(float4(vin.PosL, 1.0f), gWorldInvTranspose).xyz;
vout.NormalL = mul(vin.NormalL, (float3x3)gWorldInvTranspose);
return vout;
}
float distance(VertexOut gin)
{
GeoOut pin;
float4x4 gWorlds;
gWorlds[0][0] = 1;gWorlds[0][1] = 0;gWorlds[0][2] = 0;gWorlds[0][3] = 0;gWorlds[1][0] = 0;gWorlds[1][1]= 1;gWorlds[1][2] = 0;gWorlds[1][3] = 0;
gWorlds[2][0] = 0;gWorlds[2][1] = 0;gWorlds[2][2] = 1;gWorlds[2][3] = 0;gWorlds[3][0] = 0;gWorlds[3][1] = 0;gWorlds[3][2] = 0;gWorlds[3][3] = 0;
// Transform to World Space
pin.PosW = mul(float4(gin.PosL, 1.0f), gWorlds).xyz;
// The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW;
// Cache the distance to the eye from this surface point.
float distToEye = length(toEye);
return distToEye;
}
void Subdivide(VertexOut inVerts[3], out VertexOut outVerts[6])
{
// 1
// *
// / \
// / \
// m0*-----*m1
// / \ / \
// / \ / \
// *-----*-----*
// 0 m2 2
VertexOut m[3];
// compute edge midpoints
m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);
// derive normals
m[0].NormalL = m[0].PosL;
m[1].NormalL = m[1].PosL;
m[2].NormalL = m[2].PosL;
// interpolate texture coordinates
outVerts[0] = inVerts[0];
outVerts[1] = m[0];
outVerts[2] = m[2];
outVerts[3] = m[1];
outVerts[4] = inVerts[2];
outVerts[5] = inVerts[1];
}
void OutputSubdivision(VertexOut v[6], inout TriangleStream<GeoOut> stream)
{
GeoOut gout[6];
[unroll]
for(int i = 0; i < 6; ++i)
{
// Transform to World Space
gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose);
// Transform to homogeneous clip space
gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj);
}
// 1
// *
// / \
// / \
// m0*-----*m1
// / \ / \
// / \ / \
// *-----*-----*
// 0 m2 2
// We can draw the subdivision in two strips:
// strip 1: bottom three triangles
// strip 2: top triangle
[unroll]
for(int j = 0; j < 5; ++j)
{
stream.Append(gout[j]);
}
stream.RestartStrip();
stream.Append(gout[1]);
stream.Append(gout[5]);
stream.Append(gout[3]);
}
void Subdivide2(VertexIn inVerts[3], out VertexOut outVerts[15])
{
// 1
// *
// / \
// / \
// m0*-----*m1
// / \ / \
// / \ / \
// *-----*-----*
// 0 m2 2
VertexOut m[3];
VertexOut n[15];
// compute edge midpoints
m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL);
m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL);
m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL);
n[0].PosL = 0.5f * (inVerts[0].PosL + m[0].PosL);
n[1].PosL = 0.5f * (inVerts[0].PosL + m[2].PosL);
n[2].PosL = 0.5f * (m[0].PosL + m[2].PosL);
n[3].PosL = m[2].PosL;
n[4].PosL = 0.5f * (m[2].PosL + m[1].PosL);
n[5].PosL = 0.5f * (inVerts[2].PosL + m[2].PosL);
n[6].PosL = 0.5f * (inVerts[2].PosL + m[1].PosL);
n[7].PosL = 0.5f * (m[0].PosL + m[1].PosL);
n[8].PosL = 0.5f * (m[0].PosL + inVerts[1].PosL);
n[9].PosL = 0.5f * (m[1].PosL + inVerts[1].PosL);
n[0].PosL = normalize(n[0].PosL);
n[1].PosL = normalize(n[1].PosL);
n[2].PosL = normalize(n[2].PosL);
n[3].PosL = normalize(n[3].PosL);
n[4].PosL = normalize(n[4].PosL);
n[5].PosL = normalize(n[5].PosL);
n[6].PosL = normalize(n[6].PosL);
n[7].PosL = normalize(n[7].PosL);
n[8].PosL = normalize(n[8].PosL);
n[9].PosL = normalize(n[9].PosL);
m[0].PosL = normalize(m[0].PosL);
m[1].PosL = normalize(m[1].PosL);
m[2].PosL = normalize(m[2].PosL);
// derive normals
m[0].NormalL = m[0].PosL;
m[1].NormalL = m[1].PosL;
m[2].NormalL = m[2].PosL;
n[0].NormalL = n[0].PosL;
n[1].NormalL = n[1].PosL;
n[2].NormalL = n[2].PosL;
n[3].NormalL = n[3].PosL;
n[4].NormalL = n[4].PosL;
n[5].NormalL = n[5].PosL;
n[6].NormalL = n[6].PosL;
n[7].NormalL = n[7].PosL;
n[8].NormalL = n[8].PosL;
n[9].NormalL = n[9].PosL;
outVerts[0] = inVerts[0];
outVerts[1] = n[0];
outVerts[2] = n[1];
outVerts[3] = n[2];
outVerts[4] = n[3];
outVerts[5] = n[4];
outVerts[6] = n[5];
outVerts[7] = n[6];
outVerts[8] = inVerts[2];
outVerts[9] = m[0];
outVerts[10] = n[7];
outVerts[11] = m[1];
outVerts[12] = n[8];
outVerts[13] = n[9];
outVerts[14] = inVerts[1];
}
void OutputSubdivision2(VertexOut v[15], inout TriangleStream<GeoOut> stream)
{
GeoOut gout[15];
[unroll]
for(int i = 0; i < 15; ++i)
{
// Transform to World Space
gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz;
gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose);
// Transform to homogeneous clip space
gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj);
}
// 1
// *
// / \
// / \
// m0*-----*m1
// / \ / \
// / \ / \
// *-----*-----*
// 0 m2 2
// We can draw the subdivision in two strips:
// strip 1: bottom three triangles
// strip 2: top triangle
[unroll]
for(int j = 0; j < 9; j++)
{
stream.Append(gout[j]);
}
stream.RestartStrip();
stream.Append(gout[1]);
stream.Append(gout[9]);
stream.Append(gout[3]);
stream.Append(gout[10]);
stream.Append(gout[5]);
stream.Append(gout[11]);
stream.Append(gout[7]);
stream.RestartStrip();
stream.Append(gout[9]);
stream.Append(gout[12]);
stream.Append(gout[10]);
stream.Append(gout[13]);
stream.Append(gout[11]);
stream.RestartStrip();
stream.Append(gout[12]);
stream.Append(gout[14]);
stream.Append(gout[13]);
}
[maxvertexcount(50)]
void GS(triangle VertexOut gin[3], inout TriangleStream<GeoOut> stream)
{
if(distance(gin[0]) < 10.0f)
{
VertexOut v[15];
Subdivide2(gin, v);
OutputSubdivision2(v,stream);
}
else if(distance(gin[0]) >= 10.0f && distance(gin[1]) >= 10.0f && distance(gin[2]) >= 10.0f)
{
VertexOut v[6];
Subdivide(gin, v);
OutputSubdivision(v,stream);
}
}
float4 PS(GeoOut pin, uniform int gLightCount, uniform bool gUseTexure, uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{
// Interpolating normal can unnormalize it, so normalize it.
pin.NormalW = normalize(pin.NormalW);
// The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW;
// Cache the distance to the eye from this surface point.
float distToEye = length(toEye);
// Normalize.
toEye /= distToEye;
// Default to multiplicative identity.
float4 texColor = float4(1, 1, 1, 1);
//
// Lighting.
//
float4 litColor = texColor;
if( gLightCount > 0 )
{
// Start with a sum of zero.
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f);
// Sum the light contribution from each light source.
[unroll]
for(int i = 0; i < gLightCount; ++i)
{
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLights[i], pin.NormalW, toEye, A, D, S);
ambient += A;
diffuse += D;
spec += S;
}
// Modulate with late add.
litColor = texColor * (ambient + diffuse) + spec;
}
// float4 litColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
// litColor += float4(0.1f,0.05f,0.05f,0.1f);
//
// Fogging
//
if( gFogEnabled )
{
float fogLerp = saturate( (distToEye - gFogStart) / gFogRange );
// Blend the fog color and the lit color.
litColor = lerp(litColor, gFogColor, fogLerp);
}
// Common to take alpha from diffuse material and texture.
litColor.a *= texColor.a;
return litColor;
}