combining specular and bump mapping in shader

Started by
2 comments, last by mickeyren 15 years, 5 months ago
Hi Not too sure how I would go about this. The models I got have 4 texture maps. Diffuse, normal, specular and height/bump maps. I have a shader that only computes the diffuse and normal maps in the shader. The TBN is already computed using D3DXComputeTangentFrameEx and passed to the vertex shader. But i think the part where I need to modify the code is in the pixel shader. Could anyone modify/add the code here that takes into account specular and bump maps? (code ff is from Frank Luna's DX 9 book btw)

float4 NormalMapPS(float3 toEyeT    : TEXCOORD0,
                   float3 lightDirT : TEXCOORD1,
                   float2 tex0      : TEXCOORD2) : COLOR
{
	// Interpolated normals can become unnormal--so normalize.
	toEyeT    = normalize(toEyeT);
	lightDirT = normalize(lightDirT);
	
	// Light vector is opposite the direction of the light.
	float3 lightVecT = -lightDirT;
	
	// Sample normal map.
	float3 normalT = tex2D(NormalMapS, tex0);
	
	// Expand from [0, 1] compressed interval to true [-1, 1] interval.
    normalT = 2.0f*normalT - 1.0f;
    
    // Make it a unit vector.
	normalT = normalize(normalT);
	
	// Compute the reflection vector.
	float3 r = reflect(-lightVecT, normalT);
	
	// Determine how much (if any) specular light makes it into the eye.
	float t  = pow(max(dot(r, toEyeT), 0.0f), gMtrl.specPower);
	
	// Determine the diffuse light intensity that strikes the vertex.
	float s = max(dot(lightVecT, normalT), 0.0f);
	
	// If the diffuse light intensity is low, kill the specular lighting term.
	// It doesn't look right to add specular light when the surface receives 
	// little diffuse light.
	if(s <= 0.0f)
	     t = 0.0f;
	
	// Compute the ambient, diffuse and specular terms separatly. 
	float3 spec = t*(gMtrl.spec*gLight.spec).rgb;
	float3 diffuse = s*(gMtrl.diffuse*gLight.diffuse).rgb;
	float3 ambient = gMtrl.ambient*gLight.ambient;
	
	// Get the texture color.
	float4 texColor = tex2D(TexS, tex0);
	
	// Combine the color from lighting with the texture color.
	float3 color = (ambient + diffuse)*texColor.rgb + spec;
	
	// Output the color and the alpha.
    return float4(color, gMtrl.diffuse.a*texColor.a);
}

gMtrl is the mesh material. gLight is the light from the scene passed to the shader. Thanks.
Advertisement
What is it that you'd like done with the height map? You're already doing normal-mapping, so there's no need for bump-mapping. You could add parallax-mapping, if you wanted.

As for the specular, that's easy. Just sample the specular map and use the value from that instead of gMtrl.spec (and also gMtrl.specPower, if your specular map includes this).
Hi MJP

Thanks for your reply. But please bare with me here.

I don't think its as easy as just replacing the specular material with the specular values from the specular map.

I used parallax mapping with the height map as you suggested using the tutorial found here: http://www.ultimategameprogramming.com/demoDownload.php?category=DirectX&page=6

It requires another sample stage for the height map + computation to combine the parallax/height map with normal and diffuse map.

ie,
float4 heightCol = tex2D(HeightMapS, tex0);float2 newTexCoord = heightCol * toEyeT + tex0;float4 diffuseCol  = tex2D(DiffuseMapS, newTexCoord);   float4 normalCol   = tex2D(NormalMapS, newTexCoord);


the diffuseCol variable is just multiplied with the rest upon returning the resulted texture color.

ie,
return float4(diffuseCol * float4((ambient + (diffuseMat * diffuse)), 1));   


however some computation is done with the normalCol varable -

normalCol = (normalCol - 0.5f) * 2;   float diffuse = saturate(dot(normalCol, -lightDirT));// and a few more computation here


That's where I wonder how/where exactly does the specular mapping computation would enter?

Anyway I think I said too much, awhile ago you said to just combine to I tried and this is what I did (similar to the first post code):

// Pull out the specular map values
float3 specT = tex2D(SpecularMapS, tex0);// Mix itfloat3 spec = t*(specT*gLight.spec).rgb;	 // This one replaces this one: float3 spec = t*(gMtrl.spec*gLight.spec).rgb


And that's it? Sorry, I'm new to shaders so I'm not too sure if I'm doing it correctly.

And doing that does not yield any difference than just using the material specular color.
hmmm might have made my post too long no one wants to help anymore :)

In short, would adding these 2 lines from my first post code is the proper way to combine the specular mapping with the resulted texture?

// Extract/sample the specular texture
float3 specT = tex2D(SpecularMapS, tex0);
// This one replaces this one: float3 spec = t*(gMtrl.spec*gLight.spec).rgb
float3 spec = t*(specT*gLight.spec).rgb;

This topic is closed to new replies.

Advertisement