【图形学】纹理贴图、光照计算

本文介绍了如何在图形学中加载纹理和模型,通过OpenGL实现Bark纹理和Ground细节贴图,并结合光照计算,展示了一个3D树模型的绘制过程。核心代码展示了纹理映射、三角形面片处理及光照设置,最终运行结果呈现了逼真的光照效果。
摘要由CSDN通过智能技术生成

【图形学】纹理贴图、光照计算

1.绘制目标

纹理贴图、光照计算

在这里插入图片描述

2.核心代码

// 加载纹理
void loadTexture() {
	cv::Mat texture_img = loadImage("./Textures/bark_08.jpg", TEX_W, TEX_H);
	cv::Mat texture_img_GD = loadImage("./Textures/soil.jpg", TEX_W_GD, TEX_H_GD);

	if (texture_img.empty()) {
		cout << "Failed load the texture file!" << endl;
	}
	else {

		// 加载 图片纹理
		/// TO DO ///
		glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_W, TEX_H, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_img.data);
		glGenerateMipmap(GL_TEXTURE_2D);

		glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID_GD);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_W_GD, TEX_H_GD, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_img_GD.data);
		glGenerateMipmap(GL_TEXTURE_2D);

		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_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		cout << "Load the texture image successfully!" << endl;
	}
}

// 加载模型
bool load_mesh(const string& filename)
{
	cout << "Start loading the obj file, please wait......" << endl;

	// 读取网格对应的obj文件
	clock_t time_start = clock();
	bool load_success = OBJ_FILE_LOADER.read_file(filename);
	float time_elapsed = float(clock() - time_start) / CLOCKS_PER_SEC;
	if (!load_success) {
		cout << "Failed read the mesh obj file!" << endl;
		return false;
	}
	cout << "Finished load the obj file! Time elapsed: " << time_elapsed << " seconds." << endl;
	cout << "Total Vertices: " << OBJ_FILE_LOADER.total_vertices() << endl;
	cout << "Total Faces: " << OBJ_FILE_LOADER.total_faces() << endl;

	MIN_X = OBJ_FILE_LOADER.get_min_x();
	MIN_Y = OBJ_FILE_LOADER.get_min_y();
	MIN_Z = OBJ_FILE_LOADER.get_min_z();
	MAX_X = OBJ_FILE_LOADER.get_max_x();
	MAX_Y = OBJ_FILE_LOADER.get_max_y();
	MAX_Z = OBJ_FILE_LOADER.get_max_z();

	cout << "Min x: " << MIN_X << ", Max X: " << MAX_X << endl;
	cout << "Min y: " << MIN_Y << ", Max Y: " << MAX_Y << endl;
	cout << "Min z: " << MIN_Z << ", Max Z: " << MAX_Z << endl;

	OFFSET_X = (MIN_X + MAX_X) * 0.5f;
	OFFSET_Y = (MIN_Y + MAX_Y) * 0.5f;
	OFFSET_Z = (MIN_Z + MAX_Z) * 0.5f;
	Z_HALF_LENGTH = (MAX_Z - MIN_Z) * 0.5f;;

	// 创建显示列表
	MESH_LIST_ID = glGenLists(1);

	// 填充显示列表
	glNewList(MESH_LIST_ID, GL_COMPILE);
	glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID);
	glBegin(GL_TRIANGLES);
	for (int i = 0; i < OBJ_FILE_LOADER.total_faces(); ++i) {
		const Triangle& t = OBJ_FILE_LOADER.get_triangle_at(i);// 获取三角形面片 
		//获取三角形的顶点数据
		for (int j = 0; j < 3; ++j) {
			float vertex_coords[3] = { 0 };  // 存储顶点的x,y,z坐标
			float texture_coords[2] = { 0 }; // 存储顶点的纹理坐标
			float normal_coords[3] = { 0 }; // 保存法向量

			// TO DO : 获取并指定三角形三个顶点处的纹理坐标以及X,Y,Z空间坐标
			OBJ_FILE_LOADER.get_vertex_at(t.m_vertex_ids[j], vertex_coords);
			OBJ_FILE_LOADER.get_texture_at(t.m_texture_ids[j], texture_coords);
			OBJ_FILE_LOADER.get_normal_at(t.m_normal_ids[j], normal_coords);

			glTexCoord2f(texture_coords[0], texture_coords[1]);
			glNormal3f(normal_coords[0], normal_coords[1], normal_coords[2]);
			glVertex3f(vertex_coords[0], vertex_coords[1], vertex_coords[2]);//D
		}
	}
	glEnd();

	glEndList();

	return true;
}

// 加载模型
bool load_mesh2(const string& filename)
{
	cout << "Start loading the obj file, please wait......" << endl;

	// 读取网格对应的obj文件
	clock_t time_start = clock();
	bool load_success = OBJ_FILE_LOADER_GD.read_file(filename);
	float time_elapsed = float(clock() - time_start) / CLOCKS_PER_SEC;
	if (!load_success) {
		cout << "Failed read the mesh obj file!" << endl;
		return false;
	}
	cout << "Finished load the obj file! Time elapsed: " << time_elapsed << " seconds." << endl;
	cout << "Total Vertices: " << OBJ_FILE_LOADER_GD.total_vertices() << endl;
	cout << "Total Faces: " << OBJ_FILE_LOADER_GD.total_faces() << endl;

	MIN_X = OBJ_FILE_LOADER_GD.get_min_x();
	MIN_Y = OBJ_FILE_LOADER_GD.get_min_y();
	MIN_Z = OBJ_FILE_LOADER_GD.get_min_z();
	MAX_X = OBJ_FILE_LOADER_GD.get_max_x();
	MAX_Y = OBJ_FILE_LOADER_GD.get_max_y();
	MAX_Z = OBJ_FILE_LOADER_GD.get_max_z();

	cout << "Min x: " << MIN_X << ", Max X: " << MAX_X << endl;
	cout << "Min y: " << MIN_Y << ", Max Y: " << MAX_Y << endl;
	cout << "Min z: " << MIN_Z << ", Max Z: " << MAX_Z << endl;

	OFFSET_X = (MIN_X + MAX_X) * 0.5f;
	OFFSET_Y = (MIN_Y + MAX_Y) * 0.5f;
	OFFSET_Z = (MIN_Z + MAX_Z) * 0.5f;
	Z_HALF_LENGTH = (MAX_Z - MIN_Z) * 0.5f;;

	// 创建显示列表
	MESH_LIST_ID_GD = glGenLists(1);
	// 填充显示列表
	glNewList(MESH_LIST_ID_GD, GL_COMPILE);
	glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID_GD);
	glBegin(GL_TRIANGLE_STRIP);
	glTexCoord2f(0, 0);
	glNormal3f(0.000000, 1.000000, 0.000000);
	glVertex3f(-112.000000, -27.628487, 112.000000);//D

	glTexCoord2f(1, 0);
	glNormal3f(0.000000, 1.000000, 0.000000);
	glVertex3f(112.000000, -27.628487, 112.000000);//D

	glTexCoord2f(0, 1);
	glNormal3f(0.000000, 1.000000, 0.000000);
	glVertex3f(-112.000000, -27.628487, -112.000000);//D

	glTexCoord2f(1, 1);
	glNormal3f(0.000000, 1.000000, 0.000000);
	glVertex3f(112.000000, -27.628487, -112.000000);//D
	glEnd();
	glEndList();

	return true;
}

void init()
{
	glClearColor(1.f, 1.f, 1.f, 0.f);
	glEnable(GL_DEPTH_TEST);

	// 申请纹理
	glGenTextures(1, &BARK_TEXTURE_ID);
	glGenTextures(1, &BARK_TEXTURE_ID_GD);

	loadTexture();
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	glEnable(GL_TEXTURE_2D);
	glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient_color0);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse_and_specular0);
	glLightfv(GL_LIGHT0, GL_SPECULAR, light_diffuse_and_specular0);
	glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
	glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material_ambient_and_diffuse);
	glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular);
	glMaterialfv(GL_FRONT, GL_SHININESS, material_shininess);
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	load_mesh2("./Meshes/Tree96-Ground.obj");
	load_mesh("./Meshes/Tree96-Branch.obj");
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// TO DO: 设置照相机
	gluLookAt
	(
		0.0, 0.0, 256, /**eyex xyz*/
		0.0, 0.0, 0.0, /**center xyz*/
		0.0, 1.0, 0.0 /** up xyz*/
	);
	glRotatef(ROT_Z, 0.f, 0.f, 1.f);
	glRotatef(ROT_Y, 0.f, 1.f, 0.f);
	glRotatef(ROT_X, 1.f, 0.f, 0.f);
	glScalef(SCALE, SCALE, SCALE);
	glTranslatef(-OFFSET_X, -OFFSET_Y, -OFFSET_Z);
	glColor3f(0.f, 0.f, 1.f);
	// 调用显示列表,进行三维模型的绘制
	glCallList(MESH_LIST_ID_GD);
	glCallList(MESH_LIST_ID);

	glutSwapBuffers();
}

3.运行结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲代码两年半的练习生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值