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

7 篇文章 0 订阅
4 篇文章 0 订阅

创建更多图形

批量三角形

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();

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

变换管线

定点变换管线
首先是每个点都是一个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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值