顶点颜色在光照计算中的作用

来源:互联网 发布:linux搭建git服务器 编辑:程序博客网 时间:2024/06/04 08:27

最近在做项目的时候,碰到了使用顶点颜色没有效果的情况,研究了很久,终于把顶点颜色和渲染时的光照计算流程弄清楚了。
     首先,光照的计算与顶点的格式有关系,当顶点格式为D3DFVF_XYZ|D3DFVF_DIFFUSE时,因为没有法线信息,也无法进行光照计算,所以不管是否开启光照,渲染时都只会使用顶点颜色作为渲染的结果。
     针对D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX3 类型的顶点,当D3DRS_LIGHTING设置为TRUE,同时设置好灯光的各项参数。在这种情况下,我们来探讨一下光照计算的流程。
     首先,对于每一个顶点来说,都有一个初始颜色: InitColr = globalAmbient*vMaterialAmbient+vMaterialEmissive;然后,分别计算Diffuse和Specular的颜色值,计算过程不详细讨论,但是要注意,计算最终的值要乘以灯光的颜色并考虑灯光的衰减系数。最后将Diffuse和Specular的颜色叠加在一起: FinalColor = InitColor + Diffuse + Specular.
     我们特别需要注意的是,用于光照计算的基础颜色: vDiffuse = vLightDiffuse*vMaterialDiffuse[ vVertexDiffuse ], vSpecular = vLightSpecular*vMaterialSpecular[ vVertexSpecular ].其中第二个参数的选择是通过渲染状态来设定的:D3DRS_DIFFUSEMATERIALSOURCE,D3DRS_SPECULARMATERIALSOURCE分别控制使用材质还是顶点的颜色作为漫反射和镜面反射的颜色。而且以上渲染状态要生效必须先将D3DRS_COLORVERTEX设置为TRUE,否则顶点的颜色仍然不会被光照计算所使用,该渲染状态的详细解释如下:

D3DRS_COLORVERTEX

TRUE to enable per-vertex color or FALSE to disable it. The default value isTRUE. Enabling per-vertex color allows the system to include the color defined for individual vertices in its lighting calculations.

typedef  enum _D3DMATERIALCOLORSOURCE {  
    D3DMCS_MATERIAL = 0,   
    D3DMCS_COLOR1 = 1,   
    D3DMCS_COLOR2 = 2,   
    D3DMCS_FORCE_DWORD = 0x7fffffff}
D3DMATERIALCOLORSOURCE;
 
D3DRS_DIFFUSEMATERIALSOURCE

Diffuse color source for lighting calculations. Valid values are members of theD3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_COLOR1. The value for this render state is used only if the D3DRS_COLORVERTEX render state is set to TRUE.

D3DRS_SPECULARMATERIALSOURCE

Specular color source for lighting calculations. Valid values are members of theD3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_COLOR2.

D3DRS_AMBIENTMATERIALSOURCE

Ambient color source for lighting calculations. Valid values are members of theD3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_MATERIAL.

D3DRS_EMISSIVEMATERIALSOURCE

Emissive color source for lighting calculations. Valid values are members of theD3DMATERIALCOLORSOURCE enumerated type. The default value is D3DMCS_MATERIAL.

 

       当D3DRS_DIFFUSEMATERIALSOURCE设置为COLOR1,但是顶点并没有DIFFUSE分量时,将仍使用MATERIAL作为分量。同样,D3DRS_SPECULARMATERIALSOURCE设置为COLOR2时,如果顶点没有SPECUALR分量,仍使用MATERIAL作为分量。当设置D3DRS_LIGHTING为FALSE时,渲染会跳过光照计算的过程,直接将贴图纹理的颜色和顶点颜色的乘积作为最终的结果。当设置D3DRS_LIGHTING为TRUE但是没有设置灯光(SetLightEnable)时,最后叠加的结果将会是黑色。

     注:在顶点光照和贴图颜色叠加的时候,要注意一点,环境光加上漫反射的颜色要和贴图的颜色相乘,而镜面反射的颜色是叠加到最终的颜色之上的。如下所示:

  finalcolor =  (ambient+emmisive+diffuse)*texcolor+specular.

 1:DirectX最多支持8重纹理 索引号:0-7

2:第一层默认为D3DTOP_MODULATE,其余为D3DTOP_DISABLE.
3:逐次使用,在前一层使用以后才可启用下一层。必须安装0-1-2-3-4-5-6

-7的顺序。
4:纹理混合是阶段混合,即0和1混合后的结果再和2混合。
5:SetTextureStageState()
6:查询是否支持纹理混合以及支持几层。
if( pCaps->MaxTextureBlendStages <= 1)
   return false;
7:设置并关联纹理层
定义:
LPDIRECT3DVERTEXBUFFER9    g_pVB       = NULL;
LPDIRECT3DTEXTURE9         g_pTexture1 = NULL;      //第一层纹理
LPDIRECT3DTEXTURE9         g_pTexture2 = NULL;      //第二层纹理
创建: D3DXCreateTextureFromFile( pd3dDevice, L"Wall.bmp",

&g_pTexture1 );
          D3DXCreateTextureFromFile( pd3dDevice, L"light.jpg",

&g_pTexture2 );
关联:
       pd3dDevice->SetTexture( 0, g_pTexture1 );
       pd3dDevice->SetTexture( 1, g_pTexture2 );
8:设置纹理坐标索引
如果需要使用不同的纹理坐标,在顶点格式中包含多组坐标。
pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX,   0 );
pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX,   1 );
// 定义顶点结构和灵活顶点格式
struct CUSTOMVERTEX
{
FLOAT x, y, z;     // 未经过坐标转换的顶点坐标
DWORD color;       // 顶点漫反射颜色值
FLOAT u,v ;     // 顶点纹理坐标
FLOAT u1,v1 ;    // 顶点纹理坐标
};
9:设置纹理混合
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,  

D3DTOP_MODULATE );//将下面的纹理层贴图和漫反射颜色相乘
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1,

D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2,

D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,  

D3DTOP_DISABLE );//禁用0层和1层Alpha通道混合
pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER,

D3DTEXF_LINEAR);//设置线性过滤
pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER,

D3DTEXF_LINEAR);
pd3dDevice->SetTexture( 1, g_pTexture2 );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,  

D3DTOP_ADD);
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1,

D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2,

D3DTA_CURRENT);
pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,  

D3DTOP_DISABLE );
pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX,

1 );
pd3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER,

D3DTEXF_LINEAR);
pd3dDevice->SetSamplerState(1, D3DSAMP_MINFILTER,

D3DTEXF_LINEAR);

D3DTSS_COLORARG1:默认为D3DTA_TEXTURE,即纹理颜色
D3DTSS_COLORARG2:默认为D3DTA_CURRENT,即前一纹理层的输出颜色。当

Stage参数为0时,值为D3DTA_DIFFUSE,像素漫反射颜色值。
D3DTSS_ALPHAARG1:默认为D3DTA_TEXTURE
D3DTSS_ALPHAARG2:默认为D3DTA_CURRENT,Stage参数为0时,值为

D3DTA_DIFFUSE,像素漫反射颜色值
ALPHA混合和颜色混合是分别处理的。
10:OnDestroyDevice中:
        SAFE_RELEASE(g_pVB);
SAFE_RELEASE(g_pTexture1);
SAFE_RELEASE(g_pTexture2);
11:渲染
pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
   pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
   pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0,

2);


原创粉丝点击