欢迎来到zhooyu的专栏。 主页网址:【zhooyu】 专栏网址:【C++和OpenGL实现3D游戏编程】
🌟🌟🌟这里将通过一个OpenGL实现3D游戏编程实例教程,带大家深入学习OpenGL知识。知识无穷而人力有穷,希望能对您有所帮助。
🌟🌟🌟该教程为系列教程,每一步都有详细的教学和实例,推荐大家通过下边的【目录】系统性的了解开发过程,了解怎样一步一步从简单入手,借助C++和OpenGL实现强大的3D效果。
🌟🌟🌟同时您可以在QQ群(群号:739903792)中与大家进行沟通交流,共同解决编程过程中的困惑。
贝塞尔曲面演示:
贝塞尔曲面演示zhooyu
本专栏内容:
我们从游戏的角度出发,用C++去了解一下游戏中的功能都是怎么实现的。这一切还是要从自己玩游戏开始说起,此前就玩过一下3D游戏,当时就被游戏里的一些画面和设置深深的吸引了,同时游戏里还有很多很有趣的设定,比如,玩家的视角是怎么移动的?崎岖不平的地图是怎样制作的?人物和物体、地面的碰撞是怎样检测的?鼠标是怎样选中眼前的物体的?魔法技能是怎样释放的?不用加载进度条的无缝世界地图是怎么实现的?带着这些疑问,我们走进了一个OpenGL世界的3D世界。
一、专栏思维导图
本专栏思维导图:以下内容是本专题所涉及的部分问题,仅仅为内容概要展示,文章将根据需要会有顺序上的改变,后期也会继续补充、添加更多内容。
二、专栏文章内容目录
(一)、OpenGL基础功能的实现
🔥1.1、初探3D世界(附源码)
我们想制作一个游戏,首先必须得创建一个WINDOWS的窗口,我们先用VC创建一个最简单的窗口。就好比在学各种编程语言的时候都会创建一个基本的hello world示例程序一样,这样可以给我们的编程从感觉上带来简单容易上手的良好效果。
🔥1.2、了解并创建3D空间模型(附源码)
上一节我们创建一个简单的窗口,本节我们需要了解一下细节内容,同时为了方便观看,我们需要显示一个世界坐标轴,建立一个直观的三维空间。
🔥1.3、3D空间模型光照初步(附源码)
上一节课,我们建立了简单的坐标系,同时也显示了一个正方体,但正方体的颜色为纯红色,好像一个平面物体一样,我们这节课就可以加一些光照,并创建更多的模型,使这些物体变得更加立体一些。
🔥1.4、纹理加载的三种方式(附源码)
如果我们想让物体更加真实,就得有足够多的顶点,且指定足够多的颜色,这样会产生很多额外开销,因为每个模型需要很多顶点,而每个顶点又需要颜色属性。为了方便且减少开销,我们更习惯使用纹理来绘制更多的模型,纹理就像一张2D的贴图,把它贴在图像或模型上来增加物体的细节。这样物体细节取决于设计师的美工,而程序员则不必指定更多的顶点。
🔥1.5、纹理坐标、纹理贴图(附源码)
在OpenGL中,纹理是一种常用的技术,用于将图像或图案映射到3D模型的表面上,以增加图形的细节和真实感。那么我们上一节已经做好了纹理的准备工作,将需要的纹理图片加载并绑定到了纹理编号中,我们这一节就探讨一下怎样将对应的纹理图片显示到我们的程序中去,特别是将纹理映射到圆形或三维球体等复杂图形上,下图就是一个三维球体的纹理贴图实例。
🔥1.6、不规则图形的纹理贴图(附源码)
上一节我们讨论了纹理贴图的相关基础操作,但上一节的纹理贴图操作基本上都是规则图形,包括圆形和球形虽然复杂一点,但是它也是规则的。这一节课我们要讨论一下,怎么在不规则图形上纹理贴图,就比如文章下图的心形纹理贴图,以及纹理的平移、旋转、放大缩小功能。
🔥1.7、文字和汉字的显示(附源码)
上一节我们讨论了纹理在二维平面内不规则图形贴图的相关基础操作,本节我们开始了解游戏里文字以及汉字的显示方法。本节课我们将从基本的ASCII字符显示,拓展到中文字符的显示,最后再讲到纹理字符的显示,并对各种文字显示方法的优缺点和使用场景进行分析,这节课将使用到显示列表等操作,我们还将制作一个显示文字坠落的动画效果。
🔥1.8、纹理文字的实现与优化(附源码)
上一节课我们介绍了在opengl中文字的显示方法,但显示出来的文字无法旋转,在某些特定游戏要求下,文字是需要进行旋转的,那么这一节课我们介绍一下纹理文字的高级使用方法,将文字生成纹理,达到文字旋转的效果。
🔥1.9、镂空纹理的实现(附源码)
前面的课程中,我们学会了加载纹理并显示纹理图案,但是纹理的图案都是长方形的图片,图片就会有白色或黑色背景,那么在游戏设计过程中,我们经常不需要显示图片的背景部分,那么这节课我们就来讨论一下如何实现剔除白色或黑色背景后的镂空图像,下图就是将树的图片白色背景去除后显示的效果。
🔥1.10、纹理的半透明显示(附源码)
上一节课我们讲到了图片的镂空显示,它能在显示图片时去除指定颜色的背景,那么这节课我们来说一下图片的半透明显示效果,半透明效果能给画面带来更高质量的提升,使图片显示的更自然,产生更真实的效果。下面是一个气泡向上漂浮的效果。
🔥1.11、光照效果进阶(附源码)
我们在前面的章节里内容简单的介绍了一下光照,随着后期对纹理内容的增加,我们需要了解更多的光照知识,本节我们回顾一下光照相关内容,并了解一下怎样实现纹理的光照效果。下面这个图就是我们借助于纹理文字产生的半透明光照效果。
🔥1.12、声音的基本控制(附源码)
前面我们实现了图片纹理的显示功能,是不是感觉到非常的简单。那么今天我们就继续说下游戏声音的实现。音效也是游戏的灵魂,只有搭配了美妙动听的音效以后,游戏才能令人耳目一新,与玩家产生良好的效果。
🔥1.13、多重纹理混合详解(附源码)
前面说过纹理贴图能够大幅提升游戏画面质量,但纹理贴图是没有叠加的。在一些游戏场景中,要求将非常不同的多个纹理(如泥泞的褐色地面、绿草植密布的地面、碎石遍布的地面)叠加(混合)起来显示,实现纹理间能够自然过渡,产生看不出明显的边缘的连续场景,由此多纹理混合技术应运而生,在地形渲染中用得非常广泛。例如,你可以用3个纹理来渲染一片庄园的地面,有的地方长满了绿草、有的地方裸露着泥土、而有的地方还存在砂石,各个场景之间没有明显的过渡痕迹,带来更加逼真的环境效果。
🔥1.14、VBO、VAO和EBO应用(附源码)
我们从一开始学OpenGL到现在,OpenGL的图形绘图必须在glBegin()和glEnd()函数之间完成,在此基础之上,才能进行后续操作功能。但是我们今天要讨论一下OpenGL图形绘制的模式,从之前的立即渲染模式,开始转向核心模式,从而大幅提升显示性能。下图就是通过VBO、VAO和EBO应用画出的矩形,矩形虽然简单,但它的意义却不凡。
🔥1.15、着色器初步(附源码)
上一节我们介绍了通过VBO、VAO和EBO怎样将顶点发送到GPU显存,利用GPU与显存之间的高效处理速度,来提高我们的图形渲染效率。那么在此过程中,我们又可以通过着色器(shader)进行可编程管线操作,极大的增加了编程自由度,那么我们就来了解一下相关知识,并通过模型视图矩阵以及投影矩阵进行顶点变换,完成首次MVP操作。下图就是一个通过着色器(shader)显示的立方体。
🔥1.16、详解三维坐标转二维屏幕坐标(向量和矩阵操作实战)(附源码)
在上一课我们了解了着色器,了解了部分核心模式编程内容,从中接触到了线性代数中向量和矩阵相关知识,我们已经能够感受到向量和矩阵在OpenGL编程中的重要性。特别是后期用去了解融合、光照效果,构建自己的三维世界,都需要大量向量和矩阵的相关知识。本节会就一些线性代数的基础知识进行了解和应用,并实现三维坐标向二维屏幕坐标的转换,这是后期实现鼠标选中物体功能的铺垫。但本文并非对线性代数进行专业的介绍,而是学习计算机图形学必备知识的了解及实战应用。
🔥1.17、着色器进阶(附源码)
在前面着色器初步一节我们了解了着色器的一些初步知识,通过顶点着色器和片段着色器显示出了一个彩色的立方体。我们这节课就来了解一些在着色器中显示纹理等一系列实用操作,同时了解一些进阶的图像渲染技术,比如图像的灰度化处理,像游戏中灵魂状态下世界进行灰度化处理后的效果。使用GLSL渲染纹理是一种非常有用的技术,可以实现高效的图形处理和渲染,并且可以根据具体的应用场景和需求进行更复杂的渲染操作。
🔥1.18、建模模型obj文件的加载应用
以前我们加载过立方体木箱,立方体的顶点数据都是在程序运行时临时定义的。但后期如果模型数量增多,模型逐步复杂,我们就必须加载外部模型文件。这节课我们就先了解一下加载OBJ模型文件的方法,这样可以让编程和设计进行分工合作,极大丰富我们游戏效果,下边是我们通过OBJ文件加载的一个模型。
🔥1.19、着色器光照初步(平行光)
我们在前期的教程中,讨论了在即时渲染模式下的光照内容。那么在我们后期使用着色器的核心模式下,会经常在着色器中使光照,我们这里就讨论一下着色期光照,同时为后期的阴影效果做一些知识铺垫。我们首先讨论定向光(directional light)的使用,光照包括环境光、漫反射光和镜面反射光,在下边这个例子中,我们可以直观地感受到这些光的合成效果。
(二)、游戏基础控制和组织结构
2.1、游戏基类Object的构建
前面的章节中我们已经介绍了OpenGL中的一些基本操作,但都是一些各自独立的知识或代码。我们在游戏设计时,需要设计一个游戏的框架,能够有效的管理或组织各个游戏元素,来体现我们的设计思路和游戏流程,我们就需要从Object基类开始,深入的思考并抽象出一种游戏逻辑,达到我们的需求。下面例子中的木箱我们尝试从Object中派生一个Box类来实现,由类来负责管理加载、显示、运动等效果,从以前的面向过程转变为面向对象编程。
2.2、游戏子物体的实现(子物体的添加和删除)
上节课我们已经创建了一个基础Object类,以后所有的游戏元素都可以从这个基类中派生出来。同时为了操作方便,我们可以为任意两个Object类(及其派生类)的实例对象添加一种父子关系,后期通过父物体与子物体关系,能够轻松的实现游戏物体的操控,方便我们在游戏中对所有游戏元素的组织和管理。再比如后期加父子关系后,就可以同步控制父子物体在三维空间的位置、旋转和缩放操作。 )
2.3、父物体与子物体的消息处理机制
上一节我们了解了父子物体模式,方便我们快捷、控制游戏元素。这一节我们去了解怎样通过父子模式去处理系统消息,系统消息是我们和游戏之间互动的纽带,确定了游戏的用户体验。同时我们还将添加一些预制体,比如说立方体、球体、锥体、胶囊体等,方便我们今后的操作。另外我们此前的模型加载的较为单调,而且我们将加入一些游戏的模型元素,这个视频加载了各式各样的树木,构造出一个奇幻的森林雏形。
2.3、C++和OpenGL实现3D游戏编程【连载23】——几何着色器和法线可视化https://blog.csdn.net/zhooyu/article/details/145397694
上一节课,我们在Blend软件中导出经纬球模型时,遇到了经纬球法线导致我们在游戏中模型光照显示问题,我们在Blender软件中可以通过显示法线的方在这里插入代码片式找到问题的原因所在。但在后期我们游戏元素逐步增多时,每个都重新到Blender软件中去查看会增加游戏调试的复杂度和难度,我们这节课就来了解一下法线可视化问题,同时学习一下几何着色器知识。
2.4、C++和OpenGL实现3D游戏编程【连载24】——父物体和子物体之间的坐标转换https://blog.csdn.net/zhooyu/article/details/145789725
前面章节我们了解了父物体与子物体的结构,它不仅能够表示物体之间的层次关系,更重要的一个作用就是展示物体之间的位置关系(Unity在Transform控件中建立父子关系可能也是这个原因),也就是说当父物体移动时,所有的子物体会随之移动,但当子物体移动时父物体无需移动,这样的功能是本节要实现的主要内容。也可以这么说,所有子物体位置都是相对于父物体空间的。而处于顶层的物体(自身的父物体为空)的位置坐标也就是世界坐标,所有子物体及子子物体都处于他们的直接父物体空间内(后期的骨骼系统的基本原理也类似于这种父子结构)。下图我们演示了在一个餐桌场景下的父子结构演示图。
2.6、C++和OpenGL实现3D游戏编程【连载25】——构建并使用组件模式(Component)https://blog.csdn.net/zhooyu/article/details/147728470
组件模式在游戏开发中是一种常用的设计模式,它通过将多个功能独立包装成单独的组件,可以自由地装配或拆卸,从而达到很好的解耦效果。这种模式特别适用于需要定义许多共享不同能力的对象的情况,而采用继承的方式却无法精确地重用代码。下图中右边文字显示了TransformComponent组件内容和MeshComponent组件,里边列示了组件的详细信息。同时随着选中不同的物体,也会显示相应选中物体所拥有的组件详细信息。下图我们先选中物体1(MeshCones),再选中物体2(ChildMeshCones),最后选中物体3(MeshCube),他们的TransformComponent组件中显示不同的位置、旋转、缩放信息,在MeshComponent组件中显示了不同的模型文件路径等。
2.8、添加TransformComponent组件(设置子物体的位移、旋转、缩放)https://blog.csdn.net/zhooyu/article/details/147707550
1、本节要实现的内容 在上一节我们了解了组件的概念,接下来我们就要了解一下Transform组件。这个组件非常的常用,Transform是最基础且核心的组件之一,每个GameObject(游戏对象)都默认拥有一个Transform组件。它负责管理游戏对象的位置(Position)、旋转(Rotation)和缩放(Scale),是三维空间变换的核心。 Transform是Unity中连接场景中所有物体空间属性的桥梁。它不仅定义了物体的基本状态(位置、旋转、缩放),还通过层级关系管理复杂的场景结构。本节实现了角色朝向问题,黄色石头人与红色石头人的方向始终保持一致;绿色石头人始终面向着红色石头人的方向;蓝色石头人也始终朝着红色石头人的方向,并且红色石头人上下移动时,蓝色石头人也会改变仰俯的角度。这使用了四元数方便模型任意角度旋转。
2.9、C++和OpenGL实现3D游戏编程【连载30】——文字的多行显示
OpenGL本身不直接支持文字渲染,需要通过外部库或自定义方法实现。常见方法包括使用位图字体、FreeType库或显示列表(Display Lists)。本节我们着重进行显示列表的方法去实现文字的输入,并实现文字的多行显示、自动换行处理,根据字体样式、大小动态改变多行显示效果,并实现多个文字字符串的拼接显示,以应变游戏中对文字处理的简单需要,在后续文章中再扩展其他两种文字显示方法。 https://blog.csdn.net/zhooyu/article/details/151244258
2.4、游戏层的控制
2.5、半透明显示与视角距离的控制
(三)、二维界面控制
3.1、二维界面的实现
3.2、按键的实现
3.3、窗口的实现
3.4、窗口滚动条的实现
3.5、进度条的实现
3.6、文字锚点的实现
(四)、视角的基本控制
4.1、自由视角的实现
4.1、上帝视角的实现
4.1、玩家视角的实现
4.1、鼠标左键旋转玩家视角(不改变玩家方向)
4.1、鼠标右键旋转玩家视角(改变玩家方向)
4.1、通过视角获取三维点在二维屏幕的坐标
4.1、鼠标选择物体(设置选中模型和范围)
4.1、鼠标选择物体(判断鼠标是否选中模型)
(五)、空间转换
5.1、空间控制(点点距离、点面距离)
5.2、子物体与父物体之间的坐标和角度转换
5.3、获取子物体在世界坐标下的空间位置
(六)、地图模拟实现
6.1、地图的存储方式
6.2、贝塞尔曲线的应用
6.3、柏林噪音
6.4、无缝地图实现原理
6.5、地面检查和碰撞检查
(七)、游戏机制的应用
7.1、纹理池机制
7.2、文字池机制
7.3、音效池机制
7.4、骨骼系统实现
7.5、物品背包窗口的实现
7.6、技能书窗口的实现
7.7、物品、技能拖拽功能实现
7.8、光源池机制
(八)、网络通信及数据库相关
8.1、网络通信Tcp创建服务器和客户端
8.2、从读取数据库读取游戏信息
8.3、服务器与客户端的网络通信
更多内容持续更新…
更多专栏:
1、C++和OpenGL实现3D游戏编程【目录】
2、C++消灭星星游戏编程【目录】