美文网首页OpenGLOpenGL+Metal
OpenGL系列之1 - 初识OpenGL

OpenGL系列之1 - 初识OpenGL

作者: 窗外山海帆 | 来源:发表于2018-02-11 14:40 被阅读70次

    前言:

    这是OpenGL的的简单介绍。分为三个部分:

    1. OpenGL的简单认识
    2. 本地搭建OpenGL的环境
    3. OpenGL的部分术语

    内容:

    一. OpenGL的简单认识

    1. OpenGL的Wikipedia 介绍地址: https://en.wikipedia.org/wiki/OpenGL#Development

    Open Graphics Library (OpenGL is a cross-language, cross-platform application programming interface (API) for rendering 2D and 3D vector graphics. The API is typically used to interact with a graphics processing unit (GPU), to achieve hardware-accelerated rendering.

    1. 官方对于OpenGL ES的介绍地址:https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008793-CH1-SW1

    OpenGL ES allows an app to harness the power of the underlying graphics processor. The GPU on iOS devices can perform sophisticated 2D and 3D drawing, as well as complex shading calculations on every pixel in the final image.

    1. OpenGL的案例展示:


    2. OpenGL在iOS开发中中的应用范围:

      开放图形库(Open Graphics Library:OpenGL) 被用来展示2D和3D数据,它是一个多用途的开放标准图形库,支持2D、3D数字内容的创建,机械和建筑设计、虚拟原型、飞行模拟、视频游戏等多种应用。您可以使用OpenGL配置3D图形管线并提交数据。顶点被转换和点亮,组成原始图像,进行光栅化后生成2D图像。OpenGL旨在将函数调用转换为可发送到底层图形硬件的图形命令,该底层硬件专门用于处理图形命令,因此OpenGL绘图通常非常快。
      OpenGL for Embedded Systems(OpenGL ES)是OpenGL的简化版本(专门为嵌入式系统设计,在移动端操作系统中应用广泛),该版本消除了冗余功能,提供了更易学习且易于在移动图形硬件中实现的库。

    二.OpenGL在Mac上面的环境搭建:
    1. 搭建过程:

    图片.png
    图片.png
    图片.png
    图片.png
    图片.png
    图片.png
    图片.png
    图片.png
    1. 代码见传送门

    三. OpenGL基本的术语了解:

    1. 代码类及函数介绍:
    #include "GLShaderManager.h"
    /*
      固定管线!
     `#include<GLShaderManager.h>` 移入了GLTool 着色器管理器(shader Mananger)类。
    没有着色器,我们就不能在OpenGL(核心框架)进行着色。
    着色器管理器不仅允许我们创建并管理着色器,还提供一组“存储着色器”,
    他们能够进行一些初步䄦基本的渲染操作。
     */
    
    #include "GLTools.h"
    /*
     `#include<GLTools.h>`  GLTool.h头文件包含了大部分GLTool中类似C语言的独立函数
    */
    
    #include <GLUT/GLUT.h>
    /*
     在Mac 系统下,`#include<glut/glut.h>`
     在Windows 和 Linux上,我们使用freeglut的静态库版本并且需要添加一个宏
    */
    
    //定义一个,着色管理器
    GLShaderManager shaderManager;
    //简单的批次容器,是GLTools的一个简单的容器类。
    GLBatch triangleBatch;
    //blockSize 1/2边长
    GLfloat blockSize = 0.1f;
    GLfloat vVerts[] = {
        -blockSize,-blockSize,0.0f,
        blockSize,-blockSize,0.0f,
        blockSize,blockSize,0.0f,
        -blockSize,blockSize,0.0f
    };
    //x轴上移动的距离
    GLfloat xPos = 0.0f;
    //y轴上移动的距离
    GLfloat yPos = 0.0f;
    
    /*
     在窗口大小改变时,接收新的宽度&高度。
     */
    void changeSize(int w,int h)
    {
        /*
          x,y 参数代表窗口中视图的左下角坐标,而宽度、高度是像素为表示,通常x,y 都是为0
         */
        glViewport(0, 0, w, h);
        
    }
    
    void RenderScene(void)
    {
        
        //1.清除屏幕颜色
        glClear(GL_COLOR_BUFFER_BIT);
        
        //2.设置画笔颜色 RGBA
        GLfloat vRed[] = {1.0f,0.0f,0.0f,1.0f};
        
        //利用矩阵帮助移动
        //mFinalTransform 结果矩阵
        //mTransformMatrix 平移矩阵
        //mRotationMatrix  旋转矩阵
        M3DMatrix44f mFinalTransform,mTransformMatrix,mRotationMatrix;
        
        //平移 x,y,z,w(缩放因子= 1)
        //3D中平移的原理与矩阵之间关系
        /*
         参数1:矩阵
         参数2、3、4:X,Y,Z上平移距离
         */
        m3dTranslationMatrix44(mTransformMatrix, xPos, yPos, 0.0f);
        
        
        //增加难度! 一边移动,一边旋转
        static float yRot = 0.0f;
        
        /*
         参数1:矩阵
         参数2:弧度
         参数3:X:1,0 1:围绕X轴旋转,0不围绕X轴旋转
         参数4:Y:1,0
         参数5:Z:1,0
         */
        m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
        
        //修改旋转度数
        yRot += 5.0f;
        
        //思考:结合2个矩阵的结果 平移矩阵 * 旋转矩阵 = 最终结果矩阵
        m3dMatrixMultiply44(mFinalTransform, mTransformMatrix, mRotationMatrix);
        
        
        //平面着色器
        /*
         1.平移矩阵 mTransformMatrix 与 每个顶点 相乘 -> 新顶点 (顶点着色器)
         2.将片元着色红色 (片元着色器)
         */
        shaderManager.UseStockShader(GLT_SHADER_FLAT,mFinalTransform,vRed);
        
        
        
        //单元着色器(类型,颜色)---第一种方法用到的
        //shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
        
        triangleBatch.Draw();
        
        //从后台缓存区进行渲染
        glutSwapBuffers();
        
        
        
        
    }
    
    //移动图形 -- 修改图形坐标!
    void SpeacialKeys(int key,int x,int y)
    {
        //步长
        GLfloat stepSize = 0.025f;
        
        //计算移动距离
        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();
        
       //第一种方法:通过修改坐标移动物体
       /*
        //步长
        GLfloat stepSize = 0.025f;
        //相对点 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.0 - blockSize * 2) {
            blockX = 1.0 - blockSize * 2;
        }
        if (blockY > 1.0f) {
            blockY = 1.0f;
        }
        if (blockY < -1.0f + blockSize * 2) {
            blockY = -1.0f + blockSize * 2;
        }
        
        //计算参考点移动,借助参考D 帮助实现4个顶点的修改。
        //A:
        vVerts[0] = blockX;
        vVerts[1] = blockY - blockSize * 2;
        //B
        vVerts[3] = blockX + blockSize * 2;
        vVerts[4] = blockY - blockSize * 2;
        //C
        vVerts[6] = blockX + blockSize * 2;
        vVerts[7] = blockY;
        //D
        vVerts[9] = blockX;
        vVerts[10] = blockY;
        triangleBatch.CopyVertexData3f(vVerts);
        glutPostRedisplay();
        */
        
    }
    
    void setupRC()
    {
        //1.设置清屏颜色
        glClearColor(0.33, 0.45, 0.12, 1.0f);
        //初始化固定管线
        shaderManager.InitializeStockShaders();
        /*
        //指定三角形的顶点数据 x,y,z
        GLfloat vVerts[] = {
            -0.5f,0.0f,0.0f,
            0.5f,0.0f,0.0f,
            0.0f,0.5f,0.0f
        };
        */
        triangleBatch.Begin(GL_TRIANGLE_FAN , 4);
        triangleBatch.CopyVertexData3f(vVerts);
        triangleBatch.End();
    }
    
    int main(int argc,char *argv[])
    {
        //设置当前工作目录,针对MAC OS X
        /*
         `GLTools`函数`glSetWorkingDrectory`用来设置当前工作目录。实际上在Windows中是不必要的,因为工作目录默认就是与程序可执行执行程序相同的目录。但是在Mac OS X中,这个程序将当前工作文件夹改为应用程序捆绑包中的`/Resource`文件夹。`GLUT`的优先设定自动进行了这个中设置,但是这样中方法更加安全。
         */
        gltSetWorkingDirectory(argv[0]);
        //初始化GLUT库,这个函数只是传说命令参数并且初始化glut库
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA);
        //GLUT窗口大小、窗口标题
        glutInitWindowSize(800, 600);
        glutCreateWindow("Triangle");
        /*
         GLUT 内部运行一个本地消息循环,拦截适当的消息。然后调用我们不同时间注册的回调函数。我们一共注册2个回调函数:
         1)为窗口改变大小而设置的一个回调函数
         2)包含OpenGL 渲染的回调函数
         */
        //注册重塑函数
        glutReshapeFunc(changeSize);
        //注册显示函数
        glutDisplayFunc(RenderScene);
        glutSpecialFunc(SpeacialKeys);
        /*
         初始化一个GLEW库,确保OpenGL API对程序完全可用。
         在试图做任何渲染之前,要检查确定驱动程序的初始化过程中没有任何问题
         */
        GLenum status = glewInit();
        if (GLEW_OK != status) {
            printf("GLEW Error:%s\n",glewGetErrorString(status));
            return 1;
        }
        //设置我们的渲染环境
        setupRC();
        glutMainLoop();
        return  0;
        
    }
    
    
    1. 陌生的术语介绍:
    • 着色器

    着色器(shader),专为图形处理单元(GPU)编译的一种小型程序。

    • 图元

    图元是能够被OpenGL ES 绘制的几何物体,如三角形、线条或者精灵。

    • 光栅化

    将输入图元的数学描述转换为与屏幕位置对应的像素片元,称为光栅化。

    • 纹理

    最通常的作用是装饰我们的物体模型,它就像是贴纸一样贴在物体表面,使得物体表面拥有图案。但实际上在OpenGL中,纹理的作用不仅限于此,它可以用来存储大量的数据,一个典型的例子就是利用纹理存储地形信息。

    • 渲染

    渲染(render),表示计算机从模型创建最终图像的过程。

    • 帧缓存

    帧缓存(framebuffer),像素(pixel),是显示器上最小的可见单元。计算机系统将所有的像素保存到帧缓存当中,后者是有图形硬件设备管理的一块独立内存区域,可以直接映射到最终的显示设备上。

    参考及拓展:

    1. https://www.jianshu.com/p/62fc87833ed5
      iOS开发-OpenGL ES魔方应用(简友博客)
    2. https://www.jianshu.com/p/c5ad4a3ed1a9
      初识OpenGL,环境搭建 (简友博客)
    3. https://www.jianshu.com/p/736401c03990
      第1章 OpenGL概述(简友博客)

    代码传送门:

    相关文章

      网友评论

        本文标题:OpenGL系列之1 - 初识OpenGL

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