環境マッピング

環境マッピングです。
正面の球に部屋を反射させて描画します。
room.xは、ここからダウンロードできます。
右クリックして、名前を付けてリンク先を保存してください。

wall.png

vertex.shader

varying vec3 P;
varying vec3 N;
varying vec4 Reflect; 
uniform mat4 ViewTranspose;//ビュー変換だけのモデルビュー行列の転置行列

void main(void)
{
  P = vec3(gl_ModelViewMatrix * gl_Vertex);
  N = normalize(gl_NormalMatrix * gl_Normal);
  vec3 incident = normalize(P);//入射視線ベクトル
  vec3 reflect0 = reflect(incident, N);//その反射ベクトル
  Reflect = ViewTranspose * vec4(reflect0, 0.0);//ビュー行列の転置行列を乗じる
  gl_Position = ftransform();
}

flagment.shader

varying vec3 P;
varying vec3 N;
varying vec4 Reflect;
uniform samplerCube sampler;
uniform float reflectivity;

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;
    //オブジェクトの色と環境マップを線形補間
    gl_FragColor = mix(ambient + diffuse, textureCube(sampler, Reflect.stp), reflectivity) + specular;
}

GLSL.h

#pragma once
 #include <stdio.h>
 
//GLSLクラス
 class GLSL{
 public:
  GLuint ShaderProg;
  GLuint VertexShader, FragmentShader;
  void ReadShaderCompile(GLuint Shader, const char *File);//shader fileを読み込みコンパイルする
  void Link( GLuint Prog );//リンクする
  void InitGLSL(const char *VertexFile);//GLSLの初期化
  void InitGLSL(const char *VertexFile, const char *FragmentFile);//GLSLの初期化
  void ON();//シェーダー描画に切り替え
  void OFF();//シェーダー解除
  ~GLSL();
 };
 
 void GLSL::ReadShaderCompile(GLuint Shader, const char *File){
    FILE *fp;
    char *buf;
    GLsizei size, len;
    GLint compiled;
 
    fopen_s(&fp,File, "rb");
    if(!fp) printf("ファイルを開くことができません %s\n", File);
 
    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
 
   buf = (GLchar *)malloc(size);
    if (buf == NULL) {
      printf("メモリが確保できませんでした \n");
    }
 
    fseek(fp, 0, SEEK_SET);
    fread(buf, 1, size, fp);
    glShaderSource(Shader, 1, (const GLchar **)&buf, &size);
    free(buf);
    fclose(fp);
 
    glCompileShader(Shader);
    glGetShaderiv( Shader, GL_COMPILE_STATUS, &compiled );
 
   if ( compiled == GL_FALSE )
    {
     printf( "コンパイルできませんでした!!: %s \n ", File);
     glGetProgramiv( Shader, GL_INFO_LOG_LENGTH, &size );
     if ( size > 0 )
     {
      buf = (char *)malloc(size);
      glGetShaderInfoLog( Shader, size, &len, buf);
      printf(buf);
      free(buf);
     }
    }
  }
 
 void GLSL::Link( GLuint Prog ){
    GLsizei size, len;
    GLint linked;
    char *infoLog ;
 
   glLinkProgram( Prog );
 
   glGetProgramiv( Prog, GL_LINK_STATUS, &linked );
 
   if ( linked == GL_FALSE ){
    printf("リンクできませんでした!! \n");
    
    glGetProgramiv( Prog, GL_INFO_LOG_LENGTH, &size );
    if ( size > 0 ){
     infoLog = (char *)malloc(size);
     glGetProgramInfoLog( Prog, size, &len, infoLog );
     printf(infoLog);
     free(infoLog);
    }
   }
 }
 
void GLSL::InitGLSL(const char *VertexFile){
    GLenum err = glewInit();
    if (err != GLEW_OK)
    {
     printf("Error: %s\n", glewGetErrorString(err));
    }
    printf("VENDOR= %s \n", glGetString(GL_VENDOR));
    printf("GPU= %s \n", glGetString(GL_RENDERER));
    printf("OpenGL= %s \n", glGetString(GL_VERSION));
    printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));
    VertexShader = glCreateShader(GL_VERTEX_SHADER);
    ReadShaderCompile(VertexShader, VertexFile);
    ShaderProg = glCreateProgram();
    glAttachShader(ShaderProg, VertexShader);
    glDeleteShader(VertexShader);
    Link(ShaderProg);
  }
 
 
void GLSL::InitGLSL(const char *VertexFile, const char *FragmentFile){
    GLenum err = glewInit();
    if (err != GLEW_OK)
    {
     printf("Error: %s\n", glewGetErrorString(err));
    }
    printf("VENDOR= %s \n", glGetString(GL_VENDOR));
    printf("GPU= %s \n", glGetString(GL_RENDERER));
    printf("OpenGL= %s \n", glGetString(GL_VERSION));
    printf("GLSL= %s \n", glGetString(GL_SHADING_LANGUAGE_VERSION));
 
   VertexShader = glCreateShader(GL_VERTEX_SHADER);
    FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 
   ReadShaderCompile(VertexShader, VertexFile);
    ReadShaderCompile(FragmentShader, FragmentFile);
 
   ShaderProg = glCreateProgram();
 
    glAttachShader(ShaderProg, VertexShader);
    glAttachShader(ShaderProg, FragmentShader);
 
    glDeleteShader(VertexShader);
    glDeleteShader(FragmentShader);
    Link(ShaderProg);
  }
 
void GLSL::ON(){
  glUseProgram(ShaderProg);
 }
 
void GLSL::OFF(){
  glUseProgram(0);
 }
 
GLSL::~GLSL(){
  glDeleteProgram(ShaderProg);
 }
  

PNG.h

 #pragma once
 #include "lodepng.h"
 
//テクスチャクラス
 class TEXTURE{
 protected:
  LodePNG_Decoder decoder;//デコーダ
  unsigned char* buffer;//バッファ
  size_t buffersize, imagesize;//サイズ
 public:
  TEXTURE();
  TEXTURE(const char* FileName);//コンストラクタ
  void LOAD_PNG(const char* FileName);//PNG読み込み
  unsigned char* image;//イメージポインタ
  unsigned int Width,Height;//画像サイズ
 };
 TEXTURE::TEXTURE(){
 }
 TEXTURE::TEXTURE(const char* FileName){
  LOAD_PNG(FileName);
 }
 void TEXTURE::LOAD_PNG(const char* FileName){
  LodePNG_Decoder_init(&decoder);
  //ロード
  LodePNG_loadFile(&buffer, &buffersize, FileName);
  //デコード
  LodePNG_decode(&decoder, &image, &imagesize, buffer, buffersize);
  //幅,高さ
  Width = decoder.infoPng.width;Height = decoder.infoPng.height;
 }

xfile.h

#include "PNG.h"

using namespace std;
//3つのベクトル
struct Vector3f{
 float x;
 float y;
 float z;
}vec3d;
Vector3f & operator*(Vector3f &v,float size){
 v.x *= size;
 v.y *= size;
 v.z *= size;
 return v;
}
//4つのベクトル
struct Vector4f{
 float x;
 float y;
 float z;
 float w;
}vec4d;
//4つのカラー
struct Color4{
 float r;
 float g;
 float b;
 float a;
};
//4つの反射
struct Reflection4{
 Color4 diffuse;
 Color4 ambient;
 Color4 emission;
 Color4 specular;
};
//UV座標
struct UV{
 float u;//u値
 float v;//v値
}vec2d;
//ポリゴンデータ
struct Triangle{
 Vector3f TriVer;
 Vector3f TriNor;
 UV TriUV;
}Tri;
//ポリゴンデータ
struct Quadrangle{
 Vector3f QuadVer;
 Vector3f QuadNor;
 UV QuadUV;
}Quad;
//マテリアル構造体
struct MATERIAL{
 string MaterialName;//マテリアル名
 Reflection4 MaterialColor;//反射
 float Shininess;//shininess
 string TextureName;//テクスチャ名
 int TexNo;//テクスチャNO.
 vector <Triangle> Tridata;//三角面データ
 vector <Quadrangle> Quaddata;//四角面データ
}mtl;
//モデルクラス
class MODEL{
protected:
 vector <MATERIAL> Material;//マテリアル
 vector <TEXTURE*> TexData;//テクスチャデータ
 vector<GLuint> TexID;//テクスチャID
 GLuint TexID2;//代入用
 TEXTURE* tex;//代入用
public:
 MODEL();
 MODEL(char* FileName,int size);//コンストラクタ
 bool XFILE_Load(char* FileName,int size);//ロード
 void Draw();
};
MODEL::MODEL(){
}
MODEL::MODEL(char* FileName,int size){
 XFILE_Load(FileName, size);
}
//描画
void MODEL::Draw(){
 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_NORMAL_ARRAY);
 for(int i=0;i<(signed)Material.size();i++){
  glPushMatrix();
  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,(const GLfloat *)&Material[i].MaterialColor.ambient);
  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,(const GLfloat *)&Material[i].MaterialColor.diffuse);
  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat *)&Material[i].MaterialColor.specular);
  glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,Material[i].Shininess);
  if(Material[i].TexNo>0){
   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   glEnable(GL_TEXTURE_2D);
   glBindTexture(GL_TEXTURE_2D, TexID[Material[i].TexNo-1]);
  }else{
   glDisable(GL_TEXTURE_2D);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  }
  if(Material[i].Tridata.size()>1){
   glVertexPointer(3, GL_FLOAT,sizeof(Tri) , &Material[i].Tridata[0].TriVer.x);
   glNormalPointer(GL_FLOAT,sizeof(Tri),&Material[i].Tridata[0].TriNor.x);
   if(Material[i].TexNo>0)glTexCoordPointer(2, GL_FLOAT, sizeof(Tri), &Material[i].Tridata[0].TriUV.u);
   glDrawArrays(GL_TRIANGLES,0,Material[i].Tridata.size());
  }
  if(Material[i].Quaddata.size()>1){
   glVertexPointer(3, GL_FLOAT,sizeof(Quad) , &Material[i].Quaddata[0].QuadVer.x);
   glNormalPointer(GL_FLOAT,sizeof(Quad),&Material[i].Quaddata[0].QuadNor.x);
   if(Material[i].TexNo>0)glTexCoordPointer(2, GL_FLOAT, sizeof(Quad), &Material[i].Quaddata[0].QuadUV.u);
   glDrawArrays(GL_QUADS,0,Material[i].Quaddata.size());
  }
  glPopMatrix();
 }
 glDisableClientState(GL_VERTEX_ARRAY);
 glDisableClientState(GL_NORMAL_ARRAY);
 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
 glDisable(GL_TEXTURE_2D);
}

//Xファイル読み込み
bool MODEL::XFILE_Load(char* FileName,int size){
 vector <Vector3f> Vertex;//頂点
 vector <Vector3f> Normal;//法線
 vector <UV> uv;//UV
 vector <int> VertexIndex;
 vector <int> NormalIndex;
 vector <int> MaterialIndex;
 vector <int> FaceIndex;

 char key[255];
 char buf[255];
 //Xファイルを開いて内容を読み込む
 FILE* fp=NULL;
 fopen_s(&fp,FileName,"rt");
 
 int v1=0,v2=0,v3=0,v4=0;
 int Count=0;
 bool flag=false;
 string str="";

 //読み込み 
 fseek(fp,SEEK_SET,0);
 while(!feof(fp))
 {
  //キーワード 読み込み
  ZeroMemory(key,sizeof(key));
  fscanf_s(fp,"%s ",key,sizeof(key));

  //テンプレート読み飛ばし
  if(strcmp(key,"template")==0){
   while(strcmp(key,"}")){
    fscanf_s(fp,"%s ",key,sizeof(key));
   }
   continue;
  }

  //マテリアル読み込み
  if(strcmp(key,"Material")==0)
  {
   if(flag)Material.push_back(mtl);
   flag=true;
   fgets(buf,sizeof(buf),fp);//直後の行にあると推定 改行する
   //ディフューズ
   fscanf_s(fp,"%f;%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z,&vec4d.w);
   mtl.MaterialColor.diffuse=(const Color4 &)vec4d;
   //SHININESS  
   fscanf_s(fp,"%f;",&mtl.Shininess);
   //スペキュラー 
   fscanf_s(fp,"%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z);
   mtl.MaterialColor.specular=(const Color4 &)vec4d;
   //エミッシブ 
   fscanf_s(fp,"%f;%f;%f;;",&vec4d.x,&vec4d.y,&vec4d.z);
   mtl.MaterialColor.ambient=(const Color4 &)vec4d;

   //テクスチャー
   fscanf_s(fp,"%s ",key,sizeof(key)); 
   if(strcmp(key,"TextureFilename")==0)
   {
    fgets(buf,sizeof(buf),fp);//直後の行にあると推定 改行する
    //map_Kd テクスチャー 
    fscanf_s(fp,"%s",buf,255);
    mtl.TextureName=buf;
    str=mtl.TextureName;
    mtl.TextureName=str.substr(str.find_first_of('\"',0)+1,str.find_last_of('\"',255)-1);
     //テクスチャを作成
    TexData.push_back(tex);
    TexData[TexData.size()-1] = new TEXTURE(mtl.TextureName.c_str());;
    mtl.TexNo=TexData.size();
    TexID.push_back(TexID2);
    glGenTextures(1, (GLuint *)&TexID[TexData.size()-1]);
    glBindTexture(GL_TEXTURE_2D, TexID[TexData.size()-1]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  
    glEnable(GL_TEXTURE_2D);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,TexData[TexData.size()-1]->Width, TexData[TexData.size()-1]->Height,
     0,GL_RGBA, GL_UNSIGNED_BYTE, TexData[TexData.size()-1]->image);
    glDisable(GL_TEXTURE_2D); 
   }
  }
  //頂点 読み込み
  if(strcmp(key,"Mesh")==0)
  {
   fgets(buf,sizeof(buf),fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),fp);
   Count=atoi(buf);
   for(int i=0;i<Count ;i++)
   {
    fscanf_s(fp,"%f;%f;%f;,",&vec3d.x,&vec3d.y,&vec3d.z);
    Vertex.push_back(vec3d*(float)size);
   } 
   //頂点インデックス読み込み  
   fgets(buf,sizeof(buf),fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),fp);
   while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),fp);}//空行対策
   Count=atoi(buf);   
   for(int i=0;i<Count ;i++)
   {
    int dammy=0;
    fgets(buf,sizeof(buf),fp);
    str=buf;
    string::size_type first = str.find_first_not_of(" ");
    string::size_type index = str.find("3;");
    if(index-first==0){
     sscanf_s(buf,"%d;%d,%d,%d;,",&dammy,&v1,&v2,&v3);
     VertexIndex.push_back(v1);
     VertexIndex.push_back(v2);
     VertexIndex.push_back(v3);
    }
    if((index==-1)||(index-first>1)){
     sscanf_s(buf,"%d;%d,%d,%d,%d;,",&dammy,&v1,&v2,&v3,&v4);
     VertexIndex.push_back(v1);
     VertexIndex.push_back(v2);
     VertexIndex.push_back(v3);
     VertexIndex.push_back(v4);
    }
    FaceIndex.push_back(dammy);
   } 
  }

  //法線 読み込み
  if(strcmp(key,"MeshNormals")==0)
  {
   fgets(buf,sizeof(buf),fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),fp);
   Count=atoi(buf);
   for(int i=0;i<Count ;i++)
   {
    fscanf_s(fp,"%f;%f;%f;,",&vec3d.x,&vec3d.y,&vec3d.z);
    Normal.push_back(vec3d);
   }
   //法線インデックス読み込み  
   fgets(buf,sizeof(buf),fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),fp);
   while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),fp);}//空行対策
   Count=atoi(buf);   
   for(int i=0;i<Count ;i++)
   {
    int dammy=0;
    fgets(buf,sizeof(buf),fp);
    str=buf;
    string::size_type first = str.find_first_not_of(" ");
    string::size_type index = str.find("3;");
    if(index-first==0){
     sscanf_s(buf,"%d;%d,%d,%d;,",&dammy,&v1,&v2,&v3);
     NormalIndex.push_back(v1);
     NormalIndex.push_back(v2);
     NormalIndex.push_back(v3);
    }
    if((index==-1)||(index-first>1)){
     sscanf_s(buf,"%d;%d,%d,%d,%d;,",&dammy,&v1,&v2,&v3,&v4);
     NormalIndex.push_back(v1);
     NormalIndex.push_back(v2);
     NormalIndex.push_back(v3);
     NormalIndex.push_back(v4);
    }
   } 
  }

  //テクスチャー座標 読み込み
  if(strcmp(key,"MeshTextureCoords")==0)
  {
   fgets(buf,sizeof(buf),fp);//データは2行下にあると推定 改行する
   fgets(buf,sizeof(buf),fp);
   while(strchr(buf,';')==NULL){fgets(buf,sizeof(buf),fp);}//空行対策
   Count=atoi(buf);
   for(int i=0;i<Count ;i++)
   {
    fscanf_s(fp,"%f;%f;,",&vec2d.u,&vec2d.v);
    uv.push_back(vec2d);
   }   
  }
  //マテリアルリスト
  if(strcmp(key,"MeshMaterialList")==0)
  {
   fgets(buf,sizeof(buf),fp);//空改行
   fgets(buf,sizeof(buf),fp);//マテリアル数
   fgets(buf,sizeof(buf),fp);//リスト要素数
   Count=atoi(buf);
   for(int i=0;i<Count;i++)
   {
    fgets(buf,sizeof(buf),fp);
    int test=atoi(buf);
    MaterialIndex.push_back(test);
   }
  }
 }
 if(flag)Material.push_back(mtl);

 fclose(fp);

 Count=0;
 //マテリアル毎のデータを作成
 for(int i=0;i<(signed)MaterialIndex.size();i++){
  if(FaceIndex[i]==3){
   for(int j=0;j<3;j++){
    Tri.TriVer=Vertex[VertexIndex[Count+j]];
    Tri.TriNor=Normal[NormalIndex[Count+j]];
    Tri.TriUV=uv[VertexIndex[Count+j]];
    Material[MaterialIndex[i]].Tridata.push_back(Tri);
   }
   Count+=3;
  }else{
   for(int j=0;j<4;j++){
    Quad.QuadVer=Vertex[VertexIndex[Count+j]];
    Quad.QuadNor=Normal[NormalIndex[Count+j]];
    Quad.QuadUV=uv[VertexIndex[Count+j]];
    Material[MaterialIndex[i]].Quaddata.push_back(Quad);
   }
   Count+=4;
  }
 }

 Vertex.clear(); 
 Normal.clear();
 uv.clear();
 VertexIndex.clear();
 NormalIndex.clear();
 MaterialIndex.clear();
 FaceIndex.clear();

 return true;
}

main.cpp

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

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

#define PAI 3.141592f

//affine変換用変数
float pos[] = { 0.0f, 1.5f, 0.0f };  //object中心のxyz座標
float scale[] = { 1.0f, 1.0f, 1.0f };//大きさ(倍率)
float angle[] = { 0.0f, 0.0f, 0.0f };//回転角度
float lightPos[] = {0.0f, 5.0f, 0.0f, 1.0f};//光源位置

//カメラと視体積
struct View{
  float pos[3];//位置(視点)
  float cnt[3];//注視点
  float dist;  //注視点から視点までの距離
  float theta; //仰角(水平面との偏角)
  float phi;   //方位角
  //視体積
  float fovY;  //視野角
  float nearZ; //前方クリップ面(近平面)
  float farZ;  //後方クリップ面(遠平面)
};
View view = { 
    0.0f, 0.0f, 0.0f,//pos(仮設定)
  0.0f, 1.5f, 0.0f,//cnt 
    1.0f, 10.0f, 0.0f,//dist, theta, phi
    60.0f, 0.1f, 100.0f//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 flagLight = false;//追加

float reflectivity0 = 0.5;//反射率

GLSL glsl;
MODEL* model;
//テクスチャ用
#define TEX_WIDTH  128
#define TEX_HEIGHT 128

//テクスチャー構造体
struct Target{
    GLenum name;//ターゲット名
    GLint x, y;//部分画像の位置
    GLdouble cx, cy, cz;//注視点
    GLdouble ux, uy, uz;//アップベクトル
};

struct Target target[] = {
  { //右
    GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    0, TEX_HEIGHT,
    1.0, 0.0, 0.0,
    0.0, -1.0, 0.0,
  },
  { 
     //左
     GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    0, 0,
    -1.0, 0.0, 0.0,
    0.0, -1.0, 0.0,
  },
  { //天井
    GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    TEX_WIDTH, TEX_HEIGHT,
    0.0, 1.0, 0.0,
    0.0, 0.0, 1.0,
  },
  { 
        //床
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    TEX_WIDTH,0,
    0.0, -1.0, 0.0,
    0.0, 0.0, -1.0,
  },
  { //手前
    GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    2*TEX_WIDTH, TEX_HEIGHT,
    0.0, 0.0, 1.0,
    0.0, -1.0, 0.0,
  },
  { //奥
    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
    2*TEX_WIDTH, 0,
    0.0, 0.0, -1.0,
    0.0, -1.0, 0.0,
  }
};
void setCubeMap()
{
  for(int i = 0; i < 6; i++)
      glTexImage2D(target[i].name,0,GL_RGBA,TEX_WIDTH,TEX_HEIGHT,0,GL_RGBA,GL_UNSIGNED_BYTE, 0);

  glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_REPEAT);
  glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_REPEAT);
  glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_REPEAT);
  glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
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();

  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);
  }
 //表示ウィンドウのサイズ
  width = w;
  height = h;
}
void setCamera()
{
  double pp = PAI / 180.0f;
  view.pos[2] =(float)(view.cnt[2] + view.dist * cos(pp * view.theta) * cos(pp * view.phi));//z
  view.pos[0] =(float)(view.cnt[0] + view.dist * cos(pp * view.theta) * sin(pp * view.phi));//x
  view.pos[1] =(float)(view.cnt[1] + view.dist * sin(pp * view.theta));//y
  resize(width, height);
}
void draw(void)
{
  float ambient[] = { 0.3f, 0.3f, 0.3f, 1.0f};
  float diffuse[] = { 0.7f, 0.7f, 0.7f, 1.0f};
  float specular[]= { 0.5f, 0.5f, 0.5f, 1.0f};

  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], pos[1], pos[2]);
  glRotatef(angle[2], 0.0f, 0.0f, 1.0f);//z軸回転
  glRotatef(angle[1], 0.0f, 1.0f, 0.0f);//y軸回転
  glRotatef(angle[0], 1.0f, 0.0f, 0.0f);//x軸回転
  glScalef(scale[0], scale[1], scale[2]);
  glutSolidSphere(0.2, 20, 20);
  glPopMatrix();
}
void display(void){
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(90.0, 1.0, 0.1, 30.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  // オブジェクトから見たシーンをテクスチャに利用 
  for (int i = 0; i < 6; ++i){
    // ビューポートをテクスチャのサイズに設定する 
    glViewport(target[i].x, target[i].y, TEX_WIDTH, TEX_HEIGHT);
        // オブジェクト中心から見えるものをレンダリング 
        glPushMatrix();
        gluLookAt(pos[0], pos[1], pos[2], 
            pos[0]+target[i].cx, pos[1]+target[i].cy, pos[2]+target[i].cz,
                target[i].ux, target[i].uy, target[i].uz);
        glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
        model->Draw();
        glTranslatef(0.0, 1.0, 0.0);
        glPopMatrix();
        // レンダリングした画像をテクスチャメモリに転送 
        glCopyTexSubImage2D(target[i].name, 0, 0, 0, target[i].x, target[i].y, TEX_WIDTH, TEX_HEIGHT);
  }

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  resize(width, height);  

  glsl.ON();
  GLint refLoc = glGetUniformLocation(glsl.ShaderProg, "reflectivity");
  glUniform1f(refLoc, reflectivity0);
  float m[16] ;
  glGetFloatv(GL_MODELVIEW_MATRIX, m);
  GLint ViewTransLoc = glGetUniformLocation(glsl.ShaderProg, "ViewTranspose");
  glUniformMatrix4fv(ViewTransLoc, 1, GL_TRUE, m);

  glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
  //fragment shaderのユニフォーム変数texのインデックスを取得
  GLint samplerLoc = glGetUniformLocation(glsl.ShaderProg, "sampler");
  glUniform1i(samplerLoc, 0);
  draw(); 
  glsl.OFF();
  model->Draw();
  glutSwapBuffers();
}

void setLight()
{
  float lightAmbient0[] = {0.8f, 0.8f, 0.8f, 1.0f}; //環境光
  float lightDiffuse0[] = {1.0f, 1.0f, 1.0f, 1.0f}; //拡散光
  float lightSpecular0[] = {1.0f, 1.0f, 1.0f, 1.0f};//鏡面光
  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 mouse(int button, int state, int x, int y){
  float pp = PAI / 180.0f;

  if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN){
   xStart = x; yStart = y;
   flagMouse = true;
  }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.0f) >= 0.0f){
      view.phi -= 0.5f * (float)(x - xStart) ;//tumble
  }else{
      view.phi += 0.5f * (float)(x - xStart) ;//tumble
  }
  view.theta += 0.5f * (float)(y - yStart) ;//crane

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

void Init(void){
 //背景色
  glClearColor(0.2f, 0.2f, 0.3f, 1.0f);
  setCamera();//視点を求める
  setLight(); //光源設定
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);

  //テクスチャの設定
  setCubeMap();
  glsl.InitGLSL("vertex.shader","flagment.shader");
  model = new MODEL("room.x",1);
}
void idle(void){
  glutPostRedisplay();
}

void main(int argc, char *argv[]){
   glutInitWindowPosition(100, 100);
   glutInitWindowSize(640, 480);
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
   glutCreateWindow("環境マッピング");
   glutDisplayFunc(display);
   glutIdleFunc(idle);
   glutMouseFunc(mouse);
   glutMotionFunc(motion);
   glutReshapeFunc(resize);
   Init();
   glutMainLoop();
   return;
}

 

 

 

 

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