news 2026/7/4 6:18:16

三维几何形体场景纹理贴图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
三维几何形体场景纹理贴图

目 录

1 实验目的和内容

1.1实验目的

1.2实验内容

2 基本原理

3 主要仪器与设备

4 实验步骤/数据处理与结果

Step1:开发环境配置与项目创建

Step2:头文件参数定义

Step3:纹理映射底层实现

Step4:灯光与材质实现

Step5:3D房屋场景实现

Step6:旋转地球、旋转立方功能实现

Step7:交互功能实现

Step8:调试优化

Step9:编译运行与效果展示


1 实验目的和内容

1.1实验目的

(1)理解纹理映射就是把具有某种表面纹理的图像粘贴到物体表面,从而获得具有真实感效果的物体模型;(2)掌握纹理映射的步骤:①指定纹理;②指定纹理应用的方式;③激活纹理映射;④指定纹理坐标和几何坐标,绘制场景。

1.2实验内容

(1)设计一个有实际意义的三维几何形体场景;(2)为中心三维几何形体贴上不同的纹理,使场景表现具有真实感;(3)为场景设置灯光,添加光照效果;(4)在中心三维几何形体纹理贴图上设置材质属性,进一步增强物体真实质感。

2 基本原理

纹理映射:纹理映射(Texture Mapping)是计算机图形学中用于增强三维模型表面细节和真实感的关键技术,其核心是将二维纹理图像映射到三维几何表面。

3 主要仪器与设备

Visual Studio 2010、OpenGL函数库、BMP文件

4 实验步骤/数据处理与结果

Step1:开发环境配置与项目创建

Step2:头文件参数定义

定义场景枚举、全局参数(纹理ID、模型尺寸、灯光、材质、交互参数等),声明所有自定义函数,为main.cpp的实现提供支撑。

Step3:纹理映射底层实现

纹理映射的底层核心是“加载纹理→配置纹理→激活纹理→绑定坐标”,设计两个核心函数,实现从纹理加载到应用的完整流程。

// 加载单张纹理,实现纹理映射第一步(指定纹理)、第二步(配置纹理应用方式) GLuint LoadSingleTex(TCHAR* path){ GLuint texId = 0; // 调用GLAux库函数加载bmp纹理,判断图片有效性 AUX_RGBImageRec* img = auxDIBImageLoad(path); if(!img || !img->data){ if(img) free(img); return texId; // 加载失败返回空ID,避免底层异常 } // 生成纹理,绑定纹理ID glGenTextures(1, &texId); glBindTexture(GL_TEXTURE_2D, texId); // 纹理过滤、环绕模式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 将纹理数据传入,完成纹理指定 glTexImage2D(GL_TEXTURE_2D, 0, 3, img->sizeX, img->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, img->data); // 释放图片资源,避免内存泄漏 free(img->data); free(img); return texId; } // 批量加载所有纹理,调用单纹理加载函数,简化底层代码 void LoadAllTex(){ texDeskTop = LoadSingleTex(szDeskTop); texDeskLeg = LoadSingleTex(szDeskLeg); texFootball = LoadSingleTex(_T("football.bmp")); texFrame = LoadSingleTex(_T("frame.bmp")); texPainting = LoadSingleTex(_T("painting.bmp")); texLampBase = LoadSingleTex(_T("lamp_base.bmp")); texLampShade = LoadSingleTex(_T("lamp_shade.bmp")); texEarth = LoadSingleTex(szEarth); for(int i=0; i<6; i++){ texCube[i] = LoadSingleTex(szCube[i]); } }

Step4:灯光与材质实现

灯光与材质的底层逻辑是“配置参数→开启功能→绑定到模型”,通过OpenGL函数配置光照和材质参数,让模型呈现明暗对比和真实质感。

// 设置太阳光照,配置光照参数,开启光照功能 void SetSunLight(){ GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f}; // 漫反射光(模拟太阳光) GLfloat lightSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 镜面反射光(配合材质) GLfloat lightPosition[] = {5.0f, 8.0f, 5.0f, 1.0f}; // 光源位置(斜上方照射) // 配置光照参数,绑定到0号光源 glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular); glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); // 开启光照功能,让配置生效 glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } // 设置书桌(中心形体)材质,将材质参数绑定到模型,增强真实质感 void SetDeskMaterial(){ // 配置材质的环境光、漫反射、镜面反射参数,绑定到模型正面 glMaterialfv(GL_FRONT, GL_AMBIENT, deskMatAmbient); glMaterialfv(GL_FRONT, GL_DIFFUSE, deskMatDiffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, deskMatSpecular); glMaterialfv(GL_FRONT, GL_SHININESS, deskMatShininess); }

Step5:3D房屋场景实现

按场景标识,调用对应绘制函数,实现纹理、灯光、材质的整合应用,绘制中心形体及辅助形体,整合纹理、灯光、材质,实现室内书桌场景。

// 绘制书桌(中心形体),实现纹理映射第三步(激活纹理)、第四步(绑定坐标) void DrawDesk(){ glEnable(GL_TEXTURE_2D); // 激活纹理映射(第三步) SetDeskMaterial(); // 绑定书桌材质,与灯光交互 // 绘制书桌桌面(木质纹理) glBindTexture(GL_TEXTURE_2D, texDeskTop); glBegin(GL_QUADS); glNormal3f(0.0f, 1.0f, 0.0f); // 绑定纹理坐标与几何坐标(第四步),一一对应,确保纹理贴合 glTexCoord2f(0.0f, 0.0f); glVertex3f(-DESK_TOP_SIZE/2, DESK_HEIGHT, -DESK_TOP_SIZE/2); glTexCoord2f(1.0f, 0.0f); glVertex3f(DESK_TOP_SIZE/2, DESK_HEIGHT, -DESK_TOP_SIZE/2); glTexCoord2f(1.0f, 1.0f); glVertex3f(DESK_TOP_SIZE/2, DESK_HEIGHT, DESK_TOP_SIZE/2); glTexCoord2f(0.0f, 1.0f); glVertex3f(-DESK_TOP_SIZE/2, DESK_HEIGHT, DESK_TOP_SIZE/2); glEnd(); // 绘制书桌桌腿 glBindTexture(GL_TEXTURE_2D, texDeskLeg); for(int i=0; i<4; i++){ glPushMatrix(); //调整桌腿位置,分布在桌面四角 if(i==0) glTranslatef(-DESK_TOP_SIZE/2 + DESK_LEG_SIZE/2, DESK_HEIGHT/2, -DESK_TOP_SIZE/2 + DESK_LEG_SIZE/2); if(i==1) glTranslatef(DESK_TOP_SIZE/2 - DESK_LEG_SIZE/2, DESK_HEIGHT/2, -DESK_TOP_SIZE/2 + DESK_LEG_SIZE/2); if(i==2) glTranslatef(-DESK_TOP_SIZE/2 + DESK_LEG_SIZE/2, DESK_HEIGHT/2, DESK_TOP_SIZE/2 - DESK_LEG_SIZE/2); if(i==3) glTranslatef(DESK_TOP_SIZE/2 - DESK_LEG_SIZE/2, DESK_HEIGHT/2, DESK_TOP_SIZE/2 - DESK_LEG_SIZE/2); // 绘制桌腿 glBegin(GL_QUADS); glNormal3f(1.0f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(0, 0, 0); glTexCoord2f(1.0f, 0.0f); glVertex3f(DESK_LEG_SIZE, 0, 0); glTexCoord2f(1.0f, 1.0f); glVertex3f(DESK_LEG_SIZE, DESK_HEIGHT, 0); glTexCoord2f(0.0f, 1.0f); glVertex3f(0, DESK_HEIGHT, 0); // 其余5个面绘制逻辑 glEnd(); glPopMatrix(); // 恢复矩阵 } glDisable(GL_TEXTURE_2D); // 关闭纹理映射,避免影响其他物体 } // 绘制辅助形体(足球、相框、台灯),底层逻辑与书桌一致,整合纹理和灯光 void DrawFootball(){ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texFootball); GLUquadricObj* ballObj = gluNewQuadric(); // 初始化二次曲面,绘制球体 gluQuadricNormals(ballObj, GLU_SMOOTH); // 平滑法线,提升光照效果 gluQuadricTexture(ballObj, GL_TRUE); // 启用纹理映射 glTranslatef(DESK_TOP_SIZE/4, DESK_HEIGHT + 0.3f, DESK_TOP_SIZE/4); gluSphere(ballObj, 0.3f, 80, 80); // 绘制球体,自动绑定纹理坐标 glDisable(GL_TEXTURE_2D); gluDeleteQuadric(ballObj); // 释放资源 } void DrawFrame(){······} void DrawLamp(){······} // 整合所有形体,绘制完整核心场景,设置相机视角 void DrawDeskScene(){ gluLookAt(0.0f, 1.5f, 3.0f*scale, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f); // 相机视角 glRotatef(rotX, 1.0f, 0.0f, 0.0f); // 应用旋转 glRotatef(rotY, 0.0f, 1.0f, 0.0f); DrawDesk(); DrawFootball(); DrawFrame(); DrawLamp(); }

Step6:旋转地球、旋转立方功能实现

实现“旋转立方”与“旋转地球”功能,并优化渲染,实现自动旋转。

// 绘制旋转地球,贴地球纹理,实现自动自转 void DrawEarth(){ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texEarth); GLUquadricObj* earthObj = gluNewQuadric(); gluQuadricNormals(earthObj, GLU_SMOOTH); gluQuadricTexture(earthObj, GL_TRUE); glPushMatrix(); glRotatef(dayRot, 0.0f, 0.0f, 1.0f); // 应用自转角度 gluSphere(earthObj, EARTH_RADIUS, 80, 80); glPopMatrix(); glDisable(GL_TEXTURE_2D); gluDeleteQuadric(earthObj); } // 用显示列表绘制旋转立方 void CreateCubeList(void){ cubeList = glGenLists(1); // 创建显示列表 glNewList(cubeList, GL_COMPILE); // 编译绘制逻辑 glEnable(GL_TEXTURE_2D); // 立方6个面,分别绑定不同纹理,绑定纹理坐标与几何坐标 glBindTexture(GL_TEXTURE_2D, texCube[0]); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glEnd(); // 其余5个面绘制逻辑 glDisable(GL_TEXTURE_2D); glEndList(); // 结束编译,后续直接调用即可 }

Step7:交互功能实现

交互功能的底层核心是“回调函数绑定”,通过GLUT库绑定鼠标、菜单、定时器回调,修改全局参数,刷新场景,实现交互效果。

// 右键菜单回调,修改场景标识,实现场景切换 void MenuFunc(int value){ currentScene = (SceneType)value; // 修改当前场景标识 glutPostRedisplay(); // 刷新场景,让切换生效 } // 鼠标操作回调,记录鼠标状态,实现滚轮缩放 void Mouse(int btn,int state,int x,int y){ if(currentScene == SCENE_DESK){ // 仅核心场景生效 if(btn == GLUT_LEFT_BUTTON){ mouseDown = (state == GLUT_DOWN); // 记录左键是否按下 lastX = x; lastY = y; // 记录鼠标初始位置 } // 修改缩放参数,限制范围 if(btn == 3 || btn == 4){ scale += (btn == 3) ? 0.1f : -0.1f; scale = (scale < 0.3f) ? 0.3f : scale; scale = (scale > 2.0f) ? 2.0f : scale; glutPostRedisplay(); } } } // 鼠标拖动回调,修改旋转参数,实现场景旋转 void Motion(int x,int y){ if(currentScene == SCENE_DESK && mouseDown){ rotY += (x - lastX) * 0.3f; // 水平拖动,修改y轴旋转角度 rotX += (y - lastY) * 0.3f; // 垂直拖动,修改x轴旋转角度 lastX = x; lastY = y; glutPostRedisplay(); } } // 定时器回调,修改旋转角度,实现自动旋转 void OnTimer(int value){ dayRot += 5.0f; // 地球自转角度递增 if(dayRot > 360.0f) dayRot = 0.0f; xRotCube += 1.0f; yRotCube += 1.5f; zRotCube += 0.8f; // 立方旋转角度递增 glutPostRedisplay(); glutTimerFunc(33, OnTimer, 1); // 33ms循环调用,实现流畅旋转 } // 核心显示回调,根据场景标识绘制对应场景,整合所有绘制逻辑 void OnDisplay(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除缓存,避免叠加 glLoadIdentity(); // 重置矩阵,避免异常 switch(currentScene){ case SCENE_DESK: DrawDeskScene(); break; case SCENE_EARTH: gluLookAt(-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); DrawEarth(); break; case SCENE_CUBE: glTranslatef(0.0f, 0.0f, -5.0f); glRotatef(xRotCube, 1.0f, 0.0f, 0.0f); glRotatef(yRotCube, 0.0f, 1.0f, 0.0f); glRotatef(zRotCube, 0.0f, 0.0f, 1.0f); glCallList(cubeList); // 调用显示列表,绘制立方 break; } glutSwapBuffers(); // 双缓冲切换,避免绘制闪烁 } // 初始化函数,统一初始化所有资源,程序启动后最先执行 void Init(){ glShadeModel(GL_SMOOTH); glClearColor(0.1f, 0.1f, 0.1f, 1); glEnable(GL_DEPTH_TEST); LoadAllTex(); SetSunLight(); CreateCubeList(); } // 主函数,程序入口,绑定回调函数,启动消息循环 int main(int argc,char* argv[]){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowSize(1280,720); glutCreateWindow("3D场景纹理映射实验"); Init(); // 初始化资源 // 绑定右键菜单,实现场景切换 glutCreateMenu(MenuFunc); glutAddMenuEntry("室内书桌场景", SCENE_DESK); glutAddMenuEntry("旋转地球场景", SCENE_EARTH); glutAddMenuEntry("旋转立方场景", SCENE_CUBE); glutAttachMenu(GLUT_RIGHT_BUTTON); // 绑定所有回调函数 glutDisplayFunc(OnDisplay); glutMouseFunc(Mouse); glutMotionFunc(Motion); glutTimerFunc(33, OnTimer, 1); glutMainLoop(); // 启动消息循环,持续响应交互 return 0; }

Step8:调试优化

排查纹理路径、命名、格式是否符合底层要求,修改LoadSingleTex函数中的图片有效性判断,避免空指针闪退;检查回调函数是否正确绑定,场景标识判断是否准确,修改回调函数中的参数传递逻辑;优化显示列表(立方绘制)、纹理过滤参数,减少重复编译和绘制操作,提升底层渲染效率。

Step9:编译运行与效果展示

图 3D房屋

图 3D房屋旋转

图 旋转地球

图 旋转立方

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/27 2:34:12

企业级大模型 API 集成:从同步调用到流式响应的容错设计全解析

企业级大模型 API 集成&#xff1a;从同步调用到流式响应的容错设计全解析 一、大模型 API 集成的工程化挑战 将大模型 API 集成到企业级 Java 后端&#xff0c;远不止发一个 HTTP 请求那么简单。生产环境中的大模型调用面临三重工程化挑战&#xff1a;其一&#xff0c;推理延迟…

作者头像 李华
网站建设 2026/6/27 2:26:55

自媒体短视频伪原创消重软件

链接&#xff1a;https://pan.quark.cn/s/a845252843b51、支持同时处理多个视频&#xff0c;软件会自动判断你电脑支持同时处理几个视频&#xff0c;电脑配置好的话视频处理速度明显能感觉到快&#xff0c;可以同时处理5个视频以上。支持视频加速&#xff0c;只要你电脑显卡是N…

作者头像 李华
网站建设 2026/6/30 14:50:15

大模型首字加速:用 Node.js 原生 SSE 做流式网关

大模型首字加速&#xff1a;用 Node.js 原生 SSE 做流式网关 在 AI SaaS 产品里&#xff0c;首字延迟直接决定用户去留。大模型推理慢&#xff0c;如果让用户盯着白屏等十几秒&#xff0c;流失率会非常高。用 SSE&#xff08;Server-Sent Events&#xff09;做流式传输&#xf…

作者头像 李华
网站建设 2026/6/27 2:16:05

【基础设施管理】05-iptables到nftables迁移指南

专栏&#xff1a; 基础设施管理 难度&#xff1a; 进阶 标签&#xff1a; iptables nftables 防火墙 网络安全 Linux前言 RHEL 8 / CentOS 8 开始&#xff0c;nftables 取代 iptables 成为默认防火墙框架。但大量生产环境还在用 iptables 规则&#xff0c;本文提供完整的迁移思…

作者头像 李华
网站建设 2026/6/30 13:12:20

算法笔记:合并K个升序链表(LeetCode 23)

算法笔记&#xff1a;合并K个升序链表&#xff08;LeetCode 23&#xff09; 题目描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 输入&#xff1a;lists [[1,4,5],[1,3,4],[2,6]] 输出&…

作者头像 李华