Tutorial 08 –
天氣
這篇教程示範特效和燈光類比。
天空的漸層
我們用精靈渲染天空而不用紋理。
hgeSprite *sky;
sky=new hgeSprite(0, 0, 0, SCREEN_WIDTH, SKY_HEIGHT);
它的上下頂點上不同的顏色,平滑過渡。
hgeColor colSkyTop;
hgeColor colSkyBtm;
sky->SetColor(colSkyTop.GetHWColor(), 0);
sky->SetColor(colSkyTop.GetHWColor(), 1);
sky->SetColor(colSkyBtm.GetHWColor(), 2);
sky->SetColor(colSkyBtm.GetHWColor(), 3);
sky->Render(0, 0);
天空的顏色由一天中的時間決定,在一些顏色常量的插補中計算。
hgeColor col1, col2;
col1.SetHWColor(skyTopColors[seq[seq_id]]);
col2.SetHWColor(skyTopColors[seq[seq_id+1]]);
colSkyTop=col2*seq_residue + col1*(1.0f-seq_residue);
col1.SetHWColor(skyBtmColors[seq[seq_id]]);
col2.SetHWColor(skyBtmColors[seq[seq_id+1]]);
colSkyBtm=col2*seq_residue + col1*(1.0f-seq_residue);
大海和波浪
同樣的著色技術可以用於大海。但這次我們用hgeDistortionMesh類代替hgeSprite來類比波浪。
hgeDistortionMesh *sea;
sea=new hgeDistortionMesh(SEA_SUBDIVISION, SEA_SUBDIVISION);
sea->SetTextureRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-SKY_HEIGHT);
要建立波浪,我們為每個曲面網格的節點設定位移和顏色(我們跳過第一和最後一條線因為我們不想讓它們移動):
for(i=1; i<SEA_SUBDIVISION-1; i++)
{
// these are constants for each vertices line
a=float(i)/(SEA_SUBDIVISION-1);
col1=colSeaTop*(1-a)+colSeaBtm*a;
dwCol1=col1.GetHWColor();
fTime=2.0f*hge->Timer_GetTime();
a*=20;
for(j=0; j<SEA_SUBDIVISION; j++)
{
sea->SetColor(j, i, dwCol1);
dy=a*sinf(seaP[i]+ // precalculated phase shift
(float(j)/(SEA_SUBDIVISION-1)-0.5f)*M_PI*16.0f-fTime);
sea->SetDisplacement(j, i, 0.0f, dy, HGEDISP_NODE);
}
}
現在我們為先前跳過的第一和最後一條線設定顏色。
dwCol1=colSeaTop.GetHWColor();
dwCol2=colSeaBtm.GetHWColor();
for(j=0; j<SEA_SUBDIVISION; j++)
{
sea->SetColor(j, 0, dwCol1);
sea->SetColor(j, SEA_SUBDIVISION-1, dwCol2);
}
大海準備就緒,我們開始渲染:
sea->Render(0, SKY_HEIGHT);
在原始碼中從月亮到太陽有一條光線被類比。為了達到這點我們只需要在太陽月亮下增加一條1 bit的白色線。
天空的物體
星星,月亮和太陽是由帶顏色的點組成的精靈。
hgeSprite *sun;
hgeSprite *moon;
hgeSprite *star;
sun=new hgeSprite(texObjects,81,0,114,114);
sun->SetHotSpot(57,57);
moon=new hgeSprite(texObjects,0,0,81,81);
moon->SetHotSpot(40,40);
star=new hgeSprite(texObjects,72,81,9,9);
star->SetHotSpot(5,5);
有趣的地方是光暈和海面上的倒影。它們都是精靈:
hgeSprite *glow;
hgeSprite *seaglow;
glow=new hgeSprite(texObjects,128,128,128,128);
glow->SetHotSpot(64,64);
glow->SetBlendMode(BLEND_COLORADD | BLEND_ALPHABLEND);
seaglow=new hgeSprite(texObjects,128,224,128,32);
seaglow->SetHotSpot(64,0);
seaglow->SetBlendMode(BLEND_COLORADD | BLEND_ALPHAADD);
注意光暈精靈使用不同的渲染模式來達到適當的顏色。它們共用相同的紋理地區。
太陽和月亮的位置,比例和顏色在UpdateSimulation中計算,在RenderSimulation中渲染:
glow->SetColor(colSunGlow.GetHWColor());
glow->RenderEx(sunX, sunY, 0.0f, sunGlowS);
sun->SetColor(colSun.GetHWColor());
sun->RenderEx(sunX, sunY, 0.0f, sunS);
glow->SetColor(colMoonGlow.GetHWColor());
glow->RenderEx(moonX, moonY, 0.0f, moonGlowS);
moon->SetColor(colMoon.GetHWColor());
moon->RenderEx(moonX, moonY, 0.0f, moonS);
同樣的海面倒影:
seaglow->SetColor(colSeaGlow.GetHWColor());
seaglow->RenderEx(seaGlowX, SKY_HEIGHT,
0.0f, seaGlowSX, seaGlowSY);
注意海面倒影精靈不是適當的比例。
執行
這個例子跑在一個相當高的FPS下。這可能是因為Direct3D渲染精靈的瓶頸在於紋理頻寬,這個例子只用一塊小紋理渲染少量的精靈。大部分螢幕地區都填充單一的顏色。