美文网首页
OpenGL 基础变化

OpenGL 基础变化

作者: 江海寄余生12138 | 来源:发表于2021-05-30 21:21 被阅读0次
  • 顶点变换管线


    image.png
  • GLMatrixStack 矩阵堆栈

//类型
GLMatrixStack::GLMatrixStack(int iStackDepth = 64); 
//在堆栈顶部载⼊⼀个单元矩阵
void GLMatrixStack::LoadIdentity(void); 
//在堆栈顶部载⼊任何矩阵
//参数:4*4矩阵
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m); 
//矩阵乘以矩阵堆栈顶部矩阵,相乘结果存储到堆栈的顶部
void GLMatrixStack::MultMatrix(const M3DMatrix44f); 
//获取矩阵堆栈顶部的值 GetMatrix 函数
//为了适应GLShaderMananger的使⽤,或者获取顶部矩阵的副本
const M3DMatrix44f & GLMatrixStack::GetMatrix(void); 
void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);
//将当前矩阵压⼊堆栈
void GLMatrixStack::PushMatrix(void);
//将M3DMatrix44f 矩阵对象压⼊当前矩阵堆栈
void PushMatrix(const M3DMatrix44f mMatrix);
//将GLFame 对象压⼊矩阵对象
void PushMatrix(GLFame &frame); 
//出栈(出栈指的是移除顶部的矩阵对象)
void GLMatrixStack::PopMatrix(void);
// 仿射变换,旋转平移缩放
//Rotate 函数angle参数是传递的度数
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);

GLFrame -参考帧

  • 其中存储了1个世界坐标点和2个世界坐标下的方向向量,也就是9个glFloat值,分别用来表示:当前位置点,向前方向向量,向上方向向量
  • GLFrame可以表示世界坐标系中任意物体的位置与方向。无论是相机还是模型,都可以使用GLFrame来表示。对任意一个使用GLFrame来表示的物体而言,涉及到的坐标系有两个:永远不变的世界坐标系,针对于自身的物体坐标系(即绘图坐标系)
  • 一般来说,针对于物体自身的物体坐标系有如下特点:X轴永远平行于视口的水平方向,+X的方向根据右手定则由+Y与+Z得出;Y轴永远平行于视口的竖直方向,竖直向上为+Y;Z轴永远平行于视口的垂直纸面向里方向,正前方为+Z。也就是说,在世界坐标系中,物体坐标系的Y轴看上去就是GLFrame的向上方向向量,Z轴看上去就是GLFrame的向前方向向量,而X轴由Y轴方向向量与Z轴方向向量根据右手定则可得出
class GLFrame  { 
 protected: 
 M3DVector3f vOrigin; // Where am I? 
 M3DVector3f vForward; // Where am I going? 
 M3DVector3f vUp; // Which way is up? 

public:
//默认构造函数(世界坐标系,位置在(0,0,0)点,up为(0,1,0)朝+Y,forward为(0,0,-1)朝向-Z)
  GLFrame(void)
//设置/获取世界坐标系下模型/相机的位置
inline void SetOrigin(const M3DVector3f vPoint)
inline void SetOrigin(float x, float y, float z)
inline void GetOrigin(M3DVector3f vPoint)
//获取世界坐标系下模型/相机位置的X/Y/Z分量
inline float GetOriginX(void)
inline float GetOriginY(void)
inline float GetOriginZ(void)
 
//设置/获取世界坐标系下模型/相机向前的方向向量
inline void SetForwardVector(const M3DVector3f vDirection)
inline void SetForwardVector(float x, float y, float z)
inline void GetForwardVector(M3DVector3f vVector)
 
//设置/获取世界坐标系下模型/相机向上的方向向量
inline void SetUpVector(const M3DVector3f vDirection)
inline void SetUpVector(float x, float y, float z)
inline void GetUpVector(M3DVector3f vVector)
 
//获取世界坐标系下模型/相机X/Y/Z轴方向向量
inline void GetZAxis(M3DVector3f vVector) {GetForwardVector(vVector); }
inline void GetYAxis(M3DVector3f vVector) { GetUpVector(vVector); }
inline void GetXAxis(M3DVector3f vVector) {m3dCrossProduct(vVector, vUp, vForward); }
 
// 以世界坐标系下(x,y,z)偏移量移动模型/相机
inline void TranslateWorld(float x, float y, float z)
// 以物体坐标系下(x,y,z)偏移量移动模型/相机
inline void TranslateLocal(float x, float y, float z)
// 沿物体坐标系下Z轴以指定偏移fDelta量移动模型/相机
inline void MoveForward(float fDelta)
// 沿物体坐标系下Y轴以指定偏移fDelta移动物体/相机
inline void MoveUp(float fDelta)
// 沿物体坐标系下X轴以指定偏移fDelta移动物体/相机
inline void MoveRight(float fDelta)
 
// 获取一个用于描述模型属性的4×4的矩阵
void GetMatrix(M3DMatrix44f matrix, bool bRotationOnly = false)
// 获取一个用于描述相机属性的4×4的矩阵
inline void GetCameraOrientation(M3DMatrix44f m)
 
// 应用所有的相机变换。该函数仅用于相机
inline void ApplyCameraTransform(bool bRotOnly = false)
// 应用所有的物体变换。该函数仅用于除相机外的物体
void ApplyActorTransform(bool bRotationOnly = false)
// 令物体/相机以自身位置为中心,绕X/Y/Z轴旋转。其角度以PI为单位
void RotateLocalX(float fAngle)
void RotateLocalY(float fAngle)
void RotateLocalZ(float fAngle)
 
// Reset axes to make sure they are orthonormal. This should be called on occasion
// if the matrix is long-lived and frequently transformed.
// 规范化
void Normalize(void)
// 模型/相机绕世界坐标系下的指定轴(x,y,z)旋转fAngle度
void RotateWorld(float fAngle, float x, float y, float z)
 // 模型/相机绕当前物体坐标系下的指定轴(x,y,z)旋转fAngle度
void RotateLocal(float fAngle, float x, float y, float z)
 
// 将点/向量vLocal从当前物体坐标系转换为世界坐标系
void LocalToWorld(const M3DVector3f vLocal, M3DVector3f vWorld)
 
// 将点/向量vLocal从世界坐标系转换为当前物体坐标系
void WorldToLocal(const M3DVector3f vWorld, M3DVector3f vLocal)
 
// 通过当前frame矩阵将vPointSrc点变换为vPointDst点
void TransformPoint(M3DVector3f vPointSrc, M3DVector3f vPointDst)
 //通过当前frame矩阵将vVectorSrc向量旋转为vVectorDst向量
void RotateVector(M3DVector3f vVectorSrc, M3DVector3f vVectorDst)
}
  • GLFrustum - 视景体
// 设置正投影
void SetOrthographic(GLfloat xMin, GLfloat xMax, GLfloat yMin, GLfloat yMax, GLfloat zMin, GLfloat zMax)
// 设置透视投影
void SetPerspective(float fFov, float fAspect, float fNear, float fFar)
//  获取透视矩阵
const M3DMatrix44f& GetProjectionMatrix(void) { return projMatrix; }
  • GLBatch - 批次容器
    GLTools库中,包含了一个容器类GLBatch,可以作为7种图元批次容器使用,它知道使用GLShaderManager支持的任意存储着色器时,如何对图元进行渲染。
// 参数1:图元
// 参数2:顶点个数
// 参数3:一组或两组纹理图标
void GLBatch::Begain(GLeunm primitive,GLuint nVerts,GLuint nTexttureUnints = 0);
// 复制顶点
void CopyVertexData3f(M3DVector3f *vVerts);
// 复制表面法线
void GLBatch::CopyNormalDataf(GLfloat *vNorms);
// 复制颜色
void GLBatch::CopyColorData4f(GLfloat *vColors);
// 复制纹理坐标
void GLBatch::CopyTexCoordData2f(GLFloat *vTextCoords,GLuint u
iTextureLayer);
// 重置
void Reset(void);
// 设置顶点
void Vertex3f(GLfloat x, GLfloat y, GLfloat z);
 void Vertex3fv(M3DVector3f vVertex);
// 设置法线        
void Normal3f(GLfloat x, GLfloat y, GLfloat z);
void Normal3fv(M3DVector3f vNormal);
// 设置颜色    
void Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void Color4fv(M3DVector4f vColor);
// 设置纹理        
void MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
void MultiTexCoord2fv(GLuint texture, M3DVector2f vTexCoord);
// 画
virtual void Draw(void);
// 绘制结束
void GLBatch::End(void);
  • GLTriangleBatch - 三角形批次类
// Use these three functions to add triangles
void BeginMesh(GLuint nMaxVerts);
void AddTriangle(M3DVector3f verts[3], M3DVector3f vNorms[3], M3DVector2f vTexCoords[3]);
void End(void);
virtual void Draw(void);
  • GLGeometryTransform - 几何变换管道
// 设置模型视图矩阵堆栈
inline void SetModelViewMatrixStack(GLMatrixStack& mModelView) { _mModelView = &mModelView; }
// 设置投影视图矩阵堆栈
inline void SetProjectionMatrixStack(GLMatrixStack& mProjection) { _mProjection = &mProjection; }
// 设置模型视图投影矩阵堆栈
inline void SetMatrixStacks(GLMatrixStack& mModelView, GLMatrixStack& mProjection)  {
    _mModelView = &mModelView;
    _mProjection = &mProjection;
}
// 获取模型视图投影矩阵
const M3DMatrix44f& GetModelViewProjectionMatrix(void)
// 获取模型视图矩阵
inline const M3DMatrix44f& GetModelViewMatrix(void) { return _mModelView->GetMatrix(); }
// 获取投影视图矩阵
inline const M3DMatrix44f& GetProjectionMatrix(void) { return _mProjection->GetMatrix(); }

绘制流程

  • main函数
int main(int argc, char* argv[])
{
    // 设置工作路径
    gltSetWorkingDirectory(argv[0]);
    // 这个函数用来初始化 GLUT 库
    glutInit(&argc, argv);
    //申请一个双缓存区,颜色缓存区、深度缓存区、模板缓存区
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    //设置window 的尺寸
    glutInitWindowSize(800, 600);
    //创建window的名称
    glutCreateWindow("GL_POINTS");
    //注册回调函数(改变尺寸)
    glutReshapeFunc(ChangeSize);
    //点击空格时,调用的函数
    glutKeyboardFunc(KeyPressFunc);
    //特殊键位函数(上下左右)
    glutSpecialFunc(SpecialKeys);
    //显示函数
    glutDisplayFunc(RenderScene);
    
    //判断一下是否能初始化glew库,确保项目能正常使用OpenGL 框架
    GLenum err = glewInit();
    
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    
    // 此函数在呈现上下文中进行任何必要的初始化。.
    // 这是第一次做任何与opengl相关的任务。
    SetupRC();
    
    //runloop运行循环
    glutMainLoop();
    
    return 0;
}
  • 上下文初始化等工作
void SetupRC()
{
    // Black background
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
    
    //初始化固定着色管理器
    shaderManager.InitializeStockShaders();
    
    //开启深度测试
    glEnable(GL_DEPTH_TEST);
    
    //通过GLGeometryTransform管理矩阵堆栈
    //使用transformPipeline 管道管理模型视图矩阵堆栈 和 投影矩阵堆栈
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    
    //将观察者坐标位置Z移动往屏幕里移动15个单位位置
    //表示离屏幕之间的距离 负数,是往屏幕后面移动;正数,往屏幕前面移动
    cameraFrame.MoveForward(-15.0f);
    
    //利用三角形批次类构造图形对象
    // 球
    /*
      gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks);
     参数1:sphereBatch,三角形批次类对象
     参数2:fRadius,球体半径
     参数3:iSlices,从球体底部堆叠到顶部的三角形带的数量;其实球体是一圈一圈三角形带组成
     参数4:iStacks,围绕球体一圈排列的三角形对数
     
     建议:一个对称性较好的球体的片段数量是堆叠数量的2倍,就是iStacks = 2 * iSlices;
     绘制球体都是围绕Z轴,这样+z就是球体的顶点,-z就是球体的底部。
     */
    gltMakeSphere(sphereBatch, 3.0, 10, 20);
    
    // 环面
    /*
     gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
     参数1:torusBatch,三角形批次类对象
     参数2:majorRadius,甜甜圈中心到外边缘的半径
     参数3:minorRadius,甜甜圈中心到内边缘的半径
     参数4:numMajor,沿着主半径的三角形数量
     参数5:numMinor,沿着内部较小半径的三角形数量
     */
    gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
    
    // 圆柱
    /*
     void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
     参数1:cylinderBatch,三角形批次类对象
     参数2:baseRadius,底部半径
     参数3:topRadius,头部半径
     参数4:fLength,圆形长度
     参数5:numSlices,围绕Z轴的三角形对的数量
     参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
     */
    gltMakeCylinder(cylinderBatch, 2.0f, 2.0f, 3.0f, 15, 2);
    
    //锥
    /*
     void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
     参数1:cylinderBatch,三角形批次类对象
     参数2:baseRadius,底部半径
     参数3:topRadius,头部半径
     参数4:fLength,圆形长度
     参数5:numSlices,围绕Z轴的三角形对的数量
     参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
     */
    //圆柱体,从0开始向Z轴正方向延伸。
    //圆锥体,是一端的半径为0,另一端半径可指定。
    gltMakeCylinder(coneBatch, 2.0f, 0.0f, 3.0f, 13, 2);
    
    // 磁盘
    /*
    void gltMakeDisk(GLTriangleBatch& diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks);
     参数1:diskBatch,三角形批次类对象
     参数2:innerRadius,内圆半径
     参数3:outerRadius,外圆半径
     参数4:nSlices,圆盘围绕Z轴的三角形对的数量
     参数5:nStacks,圆盘外网到内围的三角形数量
     */
    gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);
}

  • 屏幕大小发生改变
void ChangeSize(int w, int h)
{
    // 修改视口大小
    glViewport(0, 0, w, h);
    
    //设置透视投影
    viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
    
    //projectionMatrix 矩阵堆栈 加载透视投影矩阵
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
    //modelViewMatrix 矩阵堆栈 加载单元矩阵
    modelViewMatrix.LoadIdentity();
}
  • 绘制场景
//召唤场景
void RenderScene(void)
{
    //用当前清除颜色清除窗口背景
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    
    //模型视图矩阵栈堆,压栈
    modelViewMatrix.PushMatrix();
    //获取摄像头矩阵
    M3DMatrix44f mCamera;
    //从camereaFrame中获取矩阵到mCamera
    cameraFrame.GetCameraMatrix(mCamera);
    //模型视图堆栈的 矩阵与mCamera矩阵 相乘之后,存储到modelViewMatrix矩阵堆栈中
    modelViewMatrix.MultMatrix(mCamera);
    
    //创建矩阵mObjectFrame
    M3DMatrix44f mObjectFrame;
    //从ObjectFrame 获取矩阵到mOjectFrame中
    objectFrame.GetMatrix(mObjectFrame);
    //将modelViewMatrix 的堆栈中的矩阵 与 mOjbectFrame 矩阵相乘,存储到modelViewMatrix矩阵堆栈中
    modelViewMatrix.MultMatrix(mObjectFrame);
    
    //判断你目前是绘制第几个图形
    switch(nStep) {
        case 0:
            DrawWireFramedBatch(&sphereBatch);
            break;
        case 1:
            DrawWireFramedBatch(&torusBatch);
            break;
        case 2:
            DrawWireFramedBatch(&cylinderBatch);
            break;
        case 3:
            DrawWireFramedBatch(&coneBatch);
            break;
        case 4:
            DrawWireFramedBatch(&diskBatch);
            break;
    }
    
    modelViewMatrix.PopMatrix();
    
    // Flush drawing commands
    glutSwapBuffers();
}

void DrawWireFramedBatch(GLTriangleBatch* pBatch)
{
    //平面着色器,绘制三角形
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
   
    //传过来的参数,对应不同的图形Batch
    pBatch->Draw();
    
    // 画出黑色轮廓
    glPolygonOffset(-1.0f, -1.0f);
    
    //开启线段抗锯齿
    glEnable(GL_LINE_SMOOTH);
    
    //开启混合功能
    glEnable(GL_BLEND);
    
    //颜色混合,设置混合因子
    //表示源颜色乘以自身的alpha 值,目标颜色乘以1.0减去源颜色的alpha值,这样一来,源颜色的alpha值越大,则产生的新颜色中源颜色所占比例就越大,而目标颜色所占比例则减 小。这种情况下,我们可以简单的将源颜色的alpha值理解为“不透明度”。这也是混合时最常用的方式。
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    //通过程序点大小模式来设置点的大小
    glEnable(GL_POLYGON_OFFSET_LINE);
    
    //多边形模型(背面、线) 将多边形背面设为线框模式
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    
    //线条宽度
    glLineWidth(2.5f);
    
    //平面着色器绘制线条
    shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);

    pBatch->Draw();
    
    // 恢复多边形模式和深度测试
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_POLYGON_OFFSET_LINE);
    glLineWidth(1.0f);
    glDisable(GL_BLEND);
    glDisable(GL_LINE_SMOOTH);
}
  • 按键控制
//上下左右,移动图形
void SpecialKeys(int key, int x, int y)
{
    if(key == GLUT_KEY_UP)
        //移动世界坐标系,而不是去移动物体。
        //将世界坐标系在X方向移动-5.0
        objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
    
    if(key == GLUT_KEY_DOWN)
        objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
    
    if(key == GLUT_KEY_LEFT)
        objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
    
    if(key == GLUT_KEY_RIGHT)
        objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
    
    glutPostRedisplay();
}

//点击空格,切换渲染图形
void KeyPressFunc(unsigned char key, int x, int y)
{
    if(key == 32)
    {
        nStep++;
        
        if(nStep > 4)
            nStep = 0;
    }
    
    switch(nStep)
    {
        case 0:
            glutSetWindowTitle("Sphere");
            break;
        case 1:
            glutSetWindowTitle("Torus");
            break;
        case 2:
            glutSetWindowTitle("Cylinder");
            break;
        case 3:
            glutSetWindowTitle("Cone");
            break;
        case 4:
            glutSetWindowTitle("Disk");
            break;
    }
    
    glutPostRedisplay();
}

相关文章

  • OpenGL 基础变化

    顶点变换管线image.png GLMatrixStack 矩阵堆栈 GLFrame -参考帧 其中存储了1个世...

  • OpenGL基础变换

    OpenGL ⾥的基础变换 OpenGL中涉及的基础变化主要有以下5种: 变换解释视图变换指定观察者位置模型变换在...

  • OPenGL 中的矩阵压栈/出栈

    我们知道OPenGL 中的图形变化是用矩阵来记录保存的.OpenGL 矩阵基础变化 简单来讲,当你做了一些移动或旋...

  • OpenGL四-基础变化

    一、抗锯齿 混合的2大功能:颜⾊组合、抗锯⻮ 混合处理-抗锯齿 使⽤混合实现抗锯⻮效果Demo:10-抗锯齿 二、...

  • OpenGL 矩阵基础变化

    OpenGL⾥的矩阵/向量 向量:3个值(x、y、z)组合起来表示2个重要的值,⽅向和数量. 矩阵: 在OPenG...

  • 006---OpenGL基础变化

    [toc] OpenGL 矩阵向量 向量 一个顶点同时也是一个向量. 方向 数量 长度或模为1的 当前这个顶点为 ...

  • OpenGL矩阵基础变化理解

    前言 本篇文章的目的主要是为了理解在OpenGL应该如何利用矩阵堆栈对3D图形进行基础变化操作。 三种基础仿射变化...

  • 基础渲染

    opengl opengl渲染管线基础架构 3.1 基础图形管线 3.1.1 客户机-服务器 就opengl而言,...

  • OpenGL ES2.0 c++ 基础教程

    OpenGL ES2.0 c++ 基础 什么是OpenGL ES?OpenGL ES (为OpenGL for ...

  • 九、OpenGL 基础变化与矩阵堆栈

    基础变化 OpenGL中涉及的基础变化主要有以下5种 变换说明视图变换指定观察者位置模型变换在场景中移动物体模型视...

网友评论

      本文标题:OpenGL 基础变化

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