OpenGL 控制你的正方形

3,030 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情


  1. Swift Optional
  2. Swift Enum
  3. iOS开发 做一个三角形
  4. Swfit 指针类型
  5. Swift 属性(下)
  6. Swift 属性
  7. Swift 小结
  8. Swift 类与结构体(下)
  9. Swift 类的生命周期
  10. Swift 类的初始化器
  11. Swift 类与结构体
  12. OpenGL 压缩纹理
  13. OpenGL 隧道坐标计算
  14. 0penGL 像素格式及数据类型
  15. OpenGL 纹理对象
  16. OpenGL 纹理
  17. OpenGL 模型变化
  18. OpenGL 视图
  19. OpenGL 矩阵
  20. OpenGL 向量
  21. OpenGL 颜色混合
  22. OpenGL 深度测试的潜在风险
  23. OpenGL 浅析深度测试
  24. OpenGL 浅析隐藏面消除
  25. OpenGL 图元连接方式
  26. 记WKWebView与HTML完成交互两三事
  27. OpenGL 渲染流程图解析
  28. OpenGL 控制你的正方形
  29. OpenGL 专业名词解释
  30. OpenGL 环境搭建 - MacOS

之前的 OpenGL 环境搭建 - MacOS 文章中,我们完成了OpenGL的环境搭建和测试用的绘制一个正方形。今天我们接着来做一个能够随我们控制移动的多边形。 好的,话不多说,直接开始今天的内容吧:

方法一: 我们通过注册键盘按键的回调,来计算出四个顶点的移动,然后来绘制出移动后的正方形

1 main函数中注册键盘回调

    // 注册键盘函数
    glutSpecialFunc(KeyboardCallback);

2 处理按键回调 (计算四个顶点移动后的位置,做边界控制,)

在键盘回调函数中,我们来判断上下左右四个按钮,并分别计算对应的顶点移动数据,之后再去绘制移动之后的图形。

// 移动距离
GLfloat moveDistance = 0.13f;
// 键盘按键回调
void KeyboardCallback( int key, int x, int y ) {
    
    // 1、计算各个顶点坐标
    GLfloat blockX_A = coordinatePoints[0];
    GLfloat blockY_A = coordinatePoints[1];
    GLfloat blockX_B = coordinatePoints[3];
    GLfloat blockY_B = coordinatePoints[4];
    GLfloat blockX_C = coordinatePoints[6];
    GLfloat blockY_C = coordinatePoints[7];
    GLfloat blockX_D = coordinatePoints[9];
    GLfloat blockY_D = coordinatePoints[10];
    
    // 计算移动后的数据
    if (key == GLUT_KEY_UP) {
        
        if (blockY_C >= 1.f) {// 边界控制
            
            blockY_A = 1.f-sideLength*2;
            blockY_B = 1.f-sideLength*2;
            blockY_C = 1.f;
            blockY_D = 1.f;
        }else {
            
            blockY_A += moveDistance;
            blockY_B += moveDistance;
            blockY_C += moveDistance;
            blockY_D += moveDistance;
        }
    }
    if (key == GLUT_KEY_DOWN) {
        if (blockY_A <= -1.f) {// 边界控制
            
            blockY_A = -1.f;
            blockY_B = -1.f+sideLength*2;
            blockY_C = -1.f+sideLength*2;
            blockY_D = -1.f;
        }else {
            
            blockY_A -= moveDistance;
            blockY_B -= moveDistance;
            blockY_C -= moveDistance;
            blockY_D -= moveDistance;
        }
    }
    if (key == GLUT_KEY_LEFT) {
        if (blockX_A <= -1.f) {// 边界控制
            
            blockX_A = -1.f;
            blockX_B = -1.f+sideLength*2;
            blockX_C = -1.f+sideLength*2;
            blockX_D = -1.f;
        }else {
            
            blockX_A -= moveDistance;
            blockX_B -= moveDistance;
            blockX_C -= moveDistance;
            blockX_D -= moveDistance;
        }
    }
    if (key == GLUT_KEY_RIGHT) {
        if (blockX_C >= 1.f) {// 边界控制
            
            blockX_A = 1.f-sideLength*2;
            blockX_B = 1.f;
            blockX_C = 1.f;
            blockX_D = 1.f-sideLength*2;
        }else {
         
            blockX_A += moveDistance;
            blockX_B += moveDistance;
            blockX_C += moveDistance;
            blockX_D += moveDistance;
        }
    }
    
    coordinatePoints[0] = blockX_A;
    coordinatePoints[1] = blockY_A;
    coordinatePoints[3] = blockX_B;
    coordinatePoints[4] = blockY_B;
    coordinatePoints[6] = blockX_C;
    coordinatePoints[7] = blockY_C;
    coordinatePoints[9] = blockX_D;
    coordinatePoints[10] = blockY_D;
    
    triangleBatch.CopyVertexData3f(coordinatePoints);
    glutPostRedisplay();
}

方法二:使用 平面着色器绘制

1 定义x坐标和y坐标移动的距离

GLfloat xMove = 0.f;//x坐标移动距离
GLfloat yMove = 0.f;//y坐标移动距离

2 键盘按键回调的函数中处理 x、y坐标移动的距离;并提交渲染

// 键盘按键回调
void KeyboardCallback( int key, int x, int y ) {
    
    // 计算移动后的数据
    if (key == GLUT_KEY_UP) {
        
        yMove += moveDistance;
    }
    if (key == GLUT_KEY_DOWN) {
        yMove -= moveDistance;
    }
    if (key == GLUT_KEY_LEFT) {
        xMove -= moveDistance;
    }
    if (key == GLUT_KEY_RIGHT) {
        xMove += moveDistance;
    }
    
    // 碰撞检测
    if (xMove < -1.f+sideLength) {
        xMove = -1.f+sideLength;
    }
    if (xMove > 1.f-sideLength) {
        xMove = 1.f-sideLength;
    }
    
    if (yMove<-1.f+sideLength) {
        yMove = -1.f+sideLength;
    }
    if (yMove>1.f-sideLength) {
        yMove = 1.f-sideLength;
    }
    //提交渲染 之后会执行 RenderScene 方法
    glutPostRedisplay();
    
}

3 开始渲染

先清楚缓冲区;然后 将矩阵 结果存储在 M3DMatrix44f 中; 接着调用平面着色器, 设置 方式、坐标、和颜色; 最后提交着色器,进行绘制。

//开始渲染
void RenderScene(void) {
    
    //清除一个或一组特定的缓冲区
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

    GLfloat red[] = {1.0f,0.0f,0.0f,0.0f};
    
    // 矩阵
    M3DMatrix44f mTransformMatrix;
    // 平移矩阵,结果存储在 mTransformMatrix 中;
    m3dTranslationMatrix44(mTransformMatrix, xMove, yMove, 0.f);
    
    //平面着色器(固定着色器)
    shaderManager.UseStockShader(GLT_SHADER_FLAT, mTransformMatrix,red);
    
    //提交着色器 绘制
    triangleBatch.Draw();
    
    //将在后台缓冲区进行渲染,然后在结束时交换到前台
    glutSwapBuffers();
}

总结一下方法二,我们不用去计算每一个坐标点的位置:

通过定义 M3DMatrix44f

使用 m3dTranslationMatrix44 方法来讲移动后的结果保存到 M3DMatrix44f

接着提交渲染绘制就完成了

效果如下:

2.gif