Sign in to follow this  
GambitSnax

BRDF artifact

Recommended Posts

GambitSnax    122
I've been working on a BRDF shader for a little while now and just have one final problem with it. The problem seems a little obtuse to me, but i'll do my best at explaining it. On the object's x-y plane, the object always reflects as if it is always pointing towards the light. The effect I get then is a nicely rendered BRDF object, but with a white jagged line all the way along the x-y plane of the object jutting backwards and forwards across the plane. As the coordinates at that point think it is pointing towards the light I get a strong specular reflection. I think it may be to do with my tangent frame coordinate generation as I don't have any texture coordinates for the initial object, and they are just generated from the vertex normals. Is it ok to do this? I've included my generation code below -
	// define vertex structure
	D3DVERTEXELEMENT9 VertexArray[] = 
	{
		{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},	// position
		{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
		{0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0},
		{0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
		D3DDECL_END()
	};

	LPD3DXMESH pMeshClonedBox = NULL;
	V_RETURN(a_pMesh->CloneMesh(D3DXMESH_MANAGED, VertexArray, pd3dDevice, &pMeshClonedBox))

	SAFE_RELEASE(a_pMesh);

	V_RETURN(D3DXComputeTangentFrameEx(pMeshClonedBox,	0, 0,
														D3DDECLUSAGE_BINORMAL, 0,
														D3DDECLUSAGE_TANGENT, 0,
														D3DDECLUSAGE_NORMAL, 0, 0, 0,
														0.01f, 0.25f, 0.01f, &a_pMesh, 0))

	SAFE_RELEASE(pMeshClonedBox);


There also might be a problem with my vertex shader but it looks fine to me. I've included it also. The BRDF technique used is Gram-Schmidt Half-Angle parametrization of a separable BRDF.
VSOutput VS(VSInput a_Input)
{
	VSOutput Output;

	Output.pos = mul(float4(a_Input.pos, 1.0f), g_matWorldViewProjection);
	float3 posW = mul(float4(a_Input.pos, 1.0f), g_matWorld);

	float3 toLight = normalize(mul((g_vecLightPos - posW), g_matWorldInverse));
	
	float3 toLightW = normalize(g_vecLightPos - posW);
	
	float3 toEye = normalize(mul((g_vecCameraPos - Output.pos), g_matWorldInverse));

	float3 halfVec = normalize(toEye + toLight);

	Output.coordH.x = dot(halfVec, a_Input.tan);
	Output.coordH.z = dot(halfVec, a_Input.bi);
	Output.coordH.y = dot(halfVec, a_Input.norm);

	float3 tPrime = normalize(a_Input.tan - (halfVec*dot(a_Input.tan, halfVec)));
	float3 bPrime = normalize(cross(halfVec, tPrime));

	Output.coordD.x = dot(toLight, tPrime);
	Output.coordD.z = dot(toLight, bPrime);
	Output.coordD.y = dot(toLight, halfVec);

	float3 norm = normalize(mul(float4(a_Input.norm, 0.0f), g_matWorld).xyz);
	float lightVal = max(dot(toLightW, norm), 0.0f);

	Output.col = lightVal * g_vecLightDiffuse;

	return Output;
}

The pixel shader simply uses the two calculated texture coordinates to lookup into the two texture maps and combines them together with a light intensity value (Output.col). Thanks for any suggestions of tips anyone might have. Cheers.

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