전역 주변광
- 3차원 공간에 벽, 바닥, 공 만들기
- 전역 주변광 추가
- glEnable(GL_LIGHTING)의 효과 확인
glEnable(GL_LIGHTING);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
GLfloat light_global_ambient[] = {0.0, 0.0, 0.1, 1.0}; //ambient : 주변광
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_global_ambient);
위치성 광원 추가
- 위치성 광원 1개 추가
- 광원의 위치 변경 테스트
- 광원의 색상 변경 테스트
GLfloat bNonDirectionalLight = 1.0; //DirectionalLight가 아니다.
GLfloat light_0_pos[] = {Light0_pos_x, Light0_pos_y, Light0_pos_z, bNonDirectionalLight}; //빛 위치 지정 공 바로 위에
GLfloat light_0_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_0_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_0_ambient[] = {1.0 , 1.0, 1.0, 1.0};//백색광 = 태양
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, light_0_pos); //0번째 Light Position지정 개수는 GPU에 따라 다름
glLightfv(GL_LIGHT0, GL_SPECULAR, light_0_specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_0_diffuse);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_0_ambient);
물체의 반사 설정 추가
- 물체의 빛 반사 설정
//물체 색깔
GLfloat material_0_specular[] = {1.0, 1.0, 1.0, 1.0};//빛 색깔과 그대로 맞춰주기
GLfloat material_0_diffuse[] = {0.8, 0, 0, 1.0};
GLfloat material_0_ambient[] = {1.0, 0, 0, 1.0};
GLfloat material_0_shininess[] = {25.0};// 0~128
glMaterialfv(GL_FRONT, GL_DIFFUSE, material_0_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, material_0_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, material_0_ambient);
glMaterialfv(GL_FRONT, GL_SHININESS, material_0_shininess);
법선 벡터 설정
- 벽과 바닥의 법선 벡터 설정
- 법선 벡터는 정점마다 다르게 설정할 수 있음
- 따라서, 법선 벡터의 설정에 따라 곡면 표현이 가능해짐
- 하지만, 법선 벡터의 크기는 항상 1이므로 정규화를 따로 해줘야함.
void drawFloor(GLfloat y){
glNormal3f(0, 1, 0);
glBegin(GL_POLYGON);
}
void drawWall(GLfloat z){
glPushMatrix();
glNormal3f(0,0,-1);
glBegin(GL_POLYGON);
}
glEnable(GL_NORMALIZE); //만약 법선 벡터의 크기를 1로 하지 않았다면 꼭 정규화 해줘야함
발광체 설정(스스로 빛나는 물체)
- 물체의 발광체 설정
GLfloat material_0_emission[] = {0.0, 0.0, 0.5, 1.0};
glMaterialfv(GL_FRONT, GL_EMISSION, material_0_emisson);
- 발광체는 스스로 빛을 발생
- 다른 물체에 빛을 보내지는 않음
- 시점 위치에 따른 정밀도 설정이 가능함(가까이에 있는 물체는 조금더 정밀하게 : GPU에 따라 차이 발생)
glLightModeli(GL_LIGHT_LOCAL_VIWER, GL_TRUE);
OpenGL 실습코드 : Lighting
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include <iostream>
#define _WINDOW_WIDTH 500
#define _WINDOW_HEIGHT 500
GLfloat camPos_x = 0, camPos_y = 5, camPos_z = -7; //위치
GLfloat camAt_x = 0, camAt_y = 0, camAt_z = 0; //바라보는 곳
GLfloat camUp_x = 0, camUp_y = 1, camUp_z = 0; //방향
GLfloat Light0_pos_x = 5.0, Light0_pos_y = 5.0, Light0_pos_z = 0.0;
void MaterialLightInit(GLfloat am_R, GLfloat am_G, GLfloat am_B, GLfloat am_A , GLfloat di_R, GLfloat di_G, GLfloat di_B, GLfloat di_A){
glDisable(GL_COLOR_MATERIAL); //display할 때마다 기존의 색상을 무효화시키고 새로 그려라, 이렇게 안하면 reshape될때 색이 바뀜
GLfloat material_0_specular[] = {1.0, 1.0, 1.0, 1.0};//빛 색깔과 그대로 맞춰주기
GLfloat material_0_diffuse[] = {di_R, di_G, di_B, di_A};
GLfloat material_0_ambient[] = {am_R, am_G, am_B, am_A};
GLfloat material_0_shininess[] = {25.0};// 0~128
//GLfloat material_0_emission[] = {0.0, 0.0, 1.0, 1.0};
glMaterialfv(GL_FRONT, GL_DIFFUSE, material_0_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, material_0_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, material_0_ambient);
glMaterialfv(GL_FRONT, GL_SHININESS, material_0_shininess);
//glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
void drawFloor(GLfloat y){
GLfloat x = -2.5, z = -2.5, w = 5;
MaterialLightInit(0, 0, 1.0, 1.0, 0, 0, 0.8, 1.0);
glBegin(GL_POLYGON);
glNormal3f(-2, 1, 0);
//법선벡터는 따로 해줘야 쉐이딩이 적용된다.
//법선 벡터의 방향에 따라서 평면이 볼록&오목(곡면 설정)하다라고 인식함 이를 이용해서 적절하게 음영을 주는거임
//하지만 이렇게되면 법선벡터의 크기가 1이 아니기 때문에 Normalize해줘야함.
glVertex3f(x,y,z);
glVertex3f(x,y,z+w);
glNormal3f(2, 1, 0);
glVertex3f(x+w,y,z+w);
glVertex3f(x+w,y,z);
//이렇게 설정하면 평면이 오목하게돼서 왼쪽 두 점은 더 어두워지고
//오른쪽 두 점은 약간 더 어두워짐
glEnd();
}
void drawWall(GLfloat z){
GLfloat x = -2.5, y = -2.5, w = 5;
//glColor3f(0.2, 0.6, 0.2);
MaterialLightInit(1.0, 1.0, 0, 1.0, 1.0, 1.0, 0, 1.0);
glNormal3f(0, 0, -1); //법선벡터는 따로 해줘야 쉐이딩이 적용된다.
glBegin(GL_POLYGON);
glVertex3f(x,y,z);
glVertex3f(x,y+w,z);
glVertex3f(x+w,y+w,z);
glVertex3f(x+w,y,z);
glEnd();
}
void MyReshape(int width, int height){
GLfloat left = 0, bottom = 0;
glViewport(left, bottom, width-left, height-bottom);
glMatrixMode(GL_PROJECTION);//투영변환 모드 초기화
glLoadIdentity();
GLfloat ratio = (float)(width-left)/(height-bottom); //비율 값
gluPerspective(40, ratio, 0.1, 1000); //원근 투영
}
void drawSphere(){
MaterialLightInit(1.0, 0, 0, 1.0, 0.8, 0, 0, 1.0);
glutSolidSphere(0.3, 20, 20);
}
void MyDisplay(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(camPos_x, camPos_y, camPos_z, camAt_x, camAt_y, camAt_z, camUp_x,camUp_y, camUp_z);
drawFloor(-2.5);
drawWall(2.5);
drawSphere();
//glColor3f(0.8, 0.2, 0.0);
glFlush();
}
void Init_light(){
GLfloat bNonDirectionalLight = 1.0; //DirectionalLight가 아니다.
glEnable(GL_LIGHTING); //빛을 쓰겠다
glShadeModel(GL_SMOOTH); //구로 셰이딩 쓰겠다 퐁 셰이딩은 GL에 없음
glEnable(GL_DEPTH_TEST);
GLfloat light_global_ambient[] = {0.3,0.3,0.3, 1}; //전역 주변광 색깔 지정
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_global_ambient);//전역 주변광을 주겠다.
GLfloat light_0_pos[] = {Light0_pos_x, Light0_pos_y, Light0_pos_z, bNonDirectionalLight}; //빛 위치 지정 공 바로 위에
GLfloat light_0_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_0_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_0_ambient[] = {1.0 , 1.0, 1.0, 1.0};//백색광 = 태양
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, light_0_pos); //0번째 Light Position지정 개수는 GPU에 따라 다름
// glLightfv(GL_LIGHT0, GL_SPECULAR, light_0_specular);
// glLightfv(GL_LIGHT0, GL_DIFFUSE, light_0_diffuse);
// glLightfv(GL_LIGHT0, GL_AMBIENT, light_0_ambient);
glEnable(GL_NORMALIZE);//법선벡터 정규화 크기를 1로 바꾸기
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(_WINDOW_WIDTH, _WINDOW_HEIGHT);
glutInitWindowPosition(300, 200);
glutCreateWindow("Lighting & Shading");
glClearColor(0,0,0,0.0);
Init_light();
glutDisplayFunc(MyDisplay);
glutReshapeFunc(MyReshape);
glutMainLoop();
return 0;
}
OpenGL 실습코드 : SpotLight
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include <iostream>
#define _WINDOW_WIDTH 500
#define _WINDOW_HEIGHT 500
GLfloat camPos_x = 0, camPos_y = 1, camPos_z = -2; //위치
GLfloat camAt_x = 0, camAt_y = 0, camAt_z = 0; //바라보는 곳
GLfloat camUp_x = 0, camUp_y = 1, camUp_z = 0; //방향
GLfloat Light0_pos_x = 2.0, Light0_pos_y = 2.0, Light0_pos_z = -2.0;
GLfloat bNonDirectionalLight = 1.0;
void MyReshape(int width, int height){
GLfloat left = 0, bottom = 0;
glViewport(left, bottom, width-left, height-bottom);
glMatrixMode(GL_PROJECTION);//투영변환 모드 초기화
glLoadIdentity();
GLfloat ratio = (float)(width-left)/(height-bottom); //비율 값
gluPerspective(40, ratio, 0.1, 1000); //원근 투영
}
void Init_light(){
glEnable(GL_LIGHTING); //빛을 쓰겠다
glShadeModel(GL_SMOOTH); //구로 셰이딩 쓰겠다 퐁 셰이딩은 GL에 없음
glEnable(GL_DEPTH_TEST);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
void MyDisplay(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(camPos_x, camPos_y, camPos_z, camAt_x, camAt_y, camAt_z, camUp_x,camUp_y, camUp_z);
//전역광
GLfloat light_global_ambient[] = {0.3,0.3,0.3, 1}; //전역 주변광 색깔 지정
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_global_ambient);
//조명 설정 & 스포트라이트
glEnable(GL_LIGHT0);
GLfloat light_0_pos[] = {Light0_pos_x, Light0_pos_y, Light0_pos_z, bNonDirectionalLight}; //빛 위치 지정 공 바로 위에
GLfloat light_0_dir[] = {-1, -1, 1};
GLfloat light_0_SpotAngle[] = {3};
GLfloat light_0_SpotExp1[] = {10.0};
glLightfv(GL_LIGHT0, GL_POSITION, light_0_pos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_0_dir);
glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, light_0_SpotAngle);
glLightfv(GL_LIGHT0, GL_SPOT_EXPONENT, light_0_SpotExp1); //확산 적용이 안되는 것 같음
//주변광, 확산광, 경면광
GLfloat light_0_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light_0_diffuse[] = {0, 0, 1.0, 1.0};
GLfloat light_0_ambient[] = {1.0 , 1.0, 1.0, 1.0};//백색광 = 태양
glLightfv(GL_LIGHT0, GL_SPECULAR, light_0_specular);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_0_diffuse);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_0_ambient);
//물체 반사광
glDisable(GL_COLOR_MATERIAL); //display할 때마다 기존의 색상을 무효화시키고 새로 그려라, 이렇게 안하면 reshape될때 색이 바뀜
GLfloat material_0_specular[] = {1.0, 1.0, 1.0, 1.0};//빛 색깔과 그대로 맞춰주기
GLfloat material_0_diffuse[] = {0.8,0,0.3,1.0}; // 파란색도 어느정도 반사되게 함
GLfloat material_0_ambient[] = {0.3,0.3,0.3,1.0};
GLfloat material_0_shininess[] = {25.0};// 0~128
//GLfloat material_0_emission[] = {0.0, 0.0, 1.0, 1.0};
glMaterialfv(GL_FRONT, GL_DIFFUSE, material_0_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, material_0_specular);
glMaterialfv(GL_FRONT, GL_AMBIENT, material_0_ambient);
glMaterialfv(GL_FRONT, GL_SHININESS, material_0_shininess);
//glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glutSolidTeapot(0.3);
glEnable(GL_COLOR_MATERIAL);
glFlush();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(_WINDOW_WIDTH, _WINDOW_HEIGHT);
glutInitWindowPosition(300, 200);
glutCreateWindow("Lighting & Shading");
glClearColor(0,0,0,0.0);
Init_light();
glutDisplayFunc(MyDisplay);
glutReshapeFunc(MyReshape);
glutMainLoop();
return 0;
}
'Computer Graphics' 카테고리의 다른 글
Chapter15. 텍스쳐 (0) | 2021.06.14 |
---|---|
Chapter14. 모델 Load & 조명주기 (0) | 2021.06.09 |
Chapter13. 조명과 음영 (0) | 2021.06.08 |
Chapter12. 에일리어싱과 안티 에일리어싱 (0) | 2021.06.07 |
Chapter11. 래스터 변환 (0) | 2021.06.07 |