「ビルボード」の編集履歴(バックアップ)一覧はこちら
「ビルボード」(2015/02/22 (日) 00:33:23) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
<p><strong>ビルボードです。<br />
ビルボードというのは常に視点(カメラ)を向く板の事です。<br />
古くは樹木や球のポリゴン数を減らすために用いられました。<br />
現在では火花や雪などのパーティクルとして主に使用されます。<br />
ビルボードにはビュー行列を逆行列にする方法もありますが、<br />
今回はもっと簡単に実装できるやり方がありましたので紹介して<br />
おきます。<br />
3D空間のビルボードオブジェクトの中心位置を保存しておき、<br />
glLoadIdentity(); して初期化します。<br />
中心位置から画像サイズ分だけ+-してポリゴンを描画すると<br />
行列計算なしでビルボードができます。</strong></p>
<p> <img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&act=open&pageid=50&file=billboard.png" /></p>
<table border="1" cellpadding="1" cellspacing="1" style="width:100px;"><tbody><tr><td>ファイル</td>
</tr><tr><td>main.cpp</td>
</tr><tr><td>lodepng.cpp</td>
</tr><tr><td>lodepng.h</td>
</tr><tr><td>tree.png</td>
</tr><tr><td>map.png</td>
</tr></tbody></table><p>main.cpp</p>
<table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td>
<p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br />
#include<br />
#include<br />
#include "lodepng.h"</p>
<p>#define WIDTH 320<br />
#define HEIGHT 240</p>
<p>//赤<br />
GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };<br />
//回転用<br />
float angleY=0.0f;<br />
float angleX=0.0f;<br />
bool flag=false;</p>
<p>class PNG{<br />
public:<br />
LodePNG_Decoder decoder;<br />
unsigned char* buffer;<br />
unsigned char* image;<br />
size_t buffersize, imagesize;<br />
int Width,Height;<br />
GLuint texture;<br />
PNG(char* FileName);<br />
void DrawBillBoard(float x,float y,float z,float sizeX,float sizeY);<br />
void DrawPolygon(float x,float y,float z,float sizeX,float sizeY);<br />
};<br />
PNG::PNG(char* FileName)<br />
{<br />
LodePNG_Decoder_init(&decoder);<br />
LodePNG_loadFile(&buffer, &buffersize, FileName);<br />
LodePNG_decode(&decoder, &image, &imagesize, buffer,
buffersize);<br />
Width = decoder.infoPng.width;<br />
Height = decoder.infoPng.height;<br />
glGenTextures(1, &texture);<br />
glBindTexture(GL_TEXTURE_2D, texture);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);<br />
}</p>
<p>void PNG::DrawBillBoard(float x,float y,float z,float sizeX,float sizeY)<br />
{<br />
GLdouble v[16];<br />
glPushMatrix();<br />
glPushMatrix();<br />
glTranslated(x, y, z);<br />
glGetDoublev(GL_MODELVIEW_MATRIX, v);<br />
glPopMatrix();</p>
<p> glLoadIdentity();</p>
<p> glEnable(GL_TEXTURE_2D);<br />
glEnable( GL_TEXTURE_RECTANGLE_EXT );//拡張機能を使う<br />
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, texture );<br />
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,Width, Height, 0,GL_RGBA,
GL_UNSIGNED_BYTE, image);<br />
glBegin(GL_POLYGON);<br />
<br />
glTexCoord2i(0, Height); glVertex3d( v[12]-sizeX, v[13]-sizeY,
v[14]);//左下<br />
glTexCoord2i(0, 0); glVertex3d( v[12]-sizeX, v[13]+sizeY,
v[14]);//左上<br />
glTexCoord2i(Width, 0); glVertex3d( v[12]+sizeX, v[13]+sizeY,
v[14]);//右上<br />
glTexCoord2i(Width, Height);glVertex3d( v[12]+sizeX, v[13]-sizeY,
v[14]);//右下</p>
<p> glEnd();</p>
<p> glDisable( GL_TEXTURE_RECTANGLE_EXT );<br />
glDisable(GL_TEXTURE_2D);<br />
glPopMatrix();<br />
}</p>
<p>void PNG::DrawPolygon(float x,float y,float z,float sizeX,float sizeY)<br />
{</p>
<p> glEnable(GL_TEXTURE_2D);<br />
glEnable( GL_TEXTURE_RECTANGLE_EXT );//拡張機能を使う<br />
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, texture );<br />
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,Width, Height, 0,GL_RGBA,
GL_UNSIGNED_BYTE, image);<br />
glBegin(GL_POLYGON);<br />
<br />
glTexCoord2i(0, Height); glVertex3d( x+sizeX, y-3, z+sizeY);//左下<br />
glTexCoord2i(0, 0); glVertex3d( x+sizeX, y-3, z-sizeY);//左上<br />
glTexCoord2i(Width, 0); glVertex3d( x-sizeX, y-3, z-sizeY);//右上<br />
glTexCoord2i(Width, Height);glVertex3d( x-sizeX, y-3, z+sizeY);//右下</p>
<p> glEnd();</p>
<p> glDisable( GL_TEXTURE_RECTANGLE_EXT );<br />
glDisable(GL_TEXTURE_2D);<br />
}</p>
<p>PNG *Map;<br />
PNG *Tree;</p>
<p>// 初期化<br />
void init(void)<br />
{<br />
glClearColor(1.0, 1.0, 1.0, 1.0);</p>
<p> glEnable(GL_DEPTH_TEST);<br />
glEnable(GL_BLEND);</p>
<p> glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);</p>
<p> Map = new PNG("map.png");<br />
Tree = new PNG("tree.png");<br />
}</p>
<p>void idle(void)<br />
{<br />
if(flag){angleX-=0.1f;}else{angleX+=0.1f;}<br />
if(angleX>10.0f)flag=true;<br />
if(angleX<-10.0f)flag=false;<br />
angleY+=0.5f;<br />
Sleep(1);<br />
glutPostRedisplay();<br />
}</p>
<p> </p>
<p>// 画面表示<br />
void display(void)<br />
{<br />
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />
glViewport(0, 0, WIDTH, HEIGHT);<br />
glMatrixMode(GL_PROJECTION);<br />
glLoadIdentity();<br />
//視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)<br />
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 5000.0);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
//視点の設定<br />
gluLookAt(0.0,5.0,-50.0, //カメラの座標<br />
0.0,0.0,0.0, // 注視点の座標<br />
0.0,1.0,0.0); // 画面の上方向を指すベクトル</p>
<p> glRotatef(angleY, 0.0, 1.0, 0.0);<br />
glRotatef(angleX, 1.0, 0.0, 1.0);</p>
<p> glDisable(GL_LIGHTING);<br />
glDepthMask(GL_FALSE);</p>
<p> Map->DrawPolygon(0.0,0.0,0.0,20.0,20.0);<br />
Tree->DrawBillBoard(0.0,0.0,10.0,3.0,3.0);<br />
Tree->DrawBillBoard(0.0,0.0,-10.0,3.0,3.0);<br />
Tree->DrawBillBoard(-10.0,0.0,0.0,3.0,3.0);<br />
Tree->DrawBillBoard(10.0,0.0,0.0,3.0,3.0);</p>
<p> glDepthMask(GL_TRUE);<br />
glEnable(GL_LIGHTING);<br />
glutSwapBuffers();<br />
}</p>
<p>int main(int argc, char *argv[])<br />
{<br />
glutInitWindowPosition(100, 100);<br />
glutInitWindowSize(WIDTH, HEIGHT);<br />
glutInit(&argc, argv);<br />
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />
glutCreateWindow("ビルボード");<br />
glutDisplayFunc(display);<br />
glutIdleFunc(idle);<br />
init();<br />
glutMainLoop();<br />
return 0;<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p><strong>ビルボードです。<br />
ビルボードというのは常に視点(カメラ)を向く板の事です。<br />
古くは樹木や球のポリゴン数を減らすために用いられました。<br />
現在では火花や雪などのパーティクルとして主に使用されます。<br />
ビルボードにはビュー行列を逆行列にする方法もありますが、<br />
今回はもっと簡単に実装できるやり方がありましたので紹介して<br />
おきます。<br />
3D空間のビルボードオブジェクトの中心位置を保存しておき、<br />
glLoadIdentity(); して初期化します。<br />
中心位置から画像サイズ分だけ+-してポリゴンを描画すると<br />
行列計算なしでビルボードができます。</strong></p>
<p> <img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&act=open&pageid=50&file=billboard.png" /></p>
<table border="1" cellpadding="1" cellspacing="1" style="width:100px;"><tbody><tr><td>ファイル</td>
</tr><tr><td><a href="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=main.cpp">
main.cpp</a></td>
</tr><tr><td><a href="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=lodepng.cpp">
lodepng.cpp</a></td>
</tr><tr><td><a href="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=lodepng.h">
lodepng.h</a></td>
</tr><tr><td>
<p><a href="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=tree.png">
tree.png</a></p>
<p><img alt="" src="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=tree.png" /></p>
</td>
</tr><tr><td>
<p><a href="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=map.png">
map.png</a></p>
<p><img alt="" src="http://www21.atwiki.jp/opengl?cmd=upload&act=open&pageid=50&file=map.png" style="width:320px;height:320px;" /></p>
</td>
</tr></tbody></table><p>main.cpp</p>
<table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td>
<p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br />
#include <gl/glew.h><br />
#include <GL/freeglut/freeglut.h><br />
#include "lodepng.h"</p>
<p>#define WIDTH 320<br />
#define HEIGHT 240</p>
<p>//赤<br />
GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };<br />
//回転用<br />
float angleY=0.0f;<br />
float angleX=0.0f;<br />
bool flag=false;</p>
<p>class PNG{<br />
public:<br />
LodePNG_Decoder decoder;<br />
unsigned char* buffer;<br />
unsigned char* image;<br />
size_t buffersize, imagesize;<br />
int Width,Height;<br />
GLuint texture;<br />
PNG(char* FileName);<br />
void DrawBillBoard(float x,float y,float z,float sizeX,float sizeY);<br />
void DrawPolygon(float x,float y,float z,float sizeX,float sizeY);<br />
};<br />
PNG::PNG(char* FileName)<br />
{<br />
LodePNG_Decoder_init(&decoder);<br />
LodePNG_loadFile(&buffer, &buffersize, FileName);<br />
LodePNG_decode(&decoder, &image, &imagesize, buffer,
buffersize);<br />
Width = decoder.infoPng.width;<br />
Height = decoder.infoPng.height;<br />
glGenTextures(1, &texture);<br />
glBindTexture(GL_TEXTURE_2D, texture);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);<br />
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);<br />
}</p>
<p>void PNG::DrawBillBoard(float x,float y,float z,float sizeX,float sizeY)<br />
{<br />
GLdouble v[16];<br />
glPushMatrix();<br />
glPushMatrix();<br />
glTranslated(x, y, z);<br />
glGetDoublev(GL_MODELVIEW_MATRIX, v);<br />
glPopMatrix();</p>
<p> glLoadIdentity();</p>
<p> glEnable(GL_TEXTURE_2D);<br />
glEnable( GL_TEXTURE_RECTANGLE_EXT );//拡張機能を使う<br />
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, texture );<br />
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,Width, Height, 0,GL_RGBA,
GL_UNSIGNED_BYTE, image);<br />
glBegin(GL_POLYGON);<br />
<br />
glTexCoord2i(0, Height); glVertex3d( v[12]-sizeX, v[13]-sizeY,
v[14]);//左下<br />
glTexCoord2i(0, 0); glVertex3d( v[12]-sizeX, v[13]+sizeY,
v[14]);//左上<br />
glTexCoord2i(Width, 0); glVertex3d( v[12]+sizeX, v[13]+sizeY,
v[14]);//右上<br />
glTexCoord2i(Width, Height);glVertex3d( v[12]+sizeX, v[13]-sizeY,
v[14]);//右下</p>
<p> glEnd();</p>
<p> glDisable( GL_TEXTURE_RECTANGLE_EXT );<br />
glDisable(GL_TEXTURE_2D);<br />
glPopMatrix();<br />
}</p>
<p>void PNG::DrawPolygon(float x,float y,float z,float sizeX,float sizeY)<br />
{</p>
<p> glEnable(GL_TEXTURE_2D);<br />
glEnable( GL_TEXTURE_RECTANGLE_EXT );//拡張機能を使う<br />
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, texture );<br />
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,Width, Height, 0,GL_RGBA,
GL_UNSIGNED_BYTE, image);<br />
glBegin(GL_POLYGON);<br />
<br />
glTexCoord2i(0, Height); glVertex3d( x+sizeX, y-3, z+sizeY);//左下<br />
glTexCoord2i(0, 0); glVertex3d( x+sizeX, y-3, z-sizeY);//左上<br />
glTexCoord2i(Width, 0); glVertex3d( x-sizeX, y-3, z-sizeY);//右上<br />
glTexCoord2i(Width, Height);glVertex3d( x-sizeX, y-3, z+sizeY);//右下</p>
<p> glEnd();</p>
<p> glDisable( GL_TEXTURE_RECTANGLE_EXT );<br />
glDisable(GL_TEXTURE_2D);<br />
}</p>
<p>PNG *Map;<br />
PNG *Tree;</p>
<p>// 初期化<br />
void init(void)<br />
{<br />
glClearColor(1.0, 1.0, 1.0, 1.0);</p>
<p> glEnable(GL_DEPTH_TEST);<br />
glEnable(GL_BLEND);</p>
<p> glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);</p>
<p> Map = new PNG("map.png");<br />
Tree = new PNG("tree.png");<br />
}</p>
<p>void idle(void)<br />
{<br />
if(flag){angleX-=0.1f;}else{angleX+=0.1f;}<br />
if(angleX>10.0f)flag=true;<br />
if(angleX<-10.0f)flag=false;<br />
angleY+=0.5f;<br />
Sleep(1);<br />
glutPostRedisplay();<br />
}</p>
<p> </p>
<p>// 画面表示<br />
void display(void)<br />
{<br />
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />
glViewport(0, 0, WIDTH, HEIGHT);<br />
glMatrixMode(GL_PROJECTION);<br />
glLoadIdentity();<br />
//視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)<br />
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 5000.0);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
//視点の設定<br />
gluLookAt(0.0,5.0,-50.0, //カメラの座標<br />
0.0,0.0,0.0, // 注視点の座標<br />
0.0,1.0,0.0); // 画面の上方向を指すベクトル</p>
<p> glRotatef(angleY, 0.0, 1.0, 0.0);<br />
glRotatef(angleX, 1.0, 0.0, 1.0);</p>
<p> glDisable(GL_LIGHTING);<br />
glDepthMask(GL_FALSE);</p>
<p> Map->DrawPolygon(0.0,0.0,0.0,20.0,20.0);<br />
Tree->DrawBillBoard(0.0,0.0,10.0,3.0,3.0);<br />
Tree->DrawBillBoard(0.0,0.0,-10.0,3.0,3.0);<br />
Tree->DrawBillBoard(-10.0,0.0,0.0,3.0,3.0);<br />
Tree->DrawBillBoard(10.0,0.0,0.0,3.0,3.0);</p>
<p> glDepthMask(GL_TRUE);<br />
glEnable(GL_LIGHTING);<br />
glutSwapBuffers();<br />
}</p>
<p>int main(int argc, char *argv[])<br />
{<br />
glutInitWindowPosition(100, 100);<br />
glutInitWindowSize(WIDTH, HEIGHT);<br />
glutInit(&argc, argv);<br />
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />
glutCreateWindow("ビルボード");<br />
glutDisplayFunc(display);<br />
glutIdleFunc(idle);<br />
init();<br />
glutMainLoop();<br />
return 0;<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>