OpenGL_Shader简介,OpenGL坐标系及坐标变换

OpenGL_Shader

  • shader[着色器] 是GPU执行的程序,使用类C语言GLSL编写
  • 最基本的shader有:vertexShader[顶点着色器]&fragmentShader[片元着色器]
    • vertexShader[顶点着色器]:一般用于绘制顶点线框。
    • 以下是vertexShader源代码:
    •  1 #version 450 core
       2 //使用OpenGL4.5
       3 
       4 layout (location = 0) in vec3 aPos;
       5 layout (location = 1) in vec3 aNormal;
       6 layout (location = 2) in vec2 aTexCoords;
       7 //分别从 VAO 的0,1,2号栏位加载 aPos[顶点位置],aNormal[法向量],aTexCoords[UV坐标]
       8 
       9 out vec2 TexCoords;
      10 //向之后的subShader传递UV坐标
      11 
      12 uniform mat4 model;
      13 uniform mat4 view;
      14 uniform mat4 projection;
      15 //从CPU直接向shader灌入数据,注意要在shader执行前灌入
      16 
      17 void main()
      18 {
      19     TexCoords = aTexCoords;    
      20     gl_Position = projection * view * model * vec4(aPos, 1.0);
      21 }
    • fragmentShader[片元着色器]:用于为 [片元:顶点围成的几何图元,一般是三角形] 着色。
    • 以下是fragmentShader源代码:
    •  1   #version 450 core
       2  //使用OpenGL4.5
       3  
       4  out vec4 FragColor;
       5  //向下一步的subShader输出 片元颜色
       6  
       7  in vec2 TexCoords;
       8  //接收来自前面subShader输出的数据
       9  
      10  uniform sampler2D texture_diffuse1;
      11  //接收来自CPU的 [diffuse贴图] 文件
      12  //当不使用任何光照时,传入的所有贴图 [都被视作]diffuse贴图。
      13  //除此之外还有specular贴图。
      14  
      15  void main()
      16  {    
      17      FragColor = texture(texture_diffuse1, TexCoords);
      18      //根据UV贴好贴图,并返回给FragColor
      19  }

       

至此,你已经可以在OpenGL窗口上绘制任意形状的几何体了,点此获得测试代码。

  

 

OpenGL坐标系 和各种坐标变换

  • OpenGL坐标系是右手系:
    • 以窗口中心为坐标原点,向右为[x轴正方向],向上为[y轴正方向],向内为[z轴正方向]
    • x,y轴宽度为 ±2,z轴宽度为 [0,+∞]
  • 各种坐标变换:
    • 围绕初始坐标系的变换:
      • 摄像机变换:
        • 将世界空间坐标系 与 OpenGL坐标系拆开。
        • 摄像机变换不会影响其他的变换,你可以理解为:

            世界空间坐标系也是左手系,只不过在一切变换发生结束后,叠加了一个平移变换。

      • 画面裁剪&透视裁剪变换:
        • 画面裁剪的意思是:
          • 当顶点的位置超出  OpenGL坐标系(屏幕空间)之后,就不应出现在OpenGL窗口中,
          • 此时OpenGL会重新计算片元,并进行绘制,但具体怎么计算和绘制的,与我们无关,是OpenGL内部自己的事。
            • 我们需要关心的是:顶点经过何种变换计算,会超出OpenGL坐标空间。
            • 通过这种方式,可以预测我们使用的点,在经过一系列变换后,是否还能存在于【屏幕空间坐标系】中。

 

        • 透视裁剪变换发生在摄像机变换之后,他为[片元]提供了"场景"的概念,增加了景深。
        • 透视裁剪后,OpenGL坐标系(屏幕空间) 与世界空间坐标系的联系彻底分离,因此:
          • 你不能再通过 简单地反推:摄像机变换,顶点在世界空间中的位置变化 来确定顶点是否超出屏幕了,

                 除非你完全了解透视裁剪使用的算法

 

          • 透视变换过后,在世界空间坐标系中的点需要经过透视变换,才能重新映射OpenGL屏幕坐标空间([(-2,2),(-2,2),(0,+∞)])。
            • 因此,在通常情况下,它也变相的拓宽了世界空间坐标系中,顶点的范围。
            • 顶点坐标范围的取值可以按照透视裁剪算法提供的动态约束信息自定义的世界坐标空间,来自定义提供,不再受限于OpenGL屏幕坐标空间。

 

    • 对Model的变换:
      • 旋转,平移,缩放。
      • 矩阵变换:
        • 旋转:
          • 设:X(n,m) 为 [单位矩阵 X(4,4)]  中位于[n行,m列]  的数字。
          • 设:旋转的角度为:A,弧度为:B。
          • 设:顶点向量为 Y = {X,Y,Z,W}
            • 角度 = 弧度 * (180.0f / π),弧度 = 角度 * (π / 180.0f)
            • 在坐标系中,顺时针旋转为负角,逆时针旋转为正角。
          • 沿X轴旋转:将 X(2,2) , X(2,3) , X(3,2) , X(3,3) 改为 cos(A),-sin(A),sin(A),cos(A)  
          • 沿Y轴旋转:将 X(1,1) , X(1,3) , X(3,1) , X(3,3) 改为 cos(A),sin(A),-sin(A),cos(A)
          • 沿Z轴旋转:将 X(1,1) , X(1,2) , X(2,1) , X(2,2) 改为 cos(A),-sin(A),sin(A),cos(A)
          • 最后   使用 YT * X(4,4) 得到变换后的 YT
        • 平移:
          • 设:X(n,m) 为 [单位矩阵 X(4,4)]  中位于[n行,m列]  的数字。
          • 设:平移的值为TX,TY,TZ
          • 设:顶点向量为 Y = {X,Y,Z,W}
          • 将 X(1,4) , X(2,4) , X(3,4) 改为 TX,TY,TZ
          • 最后   使用 YT * X(4,4) 得到变换后的 YT
        • 缩放:
          • 设:X(n,m) 为 [单位矩阵 X(4,4)]  中位于[n行,m列]  的数字。
          • 设:三个坐标的缩放倍数为:SX,SY,SZ
          • 设:顶点向量为 Y = {X,Y,Z,W}
          • 将 X(1,1) , X(2,2) , X(3,3) 改为  SX,SY,SZ
          • 最后   使用 YT * X(4,4) 得到变换后的 YT

 

        • 最终的model变换算式为:YT = TX(4,4) * X(4,4) * SX(4,4) * YT
          • 注意,[此处的相乘顺序] [代码处使用的相乘顺序]  一致,都是右乘。
          • 右乘:即从右向左乘,也就是从右向左变换,先缩放,再旋转,最终位移。
          • 一定要注意变换顺序(乘的顺序),否则缩放变换会影响之后的变换。

 

posted @ 2021-09-22 23:35  SupersLWF  阅读(508)  评论(0)    收藏  举报