#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"
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];
#define PAI 3.141592f
int width = 640;
int height = 480;
int xStart, yStart;
bool flagMouse = false;
bool flagLight = false;
bool flagShadow = false;
int objNo = 0;
float ang = 0.0;
float dang = 0.1;//角度増分
//床マテリアルのアルファ値
float alpha = 0.5;
GLuint texName[2];
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 lightAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f}; //環境光
float lightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; //拡散光
float lightSpecular[] = {1.0, 1.0f, 1.0f, 1.0f}; //鏡面光
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, lightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//反射光源
float lightAmbientR[] = {1.0-alpha, 1.0-alpha, 1.0-alpha, 1.0}; //環境光
float lightDiffuseR[] = {1.0-alpha, 1.0-alpha, 1.0-alpha, 1.0}; //拡散光
float lightSpecularR[] = {1.0-alpha, 1.0-alpha, 1.0-alpha, 1.0}; //鏡面光
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmbientR);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuseR);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightSpecularR);
glLightfv(GL_LIGHT1, GL_POSITION, lightPosR);
glEnable(GL_LIGHT0);//実光源
glEnable(GL_LIGHT1);//反射光源
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,"brick.png");
TexCreate(1,"marble.png");
}
void idle(void){
//再描画
glutPostRedisplay();
}
//タイマー
void timer(int value){
ang += dang;
if(ang >= 360.0f)ang = 0.0f;
glutTimerFunc(10 , timer , 0);
}
void drawcube(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};
shadowDiffuse[3] = 0.3 * alpha;
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);
glRotatef(angle[0][1], 0.0, 1.0, 0.0);
glRotatef(angle[0][0] + ang, 1.0, 0.0, 0.0);
glScalef(scale[0][0], scale[0][1], scale[0][2]);
if(!flagShadow){
drawTexCube(1.0, 1, 1);
}else{//影表示のときはTextureを付けない
drawCube(1.0);
}
glPopMatrix();
}
void drawcubeR(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};
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);
glRotatef(angle[0][1], 0.0, 1.0, 0.0);
glRotatef(-angle[0][0] - ang, 1.0, 0.0, 0.0);
glScalef(scale[0][0], scale[0][1], scale[0][2]);
drawTexCube(1.0, 1, 1);
glPopMatrix();
}
void drawLight(void){
glDisable(GL_LIGHTING);
glColor3f(1.0, 1.0, 1.0);
glPushMatrix();
glTranslatef(lightPos[0], lightPos[1], lightPos[2]);
glutSolidSphere(0.02, 10, 10);
glPopMatrix();
glEnable(GL_LIGHTING);
}
void drawLightR(void){
glDisable(GL_LIGHTING);
glColor3f(1.0, 1.0, 1.0);
glPushMatrix();
glTranslatef(lightPos[0], -lightPos[1], lightPos[2]);
glutSolidSphere(0.02, 10, 10);
glPopMatrix();
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 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()
{
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);
drawcube();
glPopMatrix();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
flagShadow = false;
}
void drawFloor(float widthX, float widthZ)
{
float diffuse[] = { 0.8, 0.8, 0.8, alpha};
float ambient[] = { 0.2, 0.2, 0.2, alpha};
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 display(void){
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);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
//texture unit と texture object の関連付け
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName[0]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texName[1]);
//本物を描画
glsl.ON();
glActiveTexture(GL_TEXTURE0);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
GLint texLoc = glGetUniformLocation(glsl.ShaderProg, "sampler");
glUniform1i(texLoc, 0);
drawcube();
glsl.OFF();
drawLight();
//鏡像光源に切り替える
glLightfv(GL_LIGHT0, GL_POSITION, lightPosR);
glsl.ON();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(-1.0, 1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
//鏡像オブジェクトを描く
glUniform1i(texLoc, 0);
drawcubeR();
glsl.OFF();
drawLightR();
//本物光源に戻す
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glsl.ON();
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
//フロアと影
glUniform1i(texLoc, 1);
glBindTexture(GL_TEXTURE_2D, texName[1]);
drawFloor(10.0, 10.0);
drawShadow();
glsl.OFF();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
glutSwapBuffers();
}
int main(int argc, char *argv[]){
glutInitWindowPosition(100, 100);
glutInitWindowSize(width, 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;
}
|