オフスクリーンレンダリング

オフスクリーンレンダリングです。
レースゲームのバックミラーの描画等で使われます。
metasequiaに付属のviolin.mqoを.xに変換して使用しています。
violin.xここからダウンロードして下さい。
右クリックして名前を付けてリンク先を保存でダウンロードできます。

violin.png

 vertex.shader

varying vec3 P;
varying vec3 N;

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

flagment.shader

varying vec3 P;
varying vec3 N;
uniform sampler2D sampler;

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);//max(0.0, 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(sampler, gl_TexCoord[0].st);
 //GL_MODULATEモード
 gl_FragColor = (ambient + diffuse) * texColor + specular;
 //任意の混合比
// gl_FragColor = mix(ambient + diffuse, texColor, 0.5) + 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 <windows.h>
#include <GL/glew.h>
#include "GLSL.h"
#include <math.h>
#include <GL/freeglut/freeglut.h>
#include "xfile.h"

float pos[] = { 0.0, 1.0, 0.0};
float scale[][3] = { 1.0, 1.0, 1.0 };
float angle[][3] = { 0.0, 0.0, 0.0};

float lightPos[] = {-5.0, 5.0, 5.0, 1.0};
float lightPosR[] = {5.0,-5.0, -5.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,
 0.0, 1.0, 0.0,
 10.0, 30.0, 20.0,
 30.0, 1.0, 100.0
};
View view0 = view;


GLSL glsl;
TEXTURE *texture[2];
MODEL* model;
#define PAI 3.141592f
int width = 640;
int height = 480;

GLuint texName[2];
int xStart, yStart;
bool flagMouse = false;
bool flagShadow = false;
int objNo = 0;
float ang = 0.0;
float dang = 0.1;

#define TEX_WIDTH  512
#define TEX_HEIGHT 512

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 drawTexCube(float size, int nRepeatS, int nRepeatT){
 float sz = 0.5 * size;
 float p[8][3] ={
  { sz, sz, sz}, {-sz, sz, sz}, {-sz,-sz, sz},
   { sz,-sz, sz}, { sz, sz,-sz}, {-sz, sz,-sz},
   {-sz,-sz,-sz}, { sz,-sz,-sz}
 };

 float s = (float)nRepeatS;
 float t = (float)nRepeatT;

 glEnable(GL_TEXTURE_2D);
  glBegin(GL_QUADS);
 //top(z軸が鉛直軸のときz方向)
 glNormal3f(0.0f,0.0f,1.0f);
 glTexCoord2f( s , 0.0); glVertex3fv(p[0]);
 glTexCoord2f( s ,  t ); glVertex3fv(p[1]);
 glTexCoord2f(0.0,  t ); glVertex3fv(p[2]);
 glTexCoord2f(0.0, 0.0); glVertex3fv(p[3]);
 //x方向(正面)
 glNormal3f(1.0f,0.0f,0.0f);
 glTexCoord2f( s ,  t ); glVertex3fv(p[0]);
 glTexCoord2f(0.0,  t ); glVertex3fv(p[3]);
 glTexCoord2f(0.0, 0.0); glVertex3fv(p[7]);
 glTexCoord2f( s , 0.0); glVertex3fv(p[4]);
 //y方向
 glNormal3f(0.0f,1.0f,0.0f);
 glTexCoord2f(0.0,  t ); glVertex3fv(p[0]);
 glTexCoord2f(0.0, 0.0); glVertex3fv(p[4]);
 glTexCoord2f( s , 0.0); glVertex3fv(p[5]);
 glTexCoord2f( s ,  t ); glVertex3fv(p[1]);
 //-x方向
 glNormal3f(-1.0f,0.0f,0.0f);
 glTexCoord2f(0.0,  t ); glVertex3fv(p[6]);
 glTexCoord2f(0.0, 0.0); glVertex3fv(p[2]);
 glTexCoord2f( s , 0.0); glVertex3fv(p[1]);
 glTexCoord2f( s ,  t ); glVertex3fv(p[5]);
 //-y方向
 glNormal3f(0.0f,-1.0f,0.0f);
 glTexCoord2f(0.0,  t ); glVertex3fv(p[2]);
 glTexCoord2f(0.0, 0.0); glVertex3fv(p[6]);
 glTexCoord2f( s , 0.0); glVertex3fv(p[7]);
 glTexCoord2f( s ,  t ); glVertex3fv(p[3]);
 //-z方向
 glNormal3f(0.0f,0.0f,-1.0f);
 glTexCoord2f(0.0, 0.0); glVertex3fv(p[6]);
 glTexCoord2f( s , 0.0); glVertex3fv(p[5]);
 glTexCoord2f( s ,  t ); glVertex3fv(p[4]);
 glTexCoord2f(0.0,  t ); glVertex3fv(p[7]);
  glEnd();
  glDisable(GL_TEXTURE_2D);
}

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 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(){
  float pp = PAI / 180.0f;
  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 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 Init(void){
  glsl.InitGLSL("vertex.shader","flagment.shader");
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  setCamera();
  setLight();
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  TexCreate(0,"marble.png");
  TexCreate(1,"marble.png");
  model = new MODEL("violin.x",2);
}
void idle(void){
  //再描画
  glutPostRedisplay();
}

void drawFloor(float widthX, float widthZ){
  float diffuse[] = { 0.8, 0.8, 0.8, 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,10);
  glEnable(GL_TEXTURE_2D);
  glNormal3d(0.0, 1.0, 0.0);
  glPushMatrix();
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
  glBegin(GL_QUADS);
  glTexCoord2f(0.0, 0.0);glVertex3d(widthX, 0.0, widthZ);
  glTexCoord2f( 1.0 , 0.0);glVertex3d(widthX, 0.0, -widthZ);
  glTexCoord2f( 1.0 ,  1.0 );glVertex3d(-widthX, 0.0, -widthZ);
  glTexCoord2f(0.0,  1.0 );glVertex3d(-widthX, 0.0, widthZ);
  glEnd();
  glPopMatrix();
  glDisable(GL_TEXTURE_2D);
}
void draw_obj(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], pos[1], pos[2]);
  glRotatef(angle[0][2], 0.0, 0.0, 1.0);//z軸回転
  glRotatef(angle[0][1]+ ang, 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)
  {
  drawTexCube(1.5, 1, 1);
  }
  else
  {//影表示のときはTextureを付けない
  drawCube(1.5);
  }
  glPopMatrix();
}
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 CalcShadowMat(int ID, float* mat){
  float ex, ey, ez;//光源の方向
  float a, b, c, d;//床の面のパラメータ
  float s; //object中心から光源までの距離
  float x, y, z;

  x = lightPos[0];
  y = lightPos[1];
  z = lightPos[2];

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

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

void drawShadow(int objNo){
  float mat[16];

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

   glDepthMask(GL_FALSE);
  CalcShadowMat(objNo, mat);
  glPushMatrix();
   glMultMatrixf(mat);
   if(objNo == 0) draw_obj();

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

void display(void){
  //textureの作成
  glClearColor( 1.0, 1.0, 1.0, 1.0 );
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  glViewport( 0, 0, TEX_WIDTH, TEX_HEIGHT );
 
 glMatrixMode( GL_PROJECTION );
 glLoadIdentity();
  gluPerspective(view.fovY, (double)TEX_WIDTH/(double)TEX_HEIGHT, view.nearZ, view.farZ);
 glMatrixMode( GL_MODELVIEW );
 glLoadIdentity();
  if(cos(PAI * view.theta /180.0) >= 0.0)
   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);

  glPushMatrix();
 glTranslatef(0.0, 1.0, 0.0);
 glRotatef(-90.0, 1.0, 0.0, 0.0);
 glRotatef(-90.0, 0.0, 0.0, 1.0);
 model->Draw();
 glPopMatrix();
 glBindTexture(GL_TEXTURE_2D, texName[1]);
 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEX_WIDTH, TEX_HEIGHT);
  glBindTexture(GL_TEXTURE_2D, 0);

  //通常のrendering
  resize(width, height);
  glClearColor(0.7, 0.7, 0.9, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  if(cos(PAI * view.theta /180.0) >= 0.0)
   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);

  glLightfv(GL_LIGHT0, GL_POSITION, lightPos);

  //描画
  glBindTexture(GL_TEXTURE_2D, texName[1]);
  glsl.ON();
  GLint samplerLoc = glGetUniformLocation(glsl.ShaderProg, "sampler");
  glUniform1i(samplerLoc, 0);//GL_TEXTURE0を適用
  draw_obj();
  glBindTexture(GL_TEXTURE_2D, texName[0]);
  drawFloor(10.0, 10.0);
  glsl.OFF();
  glBindTexture(GL_TEXTURE_2D, 0);

  drawShadow(0);

  glutSwapBuffers();
}
 //タイマー
 void timer(int value){
  ang += dang;
  if(ang >= 360.0f)ang = 0.0f;
  glutTimerFunc(10 , timer , 0);
 }
 int main(int argc, char *argv[]){
   glutInitWindowPosition(100, 100);
   glutInitWindowSize(TEX_WIDTH, TEX_HEIGHT);
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
   glutCreateWindow("オフスクリーンレンダリング");
   glutDisplayFunc(display);
   glutIdleFunc(idle);
   glutMouseFunc(mouse);
   glutMotionFunc(motion);
   glutReshapeFunc(resize);
   glutTimerFunc(10 , timer , 0);
   Init();
   glutMainLoop();
   return 0;
 }

 

 

 

 

 

 

最終更新:2014年03月01日 22:49
添付ファイル