#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib, "glew32.lib")
#include <GL/glew.h>
#include <GL/freeglut/freeglut.h>
#include "GLSL.h"
#include <math.h>
#define PAI 3.141592f
#define WIDTH 640
#define HEIGHT 480
GLSL glsl;
//回転用
float anglex = 0.0f;
//ライトの位置
GLfloat lightpos[] = { 10.0, 10.0, 10.0, 1.0 };
float Ambient[] = {0.2f, 0.1f, 0.2f, 1.0f};
float Diffuse[] = {0.8f, 0.8f, 0.0f, 1.0f};
float Specular[]= { 0.4f, 0.4f, 0.4f, 1.0f};//鏡面反射
float AmbientLight[] = { 1.0f, 1.0f, 1.0f, 1.0f};
float DiffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f};
float SpecularLight[] = {1.0f, 1.0f, 1.0f, 1.0f};//鏡面光
float pos[] = {-0.7f, 1.0f, 0.0f};//位置
bool flag=true;
//影のマテリアル
float shadowDiffuse[] = {0.0f,0.0f,0.0f,0.3f};//影の拡散光
float shadowSpecular[] = {0.0f,0.0f,0.0f,1.0f};//影の鏡面光
void setLight(){
glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
}
void draw(bool flag){
if(flag) {
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,8);
}
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glRotatef( anglex, 1.0f, 0.0f, 0.0f);//x軸回転
glutSolidTorus(0.2, 0.5, 10, 10);
glPopMatrix();
}
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.9f, 0.9f, 0.9f, 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,10);
glNormal3d(0.0, 1.0, 0.0);
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);
glVertex3d(x1, 0.0, z1);
glVertex3d(x1, 0.0, z2);
glVertex3d(x2, 0.0, z2);
glVertex3d(x2, 0.0, z1);
glEnd();
}
}
glPopMatrix();
}
void CalcShadowMat(float* mat){
float ex, ey, ez;//光源の方向
float s; //object中心から光源までの距離
float x, y, z;
x = lightpos[0] - pos[0];
y = lightpos[1] - pos[1];
z = lightpos[2] - pos[2];
//光源の方向ベクトル
s = sqrt(x * x + y * y + z * z);
ex = x / s;
ey = y / s;
ez = z / s;
//shadow matrix
mat[0] = ey;
mat[1] = 0.0f;
mat[2] = 0.0f;
mat[3] = 0.0f;
mat[4] = -ex;
mat[5] = 0.0f;
mat[6] = -ez;
mat[7] = 0.0f;
mat[8] = 0.0f;
mat[9] = 0.0f;
mat[10] = ey;
mat[11] = 0.0f;
mat[12] = 0.0f;
mat[13] = 0.001f * ey;
mat[14] = 0.0f;
mat[15] = ey;
}
void drawShadow(){
float mat[16];
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
CalcShadowMat(mat);
glPushMatrix();
glMultMatrixf(mat);
draw(true);
glPopMatrix();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//視点の設定
gluLookAt(10.0,10.0,-2.0, //カメラの座標
0.0,0.0,0.0, // 注視点の座標
0.0,1.0,0.0); // 画面の上方向を指すベクトル
//ライトの設定
setLight();
glsl.ON();
draw(false);
drawFloor(10.0, 10.0, 10, 10);
drawShadow();
glsl.OFF();
glutSwapBuffers();
}
void idle(void){
anglex+=2.0f;
if(flag){pos[2]+=0.001f;}else{pos[2]-=0.001f;}
if(pos[2]>3.0f)flag=false;
if(pos[2]<-3.0f)flag=true;
Sleep(1);
glutPostRedisplay();
}
void Init(){
glsl.InitGLSL("vertex.shader","flagment.shader");
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
}
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);
Init();
glutMainLoop();
return;
}
|