A Simple OpenGL Shader Example II
A Simple OpenGL Shader Example II
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的更多相关文章
- A Simple OpenGL Shader Example
A Simple OpenGL Shader Example eryar@163.com Abstract. OpenGL Shading Language, the high-level progr ...
- OpenGL Shader in OpenCASCADE
OpenGL Shader in OpenCASCADE eryar@163.com Abstract. As implementation of one of the strategic steps ...
- OpenGL Shader源码分享
Opengl shader程序,旗帜混合纹理加载,通过N张图片,能够组合出数百个:http://www.eyesourcecode.com/thread-39015-1-1.html 用GLSL做了一 ...
- OpenGL复习要点II
[OpenGL复习要点II] 1.视图变换必须出现在模型变换之前. 2.glMatrixMode()参数有三个,GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE. 3.变换顺 ...
- 【玩转cocos2d-x之四十】怎样在Cocos2d-x 3.0中使用opengl shader?
有小伙伴提出了这个问题.事实上GLProgramCocos2d-x引擎自带了.全然能够直接拿来用. 先上图吧. 使用opengl前后的对照: watermark/2/text/aHR0cDovL2Js ...
- 「游戏引擎 浅入浅出」4.1 Unity Shader和OpenGL Shader
「游戏引擎 浅入浅出」从零编写游戏引擎教程,是一本开源电子书,PDF/随书代码/资源下载: https://github.com/ThisisGame/cpp-game-engine-book 4.1 ...
- OpenGL shader 中关于顶点坐标值的思考
今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...
- 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高)
这段时间一直在搞视频格式的转换问题,终于最近将一个图片的YUV格式转RGB格式转换成功了.下面就来介绍一下: 由于我的工程是在vs2008中的,其中包含一些相关头文件和库,所以下面只是列出部分核心代码 ...
- OpenGL shader渲染贴图
simple.vert #version core layout (location = ) in vec3 position; layout (location = ) in vec3 color; ...
随机推荐
- The World's Only Advanced Operating System
The World's Only Advanced Operating System
- Qt下的udp编程
项目需要一个基于udp的客户端, 看着Qt是有个QUdpSocket的类的, 但自带的例子和类的说明都没咋说明白: 怎么用一个QUdpSocket既当发送端, 又当接收端? 谷歌一顿后, 发现很多老内 ...
- 我对 Java 标识符的分类命名方法
我对 Java 的各种标识符有一套固定的分类方法,以下分享一下我的命名方法以及进行一些说明. # 前缀: 方法 方法:f_doSomeThing().分类词是 f,采自 [f]unction 方法,也 ...
- Meta标签介绍
Meta标签写法与作用 meta标签是在HTML网页源代码中一个重要的html标签.meta位于head区的辅助性标签,提供用户不可用的信息. META标签用来描述一个HTML网页文档的属性,例 ...
- (转)python requests的安装与简单运用
requests是python的一个HTTP客户端库,跟urllib,urllib2类似,那为什么要用requests而不用urllib2呢?官方文档中是这样说明的: python的标准库urllib ...
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- substring()
OPENERURL.substring(OPENERURL.indexOf('/sear'));//从/sear开始截取(包括/sear): OPENERURL.substring(OPENERURL ...
- 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRemoteDeviceFind
这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRemoteDeviceFind的使用如下: ...
- 【codevs】刷题记录→_→(推荐看!)
注:本文是我原先在csdn内写的一篇博文,现转到这里,两篇博文尽量同时更新. //#include<iostream->shuati> //define 为什么刷 学长☞hzwer ...
- java开发中JDBC连接数据库代码和步骤
JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...