#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[] = { 0.0, 4.0, 0.0, 1.0 };
float Ambient[] = {0.2f, 0.1f, 0.2f, 1.0f};
float Diffuse[] = {1.0f, 1.0f, 1.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 lightDiffuse[4] = {0.0, 1.0, 0.0, 1.0}; //拡散光
float lightSpecular[4] = {0.0, 1.0, 0.0, 1.0}; //鏡面光
float spotExp = 5.0; //LIGHT1
float spotCutoff = 25.0; //LIGHT1
float spotDir[3] ; //LIGHT1
float pos[] = {-0.7f, 2.0f, 0.0f};//位置
bool flag = true;
float constAtt = 1.0;
float linearAtt = 0.0;
float quadraAtt = 0.0;
//影のマテリアル
float shadowDiffuse[] = {0.0f,0.0f,0.0f,0.3f};//影の拡散光
float shadowSpecular[] = {0.0f,0.0f,0.0f,1.0f};//影の鏡面光
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軸回転
glutSolidCube(1.0);
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 setLight(){
//LIGHT1
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse);
glLightfv(GL_LIGHT1, GL_AMBIENT, lightDiffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightSpecular);
glLightfv(GL_LIGHT1, GL_POSITION, lightpos);
//LIGHT1はスポットライト(スポットライトは常にワールド空間の原点を向く)
for(int i = 0; i < 3; i++) spotDir[i] = -lightpos[i];
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spotDir);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, spotExp);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, spotCutoff);
glEnable(GL_LIGHTING);
}
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){
if(spotExp>50.0f)flag=false;
if(spotExp<5.0f)flag=true;
if(flag){spotExp+=0.5f;}else{spotExp-=0.5f;}
anglex+=2.0f;
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_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;
}
|