#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>
#define PAI 3.141592f
float pos[][3] = { //位置(平行移動)
{ 0.3f, 3.5f, 0.0f},//obj0
{-0.4f, 1.5f, 0.0f} //obj1
};
float angle[][3] = {//姿勢(回転)
{ 0.0f, 0.0f, 0.0f}, //obj0
{ 0.0f, 0.0f, 0.0f} //obj1
};
float lightPos[] = {0.0f, 6.0f, 1.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.0f, 0.0f,//cnt
10.0f, 30.0f, 0.0f,//dist, theta, phi
40.0f, 1.0f, 100.0f//fovY,nearZ, farZ
};
View view0 = view;
GLSL glsl;
//Windowのサイズ
int width = 512;
int height = 512;
//アフィン変換
enum SELECT_KEY {ROTATE, SCALE, TRANSLATE, LIGHT};
SELECT_KEY sKey = TRANSLATE;
//マウス操作
int xStart, yStart;
bool flagMouse = false;
//オブジェクト識別番号
int objNo = 0;
//回転アニメーション
float ang = 0.0f;
//シャドウマッピング用テクスチャー
int TEX_WIDTH = width;
int TEX_HEIGHT = height;
float fov = 120.0;//シャドウマッピングの視野角
float farZ = 50.0;//シャドウマッピングの後方クリップ面
GLfloat modelview[16]; //モデルビュー変換行列の保存用
void drawCylinder(float rBottom, float rTop, float height, float thick, int
nSlice, int nStack){
int i, j;
float x, y, z, z0, z1;
float theta;
float theta0 = (float)2.0*PAI/nSlice;
//上底(Top)
glBegin(GL_QUAD_STRIP);
glNormal3f(0.0f, 0.0f, 1.0f);
for(i = 0; i <= nSlice; i++) {
theta = theta0 * (float)i;
z = height/2.0f;
//内側座標
x = (rTop - thick) * cos(theta); //x成分
y = (rTop - thick) * sin(theta); //y成分
glVertex3f(x, y, z);
//外側座標
x = rTop * cos(theta); //x成分
y = rTop * sin(theta); //y成分
glVertex3f(x, y, z);
}
glEnd();
//下底(Bottom)
glBegin(GL_QUAD_STRIP);
glNormal3f(0.0f, 0.0f, -1.0f);
for(i = 0; i <= nSlice; i++) {
theta = theta0 * (float)i;
z = -height/2.0f;
//外側座標
x = rBottom * cos(theta); //x成分
y = rBottom * sin(theta); //y成分
glVertex3f(x, y, z);
//内側座標
x = (rBottom - thick) * cos(theta); //x成分
y = (rBottom - thick) * sin(theta); //y成分
glVertex3f(x, y, z);
}
glEnd();
float t0, t1, r0, r1, phi;
float p[2][3], n[3];
float rr = rBottom - rTop;
float nz = rr / sqrt(rr*rr + height*height);
float nxy = sqrt(1.0f - nz * nz);
for(j = 0; j < nStack; j++){
//j=0は上底(x=0, y=0, z=height/2)
//2つのt座標
t0 = (float)j / (float)nStack;
t1 = (float)(j+1) / (float)nStack;
//底面からの高さ
z0 = height * (1.0f - t0);
z1 = height * (1.0f - t1);
//半径
r0 = rBottom + (rTop - rBottom) * z0 / height;
r1 = rBottom + (rTop - rBottom) * z1 / height;
//頂点z座標
p[0][2] = z0 - height / 2.0f;
p[1][2] = z1 - height / 2.0f;
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= nSlice; i++){
phi = 2.0f * PAI * (float)i / (float)nSlice;
//頂点のxy座標(i=0を真後ろ)
p[0][0] = r0 * cos(phi);//x座標
p[0][1] = r0 * sin(phi);//y座標
p[1][0] = r1 * cos(phi);//x座標
p[1][1] = r1 * sin(phi);//y座標
//法線ベクトル
n[0] = nxy * cos(phi);
n[1] = nxy * sin(phi);
n[2] = nz;
glNormal3fv(n);//法線ベクトル
glVertex3fv(p[0]);//頂点座標
glVertex3fv(p[1]);//頂点座標
}
glEnd();
}
//内側側面
for(j = 0; j < nStack; j++){
//j=0は上底(x=0, y=0, z=height/2)
//2つのt座標
t0 = (float)j / (float)nStack;
t1 = (float)(j+1) / (float)nStack;
//底面からの高さ
z0 = (float)height * (1.0f - t0);
z1 = (float)height * (1.0f - t1);
//半径
r0 = rBottom - thick + (rTop - rBottom) * z0 / height;
r1 = rBottom - thick + (rTop - rBottom) * z1 / height;
//頂点z座標
p[0][2] = z0 - height / 2.0f;
p[1][2] = z1 - height / 2.0f;
glBegin(GL_QUAD_STRIP);
for(i = nSlice; i >= 0; i--){
phi = 2.0f * PAI * (float)i / (float)nSlice;
//頂点のxy座標(i=0を真後ろ)
p[0][0] = -r0 * cos(phi);//x座標
p[0][1] = -r0 * sin(phi);//y座標
p[1][0] = -r1 * cos(phi);//x座標
p[1][1] = -r1 * sin(phi);//y座標
//法線ベクトル
n[0] = nxy * cos(phi);
n[1] = nxy * sin(phi);
n[2] = - nz;
glNormal3fv(n);//法線ベクトル
glVertex3fv(p[0]);//頂点座標
glVertex3fv(p[1]);//頂点座標
}
glEnd();
}
}
void setShadowMap(){
//テクスチャを拡大・縮小する方法の指定
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//テクスチャの繰り返し方法の指定
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//テクスチャ座標rを用いてテクセル値と比較
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_R_TO_TEXTURE);
//rの値がテクセル値以上なら影になる
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
//結果を輝度値として取得
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
}
void setTextureMatrix(){
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5, 0.5, 0.5);
glScalef(0.5, 0.5, 0.5);
glMultMatrixf(modelview);
}
void drawTorus(void){
setTextureMatrix();
glTranslatef(pos[0][0], pos[0][1], pos[0][2]);
glRotatef(angle[0][2], 0.0f, 0.0f, 1.0f);//z軸回転
glRotatef(angle[0][1], 0.0f, 1.0f, 0.0f);//y軸回転
glRotatef(angle[0][0] + ang, 1.0f, 0.0f, 0.0f);//x軸回転
float ambient[] = { 0.0f, 0.0f, 0.7f, 1.0f};
float diffuse[] = { 0.0f, 0.0f, 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);
//モデルビュー変換行列に戻す
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(pos[0][0], pos[0][1], pos[0][2]);
glRotatef(angle[0][2], 0.0f, 0.0f, 1.0f);//z軸回転
glRotatef(angle[0][1], 0.0f, 1.0f, 0.0f);//y軸回転
glRotatef(angle[0][0] + ang, 1.0f, 0.0f, 0.0f);//x軸回転
glutSolidTorus(0.2f, 0.5f, 20, 20);
glPopMatrix();
}
void drawCylinder(void){
setTextureMatrix();
glTranslatef(pos[1][0], pos[1][1], pos[1][2]);
glRotatef(angle[1][2], 0.0f, 0.0f, 1.0f);//z軸回転
glRotatef(angle[1][1], 0.0f, 1.0f, 0.0f);//y軸回転
glRotatef(angle[1][0] + ang, 1.0f, 0.0f, 0.0f);//x軸回転
float ambient[] = { 0.3f, 0.3f, 0.0f, 1.0f};
float diffuse[] = { 0.7f, 0.7f, 0.0f, 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);
//モデルビュー変換行列に戻す
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(pos[1][0], pos[1][1], pos[1][2]);
glRotatef(angle[1][2], 0.0f, 0.0f, 1.0f);//z軸回転
glRotatef(angle[1][1], 0.0f, 1.0f, 0.0f);//y軸回転
glRotatef(angle[1][0] + ang, 1.0f, 0.0f, 0.0f);//x軸回転
drawCylinder(1.0f, 0.7f, 2.0f, 0.3f, 20, 5);
glPopMatrix();
}
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.9f, 0.9f, 0.9f, 1.0f}, { 0.0f, 0.8f, 0.0f, 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);
//モデルビュー変換行列に戻す
glMatrixMode(GL_MODELVIEW);
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 resize(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(view.fovY, (float)w/(float)h, view.nearZ, view.farZ);
width = w;
height = h;
}
void display(void){
//ステップ1:デプスマップの作成
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, TEX_WIDTH, TEX_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//光源位置を視点とするモデルビュー変換行列を設定
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluPerspective(fov, (float)TEX_WIDTH / (float)TEX_HEIGHT, 1.0, farZ);
gluLookAt(lightPos[0], lightPos[1], lightPos[2], 0.0, 0.0, 0.0, 0.0, 0.0,
1.0);
//設定したモデルビュー行列を保存しておく(setTextureMatrixで使用する)
glGetFloatv(GL_MODELVIEW_MATRIX, modelview);
glColorMask(0, 0, 0, 0);
//デプスバッファには背面の奥行きを記録する
glCullFace(GL_FRONT);
//デプスマップ作成のためにシーンを描画
drawTorus();
drawCylinder();
// デプスバッファの内容をテクスチャメモリに転送
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, TEX_WIDTH,
TEX_HEIGHT, 0);
//ステップ2
//通常の描画設定に戻す
resize(width, height);
glColorMask(1, 1, 1, 1); //フレームバッファへ書き込み許可
glCullFace(GL_BACK);//背面は描画しない
//カラーバッファのクリア
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();//視点を変えるときはこの位置に必要
if(cos(view.theta*PAI/180.0) >= 0.0)// <=
90.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);
glsl.ON();
GLint texLoc = glGetUniformLocation(glsl.ShaderProg, "shadowMap");
glUniform1i(texLoc, 0);
drawTorus();
drawCylinder();
drawFloor(10.0, 10.0, 10, 10);
glsl.OFF();
glutSwapBuffers();
}
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(){
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 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.5f, 0.5f, 0.7f, 1.0f);
setCamera();
setLight();
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_SMOOTH);
glEnable(GL_CULL_FACE);
setShadowMap();
glsl.InitGLSL("vertex.shader","flagment.shader");
}
void idle(void){
glutPostRedisplay();
}
void timer(int value) {
ang+=0.1f;
glutTimerFunc(10 , timer , 0);
}
void 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;
}
|