| 導購 | 订阅 | 在线投稿
分享
 
 
 

在遊戲制作中如何實現僞體積光照效果

來源:互聯網  2008-05-19 00:45:20  評論


王朝网络

僞體積光照

1、 引言(Introduction)

在今天的許多演示及遊戲中,你可能會看到各種類型的體積效果,就如上圖所示。一個可行的想法是使用數學技巧也能做出如此令人驚奇的效果。該文的目的就是給你這個演示的實現方法 ― 它真的很容易。

In many demos and games these days you see various volumetric effects like on the picture above. One might think that it takes amazing skills in both programming as well as mathematics to do such effects. The aim of this tutorial is to show one way of doing it - and it's even an easy way!

2、理論(Theory)

首先,請你看一眼這兩張紋理:

First, take a look at these two textures:

王朝网络

左圖

王朝网络

右圖

這是我們要做的事情:

This is what we do:

1)使用彩色紋理繪制對象「射出」的光(左圖)。

Draw the object 'emitting' the light using the colour-texture (the one on the left).

2)稍微變化對象的比例。

Slightly scale the object.

3)在混合方式下使用掩碼紋理繪制對象(右圖)。

Draw the object using the mask-texture (the one on the right) in a blend mode.

4)重複2與3點 ― 你重複次數愈多,它看起來會更加漂亮(上面的效果我循環了50次)。

Repeat points 2 and 3 - the more times you repeat them, the better it looks (the image above loops 50 times).

3、實現(Implementation)

這方法不受任何特定應用程序接口(它將會與硬件及軟件一起工作)的限制,但是我想聲明的是,它受到象素填充率的限制(在GF3的640x480下運行爲50幀,而Quadro2上僅僅爲25幀)。

This method is not limited to any specific API's (it'll work with both hardware and software), apart from the fact, that it is *very* fillrate limited (i get 50fps on gf3 in 640x480, but only 25fps on quadro2).

這裏是核心的OpenGL代碼(你只需將其放進你自己的程序框架或演示系統中):

Here is the needed code for OpenGL (you need to put this into your own framework or demosystem):

GLuint texture[2];

// Load the textures into this array.

GLUquadricObj *sphere;

// This is our object - you can use your own geometric data if you like.

// Call this function from your initroutine.

void InitQuadric()

// Initialise the quadric object.

{

sphere = gluNewQuadric();

// Create new quadric.

gluQuadricNormals(sphere, GLU_SMOOTH);

// Set normals to be smooth.

gluQuadricTexture(sphere, GL_TRUE);

// Enable texturemapping.

}

// This is the main routine - call this every frame.

void DrawVolLight()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Clear screen and depthbuffer

static float angle = 0.0f;

// Variable to control rotation of the object.

glLoadIdentity();

// Reset the modelview matrix.

glTranslatef(0.0f, 0.0f, -15.0f);

// Move the object in place.

glRotatef(angle, 1.2f, 0.4f, 0.7f);

// Rotate the object.

glEnable(GL_TEXTURE_2D);

// Enable texturemapping.

glBindTexture(GL_TEXTURE_2D, texture[0]);

// Use the colour-texture.

glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

// Full colour and no blending.

gluSphere(sphere, 2, 32, 16);

// Draw the object.

glBlendFunc(GL_SRC_ALPHA, GL_ONE);

// Setup blending.

glBindTexture(GL_TEXTURE_2D, texture[1]);

// Use the mask-texture.

glEnable(GL_BLEND);

// Turn on blending.

glDepthMask(GL_NEVER);

// Don't write to depth buffer

static float numlayers = 50;

// This it the amount of loops - higher values equals better looking (and slower) light.

for (float n = 0; n

// The loop!

{

float scale = 1+n/numlayers;

// calculate the scale-factor.

float color = 1.0f/n+sin(angle/10)/16; // Calculate the percentage of colour used in the blending.

glLoadIdentity();

// Reset the modelview matrix.

glTranslatef(0.0f, 0.0f, -15.0f);

// Position the object.

glRotatef(angle, 1.2f, 0.4f, 0.7f);

// Rotate the object.

glScalef(scale, scale, scale);

// Scale the object (the coordinatesystem actually)

glColor4f(color, color, color, 1.0f);

// Set the amount of colour (used for blending).

gluSphere(sphere, 2, 32, 16);

// Draw the object using the mask-texture

}

glDepthMask(GL_TRUE);

// Make it possilbe to write to the depth-buffer again.

glDisable(GL_BLEND);

// Disable blending.

angle = 0.02*(GetTickCount()-startticks);

// Set up rotation angle for the next fram

glFlush();

// Flush the GL-pipeline (force GL to finish everything it's doing).

}

在實踐中,我可能需要調整光照體積。其由調節glColor4f的值完成。

In my implementation, i have made it possible to adjust the volume of the light. It is done by modulating the glColor4f values.

這也就是光源看起來爲什麽好象在搏動的原因。

This is what makes the light look like it's pulsing.

4、後記(Afterword)

我知道的這個方法是使用了巨量的填充率,它可能會不適合以後的遊戲。但是請你注意,它看起來非常好,而且實現過程簡單。假如你有任何改進或建議歡迎給我來信。對了,文末的附帶的資源是一個執行版(包括紋理)。

I know that this method is a fillrate-eater and that it is probably not suitable for games for the next year or two. Nevertheless! It looks good and it is not too hard to do. Improvements / suggestions are welcome! Let me know if you make you own implementation.Download.Binary version (including textures) of my implementation can be downloaded here

     [url=/bbs/detail_1440382.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129119742.jpg[/img][/url]   僞體積光照   1、 引言(Introduction)   在今天的許多演示及遊戲中,你可能會看到各種類型的體積效果,就如上圖所示。一個可行的想法是使用數學技巧也能做出如此令人驚奇的效果。該文的目的就是給你這個演示的實現方法 ― 它真的很容易。   In many demos and games these days you see various volumetric effects like on the picture above. One might think that it takes amazing skills in both programming as well as mathematics to do such effects. The aim of this tutorial is to show one way of doing it - and it's even an easy way!   2、理論(Theory)   首先,請你看一眼這兩張紋理:   First, take a look at these two textures:      [url=/bbs/detail_1440382.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129119883.jpg[/img][/url]   左圖      [url=/bbs/detail_1440382.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129120008.jpg[/img][/url]   右圖   這是我們要做的事情:   This is what we do:   1)使用彩色紋理繪制對象「射出」的光(左圖)。   Draw the object 'emitting' the light using the colour-texture (the one on the left).   2)稍微變化對象的比例。   Slightly scale the object.   3)在混合方式下使用掩碼紋理繪制對象(右圖)。   Draw the object using the mask-texture (the one on the right) in a blend mode.   4)重複2與3點 ― 你重複次數愈多,它看起來會更加漂亮(上面的效果我循環了50次)。   Repeat points 2 and 3 - the more times you repeat them, the better it looks (the image above loops 50 times).   3、實現(Implementation)   這方法不受任何特定應用程序接口(它將會與硬件及軟件一起工作)的限制,但是我想聲明的是,它受到象素填充率的限制(在GF3的640x480下運行爲50幀,而Quadro2上僅僅爲25幀)。   This method is not limited to any specific API's (it'll work with both hardware and software), apart from the fact, that it is *very* fillrate limited (i get 50fps on gf3 in 640x480, but only 25fps on quadro2).   這裏是核心的OpenGL代碼(你只需將其放進你自己的程序框架或演示系統中):   Here is the needed code for OpenGL (you need to put this into your own framework or demosystem):   GLuint texture[2];   // Load the textures into this array.   GLUquadricObj *sphere;   // This is our object - you can use your own geometric data if you like.   // Call this function from your initroutine.   void InitQuadric()   // Initialise the quadric object.   {   sphere = gluNewQuadric();   // Create new quadric.   gluQuadricNormals(sphere, GLU_SMOOTH);   // Set normals to be smooth.   gluQuadricTexture(sphere, GL_TRUE);   // Enable texturemapping.   }   // This is the main routine - call this every frame.   void DrawVolLight()   {   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // Clear screen and depthbuffer   static float angle = 0.0f;   // Variable to control rotation of the object.   glLoadIdentity();   // Reset the modelview matrix.   glTranslatef(0.0f, 0.0f, -15.0f);   // Move the object in place.   glRotatef(angle, 1.2f, 0.4f, 0.7f);   // Rotate the object.   glEnable(GL_TEXTURE_2D);   // Enable texturemapping.   glBindTexture(GL_TEXTURE_2D, texture[0]);   // Use the colour-texture.   glColor4f(1.0f, 1.0f, 1.0f, 1.0f);   // Full colour and no blending.   gluSphere(sphere, 2, 32, 16);   // Draw the object.   glBlendFunc(GL_SRC_ALPHA, GL_ONE);   // Setup blending.   glBindTexture(GL_TEXTURE_2D, texture[1]);   // Use the mask-texture.   glEnable(GL_BLEND);   // Turn on blending.   glDepthMask(GL_NEVER);   // Don't write to depth buffer   static float numlayers = 50;   // This it the amount of loops - higher values equals better looking (and slower) light.   for (float n = 0; n   // The loop!   {   float scale = 1+n/numlayers;   // calculate the scale-factor.   float color = 1.0f/n+sin(angle/10)/16; // Calculate the percentage of colour used in the blending.   glLoadIdentity();   // Reset the modelview matrix.   glTranslatef(0.0f, 0.0f, -15.0f);   // Position the object.   glRotatef(angle, 1.2f, 0.4f, 0.7f);   // Rotate the object.   glScalef(scale, scale, scale);   // Scale the object (the coordinatesystem actually)   glColor4f(color, color, color, 1.0f);   // Set the amount of colour (used for blending).   gluSphere(sphere, 2, 32, 16);   // Draw the object using the mask-texture   }   glDepthMask(GL_TRUE);   // Make it possilbe to write to the depth-buffer again.   glDisable(GL_BLEND);   // Disable blending.   angle = 0.02*(GetTickCount()-startticks);   // Set up rotation angle for the next fram   glFlush();   // Flush the GL-pipeline (force GL to finish everything it's doing).   }   在實踐中,我可能需要調整光照體積。其由調節glColor4f的值完成。   In my implementation, i have made it possible to adjust the volume of the light. It is done by modulating the glColor4f values.   這也就是光源看起來爲什麽好象在搏動的原因。   This is what makes the light look like it's pulsing.   4、後記(Afterword)   我知道的這個方法是使用了巨量的填充率,它可能會不適合以後的遊戲。但是請你注意,它看起來非常好,而且實現過程簡單。假如你有任何改進或建議歡迎給我來信。對了,文末的附帶的資源是一個執行版(包括紋理)。   I know that this method is a fillrate-eater and that it is probably not suitable for games for the next year or two. Nevertheless! It looks good and it is not too hard to do. Improvements / suggestions are welcome! Let me know if you make you own implementation.Download.Binary version (including textures) of my implementation can be downloaded here
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有