「水面」の編集履歴(バックアップ)一覧はこちら
「水面」(2014/11/18 (火) 01:14:54) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
<p>水面と集光模様です。</p>
<p><img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&act=open&pageid=314&file=water.png" /></p>
<p>vertex.shader</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:600px;"><tbody><tr><td>
<p> //フラグメントシェーダーに渡す変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル</p>
<p>void main(void){<br />
P = vec3(gl_ModelViewMatrix * gl_Vertex);<br />
N = normalize(gl_NormalMatrix * gl_Normal);<br />
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;<br />
gl_Position = ftransform();<br />
}</p>
</td>
</tr></tbody></table><p>flagment.shader</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:600px;"><tbody><tr><td><br />
//頂点シェーダーから受け取る変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル<br />
uniform sampler2D smplCaustics;<br />
void main(void){<br />
vec3 L = normalize(gl_LightSource[0].position.xyz - P);<br />
N = normalize(N);<br />
<br />
vec4 ambient = gl_FrontLightProduct[0].ambient;<br />
float dotNL = dot(N, L);<br />
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(0.0, dotNL);<br />
vec3 V = normalize(-P);<br />
vec3 H = normalize(L + V);<br />
float powNH = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);<br />
if(dotNL <= 0.0) powNH = 0.0;<br />
vec4 specular = gl_FrontLightProduct[0].specular * powNH;<br />
vec4 texColor = texture2DProj(smplCaustics, gl_TexCoord[0]);<br />
gl_FragColor = (ambient + diffuse) * texColor + specular;<br />
}</td>
</tr></tbody></table><p>main.cpp</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:600px;"><tbody><tr><td>
<p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br />
#pragma comment(lib,"glew32.lib")</p>
<p><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <windows.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <stdio.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <GL/glew.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <GL/freeglut/freeglut.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <math.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include "GLSL.h"</span></p>
<p>#define PAI 3.14159</p>
<p>GLSL glsl;<br />
//Windowのサイズ<br />
int width = 640;<br />
int height = 480;<br />
//マウス操作<br />
int xStart, yStart;<br />
bool flagMouse = false;<br />
//テクスチャー画像<br />
#define TEX_WIDTH 128<br />
#define TEX_HEIGHT 128<br />
GLubyte texImage[TEX_HEIGHT][TEX_WIDTH][3];<br />
//経過時間<br />
double curTime, lastTime, elapseTime1, elapseTime2;<br />
int fps = 0;//frame per sec<br />
float amp = 1.0;<br />
GLfloat fov = 60.0;//透視投影マッピングの視野角<br />
float Floor_Y = -1.0f;</p>
<p>struct MATRIX;</p>
<p>//マトリクス構造体<br />
struct MATRIX {<br />
union {<br />
struct {<br />
float _11, _12, _13, _14;<br />
float _21, _22, _23, _24;<br />
float _31, _32, _33, _34;<br />
float _41, _42, _43, _44;<br />
};<br />
float mat_4x4[4][4];<br />
float mat_16[16];<br />
};<br />
MATRIX(){//単位行列に初期化<br />
for(int i=0;i<16;i++){<br />
this->mat_16[i]=0;<br />
}<br />
this->_11=this->_22=this->_33=this->_44=1;<br />
}<br />
void PRINT(char* text){<br />
printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",<br />
text,<br />
this->_11,this->_21,this->_31,this->_41,<br />
this->_12,this->_22,this->_32,this->_42,<br />
this->_13,this->_23,this->_33,this->_43,<br />
this->_14,this->_24,this->_34,this->_44);<br />
}</p>
<p> MATRIX Multiplication(MATRIX& mat);//合成<br />
};<br />
//合成<br />
MATRIX MATRIX::Multiplication(MATRIX& mat)<br />
{<br />
MATRIX ret;<br />
for(int y=0;y<4;y++){<br />
for(int x=0;x<4;x++){<br />
ret.mat_16[y*4+x]=mat.mat_16[y*4]*this->mat_16[x]+mat.mat_16[y*4+1]*this->mat_16[x+4]+mat.mat_16[y*4+2]*this->mat_16[x+8]+mat.mat_16[y*4+3]*this->mat_16[x+12];<br />
}<br />
}<br />
return ret;<br />
}</p>
<p>//3つのベクトル<br />
struct Vector3f{<br />
float x;<br />
float y;<br />
float z;<br />
Vector3f(){};<br />
Vector3f(float _x,float _y,float _z){<br />
x=_x;y=_y;z=_z;<br />
};<br />
}vec3d;<br />
Vector3f & operator*(Vector3f &v,float size){<br />
v.x *= size;<br />
v.y *= size;<br />
v.z *= size;<br />
return v;<br />
}<br />
Vector3f & operator+(Vector3f &a,Vector3f &b){<br />
a.x+=b.x;<br />
a.y+=b.y;<br />
a.z+=b.z;<br />
return a;<br />
}</p>
<p>//正規化<br />
void normalize(Vector3f& v){<br />
float m=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);<br />
if(m > 0.0f){m = 1.0f / m;}else{m = 0.0f;}<br />
v.x*=m;<br />
v.y*=m;<br />
v.z*=m;<br />
}<br />
//外積<br />
void cross( Vector3f& src1, Vector3f& src2 ,Vector3f& dst){<br />
dst.x = src1.y*src2.z - src1.z*src2.y;<br />
dst.y = src1.z*src2.x - src1.x*src2.z;<br />
dst.z = src1.x*src2.y - src1.y*src2.x;<br />
}<br />
//内積<br />
void dot(Vector3f& src1,Vector3f& src2,float& dst){<br />
dst= src1.x*src2.x+src1.y*src2.y+src1.z*src2.z;<br />
}</p>
<p>//---------------------------------------------------------------------<br />
//法線方向計算ルーチン<br />
void calcNormal(float* p1,float* p2,float* p3,float* nn)<br />
{<br />
Vector3f A = Vector3f(p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);<br />
Vector3f B = Vector3f(p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]);<br />
//CVector n = A ^ B;//外積<br />
Vector3f n;<br />
cross(A,B,n);<br />
nn[0] = n.x; nn[1] = n.y; nn[2] = n.z;<br />
}</p>
<p>
//-----------------------------------------------------------------------------<br />
//四角形のメッシュ(x-y平面,中心が原点)<br />
//x軸方向,y軸方向の幅を固定<br />
void drawElevation(int Nx, int Ny, float sizeX, float sizeY, int sideFlag,
float* data)<br />
{<br />
//全体の幅,長さsizeX, sizeY<br />
//sideFlag = 0:側面表示せず<br />
//sideFlag = 1:側面表示する</p>
<p> const int NMAX = 130;<br />
int i, j;<br />
float p[NMAX][NMAX][3]; //頂点座標<br />
float a[NMAX][NMAX], b[NMAX][NMAX], c[NMAX][NMAX];//頂点の法線<br />
float pitchX, pitchY;<br />
float n1[3], n2[3], n3[3], n4[3];</p>
<p> if(Nx > NMAX) printf("NxがNMAXを超えています(drawElevation1) \n");<br />
if(Ny > NMAX) printf("NyがNMAXを超えています(drawElevation1) \n");</p>
<p> //セルのサイズ<br />
pitchX = sizeX / (float)Nx;<br />
pitchY = sizeY / (float)Ny;</p>
<p> //各頂点の座標<br />
for(j = 0; j <= Ny; j++){<br />
for(i = 0; i <= Nx; i++){<br />
p[i][j][0] = (float)(i - Nx / 2) * pitchX;<br />
p[i][j][1] = (float)(j - Ny / 2) * pitchY;<br />
p[i][j][2] = data[j * (Nx+1) + i];<br />
}<br />
}</p>
<p> <br />
//法線成分<br />
for(i = 0;i <= Nx;i++)<br />
for(j = 0;j <= Ny;j++)<br />
{ <br />
if(j == 0 )<br />
{<br />
if(i == 0) <br />
{<br />
calcNormal(p[0][0],p[1][0],p[0][1],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else if(i == Nx) <br />
{<br />
calcNormal(p[Nx-1][0],p[Nx][0],p[Nx][1],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else <br />
{<br />
calcNormal(p[i][0],p[i][1],p[i-1][0],n1);//左側<br />
calcNormal(p[i][0],p[i+1][0],p[i][1],n2);//右側<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
}<br />
else if(j == Ny)<br />
{<br />
if(i == 0) <br />
{<br />
calcNormal(p[0][Ny],p[0][Ny-1],p[1][Ny],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else if(i == Nx) <br />
{<br />
calcNormal(p[Nx][Ny],p[Nx-1][Ny],p[Nx][Ny-1],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else <br />
{<br />
calcNormal(p[i][Ny],p[i-1][Ny],p[i][Ny-1],n1);//左側<br />
calcNormal(p[i][Ny],p[i][Ny-1],p[i+1][Ny],n2);//右側<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
}<br />
else<br />
{<br />
if(i == 0) <br />
{<br />
calcNormal(p[0][j],p[1][j],p[0][j+1],n1);//上<br />
calcNormal(p[0][j],p[0][j-1],p[0][1],n2);//下<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
else if(i == Nx) <br />
{<br />
calcNormal(p[Nx][j],p[Nx][j+1],p[Nx-1][j],n1);//上<br />
calcNormal(p[Nx][j],p[Nx-1][j],p[Nx][j-1],n2);//下<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
else <br />
{//上下左右4個の三角形の平均<br />
calcNormal(p[i][j],p[i][j+1],p[i-1][j],n1);//左上<br />
calcNormal(p[i][j],p[i+1][j],p[i][j+1],n2);//右上<br />
calcNormal(p[i][j],p[i-1][j],p[i][j-1],n3);//左下<br />
calcNormal(p[i][j],p[i][j-1],p[i+1][j],n4);//右下<br />
a[i][j] = (n1[0]+n2[0]+n3[0]+n4[0])/4.0f;<br />
b[i][j] = (n1[1]+n2[1]+n3[1]+n4[1])/4.0f;<br />
c[i][j] = (n1[2]+n2[2]+n3[2]+n4[2])/4.0f; }<br />
}<br />
}</p>
<p>// int nC;<br />
//三角形で面を定義<br />
glBegin(GL_TRIANGLES);<br />
for(j = 0;j < Ny;j++)<br />
for(i = 0;i < Nx;i++)<br />
{<br />
//左下の三角形<br />
//各頂点の法線方向,テクスチャー座標,頂点座標を与える。<br />
glNormal3f(a[i][j],b[i][j],c[i][j]);//法線方向<br />
glVertex3fv(p[i][j]);//ポリゴンの頂点座標(以下これらを繰り返す)<br />
glNormal3f(a[i+1][j],b[i+1][j],c[i+1][j]);<br />
glVertex3fv(p[i+1][j]);<br />
glNormal3f(a[i][j+1],b[i][j+1],c[i][j+1]);<br />
glVertex3fv(p[i][j+1]);<br />
//右上の三角形<br />
glNormal3f(a[i+1][j],b[i+1][j],c[i+1][j]);<br />
glVertex3fv(p[i+1][j]);<br />
glNormal3f(a[i+1][j+1],b[i+1][j+1],c[i+1][j+1]);<br />
glVertex3fv(p[i+1][j+1]);<br />
glNormal3f(a[i][j+1],b[i][j+1],c[i][j+1]);<br />
glVertex3fv(p[i][j+1]);<br />
}<br />
glEnd();</p>
<p> if(sideFlag == 1)//側面描画<br />
{<br />
glBegin(GL_QUADS);<br />
//+x方向(i=Nx)<br />
glNormal3f(1.0, 0.0, 0.0);<br />
for(j = 0; j < Ny; j++)<br />
{<br />
glVertex3f(p[Nx][j][0], p[Nx][j][1], 0.0f);<br />
glVertex3f(p[Nx][j+1][0], p[Nx][j+1][1], 0.0f);<br />
glVertex3f(p[Nx][j+1][0], p[Nx][j+1][1], p[Nx][j+1][2]);<br />
glVertex3f(p[Nx][j][0], p[Nx][j][1], p[Nx][j][2]);<br />
}<br />
//-x方向(i=0)<br />
glNormal3f(-1.0, 0.0, 0.0);<br />
for(j = 0; j < Ny; j++)<br />
{<br />
glVertex3f(p[0][j][0], p[0][j][1], 0.0f);<br />
glVertex3f(p[0][j][0], p[0][j][1], p[0][j][2]);<br />
glVertex3f(p[0][j+1][0], p[0][j+1][1], p[0][j+1][2]);<br />
glVertex3f(p[0][j+1][0], p[0][j+1][1], 0.0f);<br />
}<br />
//+y方向(j=Ny)<br />
glNormal3f(0.0, 1.0, 0.0);<br />
for(i = 0; i < Nx; i++)<br />
{<br />
glVertex3f(p[i][Ny][0], p[i][Ny][1], 0.0f);<br />
glVertex3f(p[i][Ny][0], p[i][Ny][1], p[i][Ny][2]);<br />
glVertex3f(p[i+1][Ny][0], p[i+1][Ny][1], p[i+1][Ny][2]);<br />
glVertex3f(p[i+1][Ny][0], p[i+1][Ny][1], 0.0f);<br />
}<br />
//-y方向(j=0)<br />
glNormal3f(0.0, -1.0, 0.0);<br />
for(i = 0; i < Nx; i++)<br />
{<br />
glVertex3f(p[i][0][0], p[i][0][1], 0.0f);<br />
glVertex3f(p[i+1][0][0], p[i+1][0][1], 0.0f);<br />
glVertex3f(p[i+1][0][0], p[i+1][0][1], p[i+1][0][2]);<br />
glVertex3f(p[i][0][0], p[i][0][1], p[i][0][2]);<br />
}<br />
glEnd();<br />
}<br />
}</p>
<p>//waveデータ<br />
#define nMesh 128//最大分割数(両辺同じ,128が最大)<br />
int numWave = 1;//円形波の波源数(最大3)<br />
int kindWave = 1;<br />
float waveH = 3.0;//波の位置の高さ<br />
float period = 4.0;//並の速さ<br />
float lambda = 0.6;//並の細かさ<br />
//float amp0 = 1.0;<br />
float sizeX = 10.0;<br />
float sizeY = 10.0;<br />
float meshX = sizeX / (float)nMesh/4;<br />
float meshY = sizeY / (float)nMesh/4;<br />
float data[(nMesh+1)*(nMesh+1)];//Waveの高さデータ</p>
<p>void drawWave()<br />
{<br />
float diffuse[] = { 0.2f, 0.3f, 0.4f, 0.02f};<br />
float ambient[] = { 0.1f, 0.1f, 0.2f, 0.02f};<br />
float specular[]= { 0.2f, 0.2f, 0.3f, 0.02f};</p>
<p> glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);<br />
glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);<br />
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);<br />
glMaterialf(GL_FRONT,GL_SHININESS,100);</p>
<p> glPushMatrix();<br />
glTranslatef(0.0, waveH, 0.0);<br />
glRotatef(-90.0, 1.0, 0.0, 0.0);//x軸回転(y軸を鉛直軸にするため)<br />
glScalef(1.0, 1.0, 0.03);<br />
drawElevation(nMesh, nMesh, sizeX, sizeY, 0, data);<br />
glPopMatrix();<br />
}</p>
<p>void makeWavePlane(float amp, float t)<br />
{<br />
int i, j;<br />
float x, y;<br />
double pp = 2.0 * PAI;</p>
<p> float lambdaX = lambda;<br />
float lambdaY = lambda * 5.0;</p>
<p> for(j = 0; j <= nMesh; j++)<br />
{<br />
y = (float)( - nMesh / 2 + j) * meshY;<br />
for(i = 0; i <= nMesh; i++)<br />
{<br />
x = (float)( - nMesh / 2 + i) * meshX ;<br />
<br />
data[j * (nMesh + 1) + i] = amp * (<br />
sin(pp * (t/period - x/lambdaX - y/lambdaY ) +
1.0*sin(pp * x))<br />
+ sin(pp * (t/period + x/lambdaY - y/lambdaX) +
0.5*sin(pp * y))<br />
+ 0.5 * sin(pp * (2.0*t/period - x/lambdaX -
y/lambdaY))<br />
+ 0.1 * sin(pp * (3.0*t/period - x/lambdaX -
y/lambdaY))<br />
);<br />
}<br />
}<br />
}</p>
<p>//光源<br />
float lightPos[] = {0.0, 10.0, 0.0, 1.0};//光源位置<br />
float lightPos0[] = {0.0, 10.0, 0.0, 1.0};//光源位置(初期値)<br />
//影のマテリアル<br />
float shadowDiffuse[] = {0.0,0.0,0.0,0.1};//影の拡散光<br />
float shadowSpecular[] = {0.0,0.0,0.0,1.0};//影の鏡面光</p>
<p>//カメラと視体積<br />
struct View<br />
{<br />
//カメラ<br />
float pos[3];//位置(視点)<br />
float cnt[3];//注視点<br />
float dist; //注視点から視点までの距離<br />
float theta; //仰角(水平面との偏角)<br />
float phi; //方位角<br />
//視体積<br />
float fovY; //視野角<br />
float nearZ; //前方クリップ面(近平面)<br />
float farZ; //後方クリップ面(遠平面)<br />
};<br />
View view = { <br />
0.0, 0.0, 0.0,//pos(仮設定)<br />
0.0, 1.0, 0.0,//cnt <br />
15.0, 20.0, 0.0,//dist, theta, phi<br />
50.0, 1.0, 100.0//fovY,nearZ, farZ<br />
};<br />
View view0 = view;</p>
<p> </p>
<p>void setTexture(){<br />
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_WIDTH,TEX_HEIGHT,0,GL_RGB,GL_UNSIGNED_BYTE,texImage);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);<br />
}<br />
void setLight(){<br />
float lightAmbient0[] = {0.5, 0.5, 0.5, 1.0}; //環境光<br />
float lightDiffuse0[] = {1.0, 1.0, 1.0, 1.0}; //拡散光<br />
float lightSpecular0[] = {1.0, 1.0, 1.0, 1.0};//鏡面光<br />
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient0);<br />
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse0);<br />
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular0);<br />
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);<br />
glEnable(GL_LIGHT0);<br />
glEnable(GL_LIGHTING);<br />
}<br />
void setCamera(){<br />
double pp = PAI / 180.0;<br />
view.pos[2] = view.cnt[2] + view.dist * cos(pp * view.theta) * cos(pp *
view.phi);//z<br />
view.pos[0] = view.cnt[0] + view.dist * cos(pp * view.theta) * sin(pp *
view.phi);//x<br />
view.pos[1] = view.cnt[1] + view.dist * sin(pp * view.theta);//y<br />
}<br />
void makeTexImage(){<br />
int i, j;<br />
float v, a;</p>
<p> for(j = 0; j < TEX_HEIGHT; j++)<br />
for(i = 0; i < TEX_WIDTH; i++){<br />
v = data[j * (nMesh + 1) + i];<br />
if(kindWave == 0){ a = 180.0 + 75.0 * v ;<br />
}else{ a = 250.0 - 100.0 * v*v ;}<br />
if(a >= 255.0) a = 255.0;<br />
if(a < 120) a = 120;<br />
texImage[j][i][0] = texImage[j][i][1] = texImage[j][i][2] =
(GLubyte)a;<br />
}<br />
}<br />
void idle(void){<br />
//再描画<br />
glutPostRedisplay();<br />
}</p>
<p>void init(void){<br />
//背景色<br />
glClearColor(0.4, 0.6, 0.8, 1.0);</p>
<p> setCamera();//視点を求める<br />
setLight(); //光源設定<br />
glEnable(GL_DEPTH_TEST);<br />
glEnable(GL_NORMALIZE);<br />
printf("マウス/キー操作の説明には'h'キーをプッシュ \n");</p>
<p> //時間関係<br />
lastTime = timeGetTime();<br />
fps = 0;<br />
elapseTime1 = 0.0;//1sec間以内の経過時間<br />
elapseTime2 = 0.0; //init()後の総経過時間</p>
<p> glsl.InitGLSL("vertex.shader","flagment.shader");<br />
makeWavePlane(amp, elapseTime2);<br />
makeTexImage();<br />
setTexture();<br />
}</p>
<p>void resize(int w, int h){<br />
glViewport(0, 0, w, h);<br />
glMatrixMode(GL_PROJECTION);<br />
glLoadIdentity();<br />
gluPerspective(view.fovY, (double)w/(double)h, view.nearZ, view.farZ);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
width = w;<br />
height = h;<br />
}</p>
<p>void setTextureMatrix(){<br />
glMatrixMode(GL_TEXTURE);<br />
glLoadIdentity();<br />
glTranslatef(0.5, 0.5, 0.5);<br />
glScalef(0.5, 0.5, 0.5);<br />
gluPerspective(fov, 1.0, 0.1, 50.0);<br />
gluLookAt(lightPos[0], lightPos[1], lightPos[2], 0.0, waveH, 0.0, 0.0, 0.0,
-1.0);<br />
}</p>
<p>void drawFloor(float widthX, float widthZ, int nx, int nz){<br />
setTextureMatrix();<br />
int i, j;<br />
//Floor1枚当たりの幅<br />
float wX = widthX / (float)nx;<br />
float wZ = widthZ / (float)nz;</p>
<p> float diffuse[][4] = {<br />
{ 0.7, 0.7, 0.7, 1.0}, { 0.3f, 0.3, 0.3, 1.0} };<br />
float ambient[] = { 0.2, 0.2, 0.2, 1.0};<br />
float specular[]= { 0.5, 0.5, 0.5, 1.0};<br />
glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);<br />
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);<br />
glMaterialf(GL_FRONT,GL_SHININESS,100);</p>
<p> //通常のモデルビュー変換に戻す <br />
glMatrixMode(GL_MODELVIEW);<br />
glNormal3f(0.0, 1.0, 0.0);<br />
glPushMatrix();<br />
for (j = 0; j < nz; j++) {<br />
float z1 = -widthZ / 2.0 + wZ * j; float z2 = z1 + wZ;<br />
for (i = 0; i < nx; i++) {<br />
float x1 = -widthX / 2.0 + wX * i; float x2 = x1 + wX;</p>
<p> glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse[(i + j) & 1]);<br />
glBegin(GL_QUADS);<br />
glVertex3f(x1, Floor_Y, z1);<br />
glVertex3f(x1, Floor_Y, z2);<br />
glVertex3f(x2, Floor_Y, z2);<br />
glVertex3f(x2, Floor_Y, z1);<br />
glEnd();<br />
}<br />
}<br />
glPopMatrix();<br />
}</p>
<p>void display(void){<br />
//時間計測<br />
curTime = timeGetTime();<br />
float dt = (float)(curTime - lastTime) * 0.001;//secに変換<br />
elapseTime1 += dt;<br />
elapseTime2 += dt;<br />
fps ++;<br />
printf("elapseTime2 = %f \n", elapseTime2);<br />
if(elapseTime1 >= 1.0){<br />
printf("frame per sec = %d \n", fps);<br />
elapseTime1 = 0.0;<br />
fps = 0;<br />
}<br />
lastTime = curTime;</p>
<p> //波データを作成し、投影マップを設定<br />
makeWavePlane(amp, elapseTime2);<br />
makeTexImage();<br />
setTexture();</p>
<p> resize(width, height);<br />
//カラーバッファのクリア<br />
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);</p>
<p> if(cos(PAI * view.theta /180.0) > 0.0)//カメラ仰角90度でビューアップベクトル切替<br />
gluLookAt(view.pos[0], view.pos[1], view.pos[2], view.cnt[0],
view.cnt[1], view.cnt[2], 0.0, 1.0, 0.0);<br />
else<br />
gluLookAt(view.pos[0], view.pos[1], view.pos[2], view.cnt[0],
view.cnt[1], view.cnt[2], 0.0, -1.0, 0.0);</p>
<p> //光源設定//'l'を押した後光源位置可変<br />
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);</p>
<p> //fragment shaderのユニフォーム変数インデックスを取得<br />
GLint texLoc = glGetUniformLocation(glsl.ShaderProg, "smplCaustics");<br />
glUniform1i(texLoc, 0);//GL_TEXTURE0を適用</p>
<p> glsl.ON();<br />
//描画<br />
drawFloor(10.0, 10.0, 5, 5);<br />
glsl.OFF();</p>
<p> //テクスチャ、半透明物体があるとき<br />
glDepthMask(GL_FALSE); //デプスバッファを書き込み禁止<br />
glEnable(GL_BLEND);//アルファブレンディングを有効にする<br />
glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//色混合係数を決める</p>
<p> //半透明描画<br />
drawWave();<br />
//テクスチャ、半透明物体があるとき<br />
glDepthMask(GL_TRUE); //デプスバッファの書き込みを許可<br />
glDisable(GL_BLEND);</p>
<p> //終了<br />
glutSwapBuffers();<br />
}</p>
<p>void drawLight(void){<br />
glDisable(GL_LIGHTING);<br />
glColor3f(1.0, 1.0, 1.0);<br />
glPushMatrix();<br />
glTranslatef(lightPos[0], lightPos[1], lightPos[2]);<br />
glutSolidSphere(0.1, 10, 10);<br />
glPopMatrix();<br />
glEnable(GL_LIGHTING);<br />
}</p>
<p><br />
//以下の3個の関数はマウス操作による視点の変更に必要<br />
void mouse(int button, int state, int x, int y){<br />
double pp = PAI / 180.0;</p>
<p> if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){<br />
xStart = x; yStart = y;<br />
flagMouse = true;<br />
if(x > width/4 && x < 3*width/4 && y > height/4
&& y < 3*height/4){<br />
}<br />
}else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){<br />
if(x > width/4 && x < 3*width/4 && y > height/4
&& y < 3*height/4){<br />
}else if(( x < width/4 || x > 3*width/4) && (y >
height/4 && y < 3*height/4)){<br />
if(x < width/4 ) view.phi -= 1.0;<br />
else view.phi += 1.0;<br />
view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.phi) * cos(pp *
view.theta);<br />
view.cnt[0] = view.pos[0] - view.dist * sin(pp * view.phi) * cos(pp *
view.theta);<br />
}else if((x > width/4 && x < 3*width/4) && (y <
height/4 || y > 3*height/4)){<br />
if( y < height/4)<br />
view.theta += 1.0; <br />
else<br />
view.theta -= 1.0;</p>
<p> view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.theta) *
cos(pp * view.phi);<br />
view.cnt[0] = view.pos[0] - view.dist * cos(pp * view.theta) * sin(pp
* view.phi);<br />
view.cnt[1] = view.pos[1] - view.dist * sin(pp * view.theta);<br />
}<br />
else if(x < width/8 && y > 7*height/8) view.fovY -=
1.0;//zoom in<br />
else if(x > 7*width/8 && y > 7*height/8) view.fovY +=
1.0;//zoom out<br />
}<br />
else flagMouse = false;<br />
if(state == GLUT_DOWN) setCamera();<br />
}</p>
<p>void motion(int x, int y){<br />
if(!flagMouse) return;<br />
if(cos(PAI * view.theta /180.0) >= 0.0)<br />
view.phi -= 0.5 * (float)(x - xStart) ;//tumble<br />
else<br />
view.phi += 0.5 * (float)(x - xStart) ;//tumble</p>
<p> view.theta += 0.5 * (float)(y - yStart) ;//crane</p>
<p> setCamera();<br />
xStart = x;<br />
yStart = y;<br />
}</p>
<p><br />
void main(int argc, char *argv[]){<br />
glutInit(&argc, argv);<br />
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />
glutInitWindowSize(width, height);<br />
glutInitWindowPosition(100, 100);<br />
glutCreateWindow("水面と集光模様");<br />
glutReshapeFunc(resize);<br />
glutDisplayFunc(display);<br />
glutMouseFunc(mouse);<br />
glutMotionFunc(motion);<br />
glutIdleFunc(idle);<br />
init();<br />
glutMainLoop();<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p><strong>水面と集光模様です。</strong></p>
<p><img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&act=open&pageid=314&file=water.png" /></p>
<p>vertex.shader</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:600px;"><tbody><tr><td>
<p> //フラグメントシェーダーに渡す変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル</p>
<p>void main(void){<br />
P = vec3(gl_ModelViewMatrix * gl_Vertex);<br />
N = normalize(gl_NormalMatrix * gl_Normal);<br />
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;<br />
gl_Position = ftransform();<br />
}</p>
</td>
</tr></tbody></table><p>flagment.shader</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:600px;"><tbody><tr><td><br />
//頂点シェーダーから受け取る変数<br />
varying vec3 P;//位置ベクトル<br />
varying vec3 N;//法線ベクトル<br />
uniform sampler2D smplCaustics;<br />
void main(void){<br />
vec3 L = normalize(gl_LightSource[0].position.xyz - P);<br />
N = normalize(N);<br />
<br />
vec4 ambient = gl_FrontLightProduct[0].ambient;<br />
float dotNL = dot(N, L);<br />
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(0.0, dotNL);<br />
vec3 V = normalize(-P);<br />
vec3 H = normalize(L + V);<br />
float powNH = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);<br />
if(dotNL <= 0.0) powNH = 0.0;<br />
vec4 specular = gl_FrontLightProduct[0].specular * powNH;<br />
vec4 texColor = texture2DProj(smplCaustics, gl_TexCoord[0]);<br />
gl_FragColor = (ambient + diffuse) * texColor + specular;<br />
}</td>
</tr></tbody></table><p>main.cpp</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:600px;"><tbody><tr><td>
<p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br />
#pragma comment(lib,"glew32.lib")</p>
<p><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <windows.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <stdio.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <GL/glew.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <GL/freeglut/freeglut.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include <math.h></span><br style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;" /><span style="color:rgb(42,42,42);font-family:arial, helvetica, '繝偵Λ繧ョ繝手ァ偵ざ Pro W3', 'Hiragino Kaku Gothic Pro', Osaka, '繝。繧、繝ェ繧ェ', Meiryo, 'MS P繧エ繧キ繝�け', clean, sans-serif;font-size:12px;line-height:19.4559993743897px;">
#include "GLSL.h"</span></p>
<p>#define PAI 3.14159</p>
<p>GLSL glsl;<br />
//Windowのサイズ<br />
int width = 640;<br />
int height = 480;<br />
//マウス操作<br />
int xStart, yStart;<br />
bool flagMouse = false;<br />
//テクスチャー画像<br />
#define TEX_WIDTH 128<br />
#define TEX_HEIGHT 128<br />
GLubyte texImage[TEX_HEIGHT][TEX_WIDTH][3];<br />
//経過時間<br />
double curTime, lastTime, elapseTime1, elapseTime2;<br />
int fps = 0;//frame per sec<br />
float amp = 1.0;<br />
GLfloat fov = 60.0;//透視投影マッピングの視野角<br />
float Floor_Y = -1.0f;</p>
<p>struct MATRIX;</p>
<p>//マトリクス構造体<br />
struct MATRIX {<br />
union {<br />
struct {<br />
float _11, _12, _13, _14;<br />
float _21, _22, _23, _24;<br />
float _31, _32, _33, _34;<br />
float _41, _42, _43, _44;<br />
};<br />
float mat_4x4[4][4];<br />
float mat_16[16];<br />
};<br />
MATRIX(){//単位行列に初期化<br />
for(int i=0;i<16;i++){<br />
this->mat_16[i]=0;<br />
}<br />
this->_11=this->_22=this->_33=this->_44=1;<br />
}<br />
void PRINT(char* text){<br />
printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",<br />
text,<br />
this->_11,this->_21,this->_31,this->_41,<br />
this->_12,this->_22,this->_32,this->_42,<br />
this->_13,this->_23,this->_33,this->_43,<br />
this->_14,this->_24,this->_34,this->_44);<br />
}</p>
<p> MATRIX Multiplication(MATRIX& mat);//合成<br />
};<br />
//合成<br />
MATRIX MATRIX::Multiplication(MATRIX& mat)<br />
{<br />
MATRIX ret;<br />
for(int y=0;y<4;y++){<br />
for(int x=0;x<4;x++){<br />
ret.mat_16[y*4+x]=mat.mat_16[y*4]*this->mat_16[x]+mat.mat_16[y*4+1]*this->mat_16[x+4]+mat.mat_16[y*4+2]*this->mat_16[x+8]+mat.mat_16[y*4+3]*this->mat_16[x+12];<br />
}<br />
}<br />
return ret;<br />
}</p>
<p>//3つのベクトル<br />
struct Vector3f{<br />
float x;<br />
float y;<br />
float z;<br />
Vector3f(){};<br />
Vector3f(float _x,float _y,float _z){<br />
x=_x;y=_y;z=_z;<br />
};<br />
}vec3d;<br />
Vector3f & operator*(Vector3f &v,float size){<br />
v.x *= size;<br />
v.y *= size;<br />
v.z *= size;<br />
return v;<br />
}<br />
Vector3f & operator+(Vector3f &a,Vector3f &b){<br />
a.x+=b.x;<br />
a.y+=b.y;<br />
a.z+=b.z;<br />
return a;<br />
}</p>
<p>//正規化<br />
void normalize(Vector3f& v){<br />
float m=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);<br />
if(m > 0.0f){m = 1.0f / m;}else{m = 0.0f;}<br />
v.x*=m;<br />
v.y*=m;<br />
v.z*=m;<br />
}<br />
//外積<br />
void cross( Vector3f& src1, Vector3f& src2 ,Vector3f& dst){<br />
dst.x = src1.y*src2.z - src1.z*src2.y;<br />
dst.y = src1.z*src2.x - src1.x*src2.z;<br />
dst.z = src1.x*src2.y - src1.y*src2.x;<br />
}<br />
//内積<br />
void dot(Vector3f& src1,Vector3f& src2,float& dst){<br />
dst= src1.x*src2.x+src1.y*src2.y+src1.z*src2.z;<br />
}</p>
<p>//---------------------------------------------------------------------<br />
//法線方向計算ルーチン<br />
void calcNormal(float* p1,float* p2,float* p3,float* nn)<br />
{<br />
Vector3f A = Vector3f(p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);<br />
Vector3f B = Vector3f(p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]);<br />
//CVector n = A ^ B;//外積<br />
Vector3f n;<br />
cross(A,B,n);<br />
nn[0] = n.x; nn[1] = n.y; nn[2] = n.z;<br />
}</p>
<p>
//-----------------------------------------------------------------------------<br />
//四角形のメッシュ(x-y平面,中心が原点)<br />
//x軸方向,y軸方向の幅を固定<br />
void drawElevation(int Nx, int Ny, float sizeX, float sizeY, int sideFlag,
float* data)<br />
{<br />
//全体の幅,長さsizeX, sizeY<br />
//sideFlag = 0:側面表示せず<br />
//sideFlag = 1:側面表示する</p>
<p> const int NMAX = 130;<br />
int i, j;<br />
float p[NMAX][NMAX][3]; //頂点座標<br />
float a[NMAX][NMAX], b[NMAX][NMAX], c[NMAX][NMAX];//頂点の法線<br />
float pitchX, pitchY;<br />
float n1[3], n2[3], n3[3], n4[3];</p>
<p> if(Nx > NMAX) printf("NxがNMAXを超えています(drawElevation1) \n");<br />
if(Ny > NMAX) printf("NyがNMAXを超えています(drawElevation1) \n");</p>
<p> //セルのサイズ<br />
pitchX = sizeX / (float)Nx;<br />
pitchY = sizeY / (float)Ny;</p>
<p> //各頂点の座標<br />
for(j = 0; j <= Ny; j++){<br />
for(i = 0; i <= Nx; i++){<br />
p[i][j][0] = (float)(i - Nx / 2) * pitchX;<br />
p[i][j][1] = (float)(j - Ny / 2) * pitchY;<br />
p[i][j][2] = data[j * (Nx+1) + i];<br />
}<br />
}</p>
<p> <br />
//法線成分<br />
for(i = 0;i <= Nx;i++)<br />
for(j = 0;j <= Ny;j++)<br />
{ <br />
if(j == 0 )<br />
{<br />
if(i == 0) <br />
{<br />
calcNormal(p[0][0],p[1][0],p[0][1],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else if(i == Nx) <br />
{<br />
calcNormal(p[Nx-1][0],p[Nx][0],p[Nx][1],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else <br />
{<br />
calcNormal(p[i][0],p[i][1],p[i-1][0],n1);//左側<br />
calcNormal(p[i][0],p[i+1][0],p[i][1],n2);//右側<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
}<br />
else if(j == Ny)<br />
{<br />
if(i == 0) <br />
{<br />
calcNormal(p[0][Ny],p[0][Ny-1],p[1][Ny],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else if(i == Nx) <br />
{<br />
calcNormal(p[Nx][Ny],p[Nx-1][Ny],p[Nx][Ny-1],n1);<br />
a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }<br />
else <br />
{<br />
calcNormal(p[i][Ny],p[i-1][Ny],p[i][Ny-1],n1);//左側<br />
calcNormal(p[i][Ny],p[i][Ny-1],p[i+1][Ny],n2);//右側<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
}<br />
else<br />
{<br />
if(i == 0) <br />
{<br />
calcNormal(p[0][j],p[1][j],p[0][j+1],n1);//上<br />
calcNormal(p[0][j],p[0][j-1],p[0][1],n2);//下<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
else if(i == Nx) <br />
{<br />
calcNormal(p[Nx][j],p[Nx][j+1],p[Nx-1][j],n1);//上<br />
calcNormal(p[Nx][j],p[Nx-1][j],p[Nx][j-1],n2);//下<br />
a[i][j] = (n1[0]+n2[0])/2.0f;<br />
b[i][j] = (n1[1]+n2[1])/2.0f;<br />
c[i][j] = (n1[2]+n2[2])/2.0f; }<br />
else <br />
{//上下左右4個の三角形の平均<br />
calcNormal(p[i][j],p[i][j+1],p[i-1][j],n1);//左上<br />
calcNormal(p[i][j],p[i+1][j],p[i][j+1],n2);//右上<br />
calcNormal(p[i][j],p[i-1][j],p[i][j-1],n3);//左下<br />
calcNormal(p[i][j],p[i][j-1],p[i+1][j],n4);//右下<br />
a[i][j] = (n1[0]+n2[0]+n3[0]+n4[0])/4.0f;<br />
b[i][j] = (n1[1]+n2[1]+n3[1]+n4[1])/4.0f;<br />
c[i][j] = (n1[2]+n2[2]+n3[2]+n4[2])/4.0f; }<br />
}<br />
}</p>
<p>// int nC;<br />
//三角形で面を定義<br />
glBegin(GL_TRIANGLES);<br />
for(j = 0;j < Ny;j++)<br />
for(i = 0;i < Nx;i++)<br />
{<br />
//左下の三角形<br />
//各頂点の法線方向,テクスチャー座標,頂点座標を与える。<br />
glNormal3f(a[i][j],b[i][j],c[i][j]);//法線方向<br />
glVertex3fv(p[i][j]);//ポリゴンの頂点座標(以下これらを繰り返す)<br />
glNormal3f(a[i+1][j],b[i+1][j],c[i+1][j]);<br />
glVertex3fv(p[i+1][j]);<br />
glNormal3f(a[i][j+1],b[i][j+1],c[i][j+1]);<br />
glVertex3fv(p[i][j+1]);<br />
//右上の三角形<br />
glNormal3f(a[i+1][j],b[i+1][j],c[i+1][j]);<br />
glVertex3fv(p[i+1][j]);<br />
glNormal3f(a[i+1][j+1],b[i+1][j+1],c[i+1][j+1]);<br />
glVertex3fv(p[i+1][j+1]);<br />
glNormal3f(a[i][j+1],b[i][j+1],c[i][j+1]);<br />
glVertex3fv(p[i][j+1]);<br />
}<br />
glEnd();</p>
<p> if(sideFlag == 1)//側面描画<br />
{<br />
glBegin(GL_QUADS);<br />
//+x方向(i=Nx)<br />
glNormal3f(1.0, 0.0, 0.0);<br />
for(j = 0; j < Ny; j++)<br />
{<br />
glVertex3f(p[Nx][j][0], p[Nx][j][1], 0.0f);<br />
glVertex3f(p[Nx][j+1][0], p[Nx][j+1][1], 0.0f);<br />
glVertex3f(p[Nx][j+1][0], p[Nx][j+1][1], p[Nx][j+1][2]);<br />
glVertex3f(p[Nx][j][0], p[Nx][j][1], p[Nx][j][2]);<br />
}<br />
//-x方向(i=0)<br />
glNormal3f(-1.0, 0.0, 0.0);<br />
for(j = 0; j < Ny; j++)<br />
{<br />
glVertex3f(p[0][j][0], p[0][j][1], 0.0f);<br />
glVertex3f(p[0][j][0], p[0][j][1], p[0][j][2]);<br />
glVertex3f(p[0][j+1][0], p[0][j+1][1], p[0][j+1][2]);<br />
glVertex3f(p[0][j+1][0], p[0][j+1][1], 0.0f);<br />
}<br />
//+y方向(j=Ny)<br />
glNormal3f(0.0, 1.0, 0.0);<br />
for(i = 0; i < Nx; i++)<br />
{<br />
glVertex3f(p[i][Ny][0], p[i][Ny][1], 0.0f);<br />
glVertex3f(p[i][Ny][0], p[i][Ny][1], p[i][Ny][2]);<br />
glVertex3f(p[i+1][Ny][0], p[i+1][Ny][1], p[i+1][Ny][2]);<br />
glVertex3f(p[i+1][Ny][0], p[i+1][Ny][1], 0.0f);<br />
}<br />
//-y方向(j=0)<br />
glNormal3f(0.0, -1.0, 0.0);<br />
for(i = 0; i < Nx; i++)<br />
{<br />
glVertex3f(p[i][0][0], p[i][0][1], 0.0f);<br />
glVertex3f(p[i+1][0][0], p[i+1][0][1], 0.0f);<br />
glVertex3f(p[i+1][0][0], p[i+1][0][1], p[i+1][0][2]);<br />
glVertex3f(p[i][0][0], p[i][0][1], p[i][0][2]);<br />
}<br />
glEnd();<br />
}<br />
}</p>
<p>//waveデータ<br />
#define nMesh 128//最大分割数(両辺同じ,128が最大)<br />
int numWave = 1;//円形波の波源数(最大3)<br />
int kindWave = 1;<br />
float waveH = 3.0;//波の位置の高さ<br />
float period = 4.0;//並の速さ<br />
float lambda = 0.6;//並の細かさ<br />
//float amp0 = 1.0;<br />
float sizeX = 10.0;<br />
float sizeY = 10.0;<br />
float meshX = sizeX / (float)nMesh/4;<br />
float meshY = sizeY / (float)nMesh/4;<br />
float data[(nMesh+1)*(nMesh+1)];//Waveの高さデータ</p>
<p>void drawWave()<br />
{<br />
float diffuse[] = { 0.2f, 0.3f, 0.4f, 0.02f};<br />
float ambient[] = { 0.1f, 0.1f, 0.2f, 0.02f};<br />
float specular[]= { 0.2f, 0.2f, 0.3f, 0.02f};</p>
<p> glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);<br />
glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);<br />
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);<br />
glMaterialf(GL_FRONT,GL_SHININESS,100);</p>
<p> glPushMatrix();<br />
glTranslatef(0.0, waveH, 0.0);<br />
glRotatef(-90.0, 1.0, 0.0, 0.0);//x軸回転(y軸を鉛直軸にするため)<br />
glScalef(1.0, 1.0, 0.03);<br />
drawElevation(nMesh, nMesh, sizeX, sizeY, 0, data);<br />
glPopMatrix();<br />
}</p>
<p>void makeWavePlane(float amp, float t)<br />
{<br />
int i, j;<br />
float x, y;<br />
double pp = 2.0 * PAI;</p>
<p> float lambdaX = lambda;<br />
float lambdaY = lambda * 5.0;</p>
<p> for(j = 0; j <= nMesh; j++)<br />
{<br />
y = (float)( - nMesh / 2 + j) * meshY;<br />
for(i = 0; i <= nMesh; i++)<br />
{<br />
x = (float)( - nMesh / 2 + i) * meshX ;<br />
<br />
data[j * (nMesh + 1) + i] = amp * (<br />
sin(pp * (t/period - x/lambdaX - y/lambdaY ) +
1.0*sin(pp * x))<br />
+ sin(pp * (t/period + x/lambdaY - y/lambdaX) +
0.5*sin(pp * y))<br />
+ 0.5 * sin(pp * (2.0*t/period - x/lambdaX -
y/lambdaY))<br />
+ 0.1 * sin(pp * (3.0*t/period - x/lambdaX -
y/lambdaY))<br />
);<br />
}<br />
}<br />
}</p>
<p>//光源<br />
float lightPos[] = {0.0, 10.0, 0.0, 1.0};//光源位置<br />
float lightPos0[] = {0.0, 10.0, 0.0, 1.0};//光源位置(初期値)<br />
//影のマテリアル<br />
float shadowDiffuse[] = {0.0,0.0,0.0,0.1};//影の拡散光<br />
float shadowSpecular[] = {0.0,0.0,0.0,1.0};//影の鏡面光</p>
<p>//カメラと視体積<br />
struct View<br />
{<br />
//カメラ<br />
float pos[3];//位置(視点)<br />
float cnt[3];//注視点<br />
float dist; //注視点から視点までの距離<br />
float theta; //仰角(水平面との偏角)<br />
float phi; //方位角<br />
//視体積<br />
float fovY; //視野角<br />
float nearZ; //前方クリップ面(近平面)<br />
float farZ; //後方クリップ面(遠平面)<br />
};<br />
View view = { <br />
0.0, 0.0, 0.0,//pos(仮設定)<br />
0.0, 1.0, 0.0,//cnt <br />
15.0, 20.0, 0.0,//dist, theta, phi<br />
50.0, 1.0, 100.0//fovY,nearZ, farZ<br />
};<br />
View view0 = view;</p>
<p> </p>
<p>void setTexture(){<br />
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_WIDTH,TEX_HEIGHT,0,GL_RGB,GL_UNSIGNED_BYTE,texImage);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);<br />
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);<br />
}<br />
void setLight(){<br />
float lightAmbient0[] = {0.5, 0.5, 0.5, 1.0}; //環境光<br />
float lightDiffuse0[] = {1.0, 1.0, 1.0, 1.0}; //拡散光<br />
float lightSpecular0[] = {1.0, 1.0, 1.0, 1.0};//鏡面光<br />
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient0);<br />
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse0);<br />
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular0);<br />
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);<br />
glEnable(GL_LIGHT0);<br />
glEnable(GL_LIGHTING);<br />
}<br />
void setCamera(){<br />
double pp = PAI / 180.0;<br />
view.pos[2] = view.cnt[2] + view.dist * cos(pp * view.theta) * cos(pp *
view.phi);//z<br />
view.pos[0] = view.cnt[0] + view.dist * cos(pp * view.theta) * sin(pp *
view.phi);//x<br />
view.pos[1] = view.cnt[1] + view.dist * sin(pp * view.theta);//y<br />
}<br />
void makeTexImage(){<br />
int i, j;<br />
float v, a;</p>
<p> for(j = 0; j < TEX_HEIGHT; j++)<br />
for(i = 0; i < TEX_WIDTH; i++){<br />
v = data[j * (nMesh + 1) + i];<br />
if(kindWave == 0){ a = 180.0 + 75.0 * v ;<br />
}else{ a = 250.0 - 100.0 * v*v ;}<br />
if(a >= 255.0) a = 255.0;<br />
if(a < 120) a = 120;<br />
texImage[j][i][0] = texImage[j][i][1] = texImage[j][i][2] =
(GLubyte)a;<br />
}<br />
}<br />
void idle(void){<br />
//再描画<br />
glutPostRedisplay();<br />
}</p>
<p>void init(void){<br />
//背景色<br />
glClearColor(0.4, 0.6, 0.8, 1.0);</p>
<p> setCamera();//視点を求める<br />
setLight(); //光源設定<br />
glEnable(GL_DEPTH_TEST);<br />
glEnable(GL_NORMALIZE);<br />
printf("マウス/キー操作の説明には'h'キーをプッシュ \n");</p>
<p> //時間関係<br />
lastTime = timeGetTime();<br />
fps = 0;<br />
elapseTime1 = 0.0;//1sec間以内の経過時間<br />
elapseTime2 = 0.0; //init()後の総経過時間</p>
<p> glsl.InitGLSL("vertex.shader","flagment.shader");<br />
makeWavePlane(amp, elapseTime2);<br />
makeTexImage();<br />
setTexture();<br />
}</p>
<p>void resize(int w, int h){<br />
glViewport(0, 0, w, h);<br />
glMatrixMode(GL_PROJECTION);<br />
glLoadIdentity();<br />
gluPerspective(view.fovY, (double)w/(double)h, view.nearZ, view.farZ);<br />
glMatrixMode(GL_MODELVIEW);<br />
glLoadIdentity();<br />
width = w;<br />
height = h;<br />
}</p>
<p>void setTextureMatrix(){<br />
glMatrixMode(GL_TEXTURE);<br />
glLoadIdentity();<br />
glTranslatef(0.5, 0.5, 0.5);<br />
glScalef(0.5, 0.5, 0.5);<br />
gluPerspective(fov, 1.0, 0.1, 50.0);<br />
gluLookAt(lightPos[0], lightPos[1], lightPos[2], 0.0, waveH, 0.0, 0.0, 0.0,
-1.0);<br />
}</p>
<p>void drawFloor(float widthX, float widthZ, int nx, int nz){<br />
setTextureMatrix();<br />
int i, j;<br />
//Floor1枚当たりの幅<br />
float wX = widthX / (float)nx;<br />
float wZ = widthZ / (float)nz;</p>
<p> float diffuse[][4] = {<br />
{ 0.7, 0.7, 0.7, 1.0}, { 0.3f, 0.3, 0.3, 1.0} };<br />
float ambient[] = { 0.2, 0.2, 0.2, 1.0};<br />
float specular[]= { 0.5, 0.5, 0.5, 1.0};<br />
glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);<br />
glMaterialfv(GL_FRONT,GL_SPECULAR,specular);<br />
glMaterialf(GL_FRONT,GL_SHININESS,100);</p>
<p> //通常のモデルビュー変換に戻す <br />
glMatrixMode(GL_MODELVIEW);<br />
glNormal3f(0.0, 1.0, 0.0);<br />
glPushMatrix();<br />
for (j = 0; j < nz; j++) {<br />
float z1 = -widthZ / 2.0 + wZ * j; float z2 = z1 + wZ;<br />
for (i = 0; i < nx; i++) {<br />
float x1 = -widthX / 2.0 + wX * i; float x2 = x1 + wX;</p>
<p> glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse[(i + j) & 1]);<br />
glBegin(GL_QUADS);<br />
glVertex3f(x1, Floor_Y, z1);<br />
glVertex3f(x1, Floor_Y, z2);<br />
glVertex3f(x2, Floor_Y, z2);<br />
glVertex3f(x2, Floor_Y, z1);<br />
glEnd();<br />
}<br />
}<br />
glPopMatrix();<br />
}</p>
<p>void display(void){<br />
//時間計測<br />
curTime = timeGetTime();<br />
float dt = (float)(curTime - lastTime) * 0.001;//secに変換<br />
elapseTime1 += dt;<br />
elapseTime2 += dt;<br />
fps ++;<br />
printf("elapseTime2 = %f \n", elapseTime2);<br />
if(elapseTime1 >= 1.0){<br />
printf("frame per sec = %d \n", fps);<br />
elapseTime1 = 0.0;<br />
fps = 0;<br />
}<br />
lastTime = curTime;</p>
<p> //波データを作成し、投影マップを設定<br />
makeWavePlane(amp, elapseTime2);<br />
makeTexImage();<br />
setTexture();</p>
<p> resize(width, height);<br />
//カラーバッファのクリア<br />
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);</p>
<p> if(cos(PAI * view.theta /180.0) > 0.0)//カメラ仰角90度でビューアップベクトル切替<br />
gluLookAt(view.pos[0], view.pos[1], view.pos[2], view.cnt[0],
view.cnt[1], view.cnt[2], 0.0, 1.0, 0.0);<br />
else<br />
gluLookAt(view.pos[0], view.pos[1], view.pos[2], view.cnt[0],
view.cnt[1], view.cnt[2], 0.0, -1.0, 0.0);</p>
<p> //光源設定//'l'を押した後光源位置可変<br />
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);</p>
<p> //fragment shaderのユニフォーム変数インデックスを取得<br />
GLint texLoc = glGetUniformLocation(glsl.ShaderProg, "smplCaustics");<br />
glUniform1i(texLoc, 0);//GL_TEXTURE0を適用</p>
<p> glsl.ON();<br />
//描画<br />
drawFloor(10.0, 10.0, 5, 5);<br />
glsl.OFF();</p>
<p> //テクスチャ、半透明物体があるとき<br />
glDepthMask(GL_FALSE); //デプスバッファを書き込み禁止<br />
glEnable(GL_BLEND);//アルファブレンディングを有効にする<br />
glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//色混合係数を決める</p>
<p> //半透明描画<br />
drawWave();<br />
//テクスチャ、半透明物体があるとき<br />
glDepthMask(GL_TRUE); //デプスバッファの書き込みを許可<br />
glDisable(GL_BLEND);</p>
<p> //終了<br />
glutSwapBuffers();<br />
}</p>
<p>void drawLight(void){<br />
glDisable(GL_LIGHTING);<br />
glColor3f(1.0, 1.0, 1.0);<br />
glPushMatrix();<br />
glTranslatef(lightPos[0], lightPos[1], lightPos[2]);<br />
glutSolidSphere(0.1, 10, 10);<br />
glPopMatrix();<br />
glEnable(GL_LIGHTING);<br />
}</p>
<p><br />
//以下の3個の関数はマウス操作による視点の変更に必要<br />
void mouse(int button, int state, int x, int y){<br />
double pp = PAI / 180.0;</p>
<p> if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){<br />
xStart = x; yStart = y;<br />
flagMouse = true;<br />
if(x > width/4 && x < 3*width/4 && y > height/4
&& y < 3*height/4){<br />
}<br />
}else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){<br />
if(x > width/4 && x < 3*width/4 && y > height/4
&& y < 3*height/4){<br />
}else if(( x < width/4 || x > 3*width/4) && (y >
height/4 && y < 3*height/4)){<br />
if(x < width/4 ) view.phi -= 1.0;<br />
else view.phi += 1.0;<br />
view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.phi) * cos(pp *
view.theta);<br />
view.cnt[0] = view.pos[0] - view.dist * sin(pp * view.phi) * cos(pp *
view.theta);<br />
}else if((x > width/4 && x < 3*width/4) && (y <
height/4 || y > 3*height/4)){<br />
if( y < height/4)<br />
view.theta += 1.0; <br />
else<br />
view.theta -= 1.0;</p>
<p> view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.theta) *
cos(pp * view.phi);<br />
view.cnt[0] = view.pos[0] - view.dist * cos(pp * view.theta) * sin(pp
* view.phi);<br />
view.cnt[1] = view.pos[1] - view.dist * sin(pp * view.theta);<br />
}<br />
else if(x < width/8 && y > 7*height/8) view.fovY -=
1.0;//zoom in<br />
else if(x > 7*width/8 && y > 7*height/8) view.fovY +=
1.0;//zoom out<br />
}<br />
else flagMouse = false;<br />
if(state == GLUT_DOWN) setCamera();<br />
}</p>
<p>void motion(int x, int y){<br />
if(!flagMouse) return;<br />
if(cos(PAI * view.theta /180.0) >= 0.0)<br />
view.phi -= 0.5 * (float)(x - xStart) ;//tumble<br />
else<br />
view.phi += 0.5 * (float)(x - xStart) ;//tumble</p>
<p> view.theta += 0.5 * (float)(y - yStart) ;//crane</p>
<p> setCamera();<br />
xStart = x;<br />
yStart = y;<br />
}</p>
<p><br />
void main(int argc, char *argv[]){<br />
glutInit(&argc, argv);<br />
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />
glutInitWindowSize(width, height);<br />
glutInitWindowPosition(100, 100);<br />
glutCreateWindow("水面と集光模様");<br />
glutReshapeFunc(resize);<br />
glutDisplayFunc(display);<br />
glutMouseFunc(mouse);<br />
glutMotionFunc(motion);<br />
glutIdleFunc(idle);<br />
init();<br />
glutMainLoop();<br />
}</p>
</td>
</tr></tbody></table><p> </p>