欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL超级宝典笔记(一)数学基础与基础变换

程序员文章站 2022-03-25 17:27:49
...

创建更多图形

批量三角形

GlTriangleBatch
可以塞进去多个三角形,用处是把重复的点剔除掉,坏处是当三角形加了太多了之后每次添加都会更慢一些。
几个关键的api如下

GLTriangleBatch b;
b.BeginMesh(200); // 200个顶点
b.AddTriangle(M3DVector3f verts[3], M3DVector3f vNorms[3], M3DVector3f vTexCoords[3]);
b.End();
b.Draw();

e.g.

创建一个不断转动的甜甜圈。

首先看ChangeSize。

void ChangeSize(int w, int h)
{
    glViewport(0, 0, w, h);

    g_viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 100.0f);
    // 压栈投影矩阵到投影矩阵栈
    g_projectionMatrix.LoadMatrix(g_viewFrustum.GetProjectionMatrix());
    // 这是一个渲染管线,需要一个modelMatrix和一个投影矩阵
    g_transformPipeline.SetMatrixStacks(g_modelViewMatrix, g_projectionMatrix);
}

frustum翻译为视体,Perspective则代表着透视。这个方法的意义是让当前的矩阵去乘以一个透视矩阵。

void SetPerspective(float fFov, float fAspect, float fNear, float fFar);

设置一个透视矩阵。
projection(投影)矩阵从frustum那里拿到一个矩阵。
g_transformPipeline的类型是GLGeometryTransform,中文是几何变换
所以就是绑定矩阵的作用,一个model的矩阵,一个透视的矩阵。

看一下SetupRC。

void SetupRC()
{
    glClearColor(0.91f, 0.97f, 0.96f, 1.0f);
    // OpenGL必须要有shader才能着色
    g_shaderManager.InitializeStockShaders();

    gltMakeTorus(g_torusBatch, 0.4f, 0.15f, 30, 30);

    g_floorBatch.Begin(GL_LINES, 324);
    for (GLfloat x = -20.0f; x <= 20.0f; x += 0.5f)
    {
        g_floorBatch.Vertex3f(x, -0.55f, 20.0f);
        g_floorBatch.Vertex3f(x, -0.55f, -20.0f);

        g_floorBatch.Vertex3f(20.0f, -0.55f, x);
        g_floorBatch.Vertex3f(-20.0f, -0.55f, x);
    }
    g_floorBatch.End();
}

两个注意点:
- 传给torus的batch不需要add任何定点,一个空的batch足矣。
- 地板的线要研究一下怎么弄的,应该就是普通的网格而已

在这里说一下opengl的坐标系:
OpenGL超级宝典笔记(一)数学基础与基础变换

renderScene

void RenderScene()
{
    std::cout << "RenderScene" << std::endl;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    static GLfloat vFloorColor[] = { 0, 1.0f, 0, 1.0f };
    static GLfloat vTorusColor[] = { 1.0f, 0, 0, 1.0f };

    static CStopWatch rotTimer;
    float yRot = rotTimer.GetElapsedSeconds() * 60.f;

    // 复制栈顶(单位矩阵)到栈顶,避免破坏数据
    g_modelViewMatrix.PushMatrix();

    g_shaderManager.UseStockShader(GLT_SHADER_FLAT, g_transformPipeline.GetModelViewProjectionMatrix()
                                ,vFloorColor);
    g_floorBatch.Draw();

    // 把matrix旋转某个角度,再在上面画东西
    g_modelViewMatrix.Translate(0, 0, -2.5f);
    g_modelViewMatrix.Rotate(yRot, 0, 1.0f, 0);
    // 这个时候管线里面的modelMatrix已经被改变了
    // 就是把渲染管道中的两个矩阵相乘之后返回出来
    g_shaderManager.UseStockShader(GLT_SHADER_FLAT, g_transformPipeline.GetModelViewProjectionMatrix()
        , vTorusColor);
    g_torusBatch.Draw();

    // 丢弃栈顶,恢复成单位矩阵,以便下一帧可以用
    g_modelViewMatrix.PopMatrix();

    glutSwapBuffers();

    glutPostRedisplay();
}

先看一下timer是啥。这就是返回一个已流逝的时间,然后乘以60,说明速度是60。
接下来进入modelMatrix的上下文,然后做位移,旋转,然后在这之上绘制model,最后退出上下文。
用的shader是flatshader,参数是转换器返回的已投影变换的model矩阵,以及颜色。
最后这句很关键了,就继续再绘制一次,相当于无限render。

过程相当于:
1. 创建transformer,绑定一个modelMatrix和一个投影matrix
2. 渲染的时候在matrix的上下文下旋转modelMatrix,然后画图
3. 2说的画图用的是flat的shader,参数是经过model * modelMatrix * projection变换之后的矩阵

换个写法是这样的:

M3DMatrix44f mTranslate, mRotate, mModelview, mModelViewProjection;

// 位移矩阵
m3dTranslationMatrix44(mTranslate, 0, 0, -2.5f);

m3dRotationMatrix44(mRotate, m3dDegToRad(yRot), 0, 1.0f, 0);

// 把model层做位移和转动变换
m3dMatrixMultiply44(mModelview, mTranslate, mRotate);

// 将投影矩阵和model矩阵相乘,结果返回在mModelViewProjection中
m3dMatrixMultiply44(mModelViewProjection, viewFrustum.GetProjectionMatrix(), mModelview);

GLfloat vBlack[] = {0, 0, 0, 0};
// 所以最终的目的就是把变换矩阵传给shader了
shaderManager.UseStockShader(GLT_SHADER_FLAT, mModelViewProjection, vBlack);

torusBatch.Draw();

glutSwapBuffers();
glutPostRedisplay();

上面的乘法要记得顺序就是。

变换管线

OpenGL超级宝典笔记(一)数学基础与基础变换
首先是每个点都是一个1x4矩阵,w是缩放因子。要先拿去乘以模型视图矩阵,然后乘以投影矩阵,然后再去裁剪啥的。

由于这样子很麻烦,所以使用矩阵堆栈。就是上面那个例子了。
既然叫做stack,就是一个栈了,最大高度64,可以随意推matrix进去,一get就能get到栈顶。另外乘法运算也可以直接调用stack的方法,使用栈顶来乘以另一个矩阵,最后的结果会被推到栈顶去。

stack还有放射变换的api

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);
相关标签: OpenGL