OpenGL 入门

2019-05-06  本文已影响0人  紫水依
一、认识OpenGL相关概念
  1. OpenGL:用于创建3d图像的编程接口,用于PC端,是一个跨编程语言、跨平台的图形编程程序接口,只操作GPU芯片来保证跨平台性
    OpenGL ES:是OpenGL的子集,主要针对手机、PAD和游戏主机等嵌入式设备使用,用于移动端,使用的语言是GLSL,是着色器语言,iOS框架是GLKit
    DirectX:仅用于Windows平台的多媒体处理框架
    Metal:是Apple在2014年推出的3D渲染框架,性能优于OpenGL ES,使用的语言是Metal shading language,iOS框架是Metal kit

  2. 3D图形:有3个维度的图形,屏幕上的3D效果是2D+透视呈现出来的
    三维物体:高度、宽度、深度(在坐标轴上用z轴表);二维物体:高度、宽度

  3. 3D术语:

  1. 坐标系:

2D笛卡尔坐标系

3D笛卡尔坐标系

  1. 渲染:图形图像数据转换成3D空间图像的操作,如图形绘制、图片显示到屏幕等数据可视化操作
    线框渲染:平面通过线条形成;
    纯色渲染:通过颜色形成形状;
    纹理渲染:添加纹理到形状上;
    OpenGL里只有点、线、三角形,通过这三者来拼成各种形状

  2. 着色器:

着色器分类:

着色器渲染流程:
顶点数据->顶点着色器(必要,接收顶点数据,单独处理每个顶点)
->细分着色器(可选,描述物体的形状,在管线中生成新的几何体处理(平顺)模型,生成最终状态;对所有的图像进行修改几何图元类型或放弃所有凸缘)
->几何着色器
->图元设置(图形的形状)
->剪切(剪切视口之外的绘制)
->光栅化(输入图元的数学描述,转化为与屏幕对应的位置像素片元)
->片元着色器(必选,给像素点添加颜色)
->显示效果

  1. CPU与GPU的通信过程
    CPU将数据交给GPU处理需要通过OpenGL,OpenGL的buffers缓存区域(颜色缓存区、顶点缓存区、深度缓存区)解决数据饥饿问题,CPU和GPU的数据处理能力高于内存,CPU和GPU控制的内存是分开的,不能从一块内存复制到另一块内存执行,因为复制数据速度很慢,CPU和GPU都不能操作数据,也避免引起错误。

  2. OpenGL使用客户端--服务端的形式实现,客户端是我们编写的代码,服务端是计算机图形硬件厂商所提供的OpenGL实现,OpenGL ES框架相当于Client去发起图像处理请求,GPU相当于Server负责处理图形操作。

二、了解OpenGL
  1. OpenGL简介:OpenGL是跨平台计算机图形应用程序接口规范,用于可视化领域,是一种图形应用程序编程接口,图形API本质是利用GPU芯片来高效渲染图形图像

tips:CPU是串行运算,时间片快速切换调度任务,处理复杂的逻辑判断,C语言、C++代码是编译运行在CPU上的;GPU是并发运算,通过很多的计算单元执行任务,处理数据更高效,OpenGL语言GLSL,着色器语言,编译运行在GPU上

  1. OpenGL用处:实现图形的底层渲染
  1. OpenGL专业名词

OpenGL上下文(context)

OpenGL状态机

顶点数组(VertexArray)和顶点缓冲区(VertexBuffer)

管线

着色器程序shader

OpenGL在处理shader时,通过编译、链接等步骤,⽣成了着色器程序(glProgram),着色器程序同时包含了顶点着⾊器和⽚元着⾊器的运算逻辑。在OpenGL进行绘制的时候,首先由顶点着⾊器对传⼊的顶点数据进⾏运算,再通过图元装配,将顶点转换为图元,然后进⾏光栅化,将图元这种⽮量图形转换为栅格化数据,最后将栅格化数据传入⽚元着⾊器中进⾏运算。⽚元着⾊器会对栅格化数据中的每一个像素进行运算,并决定像素的颜⾊,从而形成一个图形图像。

GLSL语言

光栅化Rasterization

纹理

混合Blending

变换矩阵Transformation

投影矩阵Projection

渲染缓冲区

但是每个窗口只有一个缓冲区,如果在绘制过程中屏幕进行了刷新,窗⼝可能显示出不完整的图像,所以常规的OpenGL程序至少都会有两个缓冲区,显示在屏幕上的称为屏幕缓冲区,没有显示的称为离屏缓冲区,在一个缓冲区渲染完成之后,通过将屏幕缓冲区和离屏缓冲区交换,实现图像在屏幕上的显示。由于显示器的刷新一般是逐⾏进⾏的,因此为了防⽌交换缓冲区的时候屏幕上下区域的图像分属于两个不同的帧,因此交换一般会等待显示器刷新完成的信号,在显示器两次刷新的间隔中进⾏交换,这个信号就被称为垂直同步信号,这个技术被称为垂直同步。使⽤了双缓冲区和垂直同步技术之后,由于总是要等待缓冲区交换之后再进⾏下一帧的渲染,使得帧率无法完全达到硬件允许的最高水平。为了解决这个问题,引⼊了三缓冲区技术,在等待垂直同步时,来回交替渲染两个离屏的缓冲区,而垂直同步发生时,屏幕缓冲区和最近渲染完成的离屏缓冲区交换,实现充分利用硬件性能的⽬的。

  1. 坐标系相关

视口

投影

摄像机坐标系

标准化设备坐标系NDC范围是[-1, 1]
世界坐标系:描述世界空间,在大的环境里的位置,表示系统绝对坐标系
物体坐标系:局部空间坐标系、物体空间坐标系,描述局部空间、物体本身,物体所在的位置坐标系
摄像机坐标系:观察空间,描述观察坐标系的空间,观察者角度的坐标系
惯性坐标系:物体坐标系的旋转,是世界坐标系平移后的坐标系
裁剪空间:超过范围后需要裁剪
屏幕空间:描述屏幕显示坐标系

MVP矩阵:描述物体发生的变化,model、view、projection(投影)

图形从坐标顶点到渲染到屏幕需要经历的坐标系转换:
物体坐标(object space)->模型变换(modeling transformation)->世界坐标(world space)
->视变换(viewing transformation)(观察者)->观察者坐标(eye space)
->投影变换(projection transformation)->裁剪坐标(clip space)
->透视除法(perspective divide)->规范化设备坐标(NDC space)
->视口变换(ViewPort mapping)->屏幕坐标(screen space)

三、OpenGL环境搭建与测试
  1. 准备资料


    OpenGL环境搭建资料
  2. 创建MacOS工程,工程名字自己起,使用Objective-C


    创建MacOS工程
  3. 在General最底部Linked Frameworks and Libraries添加两个系统库OpenGL.framework 和 GLUT.framework


    两个系统库
  4. 添加准备好的资料include和libGLTools.a到工程中
    在Bulid Settings找到Header Search Paths,拖入GLTools.h 和 glew.h

    拖入GLTool.h 和 glew.h
  5. 将libGLTools.a 直接拖到工程的==Frameworks== 文件夹里面,在Linked Frameworks and Libraries里将libGLTools.a删除然后重新拖过来添加上,另外删除文件:AppDelegate.h 、 AppDelegate.m 、ViewController.h 、 ViewController.m 、 main.m ; 创建 main.cpp文件


    选择C++ File
不勾选header file
  1. 添加代码到main.cpp
#include "GLShaderManager.h"
#include "GLTools.h"
#include <glut/glut.h>

GLBatch triangleBatch;
GLShaderManager shaderManager;

//窗口大小改变时接受新的宽度和高度,其中0,0代表窗口中视口的左下角坐标,w,h代表像素
void ChangeSize(int w,int h)
{
    glViewport(0,0, w, h);
    
}

//为程序作一次性的设置
void SetupRC()
{
    //设置背影颜色
    glClearColor(0.1f,0.1f,0.1f,1.0f);
    
    //初始化着色管理器
    shaderManager.InitializeStockShaders();
    
    //设置三角形,其中数组vVert包含所有3个顶点的x,y,笛卡尔坐标对。
    GLfloat vVerts[] = {
        -0.5f,0.0f,0.0f,
        0.5f,0.0f,0.0f,
        0.0f,0.5f,0.0f,
    };
    
    //批次处理
    triangleBatch.Begin(GL_TRIANGLES,3);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
    
}

//开始渲染
void RenderScene(void)
{
    //清除一个或一组特定的缓冲区glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    
    //设置一组浮点数来表示红色
    GLfloat vRed[] = {1.0f,0.0f,0.0f,1.0f};
    
    //传递到存储着色器,即GLT_SHADER_IDENTITY着色器,这个着色器只是使用指定颜色以默认笛卡尔坐标第在屏幕上渲染几何图形
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
    
    //提交着色器
    triangleBatch.Draw();
    
    //将在后台缓冲区进行渲染,然后在结束时交换到前台
    glutSwapBuffers();
    
}

int main(int argc,char* argv[])
{
    
    //设置当前工作目录,针对MAC OS X
    gltSetWorkingDirectory(argv[0]);
    
    //初始化GLUT库
    glutInit(&argc, argv);
    
    /*初始化双缓冲窗口,其中标志GLUT_DOUBLE、GLUT_RGBA、GLUT_DEPTH、GLUT_STENCIL分别指
     
     双缓冲窗口、RGBA颜色模式、深度测试、模板缓冲区*/
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
    
    //GLUT窗口大小,标题窗口
    glutInitWindowSize(800,600);
    glutCreateWindow("Triangle");
    
    //注册回调函数
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    
    //驱动程序的初始化中没有出现任何问题。
    GLenum err = glewInit();
    
    if(GLEW_OK != err) {
        
        fprintf(stderr,"glew error:%s\n",glewGetErrorString(err));
        return 1;
        
    }
    
    //调用SetupRC
    SetupRC();
    
    glutMainLoop();
    
    return 0;
    
}
  1. 将GLBatch.h、GLShaderManager.h、GLTools.h、GLTriangleBatch.h中报错的头文件引入由<>改为"",编译时由<>系统引入,改为""普通引入,点击运行窗口出现一个三角形
上一篇 下一篇

猜你喜欢

热点阅读