OpenGL7-第一个3D图形

1、画立方体
  • 之前我们绘制的都是二维图形,今天开始我们将进入三维图形的绘制,三维图形是在二维(XY轴)平面基础上,增加了深度(Z轴),所以三维图形更具有空间感。
  • 二维变三维,图形的顶点个数会增加很多,之前的一个二维平面只需要使用4个顶点就可以描述,由于图形学的基本图元是三角形,一个长方形可分割成两个三角形,一共使用6个顶点即可表示

  • 三维图形由于新增了一个维度,一个立方体一共有8个顶点,6个平面,每个平面由两个三角形组成,一共就是12个三角形,每个三角形由3个顶点确定,所以一共需要用到36个顶点
  • 下图为长度为2的立方体,原点位于立方体中心,8个顶点坐标如下所示,顶点坐标在程序中会通过顶点缓冲区VBO传递给顶点着色器

2、模型矩阵,视图矩阵和投影矩阵
三维世界的观察者
  • 要让观察者看到三维场景,也就是在计算机中要将三维场景绘制到二维的平面上,在现实中,屏幕相当于代替了我们的眼睛
  • 想象屏幕是一个摄像头,这个摄像头看到的景象就是最终呈现在屏幕上的效果,也可以理解这个摄像头是一个观察者。
  • 定义一个观察者的状态,主要有三个要素:
    • 视点,也就是观察者的位置
    • 观察目标点,即被观察目标所在的点,视点和目标点一起可以确定视线
    • 还有最后一个上方向,因为我们最后要把观察到的景象绘制到屏幕上

视图矩阵:
  • glm库中描述观察者状态(视点坐标,目标点坐标,上方向),有一个专门的描述函数 glm::lookAt
  • vec3变量eye,指定观察者坐标位置
  • vec3变量center,指定目标点点位置,与eye共同确定视线方向,一般使用原点作为
  • vec3变量up,用于指定屏幕的上方向,一般采用Y轴正方向作为上方向。(glm::vec3(0.0f, 1.0f, 0.0f))
    glm::mat4 viewMatrix  glm::lookAt(const vec<3, T, Q> &eye,

                                     const vec<3, T, Q> &center,

                                     const vec<3, T, Q> &up);
投影矩阵:
  • 投影矩阵用于确定可视空间范围,也就是观察者能够看到的区域大小,投影矩阵一共有两种,正射投影和透视投影

正射投影: 也称盒状空间,他的可视空间由前后两个矩形表面确定,这两个表面也被称为近裁剪面和远裁剪面,只有在此空间内的物体才会被显示出来

  • opengl中提供ortho方法用于定义正射投影矩阵,其中left,right,bottom,top表示截面的的范围,near和far分别表示观察点距离近裁剪面和远裁剪面的距离。
    glm::ortho(T left, T right, T bottom, T top, T zNear, T zFar);
  • 示意图

透视投影 :模拟人眼看物体的透视效果,可以实现远处的东西看上去更小的效果,可以更好的体现深度感

  • 透视投影矩阵通过perspective方法制定,其中参数fovy表示视角范围,即可视空间顶面和底面间的夹角,数值大于0,aspect用于指定近裁剪面的宽高比。near,far分别表示视点距离近裁剪面和远裁剪面的距离。
 glm::perspective(T fovy, T aspect, T zNear, T zFar);

模型矩阵:
  • 模型矩阵一般用于指定顶点坐标的变换,包括偏移,旋转和缩放
  • OpenGL程序通过使用投影矩阵定义可视空间,使用视图矩阵定义观察者状态,才通过模型矩阵对顶点进行矩阵变化操作,最后计算得到顶点的位置
3、实战-绘制立方体
着色器代码GLSL
   const char *vertex_shader =
   "#version 410          \n"
   "layout(location=0) in vec3 a_Position;  \n"
   "uniform mat4 u_ModelMatirx; \n"   // 模型矩阵
   "uniform mat4 u_ViewMatirx; \n"   // 视图矩阵
   "uniform mat4 u_ProjMatirx; \n"   // 投影矩阵
   " void main() {"
   "  gl_Position = u_ProjMatirx * u_ViewMatirx * u_ModelMatirx * vec4(a_Position, 1.0); \n"
   "}";
通过VBO传递顶点坐标数据,一共有36个顶点数据
void init(GLFWwindow* window) {
   // 36个顶点
   float vPositions[108] = {
       -1.0f, 1.0f, -1.0f,  -1.0f, -1.0f, -1.0f,  1.0f, -1.0f, -1.0f,
       1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
       1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
       1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f,
       1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
       -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
       -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
       -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
       -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
       1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f,
       -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
       1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f
   };

   
   // 创建vao,并绑定
   glGenVertexArrays(1, vao);
   glBindVertexArray(vao[0]);
   // 创建顶点缓冲对象vbo
   glGenBuffers(2,vbo);
   glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
   // 将数据填充到缓冲区对象中
   glBufferData(GL_ARRAY_BUFFER,sizeof(vPositions),vPositions,GL_STATIC_DRAW);
}
分别为模型矩阵、视图矩阵和投影矩阵设置值
    GLuint u_ModelMatirx = glGetUniformLocation(renderProgram,"u_ModelMatirx");
    GLuint u_ViewMatirx = glGetUniformLocation(renderProgram,"u_ViewMatirx");
    GLuint u_ProjMatirx = glGetUniformLocation(renderProgram,"u_ProjMatirx");
  

   // 模型矩阵,对立方体,沿Y轴旋转30度,并向Y轴负方向偏移2个单位
    glm::mat4 rotate = glm::rotate(glm::mat4(1.0f),glm::radians(30.0f),

                                        glm::vec3(0.0f, 1.0f, 0.0f));
    glm::mat4 trans = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, -2.0f, 0.0f));
    glm::mat4 modelMatrix = trans * rotate;
   glUniformMatrix4fv(u_ModelMatirx, 1, GL_FALSE, glm::value_ptr(modelMatrix));

   
   // 视图矩阵  
   // 视点位置为(0.0f, 0.0f, 8.0f),以原点作为目标点,Y轴正方向为上方向
    glm::mat4 viewMatrix =  glm::lookAt(glm::vec3(0.0f, 0.0f, 8.0f),
                                        glm::vec3(0.0f, 0.0f, 0.0f),
                                        glm::vec3(0.0f, 1.0f, 0.0f));
   glUniformMatrix4fv(u_ViewMatirx, 1, GL_FALSE, glm::value_ptr(viewMatrix));

   
   // 透视投影
   // 可视范围为60度,近截面宽高比为1
    glm::mat4 projMatrix = glm::perspective(glm::radians(60.0f), 1.0f, 0.1f, 100.0f );
   glUniformMatrix4fv(u_ProjMatirx, 1, GL_FALSE, glm::value_ptr(projMatrix));
  • 效果图

完整代码仓库

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYQ7FHvR' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片