2011年2月27日 星期日

OpenGL物體發光效果

以前有一段時間,練習過OpenGL,現在很少用了,最近整理資料時,把以前練習寫的程式翻出來了,執行了一下,畫面如下:

雖然只是個小程式,但其實也包含了不少東西,有地形,影子,水波,公告板,雨水,各式特效等...
其中比較特別的是人物身上會有向外發散的淡淡金光,怎麼做的呢?其實就是把人物畫到貼圖上去,因為是向外發散的光,所以在一個frame內要多畫幾次,還要調整大小,這樣做好的貼圖再繪製出來就有這種效果了,
下面貼上程式碼片斷:

//先準備好貼圖
void HeroLight::Initial( void )
{
unsigned int* data;

// Create Storage Space For Texture Data (128x128x4)
data = (unsigned int*)new GLuint[((128 * 128)* 4 * sizeof(unsigned int))];
ZeroMemory(data,((128 * 128)* 4 * sizeof(unsigned int)));// Clear Storage Memory

glGenTextures(1, &Texture); // Create 1 Texture
glBindTexture(GL_TEXTURE_2D, Texture); // Bind The Texture
glTexImage2D(GL_TEXTURE_2D, 0, 4, 128, 128, 0,
GL_RGBA, GL_UNSIGNED_BYTE, data);// Build Texture Using Information In data
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

delete [] data;
}


RenderToTextureBegin與RenderToTextureEnd是拿來夾住要繪製的模型的
void HeroLight::RenderToTextureBegin( int w, int h )
{
    GLfloat glfMaterialColor[]={0.2f,0.2f,.1f,.4f}; // Set The Material Color
GLfloat specular[]={1.0f,1.0f,1.0f,1.0f};
    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,glfMaterialColor);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);
    
    Witch = w;
    Height = h;
    glViewport(0,0,128,128);
}

void HeroLight::RenderToTextureEnd( void )
{
    glBindTexture(GL_TEXTURE_2D,Texture);  
    //Copy Our ViewPort To The Texture (From 0,0 To 128,128... No Border)
    glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 128, 128, 0);
    //glClearColor(.0f, .0f, .5f, .5);// Set The Clear Color To Medium Blue
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear The Screen And Depth Buffer
    glViewport(0 , 0, Witch, Height);
}

要像這樣使用...

HeroLight.RenderToTextureBegin(Width,Height);
    glDepthFunc(GL_LESS);
    glCullFace(GL_BACK);

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_FOG);
    glDepthFunc(GL_LEQUAL);
    glFrontFace(GL_CW);
    glPolygonMode(GL_FRONT, GL_FILL);
    //角色///////////////////////////////////////////////////////////////////
    glDepthFunc(GL_LEQUAL);
    glFrontFace(GL_CW);
    glPolygonMode(GL_FRONT, GL_FILL);
    Md2Model.GetAnimate(time);
    Md2Model.SetPosition(Vector(Md2Model.GetXPosition(),
                                26,//Terrain.GetHeight(Md2Model.GetPosition())+26,
                                Md2Model.GetZPosition()));
    glBindTexture(GL_TEXTURE_2D,Md2Model.texture);
    //glDisable(GL_TEXTURE_2D);
    Md2Model.DrawModel();
    glFrontFace(GL_CCW);
    ////////////////////////////////////////////////////////////////////////
HeroLight.RenderToTextureEnd();


    //畫出模型
    /////////////////////////////////////////////////////////////////////
    glDepthFunc(GL_LESS);
    glCullFace(GL_BACK);

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_GEN_S);
    glDisable(GL_TEXTURE_GEN_T);

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_FOG);
    glDepthFunc(GL_LEQUAL);
    glFrontFace(GL_CW);
    glPolygonMode(GL_FRONT, GL_FILL);
    Md2Model.GetAnimate(time);
    Md2Model.SetPosition(Vector(Md2Model.GetXPosition(),
                                26,//Terrain.GetHeight(Md2Model.GetPosition())+26,
                                Md2Model.GetZPosition()));
    glBindTexture(GL_TEXTURE_2D,Md2Model.texture);
    //glDisable(GL_TEXTURE_2D);
    Md2Model.DrawModel();
    glFrontFace(GL_CCW);
    ////////////////////////////////////////////////////////////////////////


    HeroLight.Draw(10,.03);//最後將特效畫出

畫出的程式碼:

void HeroLight::Draw( int times, float inc ) //time約1 - 30 inc約 0.02 - 0.09
{
    float spost = 0.0f; // Starting Texture Coordinate Offset
float alphainc = 0.9f / times; // Fade Speed For Alpha Blending
float alpha = 0.2f; // Starting Alpha Value

// Disable AutoTexture Coordinates
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);

glEnable(GL_TEXTURE_2D);// Enable 2D Texture Mapping
glDisable(GL_DEPTH_TEST);// Disable Depth Testing
    glDisable(GL_LIGHTING);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);// Set Blending Mode
glEnable(GL_BLEND); // Enable Blending
glBindTexture(GL_TEXTURE_2D,Texture);// Bind To The Blur Texture
ViewOrtho(); // Switch To An Ortho View

alphainc = alpha / times;// alphainc=0.2f / Times To Render Blur

glBegin(GL_QUADS); // Begin Drawing Quads
for (int num = 0;num < times;num++)
{
glColor4f(1.0f, 1.0f, .0f, alpha);
glTexCoord2f(0+spost,1-spost);
glVertex2f(0,0);

glTexCoord2f(0+spost,0+spost);
glVertex2f(0,Height);

glTexCoord2f(1-spost,0+spost);
glVertex2f(Witch,Height);

glTexCoord2f(1-spost,1-spost);
glVertex2f(Witch,0);

spost += inc; // Gradually Increase spost (Zooming Closer To Texture Center)
alpha = alpha - alphainc;// Gradually Decrease alpha (Gradually Fading Image Out)
}
glEnd();// Done Drawing Quads

ViewPerspective();// Switch To A Perspective View
}


//調整為2D繪製
void HeroLight::ViewOrtho( void )
{
    glMatrixMode(GL_PROJECTION); // Select Projection
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
glOrtho( 0, Witch , Height , 0, -1, 1 );
glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix
glPushMatrix(); // Push The Matrix
glLoadIdentity();

}

//恢復之前的繪製矩陣
void HeroLight::ViewPerspective( void )
{
glMatrixMode( GL_PROJECTION ); // Select Projection
glPopMatrix(); // Pop The Matrix
glMatrixMode( GL_MODELVIEW );// Select Modelview
glPopMatrix(); // Pop The Matrix

}

其實要做到物體發光的效果,應該是有其它更好的做法,沒記錯的話,這應該是8年前寫的東西了,還有其它雜七雜八的東西,也打算整理一下,丟上來做個記錄.

沒有留言:

張貼留言