How to add specular effect to per-pixel lighting?
Now I already added ambient+diffuse with 2 pass,
ambient is constant color value;diffuse is a normalmap.
What need to be down to add specular?
thanks.
We create world.
Another pass to do:
(N.H)^p
Where:
- N is the normal vector,
- H is the (Blinn) Half vector: [H=normalise(V + L), V=view vector, L=light vector]
- p is the power or shininess
[As an alternative you could use the Phong specular reflection vector]
There are two difficult parts:
- normalisation of the half vector. A common technique is to use a "normalization cubemap" where the input vector is put into the u,v,w texture coordinates for a cube map. The pixels of the cube map then all correspond to the normalised result of the source vector - texture clamping keeps the coordinates in range. An alternative is to use 2 pixel shader instructions to do the normalisation.
- the power - this usually requires multiplying the output of a stage with itself a few times (easier in a shader) - so you often start to need multiple passes for highet powers. A greater problem however is that raising the power of the specular value loses the lower bits of precision from each colour (the lower bits of your 8 bits per component) so you get ugly banding. Floating point textures/frame buffers are the best way round this.
Something else you''ve ommitted which can make per-pixel stuff look better is attenuation/falloff - you can do that in a shader or with lookup textures.
--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com
(N.H)^p
Where:
- N is the normal vector,
- H is the (Blinn) Half vector: [H=normalise(V + L), V=view vector, L=light vector]
- p is the power or shininess
[As an alternative you could use the Phong specular reflection vector]
There are two difficult parts:
- normalisation of the half vector. A common technique is to use a "normalization cubemap" where the input vector is put into the u,v,w texture coordinates for a cube map. The pixels of the cube map then all correspond to the normalised result of the source vector - texture clamping keeps the coordinates in range. An alternative is to use 2 pixel shader instructions to do the normalisation.
- the power - this usually requires multiplying the output of a stage with itself a few times (easier in a shader) - so you often start to need multiple passes for highet powers. A greater problem however is that raising the power of the specular value loses the lower bits of precision from each colour (the lower bits of your 8 bits per component) so you get ugly banding. Floating point textures/frame buffers are the best way round this.
Something else you''ve ommitted which can make per-pixel stuff look better is attenuation/falloff - you can do that in a shader or with lookup textures.
--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com
Emm....the effect looks so bad...and many places should be speculared are not;and many white color blocks....
My code as follow :
{//Specular pass
m_D3DDevice.SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
m_D3DDevice.SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
m_D3DDevice.m_p->SetRenderState( D3DRS_TEXTUREFACTOR,
VectortoRGBA(&(m_vLookatPt-m_vEyePt),0.0f) );//View vector????
m_D3DDevice.m_p->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TFACTOR );
m_D3DDevice.m_p->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );//Base texture color,light vector?
m_D3DDevice.m_p->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_ADD );//Add,got halfway...
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);//dotproduct3 to get N.H
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );//Normalmap color
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
m_D3DDevice.SetTexture(m_TexNormal,1);//base texture
m_Panel.m_Texture=m_TexLocal;//Normal map
m_Panel.Render();
}
What is wrong?
Add other two questions:
1, how to change the color of diffuse light?Now I only simply use the Normalmap to Dot with tfactor,then modulate with base texture...
2, what is the point for using cube-env-mapping in diffuse per-pixel lighting...
thanks.
We create world.
[edited by - kimryo on April 28, 2003 10:14:26 PM]
My code as follow :
{//Specular pass
m_D3DDevice.SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
m_D3DDevice.SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
m_D3DDevice.m_p->SetRenderState( D3DRS_TEXTUREFACTOR,
VectortoRGBA(&(m_vLookatPt-m_vEyePt),0.0f) );//View vector????
m_D3DDevice.m_p->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TFACTOR );
m_D3DDevice.m_p->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );//Base texture color,light vector?
m_D3DDevice.m_p->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_ADD );//Add,got halfway...
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);//dotproduct3 to get N.H
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );//Normalmap color
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
m_D3DDevice.m_p->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
m_D3DDevice.SetTexture(m_TexNormal,1);//base texture
m_Panel.m_Texture=m_TexLocal;//Normal map
m_Panel.Render();
}
What is wrong?
Add other two questions:
1, how to change the color of diffuse light?Now I only simply use the Normalmap to Dot with tfactor,then modulate with base texture...
2, what is the point for using cube-env-mapping in diffuse per-pixel lighting...
thanks.
We create world.
[edited by - kimryo on April 28, 2003 10:14:26 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement