OpenGL 图元的渲染-矩阵堆栈

之前的创建文章都是用MarkDown编辑器 没想到最近创建的都是富文本编辑器,也没有发布更新看下效果 结果现在要把文章都重新发布一边 惆怅

图元基本连接方式

OpenGL 基本图元连接方式

图元连接方式
GL_TRIANGLE_STRIP优点:
  • 用前3个顶点指定第1个三角形之后,接下来的每⼀个三⻆形,只需要再指定1个顶点。需要绘制⼤量的三⻆形时,采⽤这种⽅法可以节省⼤大量的程序代码和数据存储空间。
  • 提供运算性能和节省带宽。更少的顶点意味着数据从内存传输到图形卡的速度更快,并且顶点着⾊器需要处理的次数也更少
OpenGL三⻆形环绕⽅式

-在默认情况下,OpenGL认为具有逆时针⽅向环绕的多边形为正⾯。

GL_CW: 顺时针环绕的多边形为正⾯
GL_CCW:逆时针环绕的多边形为正⾯
// 手动指定那个面为正面,一般不做修改
glFrontFace(GL_CW);

矩阵堆栈

矩阵堆栈指的就是内存中专门用来存放矩阵数据的某块特殊区域。
一般说来,矩阵堆栈常用于构造具有继承性的模型,即由一些简单目标构成的复杂模型。矩阵堆栈对复杂模型运动过程中的多个变换操作之间的联系与独立十分有利。

  • 堆栈的特点是先进后出,堆栈的默认深度是64
  • 默认值为单元矩阵即与其相乘值并不会发生变化
初始化

modelViewMatrix.LoadIdentity();

压栈

压栈即为存储一个状态

//modelViewMatrix在初始化时,初始化了一个单元矩阵,此时的压栈就是将栈顶的矩阵复制一个,然后压入栈顶
modelViewMatrix.PushMatrix()
矩阵相乘

当前矩阵乘以栈顶矩阵,结果存储到矩阵堆栈顶部

//我们使用栈顶的单元矩阵与观察者矩阵相乘,此时得到的结果是观察者矩阵,并存放到栈顶。
modelViewMatrix.MultMatrix(mCamera)

//然后再使用刚刚得到的观察者矩阵与物体矩阵相乘,得到结果存放到栈顶。
modelViewMatrix.MultMatrix(mObjectFrame

出栈

出栈会将当前栈顶矩阵推出,一般都是一个压栈对应一个出诊,例如当结束旋转状态时,需要恢复到之前状态就进行出栈操作

//出栈
modelViewMatrix.PopMatrix()
获取栈顶的矩阵
modelViewMatrix.GetMatrix()

案例分析

  • 本次键位操作图形旋转使用矩阵操作,每个顶点与旋转矩阵相乘得到旋转后的顶点坐标,不用像上个案例正方形移动一样每操作一次自己计算一次坐标
// 召唤场景
void RenderScene(void)
{
    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   
    //压栈
    modelViewMatrix.PushMatrix();
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    
    //矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
    modelViewMatrix.MultMatrix(mCamera);
    
    M3DMatrix44f mObjectFrame;
    //只要使用 GetMatrix 函数就可以获取矩阵堆栈顶部的值,这个函数可以进行2次重载。用来使用GLShaderManager 的使用。或者是获取顶部矩阵的顶点副本数据
    objectFrame.GetMatrix(mObjectFrame);
    
    //矩阵乘以矩阵堆栈的顶部矩阵,相乘的结果随后简存储在堆栈的顶部
    modelViewMatrix.MultMatrix(mObjectFrame);
    
    /* GLShaderManager 中的Uniform 值——平面着色器
     参数1:平面着色器
     参数2:运行为几何图形变换指定一个 4 * 4变换矩阵
     --transformPipeline.GetModelViewProjectionMatrix() 获取的
     GetMatrix函数就可以获得矩阵堆栈顶部的值
     参数3:颜色值(黑色)
     */
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
    
    switch(nStep) {
        case 0:
            //设置点的大小
            glPointSize(4.0f);
            pointBatch.Draw();
            glPointSize(1.0f);
            break;
        case 1:
            //设置线的宽度
            glLineWidth(2.0f);
            lineBatch.Draw();
            glLineWidth(1.0f);
            break;
        case 2:
            glLineWidth(2.0f);
            lineStripBatch.Draw();
            glLineWidth(1.0f);
            break;
        case 3:
            glLineWidth(2.0f);
            lineLoopBatch.Draw();
            glLineWidth(1.0f);
            break;
        case 4:
            DrawWireFramedBatch(&triangleBatch);
            break;
        case 5:
            DrawWireFramedBatch(&triangleStripBatch);
            break;
        case 6:
            DrawWireFramedBatch(&triangleFanBatch);
            break;
    }
    
    //还原到以前的模型视图矩阵(单位矩阵)
    modelViewMatrix.PopMatrix();
    
    // 进行缓冲区交换
    glutSwapBuffers();
}

Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。