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. xml.etree.ElementTree对CDATA的输出

    xml.etree.ElmentTree不支持CDATA 的输出,但是支持Comment的输出.由于在项目中需要输出带有CDATA块的XML文本,参考Comment的做法,修改ElmentTree中的 ...

  2. swift-Array(数组)

    Swift 数组用于存储相同类型的值的顺序列表.Swift 要严格检查,不允许不同类型的值在同一个数组中 声明一个数组 var someArray = [SomeType]() var someArr ...

  3. mac和virtualbox虚拟机共享

    virtualbox安装增强工具 打开虚拟机,devices—shared folders—settings 打开窗口,选择“共享文件夹”,点击“带加号的文件夹图标”, 点击文件夹路径,选择其它,然后 ...

  4. UML类图关系--继承(泛化)、实现、关联、聚合、组合、依赖

    在UML类图中,常见的有以下几种关系:  泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregation),组合(Composi ...

  5. HTML5

    一.头部设置 <!--页面窗口自动调整到设备宽度,并禁止用户及缩放页面--> <meta name="viewport" content="width= ...

  6. AmazeUI 框架知识点-布局和样式整理

    1.Amaze UI 将所有元素的盒模型设置为 border-box.这下好了,妈妈再也不用担心没计算好 padding.border 而使布局破相了. 2.Amaze UI 将浏览器的基准字号设置为 ...

  7. JavaIO 将数据写入到文件中去

    package com.Practice_FileWriter; import java.io.FileWriter; import java.io.IOException; public class ...

  8. swiper的初步使用

    1.引入文件,顺序引入(此处基于jquery,且版本至少1.7以上) <link rel="stylesheet" href="path/to/swiper-3.4 ...

  9. Odoo 二次开发教程(四)-只读、唯一性验证和ORM方法介绍

    一.只读和唯一性验证 只读的设置有两种方法,一种是实在字段定义时设置为只读,第二种是在页面视图中进行设置. 接前例,我们将学生(tech.student)的名字name字段设置成只读. 方法一:字段定 ...

  10. ubuntu中source insight打不开,报错pagefault的解决方法

    在ubuntu中装了source insight用来看代码. 但用了一段时间后,有一天突然就发现打不开了,打开马上会弹出wine的错误,详细信息里面是什么PageFault 0x0000008之类的, ...