ディスプレースメントマップ

ディスプレイスメントマップです。
右がディスプレイスメントマップで、左がバンプマッピングです。
右の方はポリゴン形状が変化しているのに対して左は1枚のポリゴンです。
実際に形状が変化しているので非常にリアルな表現ができます。

brick128.png

bump128.png

vertex.shader

//フラグメントシェーダーに渡す変数
varying vec3 P;//位置ベクトル
varying vec3 N;//法線ベクトル
varying vec3 T;//接線ベクトル
varying vec3 B;//従法線ベクトル
attribute vec3 tangent;//OpenGLから

void main(void)
{
  P = vec3(gl_ModelViewMatrix * gl_Vertex);
  N = normalize(gl_NormalMatrix * gl_Normal);
  T = normalize(gl_NormalMatrix * tangent);
  B = cross(N, T);//従法線ベクトル
  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform() ;
}

flagment.shader

//頂点シェーダーから受け取る変数
varying vec3 P;//位置ベクトル
varying vec3 N;//法線ベクトル
varying vec3 T;//接線ベクトル
varying vec3 B;//従法線ベクトル
uniform sampler2D colorMap;//カラーマップ
uniform sampler2D normalMap;//法線マップ

void main(void)
{
    //高度勾配
    vec3 grad = (texture2D(normalMap, gl_TexCoord[0].st).xyz - 0.5) * 2.0;
    N = normalize( N - grad.x * T - grad.y * B); 
    //以下は通常のライティング
  vec3 L = normalize(gl_LightSource[0].position.xyz - P);

  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 = texture2D(colorMap, gl_TexCoord[0].st);
    gl_FragColor = (ambient + diffuse) * texColor + specular;  
}

displacement_vertex.shader

varying vec3 P;
varying vec3 N;
varying vec3 T;
varying vec3 B;
attribute vec3 tangent;
uniform sampler2D normalMap;//法線マップ
uniform float inv;
uniform float fDisp;
uniform float bias;

void main(void)

    if(inv == 1.0)
        gl_Vertex.xyz +=  fDisp * gl_Normal.xyz * (texture2D(normalMap, gl_MultiTexCoord0.xy).b - 1.0 +bias);
    else
        gl_Vertex.xyz +=  fDisp * gl_Normal.xyz * (texture2D(normalMap, gl_MultiTexCoord0.xy).b - bias);
  P = (gl_ModelViewMatrix * gl_Vertex).xyz;
  N = normalize(gl_NormalMatrix * gl_Normal).xyz;
  T = normalize(gl_NormalMatrix * tangent).xyz;
  B = cross(N, T);

  gl_TexCoord[0] = gl_MultiTexCoord0;
  gl_Position = ftransform() ;
}

displacement_flagment.shader

varying vec3 P;//位置ベクトル
varying vec3 N;//法線ベクトル
varying vec3 T;//接線ベクトル
varying vec3 B;//従法線ベクトル
uniform sampler2D colorMap;//カラーマップ
uniform sampler2D normalMap;//法線マップ

void main(void)
{
    //高度勾配を取得
    vec3 grad = (texture2D(normalMap, gl_TexCoord[0].st).xyz - 0.5) * 2.0;
    //修正された法線ベクトル
    N = normalize( N - grad.x * T - grad.y * B) ;
    //以下は通常のライティング
  vec3 L = normalize(gl_LightSource[0].position.xyz - P);
  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 = texture2D(colorMap, gl_TexCoord[0].st);
  gl_FragColor = (ambient + diffuse) * texColor  + specular;  
}

main.cpp

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

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

#define PAI 3.14159

GLSL glsl[2];

//affine変換用変数
float pos[][3] = { //位置(平行移動)
    { 1.5, 1.0, 0.0},//obj0
    {-1.5, 1.0, 0.0} //obj1
};

float scale[][3] = {//サイズ(スケーリング)
    { 2.0, 2.0, 2.0 },//obj0
    { 2.0, 2.0, 2.0 } //obj1
};

float angle[][3] = {//姿勢(回転)
    { 0.0, 0.0, 0.0}, //obj0
    { 0.0, 0.0, 0.0}  //obj1
};

//光源
float lightPos[] =  {10.0, 15.0, 10.0, 1.0};//光源位置
float lightPos0[] = {10.0, 15.0, 10.0, 1.0};//光源位置(初期値)
//影のマテリアル
float shadowDiffuse[] =  {0.0,0.0,0.0,0.3};//影の拡散光
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 
    10.0, 30.0, 20.0,//dist, theta, phi
    30.0, 1.0, 100.0//fovY,nearZ, farZ
};
View view0 = view;

//Windowのサイズ
int width = 640;
int height = 480;
//アフィン変換
enum SELECT_KEY {ROTATE, SCALE, TRANSLATE, LIGHT};
SELECT_KEY sKey = TRANSLATE;
//マウス操作
int xStart, yStart;
bool flagMouse = false;
//影のフラグ
bool flagShadow = false;
//texture
#define TEX_WIDTH 128
#define TEX_HEIGHT 128
GLubyte texImage[TEX_HEIGHT][TEX_WIDTH][4];
GLubyte normalMap[TEX_HEIGHT][TEX_WIDTH][3];
GLuint texName[6];
TEXTURE *texture[6];
float inv = 1.0;//凹凸反転
float fGrad = 5.0;//勾配強調
float fDisp = 0.15;//変位量調整
float bias = 0.3;//面変位量調整

void drawCube(float s){
    float p[8][3] = { {0.5*s,0.5*s,0.5*s}, {-0.5*s,0.5*s,0.5*s}, {-0.5*s,-0.5*s,0.5*s}, 
      {0.5*s,-0.5*s,0.5*s},{0.5*s,0.5*s,-0.5*s}, {-0.5*s,0.5*s,-0.5*s},
      {-0.5*s,-0.5*s,0-0.5*s}, {0.5*s,-0.5*s,-0.5*s}
    };

    glBegin(GL_QUADS);
        glNormal3f(0.0f,0.0f,1.0f); //z方向
        glVertex3fv(p[0]); glVertex3fv(p[1]);
        glVertex3fv(p[2]); glVertex3fv(p[3]);

        glNormal3f(1.0f,0.0f,0.0f); //x方向(正面)
        glVertex3fv(p[0]); glVertex3fv(p[3]);
        glVertex3fv(p[7]); glVertex3fv(p[4]);

        glNormal3f(0.0f,1.0f,0.0f); //y方向
        glVertex3fv(p[0]); glVertex3fv(p[4]);
        glVertex3fv(p[5]); glVertex3fv(p[1]);

         glNormal3f(-1.0f,0.0f,0.0f); //-x方向
        glVertex3fv(p[1]); glVertex3fv(p[5]);
        glVertex3fv(p[6]); glVertex3fv(p[2]);

        glNormal3f(0.0f,-1.0f,0.0f); //-y方向
        glVertex3fv(p[2]); glVertex3fv(p[6]);
        glVertex3fv(p[7]); glVertex3fv(p[3]);

        glNormal3f(0.0f,0.0f,-1.0f); //-z方向
        glVertex3fv(p[4]); glVertex3fv(p[7]);
        glVertex3fv(p[6]); glVertex3fv(p[5]);
    glEnd();
}

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 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 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
  resize(width, height);
}

void idle(void){
  glutPostRedisplay();
}

void TexCreate(int NO,char* FileName){
  glGenTextures(1, &texName[NO]);
  texture[NO] = new TEXTURE(FileName);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  //テクスチャオブジェクトの作成
  glBindTexture(GL_TEXTURE_2D, texName[NO]);
  //テクスチャの指定
  glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,texture[NO]->Width,texture[NO]->Height,0,GL_RGBA,GL_UNSIGNED_BYTE,texture[NO]->image);
  //テクスチャの繰り返し方法の指定
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);//GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);//GL_CLAMP);
  //テクスチャを拡大・縮小する方法の指定
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//NEAREST);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//NEAREST);
  glBindTexture(GL_TEXTURE_2D, 0);
}

void makeNormalMap(int NO, char* FileName){
    //法線マップ用配列作成
  int i, j, ip, jp;
  float r, g;

  texture[NO] = new TEXTURE(FileName);
    //BMPファイルから高さマップをロード
  for(j = 0; j < TEX_HEIGHT; j++){
        for(i = 0; i < TEX_WIDTH; i++){
      //高度マップを取得
            normalMap[j][i][2] = ((texture[NO]->image[i*4+j*4 * TEX_WIDTH])
            + (texture[NO]->image[i*4+j*4 * TEX_WIDTH+1]) + (texture[NO]->image[i*4+j*4 * TEX_WIDTH+2])) / 3;
        }
  }
  //高さマップから法線マップを作成
  for(j = 0; j < TEX_HEIGHT; j++){
        jp = j+1;
        if(jp >= TEX_HEIGHT) jp = 0;
        for(i = 0; i < TEX_WIDTH; i++){
            ip = i+1;
            if(ip >= TEX_WIDTH) ip = 0;
            float deltaS = inv * (normalMap[j][ip][2] - normalMap[j][i][2]);
            float deltaT = inv * (normalMap[jp][i][2] - normalMap[j][i][2]);
            r = 127.5 + deltaS * fGrad;
            if(r < 0.0) r = 0.0;
            if(r > 255.0) r = 255.0;
            g = 127.5 + deltaT * fGrad;
            if(g < 0.0) g = 0.0;
            if(g > 255.0) g = 255.0;
            normalMap[j][i][0] = (GLubyte)r;
            normalMap[j][i][1] = (GLubyte)g;
            if(inv == -1.0) 
                normalMap[j][i][2] = - normalMap[j][i][2];
        }
  }
    glBindTexture(GL_TEXTURE_2D, texName[NO]);//テクスチャをバインドする

  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_WIDTH,TEX_HEIGHT,0,GL_RGB,GL_UNSIGNED_BYTE,normalMap);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);//LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//LINEAR);
  glBindTexture(GL_TEXTURE_2D, 0);//バインドを解除
}

void init(void){
  glClearColor(0.8, 0.8, 1.0, 1.0);
  setCamera();
  setLight();
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glsl[0].InitGLSL("vertex.shader","flagment.shader");
  glsl[1].InitGLSL("displacement_vertex.shader","displacement_flagment.shader");
  //テクスチャー作成
  glGenTextures(4, texName);
  //普通に表示
  TexCreate(0,"brick128.png");
  makeNormalMap(1,"bump128.png");
  //バンプマップ表示
  TexCreate(2,"brick128.png");
  makeNormalMap(3,"bump128.png");
}


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

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

  glNormal3f(0.0f, 1.0f, 0.0f);
  glPushMatrix();
  for (j = 0; j < nz; j++) {
    float z1 = -widthZ / 2.0f + wZ * j; float z2 = z1 + wZ;
    for (i = 0; i < nx; i++) {
      float x1 = -widthX / 2.0f + wX * i; float x2 = x1 + wX;

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

void CalcShadowMat(int ID, float* mat){
  float ex, ey, ez;//光源の方向
  float a, b, c, d;//床の面のパラメータ
  float s; //object中心から光源までの距離
  float x, y, z;

  x = lightPos[0] - pos[ID][0];
  y = lightPos[1] - pos[ID][1];
  z = lightPos[2] - pos[ID][2];

  //光源の方向ベクトル
  s = sqrt(x * x + y * y + z * z);
  ex = x / s;
  ey = y / s;
  ez = z / s;

  //フロアの方向ベクトル(y方向)
  a = 0.0;
  b = 1.0;
  c = 0.0;
  d = -0.001; //フロアと影の干渉を防ぐため
    //shadow matrix
  mat[0] = b * ey + c * ez;
  mat[1] = -a * ey;
  mat[2] = -a * ez;
  mat[3] = 0.0;
  mat[4] = -b * ex;
  mat[5] = a * ex + c * ez;
  mat[6] = -b * ez;
  mat[7] = 0.0;
  mat[8] = -c * ex;
  mat[9] = -c * ey;
  mat[10] = a * ex + b * ey;
  mat[11] = 0.0;
  mat[12] = -d * ex;
  mat[13] = -d * ey;
  mat[14] = -d * ez;
  mat[15] = a * ex + b * ey + c * ez;
}

void drawPlate(float s){
    static float p[4][3] = {
        { s/2.0,-s/2.0, 0.0}, { s/2.0, s/2.0, 0.0}, {-s/2.0, s/2.0, 0.0}, {-s/2.0,-s/2.0, 0.0}};

    glBegin(GL_QUADS);
        glNormal3f(0.0, 0.0, 1.0); //z方向の法線
        glVertex3fv(p[0]);
        glVertex3fv(p[1]);
        glVertex3fv(p[2]);
        glVertex3fv(p[3]);
    glEnd();
}

void drawBumpPlate(float size, int nRepeatS, int nRepeatT){
    float tnt[3];
    float s, t;
    float sz = 0.5 * size;
    static float p[4][3] = { 
        { sz, sz, 0.0}, {-sz, sz, 0.0}, 
        {-sz,-sz, 0.0}, { sz,-sz, 0.0}
    };

    s = (float)nRepeatS;
    t = (float)nRepeatT;
    GLuint tangentLoc = glGetAttribLocation(glsl[0].ShaderProg, "tangent");
  glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
        tnt[0] = 1.0; tnt[1] = 0.0; tnt[2] = 0.0;
        glVertexAttrib3fv(tangentLoc, tnt);
        glNormal3f(0.0, 0.0, 1.0); //z方向の法線
        //テクスチャー座標と頂点番号との対応付け
        glTexCoord2f(0.0, 0.0); glVertex3fv(p[2]);
        glTexCoord2f( s , 0.0); glVertex3fv(p[3]);
        glTexCoord2f( s ,  t ); glVertex3fv(p[0]);
        glTexCoord2f(0.0,  t ); glVertex3fv(p[1]);
    glEnd();
    glDisable(GL_TEXTURE_2D);
}

void drawDispPlate(float size, int nDiv, int nRepeatS, int nRepeatT){
    float tnt[3];
    float s, t;
    float q[4][3];//平面上の分割頂点
    float s0, s1, t0, t1, d0, d1;
    int i, j;
    float sz = 0.5 * size;
    static float p[4][3] = { 
        { sz, sz, 0.0}, {-sz, sz, 0.0}, 
        {-sz,-sz, 0.0}, { sz,-sz, 0.0}
    };

    s = (float)nRepeatS;
    t = (float)nRepeatT;
    GLuint tangentLoc = glGetAttribLocation(glsl[1].ShaderProg, "tangent");
  glEnable(GL_TEXTURE_2D);
    glBegin(GL_QUADS);
    tnt[0] = 1.0; tnt[1] = 0.0; tnt[2] = 0.0;
    glVertexAttrib3fv(tangentLoc, tnt);
    glNormal3f(0.0, 0.0, 1.0); //z方向の法線
    for(j = 0; j < nDiv; j++){
        d0 = (float)j / (float)nDiv;
        d1 = (float)(j+1) / (float)nDiv;
        //z座標
        q[0][2] = q[1][2] = q[2][2] = q[3][2] = p[0][2];
        //y座標
        q[0][1] = q[1][1] = p[2][1] + (p[1][1] - p[2][1]) * d0;
        q[2][1] = q[3][1] = p[2][1] + (p[1][1] - p[2][1]) * d1;
    //t テクスチャ座標
        t0 = t * d0; t1 = t * d1;
        for(i = 0; i < nDiv; i++){
            d0 = (float)i / (float)nDiv;
            d1 = (float)(i+1) / (float)nDiv;
            //x座標
            q[0][0] = q[3][0] = p[1][0] + (p[0][0] - p[1][0]) * d0;
            q[1][0] = q[2][0] = p[1][0] + (p[0][0] - p[1][0]) * d1;
            //s テクスチャ座標
            s0 = s * d0; s1 = s * d1;

            glTexCoord2f( s0, t0); glVertex3fv(q[0]);
            glTexCoord2f( s1, t0); glVertex3fv(q[1]);
            glTexCoord2f( s1, t1); glVertex3fv(q[2]);
            glTexCoord2f( s0, t1); glVertex3fv(q[3]);
        }
    }
    glEnd();
    glDisable(GL_TEXTURE_2D);
}
void DrawBumpPlate(void){
  float ambient[] = { 0.3, 0.3, 0.3, 1.0};
  float diffuse[] = { 0.7, 0.7, 0.7, 1.0};
  float specular[]= { 0.5, 0.5, 0.5, 1.0};

    if(flagShadow){
      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,shadowDiffuse);
      glMaterialfv(GL_FRONT,GL_SPECULAR,shadowSpecular);
  }else{    
      glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);
      glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);
      glMaterialfv(GL_FRONT,GL_SPECULAR,specular);
      glMaterialf(GL_FRONT,GL_SHININESS,100);
  }

  glPushMatrix();
    glTranslatef(pos[1][0], pos[1][1], pos[1][2]);
  glRotatef(angle[1][2], 0.0, 0.0, 1.0);//z軸回転
  glRotatef(angle[1][1], 0.0, 1.0, 0.0);//y軸回転
  glRotatef(angle[1][0], 1.0, 0.0, 0.0);//x軸回転
  glScalef(scale[1][0], scale[1][1], scale[1][2]);
  //オブジェクト形状
  if(!flagShadow){
      drawBumpPlate(1.0,1,1);
  }else{//影表示のときはTextureを付けない
      drawPlate(1.0);
  }

  glPopMatrix();
}
void DrawDispPlate(void){
  float ambient[] = { 0.3, 0.3, 0.3, 1.0};
  float diffuse[] = { 0.7, 0.7, 0.7, 1.0};
  float specular[]= { 0.5, 0.5, 0.5, 1.0};

    if(flagShadow){
      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,shadowDiffuse);
      glMaterialfv(GL_FRONT,GL_SPECULAR,shadowSpecular);
  }else{    
      glMaterialfv(GL_FRONT,GL_AMBIENT,ambient);
      glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse);
      glMaterialfv(GL_FRONT,GL_SPECULAR,specular);
      glMaterialf(GL_FRONT,GL_SHININESS,100);
  }

  glPushMatrix();
    glTranslatef(pos[0][0], pos[0][1], pos[0][2]);
  glRotatef(angle[0][2], 0.0, 0.0, 1.0);//z軸回転
  glRotatef(angle[0][1], 0.0, 1.0, 0.0);//y軸回転
  glRotatef(angle[0][0], 1.0, 0.0, 0.0);//x軸回転
  glScalef(scale[0][0], scale[0][1], scale[0][2]);
  //オブジェクト形状
  if(!flagShadow){
        drawDispPlate(1.0,100,1,1);
  }else{//影表示のときはTextureを付けない
      drawPlate(1.0);
  }

  glPopMatrix();
}

void drawShadow(){
  //計算は平行光線に対する影
  //オブジェクトごとに光源の方向を変え、疑似的に点光源に対する影を作る
  float mat[16]; //影行列の要素

  flagShadow = true;
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

      glDepthMask(GL_FALSE);
  //影の描画
  CalcShadowMat(0, mat);
  glPushMatrix();
      glMultMatrixf(mat);
      DrawBumpPlate();
  glPopMatrix();
  CalcShadowMat(1, mat);
  glPushMatrix();
      glMultMatrixf(mat);
      DrawDispPlate();
  glPopMatrix();

  glDepthMask(GL_TRUE);
  glDisable(GL_BLEND);
  flagShadow = false;
}

void display(void){

  //カラーバッファ,デプスバッファのクリア
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();//視点を変えるときはこの位置に必要
 
  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);

  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, texName[0]);
  glActiveTexture(GL_TEXTURE1);
  glBindTexture(GL_TEXTURE_2D, texName[1]);
  glActiveTexture(GL_TEXTURE2);
  glBindTexture(GL_TEXTURE_2D, texName[2]);
  glActiveTexture(GL_TEXTURE3);
  glBindTexture(GL_TEXTURE_2D, texName[3]);

  // シェーダプログラムの適用 
  glUseProgram(glsl[0].ShaderProg);

  //バンプマッピング描画
  GLint texColorLoc = glGetUniformLocation(glsl[0].ShaderProg, "colorMap");
  GLint texNormalLoc = glGetUniformLocation(glsl[0].ShaderProg, "normalMap");
  glUniform1i(texColorLoc, 2);
  glUniform1i(texNormalLoc, 3);
  DrawBumpPlate();
  // シェーダプログラムの適用を解除    
  glUseProgram(0);

    // シェーダプログラムの適用 
  glUseProgram(glsl[1].ShaderProg);

  //ディスプレイスメントマップ描画
    GLint dispLoc = glGetUniformLocation(glsl[1].ShaderProg, "fDisp");
    GLint invLoc = glGetUniformLocation(glsl[1].ShaderProg, "inv");
    GLint biasLoc = glGetUniformLocation(glsl[1].ShaderProg, "bias");
  texColorLoc = glGetUniformLocation(glsl[1].ShaderProg, "colorMap");
  texNormalLoc = glGetUniformLocation(glsl[1].ShaderProg, "normalMap");
    glUniform1f(dispLoc, fDisp);
    glUniform1f(invLoc, inv);
    glUniform1f(biasLoc, bias);
  glUniform1i(texColorLoc, 0);//GL_TEXTURE0を適用
  glUniform1i(texNormalLoc, 1);//GL_TEXTURE1を適用
  DrawDispPlate();
  glPopMatrix();
  // シェーダプログラムの適用を解除    
  glUseProgram(0);

  drawFloor(10.0, 10.0, 5, 5);
  //影
  drawShadow();

  //終了
  glutSwapBuffers();
}

 

//以下の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)//dolly
      {
      }
  }else if(button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN){
      if(x > width/4 && x < 3*width/4 && y > height/4 && y < 3*height/4)//dolly
      {
      }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();
  glDeleteTextures(4, texName);
}

 

 

 

 

 

 

最終更新:2014年11月23日 14:06