水面

水面と集光模様です。

vertex.shader

  //フラグメントシェーダーに渡す変数
  varying vec3 P;//位置ベクトル
  varying vec3 N;//法線ベクトル

void main(void){
  P = vec3(gl_ModelViewMatrix * gl_Vertex);
  N = normalize(gl_NormalMatrix * gl_Normal);
  gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;
  gl_Position = ftransform();
}

flagment.shader


  //頂点シェーダーから受け取る変数
  varying vec3 P;//位置ベクトル
  varying vec3 N;//法線ベクトル
uniform sampler2D smplCaustics;
void main(void){
  vec3 L = normalize(gl_LightSource[0].position.xyz - P);
  N = normalize(N);
  
  vec4 ambient = gl_FrontLightProduct[0].ambient;
  float dotNL = dot(N, L);
  vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(0.0, dotNL);
    vec3 V = normalize(-P);
    vec3 H = normalize(L + V);
    float powNH = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
    if(dotNL <= 0.0) powNH = 0.0;
    vec4 specular = gl_FrontLightProduct[0].specular * powNH;
  vec4 texColor = texture2DProj(smplCaustics, gl_TexCoord[0]);
    gl_FragColor = (ambient + diffuse) * texColor + specular;
}

main.cpp

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib,"glew32.lib")

#include <windows.h>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/freeglut/freeglut.h>
#include <math.h>
#include "GLSL.h"

#define PAI 3.14159

GLSL glsl;
//Windowのサイズ
int width = 640;
int height = 480;
//マウス操作
int xStart, yStart;
bool flagMouse = false;
//テクスチャー画像
#define TEX_WIDTH 128
#define TEX_HEIGHT 128
GLubyte texImage[TEX_HEIGHT][TEX_WIDTH][3];
//経過時間
double curTime, lastTime, elapseTime1, elapseTime2;
int fps = 0;//frame per sec
float amp = 1.0;
GLfloat fov = 60.0;//透視投影マッピングの視野角
float Floor_Y = -1.0f;

struct MATRIX;

//マトリクス構造体
struct MATRIX {
    union {
        struct {
            float _11, _12, _13, _14;
            float _21, _22, _23, _24;
            float _31, _32, _33, _34;
            float _41, _42, _43, _44;
        };
        float mat_4x4[4][4];
        float mat_16[16];
    };
 MATRIX(){//単位行列に初期化
  for(int i=0;i<16;i++){
   this->mat_16[i]=0;
  }
  this->_11=this->_22=this->_33=this->_44=1;
 }
 void PRINT(char* text){
  printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",
   text,
   this->_11,this->_21,this->_31,this->_41,
   this->_12,this->_22,this->_32,this->_42,
   this->_13,this->_23,this->_33,this->_43,
   this->_14,this->_24,this->_34,this->_44);
 }

 MATRIX Multiplication(MATRIX& mat);//合成
};
//合成
MATRIX MATRIX::Multiplication(MATRIX& mat)
{
 MATRIX ret;
 for(int y=0;y<4;y++){
  for(int x=0;x<4;x++){
   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];
  }
 }
 return ret;
}

//3つのベクトル
struct Vector3f{
 float x;
 float y;
 float z;
 Vector3f(){};
 Vector3f(float _x,float _y,float _z){
  x=_x;y=_y;z=_z;
 };
}vec3d;
Vector3f & operator*(Vector3f &v,float size){
 v.x *= size;
 v.y *= size;
 v.z *= size;
 return v;
}
Vector3f & operator+(Vector3f &a,Vector3f &b){
 a.x+=b.x;
 a.y+=b.y;
 a.z+=b.z;
 return a;
}

//正規化
void normalize(Vector3f& v){
 float m=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
 if(m > 0.0f){m = 1.0f / m;}else{m = 0.0f;}
 v.x*=m;
 v.y*=m;
 v.z*=m;
}
//外積
void cross( Vector3f& src1, Vector3f& src2 ,Vector3f& dst){
 dst.x = src1.y*src2.z - src1.z*src2.y;
 dst.y = src1.z*src2.x - src1.x*src2.z;
 dst.z = src1.x*src2.y - src1.y*src2.x;
}
//内積
void dot(Vector3f& src1,Vector3f& src2,float& dst){
 dst= src1.x*src2.x+src1.y*src2.y+src1.z*src2.z;
}

//---------------------------------------------------------------------
//法線方向計算ルーチン
void calcNormal(float* p1,float* p2,float* p3,float* nn)
{
    Vector3f A = Vector3f(p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]);
    Vector3f B = Vector3f(p3[0] - p2[0], p3[1] - p2[1], p3[2] - p2[2]);
    //CVector n = A ^ B;//外積
    Vector3f n;
    cross(A,B,n);
    nn[0] = n.x; nn[1] = n.y; nn[2] = n.z;
}

//-----------------------------------------------------------------------------
//四角形のメッシュ(x-y平面,中心が原点)
//x軸方向,y軸方向の幅を固定
void drawElevation(int Nx, int Ny, float sizeX, float sizeY, int sideFlag, float* data)
{
    //全体の幅,長さsizeX, sizeY
    //sideFlag = 0:側面表示せず
    //sideFlag = 1:側面表示する

    const int NMAX = 130;
    int i, j;
    float p[NMAX][NMAX][3]; //頂点座標
    float a[NMAX][NMAX], b[NMAX][NMAX], c[NMAX][NMAX];//頂点の法線
    float pitchX, pitchY;
    float n1[3], n2[3], n3[3], n4[3];

    if(Nx > NMAX) printf("NxがNMAXを超えています(drawElevation1) \n");
    if(Ny > NMAX) printf("NyがNMAXを超えています(drawElevation1) \n");

    //セルのサイズ
    pitchX = sizeX / (float)Nx;
    pitchY = sizeY / (float)Ny;

    //各頂点の座標
    for(j = 0; j <= Ny; j++){
        for(i = 0; i <= Nx; i++){
            p[i][j][0] = (float)(i - Nx / 2) * pitchX;
            p[i][j][1] = (float)(j - Ny / 2) * pitchY;
            p[i][j][2] = data[j * (Nx+1) + i];
        }
    }

            
    //法線成分
    for(i = 0;i <= Nx;i++)
        for(j = 0;j <= Ny;j++)
        {            
            if(j == 0 )
            {
                if(i == 0) 
                {
                    calcNormal(p[0][0],p[1][0],p[0][1],n1);
                    a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }
                else if(i == Nx) 
                {
                    calcNormal(p[Nx-1][0],p[Nx][0],p[Nx][1],n1);
                    a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }
                else 
                {
                    calcNormal(p[i][0],p[i][1],p[i-1][0],n1);//左側
                    calcNormal(p[i][0],p[i+1][0],p[i][1],n2);//右側
                    a[i][j] = (n1[0]+n2[0])/2.0f;
                    b[i][j] = (n1[1]+n2[1])/2.0f;
                    c[i][j] = (n1[2]+n2[2])/2.0f; }
            }
            else if(j == Ny)
            {
                if(i == 0) 
                {
                    calcNormal(p[0][Ny],p[0][Ny-1],p[1][Ny],n1);
                    a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }
                else if(i == Nx) 
                {
                    calcNormal(p[Nx][Ny],p[Nx-1][Ny],p[Nx][Ny-1],n1);
                    a[i][j] = n1[0]; b[i][j] = n1[1]; c[i][j] = n1[2]; }
                else 
                {
                    calcNormal(p[i][Ny],p[i-1][Ny],p[i][Ny-1],n1);//左側
                    calcNormal(p[i][Ny],p[i][Ny-1],p[i+1][Ny],n2);//右側
                    a[i][j] = (n1[0]+n2[0])/2.0f;
                    b[i][j] = (n1[1]+n2[1])/2.0f;
                    c[i][j] = (n1[2]+n2[2])/2.0f; }
            }
            else
            {
                if(i == 0) 
                {
                    calcNormal(p[0][j],p[1][j],p[0][j+1],n1);//上
                    calcNormal(p[0][j],p[0][j-1],p[0][1],n2);//下
                    a[i][j] = (n1[0]+n2[0])/2.0f;
                    b[i][j] = (n1[1]+n2[1])/2.0f;
                    c[i][j] = (n1[2]+n2[2])/2.0f; }
                else if(i == Nx) 
                {
                    calcNormal(p[Nx][j],p[Nx][j+1],p[Nx-1][j],n1);//上
                    calcNormal(p[Nx][j],p[Nx-1][j],p[Nx][j-1],n2);//下
                    a[i][j] = (n1[0]+n2[0])/2.0f;
                    b[i][j] = (n1[1]+n2[1])/2.0f;
                    c[i][j] = (n1[2]+n2[2])/2.0f; }
                else 
                {//上下左右4個の三角形の平均
                    calcNormal(p[i][j],p[i][j+1],p[i-1][j],n1);//左上
                    calcNormal(p[i][j],p[i+1][j],p[i][j+1],n2);//右上
                    calcNormal(p[i][j],p[i-1][j],p[i][j-1],n3);//左下
                    calcNormal(p[i][j],p[i][j-1],p[i+1][j],n4);//右下
                    a[i][j] = (n1[0]+n2[0]+n3[0]+n4[0])/4.0f;
                    b[i][j] = (n1[1]+n2[1]+n3[1]+n4[1])/4.0f;
                    c[i][j] = (n1[2]+n2[2]+n3[2]+n4[2])/4.0f; }
            }
        }

//    int nC;
    //三角形で面を定義
    glBegin(GL_TRIANGLES);
    for(j = 0;j < Ny;j++)
        for(i = 0;i < Nx;i++)
        {
            //左下の三角形
            //各頂点の法線方向,テクスチャー座標,頂点座標を与える。
            glNormal3f(a[i][j],b[i][j],c[i][j]);//法線方向
            glVertex3fv(p[i][j]);//ポリゴンの頂点座標(以下これらを繰り返す)
            glNormal3f(a[i+1][j],b[i+1][j],c[i+1][j]);
            glVertex3fv(p[i+1][j]);
            glNormal3f(a[i][j+1],b[i][j+1],c[i][j+1]);
            glVertex3fv(p[i][j+1]);
            //右上の三角形
            glNormal3f(a[i+1][j],b[i+1][j],c[i+1][j]);
            glVertex3fv(p[i+1][j]);
            glNormal3f(a[i+1][j+1],b[i+1][j+1],c[i+1][j+1]);
            glVertex3fv(p[i+1][j+1]);
            glNormal3f(a[i][j+1],b[i][j+1],c[i][j+1]);
            glVertex3fv(p[i][j+1]);
        }
    glEnd();

    if(sideFlag == 1)//側面描画
    {
        glBegin(GL_QUADS);
        //+x方向(i=Nx)
        glNormal3f(1.0, 0.0, 0.0);
        for(j = 0; j < Ny; j++)
        {
            glVertex3f(p[Nx][j][0], p[Nx][j][1], 0.0f);
            glVertex3f(p[Nx][j+1][0], p[Nx][j+1][1], 0.0f);
            glVertex3f(p[Nx][j+1][0], p[Nx][j+1][1], p[Nx][j+1][2]);
            glVertex3f(p[Nx][j][0], p[Nx][j][1], p[Nx][j][2]);
        }
        //-x方向(i=0)
        glNormal3f(-1.0, 0.0, 0.0);
        for(j = 0; j < Ny; j++)
        {
            glVertex3f(p[0][j][0], p[0][j][1], 0.0f);
            glVertex3f(p[0][j][0], p[0][j][1], p[0][j][2]);
            glVertex3f(p[0][j+1][0], p[0][j+1][1], p[0][j+1][2]);
            glVertex3f(p[0][j+1][0], p[0][j+1][1], 0.0f);
        }
        //+y方向(j=Ny)
        glNormal3f(0.0, 1.0, 0.0);
        for(i = 0; i < Nx; i++)
        {
            glVertex3f(p[i][Ny][0], p[i][Ny][1], 0.0f);
            glVertex3f(p[i][Ny][0], p[i][Ny][1], p[i][Ny][2]);
            glVertex3f(p[i+1][Ny][0], p[i+1][Ny][1], p[i+1][Ny][2]);
            glVertex3f(p[i+1][Ny][0], p[i+1][Ny][1], 0.0f);
        }
        //-y方向(j=0)
        glNormal3f(0.0, -1.0, 0.0);
        for(i = 0; i < Nx; i++)
        {
            glVertex3f(p[i][0][0], p[i][0][1], 0.0f);
            glVertex3f(p[i+1][0][0], p[i+1][0][1], 0.0f);
            glVertex3f(p[i+1][0][0], p[i+1][0][1], p[i+1][0][2]);
            glVertex3f(p[i][0][0], p[i][0][1], p[i][0][2]);
        }
        glEnd();
    }
}

//waveデータ
#define nMesh 128//最大分割数(両辺同じ,128が最大)
int numWave = 1;//円形波の波源数(最大3)
int kindWave = 1;
float waveH = 3.0;//波の位置の高さ
float period = 4.0;//並の速さ
float lambda = 0.6;//並の細かさ
//float amp0 = 1.0;
float sizeX = 10.0;
float sizeY = 10.0;
float meshX = sizeX / (float)nMesh/4;
float meshY = sizeY / (float)nMesh/4;
float data[(nMesh+1)*(nMesh+1)];//Waveの高さデータ

void drawWave()
{
    float diffuse[] = { 0.2f, 0.3f, 0.4f, 0.02f};
    float ambient[] = { 0.1f, 0.1f, 0.2f, 0.02f};
    float specular[]= { 0.2f, 0.2f, 0.3f, 0.02f};

  glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);
  glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);
  glMaterialfv(GL_FRONT,GL_SPECULAR,specular);
  glMaterialf(GL_FRONT,GL_SHININESS,100);

  glPushMatrix();
  glTranslatef(0.0, waveH, 0.0);
  glRotatef(-90.0, 1.0, 0.0, 0.0);//x軸回転(y軸を鉛直軸にするため)
    glScalef(1.0, 1.0, 0.03);
  drawElevation(nMesh, nMesh, sizeX, sizeY, 0, data);
  glPopMatrix();
}

void makeWavePlane(float amp, float t)
{
  int i, j;
  float x, y;
    double pp = 2.0 * PAI;

    float lambdaX = lambda;
    float lambdaY = lambda * 5.0;

  for(j = 0; j <= nMesh; j++)
  {
      y = (float)( - nMesh / 2 + j) * meshY;
      for(i = 0; i <= nMesh; i++)
      {
          x = (float)( - nMesh / 2 + i) * meshX ;
          
                    data[j * (nMesh + 1) + i] = amp * (
                         sin(pp * (t/period - x/lambdaX - y/lambdaY ) + 1.0*sin(pp * x))
                         + sin(pp * (t/period + x/lambdaY - y/lambdaX) + 0.5*sin(pp * y))
                         + 0.5 * sin(pp * (2.0*t/period - x/lambdaX - y/lambdaY))
                         + 0.1 * sin(pp * (3.0*t/period - x/lambdaX - y/lambdaY))
                         );
      }
  }
}

//光源
float lightPos[] = {0.0, 10.0, 0.0, 1.0};//光源位置
float lightPos0[] = {0.0, 10.0, 0.0, 1.0};//光源位置(初期値)
//影のマテリアル
float shadowDiffuse[] =  {0.0,0.0,0.0,0.1};//影の拡散光
float shadowSpecular[] = {0.0,0.0,0.0,1.0};//影の鏡面光

//カメラと視体積
struct View
{
  //カメラ
    float pos[3];//位置(視点)
    float cnt[3];//注視点
  float dist;  //注視点から視点までの距離
  float theta; //仰角(水平面との偏角)
  float phi;   //方位角
  //視体積
  float fovY;  //視野角
  float nearZ; //前方クリップ面(近平面)
  float farZ;  //後方クリップ面(遠平面)
};
View view = { 
    0.0, 0.0, 0.0,//pos(仮設定)
  0.0, 1.0, 0.0,//cnt 
    15.0, 20.0, 0.0,//dist, theta, phi
    50.0, 1.0, 100.0//fovY,nearZ, farZ
};
View view0 = view;

 

void setTexture(){
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_WIDTH,TEX_HEIGHT,0,GL_RGB,GL_UNSIGNED_BYTE,texImage);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
void setLight(){
  float lightAmbient0[] = {0.5, 0.5, 0.5, 1.0}; //環境光
  float lightDiffuse0[] = {1.0, 1.0, 1.0, 1.0}; //拡散光
  float lightSpecular0[] = {1.0, 1.0, 1.0, 1.0};//鏡面光
  glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient0);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse0);
  glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular0);
  glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHTING);
}
void setCamera(){
  double pp = PAI / 180.0;
  view.pos[2] = view.cnt[2] + view.dist * cos(pp * view.theta) * cos(pp * view.phi);//z
  view.pos[0] = view.cnt[0] + view.dist * cos(pp * view.theta) * sin(pp * view.phi);//x
  view.pos[1] = view.cnt[1] + view.dist * sin(pp * view.theta);//y
}
void makeTexImage(){
  int i, j;
    float v, a;

  for(j = 0; j < TEX_HEIGHT; j++)
        for(i = 0; i < TEX_WIDTH; i++){
            v = data[j * (nMesh + 1) + i];
            if(kindWave == 0){ a = 180.0 + 75.0 * v ;
            }else{              a = 250.0 - 100.0 * v*v  ;}
            if(a >= 255.0) a = 255.0;
            if(a < 120) a = 120;
             texImage[j][i][0] = texImage[j][i][1] = texImage[j][i][2] = (GLubyte)a;
    }
}
void idle(void){
  //再描画
  glutPostRedisplay();
}

void init(void){
 //背景色
  glClearColor(0.4, 0.6, 0.8, 1.0);

  setCamera();//視点を求める
  setLight(); //光源設定
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  printf("マウス/キー操作の説明には'h'キーをプッシュ \n");

  //時間関係
  lastTime = timeGetTime();
  fps = 0;
  elapseTime1 = 0.0;//1sec間以内の経過時間
  elapseTime2 = 0.0; //init()後の総経過時間

  glsl.InitGLSL("vertex.shader","flagment.shader");
  makeWavePlane(amp, elapseTime2);
  makeTexImage();
  setTexture();
}

void resize(int w, int h){
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(view.fovY, (double)w/(double)h, view.nearZ, view.farZ);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  width = w;
  height = h;
}

void setTextureMatrix(){
  glMatrixMode(GL_TEXTURE);
  glLoadIdentity();
  glTranslatef(0.5, 0.5, 0.5);
  glScalef(0.5, 0.5, 0.5);
  gluPerspective(fov, 1.0, 0.1, 50.0);
  gluLookAt(lightPos[0], lightPos[1], lightPos[2], 0.0, waveH, 0.0, 0.0, 0.0, -1.0);
}

void drawFloor(float widthX, float widthZ, int nx, int nz){
  setTextureMatrix();
  int i, j;
  //Floor1枚当たりの幅
  float wX = widthX / (float)nx;
  float wZ = widthZ / (float)nz;

  float diffuse[][4] = {
    { 0.7, 0.7, 0.7, 1.0}, { 0.3f, 0.3, 0.3, 1.0} };
  float ambient[] = { 0.2, 0.2, 0.2, 1.0};
  float specular[]= { 0.5, 0.5, 0.5, 1.0};
  glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);
  glMaterialfv(GL_FRONT,GL_SPECULAR,specular);
  glMaterialf(GL_FRONT,GL_SHININESS,100);

  //通常のモデルビュー変換に戻す 
  glMatrixMode(GL_MODELVIEW);
  glNormal3f(0.0, 1.0, 0.0);
  glPushMatrix();
  for (j = 0; j < nz; j++) {
    float z1 = -widthZ / 2.0 + wZ * j; float z2 = z1 + wZ;
    for (i = 0; i < nx; i++) {
      float x1 = -widthX / 2.0 + wX * i; float x2 = x1 + wX;

      glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse[(i + j) & 1]);
            glBegin(GL_QUADS);
      glVertex3f(x1, Floor_Y, z1);
      glVertex3f(x1, Floor_Y, z2);
      glVertex3f(x2, Floor_Y, z2);
      glVertex3f(x2, Floor_Y, z1);
            glEnd();
    }
  }
  glPopMatrix();
}

void display(void){
    //時間計測
  curTime = timeGetTime();
  float dt = (float)(curTime - lastTime) * 0.001;//secに変換
  elapseTime1 += dt;
  elapseTime2 += dt;
  fps ++;
        printf("elapseTime2 = %f \n", elapseTime2);
  if(elapseTime1 >= 1.0){
        printf("frame per sec = %d \n", fps);
        elapseTime1 = 0.0;
        fps = 0;
  }
  lastTime = curTime;

    //波データを作成し、投影マップを設定
    makeWavePlane(amp, elapseTime2);
    makeTexImage();
    setTexture();

    resize(width, height);
    //カラーバッファのクリア
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  if(cos(PAI * view.theta /180.0) > 0.0)//カメラ仰角90度でビューアップベクトル切替
      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);
  else
      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);

  //光源設定//'l'を押した後光源位置可変
  glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

  //fragment shaderのユニフォーム変数インデックスを取得
  GLint texLoc = glGetUniformLocation(glsl.ShaderProg, "smplCaustics");
  glUniform1i(texLoc, 0);//GL_TEXTURE0を適用

  glsl.ON();
  //描画
    drawFloor(10.0, 10.0, 5, 5);
  glsl.OFF();

    //テクスチャ、半透明物体があるとき
    glDepthMask(GL_FALSE); //デプスバッファを書き込み禁止
    glEnable(GL_BLEND);//アルファブレンディングを有効にする
    glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);//色混合係数を決める

    //半透明描画
    drawWave();
    //テクスチャ、半透明物体があるとき
    glDepthMask(GL_TRUE); //デプスバッファの書き込みを許可
    glDisable(GL_BLEND);

  //終了
  glutSwapBuffers();
}

void drawLight(void){
    glDisable(GL_LIGHTING);
    glColor3f(1.0, 1.0, 1.0);
  glPushMatrix();
    glTranslatef(lightPos[0], lightPos[1], lightPos[2]);
    glutSolidSphere(0.1, 10, 10);
  glPopMatrix();
    glEnable(GL_LIGHTING);
}


//以下の3個の関数はマウス操作による視点の変更に必要
void mouse(int button, int state, int x, int y){
  double pp = PAI / 180.0;

  if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
      xStart = x; yStart = y;
      flagMouse = true;
      if(x > width/4 && x < 3*width/4 && y > height/4 && y < 3*height/4){
      }
  }else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
      if(x > width/4 && x < 3*width/4 && y > height/4 && y < 3*height/4){
      }else if(( x < width/4 || x > 3*width/4) && (y > height/4 && y < 3*height/4)){
          if(x < width/4 ) view.phi -= 1.0;
          else view.phi += 1.0;
          view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.phi) * cos(pp * view.theta);
          view.cnt[0] = view.pos[0] - view.dist * sin(pp * view.phi) * cos(pp * view.theta);
      }else if((x > width/4 && x < 3*width/4) && (y < height/4 || y > 3*height/4)){
          if( y < height/4)
              view.theta += 1.0; 
          else
              view.theta -= 1.0;

          view.cnt[2] = view.pos[2] - view.dist * cos(pp * view.theta) * cos(pp * view.phi);
          view.cnt[0] = view.pos[0] - view.dist * cos(pp * view.theta) * sin(pp * view.phi);
          view.cnt[1] = view.pos[1] - view.dist * sin(pp * view.theta);
      }
      else if(x < width/8 && y > 7*height/8) view.fovY -= 1.0;//zoom in
      else if(x > 7*width/8 && y > 7*height/8) view.fovY += 1.0;//zoom out
  }
  else flagMouse = false;
  if(state == GLUT_DOWN) setCamera();
}

void motion(int x, int y){
  if(!flagMouse) return;
  if(cos(PAI * view.theta /180.0) >= 0.0)
    view.phi -= 0.5 * (float)(x - xStart) ;//tumble
  else
    view.phi += 0.5 * (float)(x - xStart) ;//tumble

  view.theta += 0.5 * (float)(y - yStart) ;//crane

  setCamera();
  xStart = x;
  yStart = y;
}


void main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
  glutInitWindowSize(width, height);
  glutInitWindowPosition(100, 100);
  glutCreateWindow("水面と集光模様");
  glutReshapeFunc(resize);
  glutDisplayFunc(display);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutIdleFunc(idle);
  init();
  glutMainLoop();
}

 

最終更新:2014年11月18日 01:14
添付ファイル