OpenGL的图形渲染过程
一.什么是openGL
OpenGL被定义为“图形硬件的一种软件接口”。从本质上说,它是一个3D图形和模型库,具有高度的可移植性,具有非常快的速度。
二.管线
管线这个术语描述了opengl渲染的整个过程。openGL采用cs模型:c是cpu,s是GPU,c给s的输入是vertex信息和Texture信息,s的输出是显示器上显示的图像。下面这2个图比较清楚的讲解了opengl的渲染管线。
相信没有opengl基础的应该看不懂,下面会简单的介绍这个流程,再看下文之前,建议先看GPU大百科全书系列文章,对理解opengl工作原理绝对有帮助。
三.管线详解
下面这个图取自《OpenGL ES 3.0编程指南》,此流程为可编程管线。
1.VBO/VAO(顶点缓冲区对象或顶点数组对象):
VBO/VAO(到底是啥,下回讲解)是cpu提供给GPU的顶点信息,包括了顶点的位置、颜色(只是顶点的颜色,和纹理的颜色无关)、纹理坐标(用于纹理贴图)等顶点信息。
2.VertexShader(顶点着色器):
顶点着色器是处理VBO/VAO提供的顶点信息的程序。VBO/VAO提供的每个顶点都执行一遍顶点着色器。Uniforms(一种变量类型)在每个顶点保持一致,Attribute每个顶点都不同(可以理解为输入顶点属性)。执行一次VertexShader输出一个Varying和gl_positon。
3.PrimitiveAssembly(图元装配):
顶点着色器下一个阶段是图元装配,图元(prmitive)是三角形、直线或者点精灵等几何对象。这个阶段,把顶点着色器输出的顶点组合成图元。
4.rasterization(光栅化):
光栅化是将图元转化为一组二维片段的过程,然后,这些片段由片段着色器处理(片段着色器的输入)。这些二维片段代表着可在屏幕上绘制的像素。用于从分配给每个图元顶点的顶点着色器输出生成每个片段值的机制称作插值(Interpolation)。这句不是人话的话解释了一个问题,就是从cpu提供的分散的顶点信息是如何变成屏幕上密集的像素的,图元装配后顶点可以理解成变为图形,光栅化时可以根据图形的形状,插值出那个图形区域的像素(纹理坐标v_texCoord、颜色等信息)。注意,此时的像素并不是屏幕上的像素,是不带有颜色的。接下来的片段着色器完成上色的工作。
5.FragmentShader(片段着色器):
片段着色器为片段(像素)上的操作实现了通用的可编程方法,光栅化输出的每个片段都执行一遍片段着色器,对光栅化阶段生成每个片段执行这个着色器,生成一个或多个(多重渲染)颜色值作为输出。
6.Per-Fragment Operations(逐片段操作)
在此阶段,每个片段上执行如下功能:
(1)pixelOwnershipTest(像素归属测试):
这个用来确定帧缓冲区中位置(x,y)的像素是不是归当前上下文所有。例如,如果一个显示帧缓冲区窗口被另一个窗口所遮蔽,则窗口系统可以确定被遮蔽的像素不属于此opengl的上下文,从而不显示这些像素。
(2)ScissorTest(剪裁测试):
如果该片段位于剪裁区域外,则被抛弃
(3)StencilTest and DepthTest(模板和深度测试):
深度测试比较好理解,若片段着色器返回的深度小于缓冲区中的深度,则舍弃。模板测试没有用过,不清楚具体功能,猜测功能应该和名字一样,模板形状内可通过。
(4)Blending(混合):
将新生成的片段颜色值与保存在帧缓冲区的颜色值组合起来,产生新的RGBA。
(5)dithering(抖动):
不知道这个是神马作用?
最后把产生的片段放到帧缓冲区(前缓冲区或后缓冲区或FBO)中,若不是FBO,则屏幕绘制缓冲区中的片段,产生屏幕上的像素。
7.固定管线
固定管线是没有shader参与的OpenGL绘制管线,OpenGL3.0已经废除了这个功能。固定管线的流程如下所示:
#include <iostream>
#include <GLUT/GLUT.h>
#include <OpenGL/gl.h>void RenderScene(void) {glClear(GL_COLOR_BUFFER_BIT);glShadeModel(GL_SMOOTH);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glBegin(GL_TRIANGLES);glColor3ub((GLubyte)255, (GLubyte)0, (GLubyte)0);glVertex3f(0, 200, 0);glColor3ub((GLubyte)0, (GLubyte)255, (GLubyte)0);glVertex3f(200, -70, 0);glColor3ub((GLubyte)0, (GLubyte)0, (GLubyte)255);glVertex3f(-200, -70, 0);glEnd();glutSwapBuffers();
}void SetupRC(void) {glClearColor(0, 0, 0, 1);
}void changeSize(int w, int h) {GLfloat windowHeight, windowWidth;if (h == 0) {h = 1;}glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();windowHeight = windowWidth = 250;glOrtho(-windowWidth, windowWidth, -windowHeight, windowHeight, -1, 1);
}int main(int argc, char * argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(600, 600);glutCreateWindow("Simple");const GLubyte * info = glGetString(GL_VERSION);std::cout << ( const char *)info << std::endl;glutReshapeFunc(changeSize);glutDisplayFunc(RenderScene);SetupRC();glutMainLoop();return 0;
}
效果为:
8.可编程管线:
OpenGL 2.0引入了可编程管线,shader得到支持,流程如下图所示:
要得到相同的效果,代码如下:
#include <iostream>
#include <GLUT/GLUT.h>
#include <OpenGL/gl.h>GLuint createShader(GLenum type, const char * shaderSrc) {GLuint shader;GLint compiled;shader = glCreateShader(type);if (shader == 0) {return 0;}glShaderSource(shader, 1, &shaderSrc, NULL);glCompileShader(shader);glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);if (!compiled) {GLint infoLen = 0;glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1) {char * infoLog = (char *)malloc(sizeof(char) * infoLen);glGetShaderInfoLog(shader, infoLen, NULL, infoLog);std::cout << "Error compiling shader: " << infoLog << std::endl;free(infoLog);}glDeleteShader(shader);return 0;}return shader;
}GLuint programObject;bool init() {//todo 读文件char * vShaderStr ="attribute vec4 vPositon; \n""attribute vec4 aColor; \n""varying vec4 vertexColor; \n""void main() { \n"" gl_Position = gl_ModelViewProjectionMatrix * vPositon; \n"" vertexColor = aColor; \n""}";char * fShaderStr ="varying vec4 vertexColor;""void main() {"" gl_FragColor = vertexColor;""}";GLuint vertexShader;GLuint fragmentShader;GLint linked;vertexShader = createShader(GL_VERTEX_SHADER, vShaderStr);fragmentShader = createShader(GL_FRAGMENT_SHADER, fShaderStr);programObject = glCreateProgram();if (programObject == 0) {return false;}glAttachShader(programObject, vertexShader);glAttachShader(programObject, fragmentShader);glLinkProgram(programObject);glGetProgramiv(programObject, GL_LINK_STATUS, &linked);if (!linked) {GLint infoLen = 0;glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1) {char * infoLog =(char *)malloc(sizeof(char) * infoLen);glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);std::cout << "Error linking program: " << infoLog << std::endl;free(infoLog);}glDeleteProgram(programObject);return false;}glClearColor(0, 0, 0, 0);return true;
}void RenderScene(void) {GLfloat vVerties[] = {0, 200, 0,200, -70, 0,-200, -70, 0};GLfloat vertexColor[] = {1,0,0,1,0,1,0,1,0,0,1,1};glClear(GL_COLOR_BUFFER_BIT);glUseProgram(programObject);GLint attributePos = glGetAttribLocation(programObject, "vPositon");glVertexAttribPointer(attributePos, 3, GL_FLOAT, GL_FALSE, 0, vVerties);glEnableVertexAttribArray(attributePos);GLint colorPos = glGetAttribLocation(programObject, "aColor");glVertexAttribPointer(colorPos, 4, GL_FLOAT, GL_FALSE, 0, vertexColor);glEnableVertexAttribArray(colorPos);glDrawArrays(GL_TRIANGLES, 0, 3);glutSwapBuffers();
}void changeSize(int w, int h) {glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();GLfloat windowHeight, windowWidth;windowHeight = windowWidth = 250;glOrtho(-windowHeight, windowHeight, -windowWidth, windowWidth, -1, 1);}int main(int argc, char * argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(600, 600);glutCreateWindow("Simple");glutReshapeFunc(changeSize);glutDisplayFunc(RenderScene);init();glutMainLoop();return 0;
}
OpenGL的图形渲染过程相关推荐
- Android平台使用OpenGL实现图形渲染
一.前言 OpenGL定义了一个跨编程语言.跨平台的专业图形程序接口.可用于二维或三维图像的处理与渲染,它是一个功能强大.调用方便的底层图形库.对于嵌入式设备,其提供了OpenGL ES(OpenGL ...
- opengl---2.图形渲染的过程
一.过程介绍 在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转变为适应你屏幕的2D像素.3D坐标转为2D坐标的处理过程是由Op ...
- 【Modern OpenGL】第一个三角形
>说明:跟着learnopengl的内容学习,不是纯翻译,只是自己整理记录.>强烈推荐原文,无论是内容还是排版. [原文链接](http://learnopengl.com/#!Getti ...
- 基于OpenGL的Android系统视频转换功能实现
第1章OpenGL ES 3D图形编程首先OpenGL.OpenGL的英文全称是OpenGL Graphics Library,中午名称是开发式图形库.OpenGL为程序开发人员定义了一个 ...
- 开源项目推荐:OpenGL/Vulkan/Cairo/Skia/angle/VTK/OpenVG/MyPaint/GIMP/Krita/Pencil2D/inkspace/enve等绘图库或画图软件
绘图引擎简介 Windows环境下二维绘图引擎有多种选择:GDI.GDI+.DirectDraw.Qt/QPainter.Agg.Cairo.skia.Direct2D.Direct3D.OpenGL ...
- 我对OpenGL教程的学习(入门篇)
唠嗑: 做前端有小两年了,对自己使用的渲染技术却还是门外汉,这怎么说得过去,毕竟自己当初还是因为这神奇的技术才入了这个坑的呢. 关于OpenGL 我竟然都懒得去百度百科复制粘贴了.OpenGL其实是一 ...
- OpenGL核心模式详细讲解[结合LearnOpenGL]
OpenGL立即渲染模式&核心模式 OpenGL (for"Open Graphics Library") is an API (Application Programmi ...
- OpenGL 和 OpenGL ES基础知识
当今许多视觉应用程序,从简单的游戏到高级工程领域,都使用OpenGL(Open Graphics Library)和OpenGL ES(OpenGL for Embedded Systems)作为其图 ...
- 【OpenGL】GLFW创建三角形
文章目录 基础知识 顶点输入 创建顶点着色器 片段着色器 链接顶点属性和VAO顶点数组对象 元素缓冲对象EBO 完整程序 基础知识 在学习图形渲染前,首先了解3个词汇: 顶点数组对象:Vertex A ...
最新文章
- 【直播】王茂霖:二手车交易价格预测-千变万化特征工程(河北高校数据挖掘邀请赛)
- 苹果的浏览器safari无法识别 2016-1-1这样的日期,会返回Invalid Date
- 小白学phoneGap《构建跨平台APP:phoneGap移动应用实战》连载一(PhoneGap中的API)...
- ActiveMQ安装使用
- openwrt系统安装到云服务器异常,OpenWrt路由器系统下服务OpenClash 安装教程及其折腾踩坑记录...
- Mysql5.7.20使用group by查询(select *)时出现错误--修改sql mode
- 安川机器人报错代码_今日 IPO|对标库卡机器人的先惠技术上市 近八成收入靠上汽...
- 准确率 召回率_机器学习中F值(F-Measure)、准确率(Precision)、召回率(Recall)
- Elasticsearch的javaAPI之percolator
- Remote System Explorer Operation卡死Eclipse解决方案
- 人声歌姬语音合成器+全套拓展 – Yamaha Vocaloid 4.3.0 + ALL Libraries WiN
- Tomcat角色说明及配置
- 如何查看CDR文件是出自哪个版本?
- 有哪些在家健身的软件?Mac健身软件推荐
- CJOJ 1659 【中学高级本】倒酒
- 1.投骰子的随机游戏
- mc服务器linux配置,详细教程——基于Centos搭建MC服务器(outdated)
- python代码怎么变成软件_从Python代码到APP,你只需要一个小工具:GitHub已超6000星
- distill介绍及优秀博客记录
- C++学习之路抓紧跑路版(七)-动态申请内存空间
热门文章
- Java统计数组中各个数字出现的个数和字符串中各个字符出现的个数
- 视频教程-JAVAEE真实课堂系列之javaScript全讲-云计算基础架构
- IDEA使用单元测试对数据库的insert语句进行测试,出现添加多条问题的解决方案
- Base-N 算法加密解密实现:
- 【LeetCode】【剑指offer】【剪绳子(二)】
- LaTex:有关LaTex的入门、语法使用
- 用eclipse配置hibernate的hbm.xml文件时遇到的一些问题
- PHP软件库源码+支持CDKey卡密充值
- 关于Google多账户登录
- 硬核粉丝 | 清华双胞胎“YCY Dance Now”杀进超越杯编程大赛决赛