着色器(shader)是运行在GPU上小程序。

也是一种非常独立的程序,它们之间不能相互通信;它们之间唯一的沟通只有通过输入和输出。

着色器的开头总是要声明版本,接着是输入和输出变量,uniform和main函数。

每个输入变量也叫顶点属性(Vertex Attribute)。能声明的顶点属性是有上限的,OpenGL确保至少有16个包含4分量的顶点属性可用。

可以通过以下查询:

GLint nrAttributes;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&nrAttributes);
cout<< "Maximum nr of vertex attributes supported: "<< nrAttributes <<endl;

数据类型:

GLSL有数据类型可以来指定变量的种类。

GLSL中包含C等其他语言大部分的默认基础数据类型:

int、float、double、uint、bool;

GLSL也有两种容器类型:

向量(Vector) 和 矩阵(Matrix);

向量

向量是一个可以包含1、2、3或者4个分量的容器:

vecn    包含N个float分量的默认向量

bvecn    包含n个bool分量的向量

ivecn     包含n个int分量的向量

uvecn    包含n个unsigned int分量的向量

dvecn    包含n个double分量的向量

一个向量的分量可以通过vec.x这种方式获取。vec.x、vec.y、vec.z、vec.w来获取第1、2、3、4个分量。

对颜色使用rgba 对纹理使用stqp

GLSL定义了in或out关键字专门来实现数据交流和传递。

每个着色器使用这两个关键字设定输入和输出,只要一个输出变量与下一个着色器阶段的输入匹配,

它就会传递下去。但顶点和片段着色器中会有点不同。

顶点着色器应该接收的是一种特殊形式的输入,否则就会效率低下。

顶点着色器的输入特殊在,它从顶点数据中直接接收输入。

为了定义顶点数据该如何管理,我们使用location这一元数据指定输入变量,这样我们才可以在cpu上配置顶点属性。

也可以忽略layout (location=0)标识符,通过在OpenGL代码中使用glGetAttribLocation查询属性位置值(Location)。//没太懂!

另外一个例外是片段着色器,它需要一个vec4颜色输出变量,如果在片段着色器没有定义输出颜色,OpenGL会把你的物体渲染为黑色(或)白色。

一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一个输出,在接收方着色器中声明一个类似的输入。

当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起,它们之间就能发送数据了(这是在链接程序对象时完成的)。

Uniform

Uniform是一种从cpu中的应用想GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。

首先,uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且可以被着色器程序的任意阶段访问。

第二,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。

如果声明了一个uniform却在GLSL代码中没用过,编译器会静默移除这个变量,导致最后编译出的版本并不会包含它。

下面通过uniform设置三角形的颜色:

#version  core
out vec4 color; uniform vec4 ourColor; void main()
{
color = ourColor;
}

首先,需要找到这个着色器中uniform属性的索引/位置值。

当我们得到uniform的索引/位置值后,我们就可以更新它的值了。

我们用glGetUniformLocation 查询uniform ourColor的位置值。我们查询函数提供着色器程序和uniform的名字。

如果glGetUniformLocation 返回-1 就代表没有找到这个位置值。

最后我们可以通过glUniform4f函数设置uniform值。

注意,查询uniform地址不要求你之前使用过着色器程序,但是更新一个uniform 之前你必须先使用程序(调用glUseProgram),因为它是在当前激活的着色器程序中设置uniform的。

OpenGL不支持类型重载,在函数参数不同的时候就要为其定义新的函数;

glUniform是一个典型例子。这个函数有一个特定的后缀,标识设定uniform的类型。

可能的后缀有:

f      函数需要一个float作为它的值

i      函数需要一个int作为它的值

ui    函数需要一个unsigned int作为它的值

3f    函数需要3个float作为它的值

fv    函数需要一个float向量/数组作为它的值

如果打算让颜色慢慢变化,就需要在游戏循环每一次迭代中更新这个uniform。

更多属性

我们同样打算把颜色数据加进顶点数据中。我们将把颜色数据添加为3个float值至vertices数组。

将把三角形的三个角分别指定为红、绿、蓝:

GLfloat vertices[] = {
//位置 //颜色
0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, //右下
-0.5f,-0.5f,0.0f, 0.0f,1.0f,0.0f, //左下
0.0f,0.5f,0.0f, 0.0f,0.0f,1.0f //顶部
};

由于更多数据要发送到顶点着色器,有必要调整一下顶点着色器,使它能够接收颜色值作为一个顶点属性输入。

需要注意的是我们用layout标识符来把color 属性的位置值设置为1:

#version  core
layout (location =) in vec3 position; //位置变量的属性位置值为0
layout (location =) in vec3 color; //颜色变量的属性位置值为1 out vec3 ourColor; void main()
{
gl_Position = vec4(position,1.0);
ourColor = color;
}

修改片段着色器:

#version  core
in vec3 ourColor;
out vec4 color; void main()
{
color = vec4(ourColor,1.0f);
}

VBO内存中的数据。

------------------------

知道了现在使用的布局,我们就可以使用glVertexAttribPointer 函数更新顶点格式:

//位置属性
glVertexAttribPointer(,,GL_FLOAT,GL_FALSE,*sizeof(GLfloat),(GLvoid*));
glEnableVertexAttribArray(); //颜色属性
glVertexAttribPointer(,,GL_FLOAT,GL_FALSE,*sizeof(GLfloat),(GLvoid*)(*sizeof(GLfloat)));
glEnableVertexAttribArray();

由于我们现在有了两个顶点属性,我们不得不重新计算步长值。

为获得数据队列中下一个属性值(比如位置向量的下个x分量)我们必须向右移动6个float ,其中3个是位置值,另外3个颜色值。

同样必须指定一个偏移量。对于每个顶点来说,位置顶点属性在前,所以它的偏移量是0。

颜色属性紧随位置数据之后,所以偏移量就是3*sizeof(GLfloat)。

片段插值(Fragment Interpolation)

当渲染一个三角形时,光栅化(Rasterization)阶段通常会造成比原来指定顶点更多的片段。

光栅会根据每个片段在三角形形状上所处相对位置决定这些片段的位置。

OpenGL 着色器 03的更多相关文章

  1. OpenGL着色器入门简介

    说明:本文翻译自LearnOpengl经典教程,OpenGL着色器基础介绍的比较通俗易懂,特总结分享一下! 为什么要使用着色器?我们知道,OpenGL一般使用经典的固定渲染管线来渲染对象,但是随着Op ...

  2. WebGL中的OpenGL着色器语言

    在webgl中,调用了OpenGL-ES-2.0的API,而在OpenGL-ES专为嵌入式设备设计,其和其它设备一样,都是使用GLSL(GL Shading Language)来编写片段程序并执行于G ...

  3. 【OPENGL】第三篇 着色器基础(二)

    在这一小节,主要学习GLSL的基本数据类型以及控制结构.GLSL具备了C++和Java的很多特性,我们会先了解所有着色阶段共有的特性,再了解各个着色器的专属特性. 1.着色器的基本结构 一个着色器程序 ...

  4. OpenGL官方教程——着色器语言概述

    OpenGL官方教程——着色器语言概述 OpenGL官方教程——着色器语言概述 可编程图形硬件管线(流水线) 可编程顶点处理器 可编程几何处理器 可编程片元处理器 语言 可编程图形硬件管线(流水线) ...

  5. OpenGL入门1.3:着色器 GLSL

    前言 经过之前一段时间的学习(渲染管线简介)我们已经知道了着色器(Shader)是运行在GPU上的程序,这些小程序为图形渲染管线的某个特定部分而运行,着色器只是一种把输入转化为输出的程序,着色器也是一 ...

  6. [GEiv]第七章:着色器 高效GPU渲染方案

    第七章:着色器 高效GPU渲染方案 本章介绍着色器的基本知识以及Geiv下对其提供的支持接口.并以"渐变高斯模糊"为线索进行实例的演示解说. [背景信息] [计算机中央处理器的局限 ...

  7. GLSL 着色器程序

    除了使用Cg/HSL 着色器程序以外, OpenGL 着色器语言(GLSL)着色器可以直接书写shader. 然而,使用原生的GLSL只推荐作为测试使用,或者你清晰的知道你的目标平台是 Mac OS ...

  8. OpenGL管线(用经典管线代说着色器内部)

    图形管线(graphics pipeline)向来以复杂为特点,这归结为图形任务的复杂性和挑战性.OpenGL作为图形硬件标准,是最通用的图形管线版本.本文用自顶向下的思路来简单总结OpenGL图形管 ...

  9. 【OPENGL】第三篇 着色器基础(一)

    在这一章,我们会学习什么是着色器(Shader),什么是着色器语言(OpenGL Shading Language-GLSL),以及着色器怎么和OpenGL程序交互. 首先我们先来看看什么叫着色器. ...

随机推荐

  1. jmeter ant 运行 提示Error occurred during initialization of VM

    运行ant提示错误 网上找到的方法 将set HEAP= -Xms512m -Xmx1024m 改成set HEAP= -Xms512m -Xmx512m 保存后运行成功

  2. Python之单例模式总结

    一.单例模式 a.单例模式分为四种:文件,类,基于__new__方法实现单例模式,基于metaclass方式实现 b.类实现如下: class Sigletion(objects): import t ...

  3. python3与anaconda2共存

    我是先下载了python3,后来因为需要2为了省事就去下载了anaconda2,但发现这里有个很严重的共存问题. 找了一下网上的各种共存问题,发现网上的基本上都是基于一个anaconda然后通过虚拟环 ...

  4. 通过YUM命令查找对应命令是通过何种软件提供的

    # yum whatprovides [命令]

  5. js命令模式

    命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 从命令模式的结构图可以看出,它涉及到五个角色,它们分别是 ...

  6. linux---mysql忘记密码

    二.忘记原来的myql的root的密码: 首先,你必须要有操作系统的root权限了.要是连系统的root权限都没有的话,先考虑root系统再走下面的步骤.类似于安全模式登录系统,有人建议说是pkill ...

  7. 【疯了Labview】(一)仿JKI的RCF 挂件

    最近在疯狂的学习C#中,学习的最好的一个途径便是论坛,发帖,看帖和被骂,新手往往在这个过程中慢慢长大一直想做个类似JKI RCF挂件的东西,目前实现了,想想其实思路也不是很难, RCF是JKI做的通过 ...

  8. 安装及使用webpack

    Webpack 什么是webpack:现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包.为了简化开发的复杂度,前端社区涌现出了很多好的实践方法:1.模 ...

  9. 【WCF】利用WCF实现上传下载文件服务

    引言     前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载.出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务. 服务端 1.首先新建一个名 ...

  10. 2018.7.7 MBA -从专业到管理(1)—— 技术人才与的管理人才比较

    目录 1从基层员工到基层管理 专业,专长,专能,受赏识,团结同事 2从 基层管理到中层管理 重点:一专多能, 打造团队, 获取资源,对外沟通 3从中层到高层 重点:战略规划, 选拔人才 , 市场扩展