美文网首页
OpenGL 出栈压栈理解分析

OpenGL 出栈压栈理解分析

作者: 如意神王 | 来源:发表于2019-06-21 12:13 被阅读0次

1.OpenGL压栈出栈作用概念

1.压栈出栈操作的是矩阵,一般分为模型视图矩阵和投影矩阵

2.出栈压栈是针对顶点的变化的,为了方便实施,所以用矩阵统一记录且作用在顶点上面

3.压栈出栈一定要成对出现,OpenGL里面模型视图矩阵是全局的,PushMatrix的作用是把当前的栈顶拷贝一份复制在栈顶上,利用这个新的栈顶记录新的变化,绘制新的变化,绘制完毕,PopMatrix是把这个新的栈顶删除掉,栈顶变为记录这次变化之前的栈顶,也就是说通过push和pop达到了既绘制了当前的变化,又没有影响到之前的栈顶状态

// 假设ABC是要作用在需要绘制物体Object上的,Object.Draw()->Object使用Draw()函数绘制完毕,PopMatrix(),恢复之前的栈顶状态

绘制Object的变化,不影响全局的模型视图矩阵
modelViewMatrix.PushMatrix();
模型视图矩阵变化A
模型视图矩阵变化B
模型视图矩阵变化C
Object.Draw();
modelViewMatrix.PopMatrix();

绘制AABBCC的变化,不影响全局的模型视图矩阵
modelViewMatrix.PushMatrix();
模型视图矩阵变化AA
模型视图矩阵变化BB
模型视图矩阵变化CC
AABBCC.Draw();
modelViewMatrix.PopMatrix();

某些变化模型视图矩阵或者投影矩阵要影响全局的那么
模型视图矩阵变化xyz,投影矩阵,影响全局,那么只需要push前面即可,push pop中间的绘制完毕会被清楚掉,如果不在这个范围内就持续影响后续的物体的绘制状态,因为OpenGL状态机是全局的
modelViewMatrix.PushMatrix();
模型视图矩阵变化AAA
模型视图矩阵变化BBA
模型视图矩阵变化CCA
AABBCC.Draw();
modelViewMatrix.PopMatrix();

2.压栈压栈代码实现

//进行调用以绘制场景
void RenderScene(void)
{
    //1.颜色值(地板,大球,小球颜色)
    static GLfloat vFloorColor[] = { 0.0f, 1.0f, 0.0f, 1.0f};
    static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f};
    static GLfloat vSphereColor[] = { 0.0f, 0.0f, 1.0f, 1.0f};
    
    //2.基于时间动画
    static CStopWatch rotTimer;
    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
    
    //3.清除颜色缓存区和深度缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //4.加入观察者 平移10步(地板,大球,小球,小小球)
    
    // PushMatrix->1
    // cameraFrame是摄像机矩阵,被模型视图矩阵modelViewMatrix作用,第一个PushMatrix前面影响全局
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.PushMatrix(mCamera);


    //5.获取光源位置
    M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
    
    //6.绘制地面
    shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vFloorColor);
    // 绘制地面,上面的摄像机矩阵PushMatrix->1是作用在这个上面的,通过模型视图矩阵的变化
    floorBatch.Draw();
    
    //大球默认位置(0,0,0)Z深度(3.0) 正负指的是方向, 数字指的移动距离
    //7.使得大球位置平移(3.0)向屏幕里面  只移动1次
    // 模型视图矩阵发生变化2,作用在后续所有需要绘制的物体上面
     modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
    
    //8.压栈(复制栈顶)
    // PushMatrix->2
    // 准备绘制大球,压栈->复制新的栈顶放在原来的栈顶上面
    modelViewMatrix.PushMatrix();
   
    //9.大球自转
    // 这个模型视图矩阵的变化在PushMatrix->2和PopMatrix->2之间,只对torusBatch的绘制起作用
    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    
    //10.指定合适的着色器(点光源着色器)
    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
                                 transformPipeline.GetProjectionMatrix(), vLightPos, vTorusColor);
    torusBatch.Draw();
    //11.绘制完毕则Pop
    // 大球绘制完毕PopMatrix->2
    modelViewMatrix.PopMatrix();
    
 
    //12.画小球
    for (int i = 0; i < NUM_SPHERES; i++) {
        // PushMatrix->3 绘制若干小球
        modelViewMatrix.PushMatrix();
        
        // 是作用在若干小球上的模型视图矩阵modelViewMatrix的变化
        modelViewMatrix.MultMatrix(spheres[i]);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
                                     transformPipeline.GetProjectionMatrix(), vLightPos, vSphereColor);
        sphereBatch.Draw();
        // PopMatrix->3 若干小球绘制完毕
        modelViewMatrix.PopMatrix();
    }

    //13. 让一个小篮球围绕大球公众自转
    //学员提问: 为什么这里老师没有加PushMatrix/PopMatrix ,是可以加的.但是因为是最后的绘图因为没有不会影响就么有添加. 这边给大家添加一组.
    
    // PushMatrix->4 绘制围绕大球公转的一个小球
    modelViewMatrix.PushMatrix();
    
    // 公转小球的变化只作用在自身上
    modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vSphereColor);
    sphereBatch.Draw();
    // PopMatrix->4 绘制完毕
    modelViewMatrix.PopMatrix();
    
    // PopMatrix->1 全部结束PopMatrix
   modelViewMatrix.PopMatrix();
    
    
    //14.执行缓存区交换
    glutSwapBuffers();
    
    //15
    glutPostRedisplay();
}

3.压栈出栈流程提取

    // PushMatrix->1
    // cameraFrame是摄像机矩阵,被模型视图矩阵modelViewMatrix作用,第一个PushMatrix前面影响全局
   modelViewMatrix.PushMatrix(mCamera);

    // 模型视图矩阵发生变化2,作用在后续所有需要绘制的物体上面
     modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
    
    // PushMatrix->2
    modelViewMatrix.PushMatrix();
    //9.大球自转
    // 这个模型视图矩阵的变化在PushMatrix->2和PopMatrix->2之间,只对torusBatch的绘制起作用,大球的变化
    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    // 大球绘制完毕PopMatrix->2
    modelViewMatrix.PopMatrix();
    
    //12.画小球
    for (int i = 0; i < NUM_SPHERES; i++) {
        // PushMatrix->3 绘制若干小球
        modelViewMatrix.PushMatrix();
        // 是作用在若干小球上的模型视图矩阵modelViewMatrix的变化
        modelViewMatrix.MultMatrix(spheres[i]);
        // PopMatrix->3 若干小球绘制完毕
        modelViewMatrix.PopMatrix();
    }

    // PushMatrix->4 绘制围绕大球公转的一个小球
    modelViewMatrix.PushMatrix();
    // 公转小球的变化只作用在自身上
    modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
    // PopMatrix->4 绘制完毕
    modelViewMatrix.PopMatrix();
    
    // PopMatrix->1 全部结束PopMatrix
   modelViewMatrix.PopMatrix();

4.是否一定需要使用矩阵

mv->模型视图矩阵
mvp->模型视图投影矩阵
p->投影矩阵

问题(1): 在绘图时,可以不用矩阵堆栈吗?
答案: 如果绘制比较多,没有push pop是不行的,否则别的变化都作用在mv上了,mv是全局的,本来不是你的也被影响了,push的意思就是,我先占用,等我绘制完了,pop是把我的变化从全局的mv的剔除掉,保持原来的模样,否则就乱套了,push pop就是为了把变化绘制了,还不影响整体环境,如果你不用push或者pop,那你自己精细算mv的数据也是可以的,比如mv+abc-897 绘制,完成绘制之后mv-abc+897,这也可以,但是这只是规则变化,有规律可循,即使你数学非常牛逼,任何一个复杂的图形怎么变化我都能计算出各个顶点的数值,变化完成之后我都可以复原,也可以自己算自己复原,但是,push 和 pop就搞定了,非得自己搞那些事干什么捏

问题(2): MVP矩阵在堆栈中充当什么样角色?
答案: mv只有一个是全局的大家都在用,如果某个图形A,他要有bcdefg变化,那么 push -> mvbcdefg -> pop mv,这时候物体B有一个abc999-366的变化,push -> mv * abc999-366 ->pop ->mv, A和B都是要自己的变化,比如A必须要bcdefg都叉乘了才可作为A的最后的mv渲染,B也是同理,如果不使用push pop,把mvbcdefg abc999-366给B或者A,都是不对的,那就乱套了,不影响全局的变化放在push 和 pop之间,push->占用mv->记录变化->绘制完毕->pop->复原mv

相关文章

  • OpenGL 出栈压栈理解分析

    1.OpenGL压栈出栈作用概念 1.压栈出栈操作的是矩阵,一般分为模型视图矩阵和投影矩阵 2.出栈压栈是针对顶点...

  • 压栈、出栈总结

    一 关于堆栈的理解 二 OpenGL压栈、出栈 https://www.jianshu.com/p/ce3b51b...

  • OpenGL_矩阵压栈和出栈

    1. 压栈和出栈的理解 压栈出栈操作的是矩阵 用来记录矩阵的状态 压栈PushMatrix和出栈PopMatrix...

  • OpenGL笔记六:纹理常用API(一)

    前言 期待您移步上篇:OpenGL笔记五:综合实例理解-压栈、出栈、堆栈矩阵相乘、矩阵相乘、向量相乘 纹理 纹理只...

  • OpenGL压栈出栈流程

    当我们在使用OpenGL对一个图形进行旋转,平移,缩放操作时,一般是将这些操作放入矩阵中,然后利用点乘即MultM...

  • Java实现栈

    数组栈:压栈、出栈、返回栈顶元素 链式栈:压栈、出栈、返回栈顶元素

  • OpenGL向量/矩阵、压栈/出栈

    我们大家可能对矩阵的乘法有点模糊了,不用担心!我们在这里只需要先明白向量、矩阵的含义,以及在OpenGL中的作用,...

  • OpenGL中矩阵堆栈的压栈和出栈操作理解

    OpenGL中矩阵堆栈的频繁压栈和出栈操作往往是入门时最大的门槛,也是最容易造成困惑的地方,今天我们来详细理解一下...

  • OpenGL学习笔记五

    使⽤矩阵堆栈 压栈.出栈 压栈: 存储一个状态出栈: 恢复⼀个状态 仿射变换

  • OpenGL的矩阵压栈与出栈

    初学时,我们通常会对矩阵压栈和出栈这对“难兄难弟”感到疑惑,为什么它们是成对出现的?它们做的又是什么操作呢?那,今...

网友评论

      本文标题:OpenGL 出栈压栈理解分析

      本文链接:https://www.haomeiwen.com/subject/ygtyqctx.html