Jump to content
  • Advertisement
Sign in to follow this  
tokaplan

Bump mapping via D3DTOP_DOTPRODUCT3

This topic is 4848 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

I've just looked through DotProduct3 DX SDK sample. D3DTOP_DOTPRODUCT3 really produces very nice bumpmapping effect. But they do not use any base texture in that sample and this is exactly what I have problems with. The thing is, after using D3DTOP_DOTPRODUCT3 in first stage: pd3dDevice->SetTexture( 0, <normal map here> ); pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, <light vector here> ); pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 ); pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR ); ...I receive black and white pixels as an input for the second stage. D3DTOP_DOTPRODUCT3 returns 0 for not lit vertices and 1 for completely lit vertices, and some shade for partly lit vertices ( it is dot product of the vertex normal and the light direction). The problem is: I need to apply the model's texture also. But after having tried several methods of combining stages I found out it's not that easy. D3DTOP_ADD does not do because the result's too bright for lit vertices. On the contrary, D3DTOP_MODULATE gives absolutely black result for not lit vertices. Maybe there is some more complicated algorithm that would do the trick, or some other way of applying D3DTOP_DOTPRODUCT3. Thank you

Share this post


Link to post
Share on other sites
Advertisement
Try this:

// Diffuse texture stage states
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); // Multiply arguments together
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); // Result from previous texture stage
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); // Diffuse texture


Here you take the result from stage 0 (dot 3 lighting result) and modulate it with diffuse texture, which should produce correct results.

Share this post


Link to post
Share on other sites
Perhaps you could insert another stage to add a constant (or variable if you get creative) to the output from the dot product. This would allow you to add a bit of light to the base black pixels. The downside is that it adds more light to all of the pixels, including the already bright pixels, so it may not be what you're looking for.

Chris

Share this post


Link to post
Share on other sites
Quote:
Original post by centipede
Try this:

// Diffuse texture stage states
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); // Multiply arguments together
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); // Result from previous texture stage
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE); // Diffuse texture


Here you take the result from stage 0 (dot 3 lighting result) and modulate it with diffuse texture, which should produce correct results.


What do you mean by "diffuse texture"?

Share this post


Link to post
Share on other sites
I've tried this, but it's too dark. Unlit pixels remain black after multiplication, naturally, and it looks awful.

Share this post


Link to post
Share on other sites
I think what I need is to add some value depending on the color of the pixel. Something like


newColorComponent = oldColorComponent + value*(1-oldColorComponent);

Share this post


Link to post
Share on other sites
You should be using just modulate with the final stage between the DOT3 result and your model texture. Something may be wrong with your DOT3 inputs.

If I recall correctly your light vector (in TFACTOR) needs to be biased just like the normal map. So, your normalized light vector (which will have values in the range of -1 to 1) needs to be adjusted like so: TFACTOR = 0.5 + lightvector * 0.5. This puts it in the 0 to 1 range just like the normal map. The hardware expects this and does the appropriate math to convert them back to the -1 to 1 range.



Share this post


Link to post
Share on other sites
This is exactly what I'm doing:


D3DLIGHT9 light;
pd3dDevice->GetLight( 0, &light );

D3DXVECTOR3 lightDir = light.Direction;
D3DXVec3Normalize( &lightDir, &lightDir ); //not necessary, is it?
D3DXVec3TransformNormal( &lightDir, &lightDir, matWorld );

// Store the light vector, so it can be referenced in D3DTA_TFACTOR
DWORD dwFactor = VectortoRGBA( &lightDir, 0.0f );
pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, dwFactor );

pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );


pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );

pd3dDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );


And VectortoRGBA used above follows:


DWORD VectortoRGBA( D3DXVECTOR3* v, FLOAT fHeight )
{
DWORD r = (DWORD)( 127.0f * v->x + 128.0f );
DWORD g = (DWORD)( 127.0f * v->y + 128.0f );
DWORD b = (DWORD)( 127.0f * v->z + 128.0f );
DWORD a = (DWORD)( 255.0f * fHeight );

return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) );
}


Is this correct?

Share this post


Link to post
Share on other sites
Your current code is only doing the light contribution of your one light via DOT3. You really need an additional stage in the middle to add in the rest of your lighting. Ambient, tint, whatever.

pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );

pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADD );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );

pd3dDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_MODULATE );
pd3dDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT );
pd3dDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 0 );

pd3dDevice->SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE );

Or you could alternatively use something like this if you have some vertex based lighting going on as well (substitute this in the above stuff for stage 1):

pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MULTIPLYADD );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG0, D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_SPECULAR );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );


Or you could do it multipass and have a base pass that does the ambient lighting and then blend(add) the DOT3 results for each light in and then in the final pass blend(multiply) the model texture in.

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!