• iOS 渲染学习(二)


    iOS 渲染学习(二)

    OpenGL渲染正方形&平移

    渲染

    // 定义一个着色器管理器
    GLShaderManager shaderManager;
    
    //简单的批次容器,是GLTools的一个简单的容器类
    GLBatch triangleBatch;
    
    //设定的边长
    GLfloat blockSize = 0.1f;
    
    //正方形的四个点的坐标
    GLfloat vVerts[] = {
        -blockSize,-blockSize,0.1f,
        blockSize,-blockSize,0.1f,
        blockSize,blockSize,0.1f,
        -blockSize,blockSize,0.1f,
    };
    
    //窗口大小改变时,接收新的宽度和高度
    void changeSize(int w,int h){
        glViewport(0, 0, w, h);
    }
    

    核心代码

    // 显示函数
    void RenderScene(void){
        
        // 1. 首先需要清除一个或一组特定的缓存区
        // 清屏
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        // 2. 设置一组浮点数 设定颜色
        GLfloat vRed[] = {0.0f,1.0f,0.0f,1.0f};
        
        // 3. 传递给存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色 以默认笛卡尔坐标在屏幕上渲染几何图形
        shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
        
        // 4. 提交着色器 绘制
        triangleBatch.Draw();
        
        // 在开始设置OpenGL窗口的时候,指定一个双缓冲区的渲染环境,这就意味着将在后台缓冲区进行渲染,渲染结束后交还给前台,这种方式可以防止观察者看到 可能伴随着动画帧与动画帧之间 闪烁的渲染过程,缓冲区交换平台将以平台特定的方式进行
        // 5.将后台缓冲区进行渲染,结束后交还给前台
        glutSwapBuffers();
        
    }
    
    void setupRC(){
        
        // 设置清屏颜色(背景颜色)
        glClearColor(0.98f, 0.3f, 0.8f, 1.0f);
        
        // 初始化一个渲染管理器
        shaderManager.InitializeStockShaders();
        
        // 指定顶点 GL_TRIANGLE_FAN 绘制连接方式。   
        triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
        triangleBatch.CopyVertexData3f(vVerts);
        triangleBatch.End();
    }
    

    绘制连接方式

    实现

    int main(int argc, char *argv[]){
        // 设置当前工作目录,针对MACOSX
        gltSetWorkingDirectory(argv[0]);
        // 初始化GLUT库
        glutInit(&argc, argv);
        // 初始化双缓冲窗口,其中标志GLUT_DOUBLE(双缓冲窗口),GLUT_RGBA(RGBA颜色模式),GLUT_DEPTH(深度测试),GLUT_STENCIL(模版缓冲区)
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
        // GLUT窗口大小 标题窗口
        glutInitWindowSize(500, 500);
        glutCreateWindow("Triangle");
    
        /*
         GLUT内部会运行一个本地消息循环,拦截适当的消息,然后调用我们不同时间注册的回调函数,我们一共注册了2个回调函数
         1.为窗口改变大小而设置的一个回调函数
         2.包含OpenGL 渲染的回调函数
         */
        // 注册重塑函数
        glutReshapeFunc(changeSize);
        // 注册显示函数
        glutDisplayFunc(RenderScene);
        
        GLenum status = glewInit();
        // 驱动程序的初始化是否出现问题
        if (GLEW_OK != status) {
            printf("GLEW error : %s
    ",glewGetErrorString(status));
            return 1;
        }
        
        // 设置渲染环境
        setupRC();
        
        glutMainLoop();
    
        return 0;
    }
    

    平移

    1.坐标更新方式

    void specialKeys(int key, int x, int y){
        
        // 每次移动的长度
        GLfloat stepSize = 0.025f;
        // blockX/blockY: 相对移动顶点D
        GLfloat blockX = vVerts[0];
        GLfloat blockY = vVerts[10];
        // 键盘上
        if (key == GLUT_KEY_UP) {
            blockY += stepSize;
        }
        // 键盘下
        if (key == GLUT_KEY_DOWN) {
            blockY -= stepSize;
        }
        // 键盘左
        if (key == GLUT_KEY_LEFT) {
            blockX -= stepSize;
        }
        //键盘右
        if (key == GLUT_KEY_RIGHT) {
            blockX += stepSize;
        }
        
        // 触碰到边界的处理
        // 最左边
        if (blockX <= -1.0f) {
            blockX = -1.0f;
        }
        // 最右边
        if (blockX >= 1.0f-blockSize*2) {
            blockX = 1.0f-blockSize*2;
        }
        // 最上边
        if (blockY >= 1.0f) {
            blockY = 1.0f;
        }
        // 最下边
        if (blockY <= -1.0f+blockSize*2) {
            blockY = -1.0f+blockSize*2;
        }
        
        // 四个顶点坐标进行更新
        vVerts[0] = blockX;
        vVerts[1] = blockY - blockSize*2;
        
        vVerts[3] = blockX + blockSize*2;
        vVerts[4] = blockY - blockSize*2;
        
        vVerts[6] = blockX + blockSize*2;
        vVerts[7] = blockY;
        
        vVerts[9] = blockX;
        vVerts[10] = blockY;
        //将顶点数组通过GLBatch帮助类将顶点传输到存储着⾊器中,并⼿动触发渲染函数.
        triangleBatch.CopyVertexData3f(vVerts);
        glutPostRedisplay();
        
    }
    
    // 注册特殊函数
    glutSpecialFunc(specialKeys);
    

    2.矩阵方式

    相比坐标更新的方式,矩阵方式适合顶点很多的图形,因为它不需要对每一个顶点的坐标都进行更新,更像根据图形的中心点xPos&yPos的移动进行平移.

    添加中心点

    // 记录x y 平移的距离
    GLfloat xPos = 0.0f;
    GLfloat yPos = 0.0f;
    

    修改RenderScene和specialKeys函数

    void RenderScene(void){
    
        // 矩阵计算
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        GLfloat vRed[] = {0.0f,1.0f,0.0f,1.0f};
        
        // 矩阵
        M3DMatrix44f mTransfromMatrix;
        
        m3dTranslationMatrix44(mTransfromMatrix, xPos , yPos, 0.0f);
        
        // 平面着色器
        shaderManager.UseStockShader(GLT_SHADER_FLAT,mTransfromMatrix,vRed);
        
        triangleBatch.Draw();
        glutSwapBuffers();
        
    }
    
    void specialKeys(int key, int x, int y){
        
        // 每次移动的长度
        GLfloat stepSize = 0.025f;
        
        GLfloat blockX = vVerts[0];
        GLfloat blockY = vVerts[10];
        
        if (key == GLUT_KEY_UP) {
            yPos += stepSize;
        }
        if (key == GLUT_KEY_DOWN) {
            yPos -= stepSize;
        }
        if (key == GLUT_KEY_LEFT) {
            xPos -= stepSize;
        }
        if (key == GLUT_KEY_RIGHT) {
            xPos += stepSize;
        }
        
        // 边界碰撞检测
        if (xPos <= -1.0f+blockSize) {
            xPos = -1.0f+blockSize;
        }
        
        if (xPos >= 1.0f-blockSize) {
            xPos = 1.0f-blockSize;
        }
        
        if (yPos >= 1.0f-blockSize) {
            yPos = 1.0f-blockSize;
        }
        if (yPos <= -1.0f+blockSize) {
            yPos = -1.0f+blockSize;
        }
        
        glutPostRedisplay();
        
    }
    
  • 相关阅读:
    构造函数模式知识的扩展
    JavaScript 创建对象之单例、工厂、构造函数模式
    javaScript 计算两个日期的天数相差
    类似购物车循环判断方法
    spring的@Transactional注解详细用法
    String.getBytes()方法中的中文编码问题(转)
    spring 定时任务的 执行时间设置规则-----看完这篇就懂了
    为什么说Redis是单线程的?
    你应该知道的 RPC 原理
    关系型数据库与NoSQL的对比
  • 原文地址:https://www.cnblogs.com/en815/p/13253609.html
Copyright © 2020-2023  润新知