【OPENGL】第三篇 着色器基础(一)
在这一章,我们会学习什么是着色器(Shader),什么是着色器语言(OpenGL Shading Language-GLSL),以及着色器怎么和OpenGL程序交互。
首先我们先来看看什么叫着色器。
Shader(着色器)是用来实现图像渲染的,用来替代固定渲染管线的可编程程序。
着色器替代了传统的固定渲染管线,可以实现3D图形学计算中的相关计算,由于其可编程性,可以实现各种各样的图像效果而不用受显卡的固定渲染管线限制。这极大的提高了图像的画质。
在上一篇文章( http://www.cnblogs.com/MyGameAndYOU/p/4681710.html )
关于OpenGL的第一个例子中,我们已经接触过顶点着色器(Vertex Shader)以及片段着色器(Fragment Shader)的相关代码。另外,有些书籍或者文章也将片段着色器称为像素着色器(Pixel Shader)。
话说回来,在我们了解着色器之前,让我们先了解固定渲染管线(fixed-function pipeline)究竟是什么。
渲染管线,也称之为渲染流水线,可以理解为工厂的流水线工作,而在这里它的工作是让计算机把模型通过一系列的处理最终生成图像的过程,
网上也有人这么描述它:渲染管线是显示芯片内部处理图形信号相互独立的的并行处理单元。顶点管线在GPU中的作用就是处理几何数据,并将3D数据投射到二维的屏幕上。借用一个网友说的简单例子来通俗的说明一下顶点管线和像素渲染管线的作用。一个画家在做画的时候,都需要先把所画人或物的轮廓,框架画出来,这里我们称之为“构图”;然后再根据光照进行着色,这里我们称之为“渲染”。顶点管线和像素渲染管线所起的就是这两个作用,顶点管线和引擎负责把“轮廓、框架”画出来,而像素渲染管线和引擎则负责对画好的“轮廓、框架”根据光照等因素进行着色,构成一幅完整的图形。渲染管线直接关系到显卡对画面的渲染性能。
那为何称之为固定呢?这是说芯片上一组电路已经固定实现了特定的运算功能,程序能做的只是提供场景数据以及微调运算功能的参数。我们只能通过调用不同的API组合实现特定效果,但是比较死板。
那么问题又来了,流水线的处理过程分哪些步骤呢?
关于OpenGL的流水线,大家可以看这里的图形流水线教程,非常详细。CSDN博客地址:http://blog.csdn.net/racehorse/article/details/6593719
在这里,我借助前人的经验,把相关的知识再进一步分享给大家。
一个固定渲染管线包括如下功能:
1、顶点变换(Vertex Transformation)
这里的顶点是信息的集合,包含空间中的位置、颜色、法线、纹理坐标等等。主要用于顶点位置变换、对每个顶点计算光照、纹理坐标的生成以及变换。
2、图元组合和光栅化(Primitive Assembly and Rasterization)
该阶段处理的是上一个阶段输出的变换后的顶点以及它们的连接信息。连接信息用来描述顶点如何组成图元(三角形、四边形等等)。利用在顶点变换阶段计算出的数据,结合连接信息计算出片段的数据。(例如,每个顶点包含一个变换后的位置,当它们组成图元时,就可以用来计算图元的片断位置。另一个例子是使用颜色,如果多边形的每个顶点都有自己的颜色值,那么多边形内部片断的颜色值就是各个顶点颜色插值得到的。)另外此阶段还负责视锥体(view frustum)的剪裁和背面剔除。
光栅化决定了片断(fragment),以及图元的像素位置。这里的片断是指一块数据,用来更新帧缓存(frame buffer)中特定位置的一个像素。一个片断除了包含颜色,还有法线和纹理坐标等属性,这些信息用来计算新的像素颜色值。本阶段的输出包括帧缓存中片段的位置,以及经过插值后的片段信息。
3、片断纹理化和色彩化(Fragment Texturing and Coloring)
此阶段的输入是经过插值的片段信息。在前一阶段已经通过插值计算了纹理坐标和一个颜色值,这个颜色在本阶段可以用来和纹理元素进行组合。此外,这一阶段还可以进行雾化处理。通常最后的输出是片断的颜色值以及深度信息。
4、光栅操作(Raster Operations)
此阶段的输入包括像素位置、片断深度和颜色值。这个阶段对片段进行一系列的测试,包括:剪切测试(scissor test)、Alpha测试、模版测试、深度测试。
如果测试成功,则根据当前的混合模式(blend mode)用片段信息来更新像素值。注意混合只能在此阶段进行,因为片断纹理化和颜色化阶段不能访问帧缓存。帧缓存只能在此阶段访问。
一幅图总结固定功能流水线(Visual Summary of the Fixed Functionality)
下图直观地总结了上述流水线的各个阶段:
该图的出处http://blog.csdn.net/racehorse/article/details/6593719
而在我们即将进行的着色器编程中,上述的流程,有两个阶段被编程替代
1、顶点变换(Vertex Transformation) 这个阶段使用顶点着色器实现。
2、片断纹理化和色彩化(Fragment Texturing and Coloring) 这个阶段使用片段着色器实现。
在OpenGL 3.0版本之前(包含3.0),或者使用了兼容模式(compatibility profile)的OpenGL环境下,我们还可以使用之前的固定渲染管线,在不使用着色器的情况下处理几何与像素数据。
但从3.1版本开始,固定渲染管线从核心模式(core profile)去除,所以如果使用该版本之后的核心模式来编程的话,我们必须使用着色器。
GLSL在OpenGL 2.0版本左右发布的(在之前是属于扩展功能)。与OpenGL与时俱进,它是一种专门为图形开发设计的编程语言,但我们可以从其身上找到C/C++的影子。
每一个着色器代码看起来像是一个完整的C程序,同样有一个main入口函数。但是与C不同的是,着色器的main函数没有任何参数,在某个着色阶段中的输入和输出的所有数据都是通过着色器中的特殊全局变量来传递的。最重要一点是,不要把它们与应用程序中的全局变量混淆,它们两者没有任何关系。
#version 430 core in vec4 vPosition
in vec4 vColor; out vec4 color; uniform mat4 ModelViewProjectionMatrix; void main(){
color = vColor;
gl_Position = ModelViewProjectionMatrix * vPosition;
}
正如上面的代码,OpenGL会使用输入和输出变量来传递着色器所需要的数据,变量的值会在OpenGL每次执行着色器的时候更新。
还有一种是变量是直接从OpenGL应用程序中接收数据的,称为uniform变量。uniform表示唯一,对所有几何图元的值都是一致的,除非应用程序对它执行了更新,否则着色器是并不会影响它的值的变化的。
在这一小节中,我们主要了解什么是着色器,为什么会出现着色器,它和固定管线有什么区别。另外,还有图形流水线知识,下一小节,我们会继续学习GLSL的基本变量以及相关操作。
2015.08.12
广州
【OPENGL】第三篇 着色器基础(一)的更多相关文章
- 【OPENGL】第三篇 着色器基础(二)
在这一小节,主要学习GLSL的基本数据类型以及控制结构.GLSL具备了C++和Java的很多特性,我们会先了解所有着色阶段共有的特性,再了解各个着色器的专属特性. 1.着色器的基本结构 一个着色器程序 ...
- [OpenGL ES 02]OpenGL ES渲染管线与着色器
[OpenGL ES 02]OpenGL ES渲染管线与着色器 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创 ...
- Unity 着色器基础知识
一.着色器基础知识 着色器通过代码模拟物体表面发生的事情,其实就是GPU中运行的一段代码. 着色器的类型: 顶点着色器.片元着色器.无光照着色器.表面着色器.图像特效着色器.计算着色器. 坐标空间: ...
- OpenGL学习笔记(三)着色器
目录 Shader是什么 GLSL 数据类型 输入与输出 顶点着色器向片段着色器发送数据 Uniform 制作三色渐变三角形 对着色器程序进行封装 参考资料:OpenGL中文翻译 Shader是什么 ...
- Unity 渲染教程(二):着色器基础
转载:https://www.jianshu.com/p/7db167704056 这是关于渲染基础的系列教程的第二部分.这个渲染基础的系列教程的第一部分是有关矩阵的内容.在这篇文章中我们将编写我们的 ...
- 第三篇、Swift基础学习
1.常量与变量 什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 变量的 ...
- 第三篇:python基础_3
本篇内容 文件处理补充 函数基本语法及特性 参数 返回值 嵌套函数 一.文件处理补充 1.文件操作的内置方法 #!/usr/bin/env pyhon #encoding: utf-8 #auth: ...
- 第三篇:python基础之数据类型与变量
阅读目录 一.变量 二.数据类型 2.1 什么是数据类型及数据类型分类 2.2 标准数据类型: 2.2.1 数字 2.2.1.1 整型: 2.2.1.2 长整型long: 2.2.1.3 布尔bool ...
- 第三篇:python基础之编码问题
python基础之编码问题 python基础之编码问题 本节内容 字符串编码问题由来 字符串编码解决方案 1.字符串编码问题由来 由于字符串编码是从ascii--->unicode---&g ...
随机推荐
- linux tar命令的使用
tar格式,会打包成一个文件,可以对多个目录,或者多个文件进行打包 tar命令只是打包,不会压缩,打包前后大小是一样的 tar命令 -c //打包 -x //解压 -f //指定文件 ...
- Android在外部存储空间中读写文件
一.外部存储的目录 1.2.3之前是/sdcard 2.4.3之前是在/mnt/sdcard 3.4.3之后是在/storage/sdcard 二.读写读写外部存储 1.直接写路径 File file ...
- compare
icompareble 默认的比较器 list.sort() compareto icompare Keyvaluepair<k,p>Where k:new()
- 每天学习一点点--word-break和word-wrap用法和区别
有时候一个又臭又长的单词出现在一个并不宽到足以容纳这个单词时会出现内容溢出容器这种情况: <!DOCTYPE html> <html lang="en"> ...
- java java.lang.NoClassDefFoundError 的解决办法
以简单而经典的 "HelloWorld.java" 为例 不含包层次的HelloWorld.Java public class HelloWorld { public static ...
- php基础排序算法 冒泡排序 选择排序 插入排序 归并排序 快速排序
<?php$arr=array(12,25,56,1,75,13,58,99,22);//冒泡排序function sortnum($arr){ $num=count($arr); ...
- JavaScript面试题
一道常被人轻视的前端JS面试题 标签(空格分隔): JavaScript function Foo() { getName = function () { alert (1); }; return t ...
- Teleport Ultra 下载网页修复
1 三个基本正则替换 tppabs="h[^"]*"/\*tpa=h[^"]*/javascript:if\(confirm\('h[^"]*[Ult ...
- 将对象序列化,反序列化到XML
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...
- ansible代码分析第一篇--主文件—ansible分析
2016年2月23日,学习,分析ansible代码 ansible是一种运维中使用的批量部署的工具,它本身是一种框架,具体的部署和架构分析,下面这篇文章讲的不错. http://os.51cto.co ...