#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <SOIL.h>
// 纹理ID数组
GLuint textures[3];
// 光照设置
void initLighting() {
// 启用光照
glEnable(GL_LIGHTING);
// 光源1 (点光源)
GLfloat light0_ambient[] = {0.2, 0.2, 0.2, 1.0};
GLfloat light0_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light0_specular[] = {1.0, 1.0, 1.0, 1.0};
GLfloat light0_position[] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glEnable(GL_LIGHT0);
// 光源2 (平行光)
GLfloat light1_ambient[] = {0.1, 0.1, 0.1, 1.0};
GLfloat light1_diffuse[] = {0.8, 0.8, 0.8, 1.0};
GLfloat light1_specular[] = {0.5, 0.5, 0.5, 1.0};
GLfloat light1_position[] = {-1.0, -1.0, -1.0, 0.0}; // w=0表示平行光
glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
glEnable(GL_LIGHT1);
}
// 加载纹理
void loadTextures() {
glGenTextures(3, textures);
// 纹理1
glBindTexture(GL_TEXTURE_2D, textures[0]);
int width, height;
unsigned char* image = SOIL_load_image("texture1.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 纹理2
glBindTexture(GL_TEXTURE_2D, textures[1]);
image = SOIL_load_image("texture2.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 纹理3 (用于另一个物体)
glBindTexture(GL_TEXTURE_2D, textures[2]);
image = SOIL_load_image("texture3.jpg", &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
// 绘制立方体
void drawCube() {
glBegin(GL_QUADS);
// 前面
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
// 后面
glNormal3f(0.0, 0.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
// 上面
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
// 下面
glNormal3f(0.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
// 右面
glNormal3f(1.0, 0.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
// 左面
glNormal3f(-1.0, 0.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glEnd();
}
// 绘制球体
void drawSphere() {
glutSolidSphere(1.0, 50, 50);
}
// 显示函数
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// 设置材质1 (用于立方体)
GLfloat mat_ambient1[] = {0.7, 0.7, 0.7, 1.0};
GLfloat mat_diffuse1[] = {0.8, 0.8, 0.8, 1.0};
GLfloat mat_specular1[] = {1.0, 1.0, 1.0, 1.0};
GLfloat mat_shininess1[] = {50.0};
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient1);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse1);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular1);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess1);
// 绘制带纹理的立方体 (使用两种纹理)
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// 前面和后面使用纹理1
glBindTexture(GL_TEXTURE_2D, textures[0]);
glPushMatrix();
glTranslatef(-2.0, 0.0, 0.0);
glRotatef(30, 1.0, 1.0, 0.0);
drawCube();
glPopMatrix();
// 设置材质2 (用于球体)
GLfloat mat_ambient2[] = {0.2, 0.2, 0.5, 1.0};
GLfloat mat_diffuse2[] = {0.3, 0.3, 0.8, 1.0};
GLfloat mat_specular2[] = {0.8, 0.8, 0.8, 1.0};
GLfloat mat_shininess2[] = {30.0};
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient2);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse2);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular2);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess2);
// 绘制带纹理的球体 (使用不同纹理)
glBindTexture(GL_TEXTURE_2D, textures[2]);
glPushMatrix();
glTranslatef(2.0, 0.0, 0.0);
drawSphere();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
}
// 键盘回调函数
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case '1':
glShadeModel(GL_FLAT);
break;
case '2':
glShadeModel(GL_SMOOTH);
break;
case 27: // ESC键
exit(0);
break;
}
glutPostRedisplay();
}
// 窗口大小调整
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// 初始化函数
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
initLighting();
loadTextures();
// 默认使用平滑着色
glShadeModel(GL_SMOOTH);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("真实感图形生成实验");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}