A Simple OpenGL Shader Example II

eryar@163.com

Abstract. The OpenGL Shading Language syntax comes from the C family of programming languages. Tokes, identifiers, semicolons, nesting with curly braces, control-flow, and many key words look like C. GLSL provides three qualifiers which form the interfaces of the shaders to their outside world.

Key Words. OpenGL, GLSL, Qualifiers,

1. Introduction

GLSL的特性与C/C++非常类似,包括它的数据类型。GLSL有三种基本数据类型:float, int和bool,及由这些数据类型组成的数组和结构体。需要注意的是GLSL并不支持指针。

GLSL 中有4个限定符(Qualifier)可供使用,它们限定了被标记的变量不能被更改的“范围”。及通过这几个限定符可以与OpenGL的程序来通信,即为 OpenGL程序提供了一个将数据传递给Shader的界面(Interface to a Shader)。

OpenCASCADE中使用GLSL实现了Ray Tracing效果,刚开始使用第三方库OpenCL来使用GPU加速,最新版本统一使用GLSL。

Figure 1.1 OpenGL Training

在《OpenGL高级编程技术培训教材》中,GLSL也是一个重要内容。虽然当时听得云里雾里,还是要感谢公司提供这样的培训机会。

2.GLSL Data Types

GLSL内置了许多数据类型,使图形操作的表达式计算更方便。布尔类型、整型、矩阵、向量及结构、数组等都包括在内。

Scalars

float

Declares a single floating-point number.

int

Declares a single integer number.

bool

Declares a single Boolean number.

这三种是GLSL的基本类型。

Vectors

vec2

Vector of two floating-point numbers

vec3

Vector of three floating-point numbers

vec4

Vector of four floating-point numbers

ivec2

Vector of two integers

ivec3

Vector of three integers

ivec4

Vector of four integers

bvec2

Vector of two booleans

bvc3

Vector of three booleans

bvc4

Vector of four booleans

向量非常有用,可以用来存储和操作颜色、位置、纹理坐标等等。GLSL内置的很多变量及函数中就大量使用了向量。

Matrices

mat2

2x2 matrix of floating-point numbers

mat3

3x3 matrix of floating-point numbers

mat4

4x4 matrix of floating-point numbers

矩阵主要用来实现线性变换。

Samplers

sampler1D

Accesses a one-dimensional texture

sampler2D

Accesses a two-dimensional texture

sampler3D

Accesses a three-dimensional texture

samplerCube

Accesses a cube-map texture

sampler1DShadow

Accesses a one-dimensional depth texture with comparison

sampler2DShadow

Accesses a two-dimensional depth texture with comparison

3.Qualifiers

GLSL有4个限定符可供使用,它们限定了被标记的变量不能被更改的范围:

Qualifiers

attribute

For frequently changing information, from the application to a vertex shader

uniform

For infrequently changing information, from the application to either a vertex shader or a fragment shader

varying

For interpolated information passed from a vertex shader to a fragment shader

const

For declaring nonwritable, compile-time constant variables as in C

const限定符和C/C++里的相同,表示限定的变量在编译时不可被修改,即它标记了一个常量。const限定符是4个限定符中被标记变量不可被更改的范围最大的。其余3个限定符是GLSL特有的,所以它们都用在着色器内部声明变量。

attribute限定符标记的是一种全局变量,该变量被用作从OpenGL应用程序向顶点着色器中传递参数,因此该限定符仅用于顶点着色器。

uniform限定符也标也一种全局变量,该变量对于一个图元来说是不可改变的。同attribute限定符一样,uniform可以从OpenGL应用程序中接收传递过来的数据。uniform限定符可以用于顶点着色器和像素着色器。

最后GLSL还提供了从顶点着色器向片段着色器传递数据的方法,即使用varying限定符。

4.Code Example

在《A Simple OpenGL Shader Example
中已经成功实现了一个带Shader的OpenGL程序。事实上这是两个相对独立的Shader,它们只能使用OpenGL内置的变量从外部OpenGL
程序中获取一些数据。比如当前顶点坐标、当前像素颜色等。这些Shader还没有自定义的变量,以便从OpenGL程序中传递数据。通常程序的设计者需要
在OpenGL程序中更好地控制shader的行为,这就需要从OpenGL程序向shader传递数据。

如上述的4个限定符,可以用来声明变量帮助shader从外部获取数据。其中uniform变量可以用来从OpenGL程序中给vertex shader或fragment shader传递数据,最很常用的一个限定符变量。将《A Simple OpenGL Shader Example》中的程序稍做修改,使得片段shader可以收到一个来自OpenGL程序里面的数据。

实现的主要代码在这两个函数中:

void ShaderWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); mAngle += 0.1;
glRotatef(mAngle, 0.0, 1.0, 1.0); // update uniform variable value
mShaderProgram->setUniformValue(mTimeId, mAngle); glutSolidTeapot(1.0);
//glutWireTeapot(1.0);
}
void ShaderWidget::setShader()
{
if (!isValid())
{
return;
} const QGLContext* aGlContext = context(); mShaderProgram = new QGLShaderProgram(aGlContext); //mShaderProgram->addShaderFromSourceFile(QGLShader::Vertex, "vertex.vs");
mShaderProgram->addShaderFromSourceFile(QGLShader::Fragment, "uniform.fs"); mShaderProgram->link();
mShaderProgram->bind();
QString aLog = mShaderProgram->log(); // save the location of the uniform variable name within the shader program.
mTimeId = mShaderProgram->uniformLocation("v_time");
}

首 先通过QShaderProgram的函数uniformLocation()给GLSL中的变量用一个整数标记,对应在OpenGL中的函数是 GLint glGetUniformLocation(GLuint program, const char* name);再通过函数setUniformValue()来更新GLSL中变量的值,对应OpenGL中的函数为:glUniform{1234} (if,ui}。最后只用了一个片段着色器,代码如下所示:

// time(passed in from the application)
uniform float v_time; void main()
{
float fr = 0.9 * sin(0.0 + v_time*0.05) + 1.0;
float fg = 0.9 * cos(0.33 + v_time*0.05) + 1.0;
float fb = 0.9 * sin(0.67 + v_time*0.05) + 1.0; gl_FragColor = vec4(fr/2.0, fg/2.0, fb/2.0, 1.0);
}

运行程序,当程序视图重绘时就会改变茶壶的颜色,如下图所示:

Figure 4.1 Test uniform variable in GLSL

当将uniform.fs中的v_time改名后,就会发现视图一片漆黑,说明shader已经起作用了。

5.Conclusion

综上所述,GLSL中通过限定符Qualifiers来实现OpenGL程序与GLSL的数据传递。其中uniform变量可以用来从OpenGL程序向片段着色器和顶点传递数据,是很常用的一种方式。

本文在Qt中测试了uniform变量效果,可以发现Qt对OpenGL的面向对象封装还是很方便使用,也很容易找到与之对应的OpenGL函数。通过学习使用Qt中的OpenGL来方便学习理解OpenGL相关知识点。

6. References

1. san. Shader support in OCCT6.7.0. http://dev.opencascade.org/index.php?q=node/902

2. Qt Assistant.

PDF version and Source code: A Simple OpenGL Shader Example II

A Simple OpenGL Shader Example II的更多相关文章

  1. A Simple OpenGL Shader Example

    A Simple OpenGL Shader Example eryar@163.com Abstract. OpenGL Shading Language, the high-level progr ...

  2. OpenGL Shader in OpenCASCADE

    OpenGL Shader in OpenCASCADE eryar@163.com Abstract. As implementation of one of the strategic steps ...

  3. OpenGL Shader源码分享

    Opengl shader程序,旗帜混合纹理加载,通过N张图片,能够组合出数百个:http://www.eyesourcecode.com/thread-39015-1-1.html 用GLSL做了一 ...

  4. OpenGL复习要点II

    [OpenGL复习要点II] 1.视图变换必须出现在模型变换之前. 2.glMatrixMode()参数有三个,GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE. 3.变换顺 ...

  5. 【玩转cocos2d-x之四十】怎样在Cocos2d-x 3.0中使用opengl shader?

    有小伙伴提出了这个问题.事实上GLProgramCocos2d-x引擎自带了.全然能够直接拿来用. 先上图吧. 使用opengl前后的对照: watermark/2/text/aHR0cDovL2Js ...

  6. 「游戏引擎 浅入浅出」4.1 Unity Shader和OpenGL Shader

    「游戏引擎 浅入浅出」从零编写游戏引擎教程,是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book 4.1 ...

  7. OpenGL shader 中关于顶点坐标值的思考

    今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...

  8. 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高)

    这段时间一直在搞视频格式的转换问题,终于最近将一个图片的YUV格式转RGB格式转换成功了.下面就来介绍一下: 由于我的工程是在vs2008中的,其中包含一些相关头文件和库,所以下面只是列出部分核心代码 ...

  9. OpenGL shader渲染贴图

    simple.vert #version core layout (location = ) in vec3 position; layout (location = ) in vec3 color; ...

随机推荐

  1. Linux下不同机器之间拷贝文件

    在Linux系统下,不同机器上实现文件拷贝 一.将本地文件拷贝到远程机器: scp /home/administrator/news.txt root@192.168.6.129:/etc/squid ...

  2. BOM

    一.window对象1.全局作用域全局变量不能通过delete操作删除,而直接在window对象上定义的属性可以 var a = 1; delete a; console.log(a); window ...

  3. LabVIEW 吸星大法 - 看见的好东西都是我的(中篇)

    前言 写了多年的LabVIEW程序,你是否面临这样的问题 总是在做一些重复的工作,感觉很没有意思: 总在不停的写代码,做类似的控件,实现相同的功能,丝毫没有成就感: 总在天加班,没有时间去提高自己; ...

  4. angular input标签只能单向传递数据的问题

    angularjs input标签只能单向传递数据的问题 <ion-view title = "{{roomName}}" style = "height:90%; ...

  5. java并发编程(十七)内存操作总结

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17377197 主内存与工作内存 Java内存模型的主要目标是定义程序中各个变量的访问规则, ...

  6. opengles 矩阵计算

    总的变换矩阵: matrix = projection * view * model 模型矩阵: modelMatrix=translateMatrix * scaleMatrix * rotateM ...

  7. 华为oj 购物单

    这两天断断续续敲完这个(放假的时候比较懒),一次成功有点小激动(●'◡'●)  不过貌似从第一次打开开始计时..... 这道题目很像01背包,我将附件与它们的主件绑定(就是link起来)然后套用动态规 ...

  8. java的英文词频算法

    java实现的英文词频算法,通常是采用单词树来实现的.使用java实现词频统计,为了统计词汇出现频率,最简单的做法是再建立一个map,其中,key是单词,value代表次数.将文章从头读到尾,读到一个 ...

  9. java中类的加载情况

    当一个类存在继承且与其他类有关联情况时,类中各模块加载顺序如下: 1.首先找到public类,判断该类是否继承其他类,如果没有继承其他类(Object类除外),则加载该类:否则转去加载该类的超类,超类 ...

  10. SQLSERVER中的ALL、PERCENT、CUBE关键字、ROLLUP关键字和GROUPING函数

    SQLSERVER中的ALL.PERCENT.CUBE关键字.ROLLUP关键字和GROUPING函数 先来创建一个测试表 USE [tempdb] GO )) GO INSERT INTO [#te ...