A Simple OpenGL Shader Example II
2015-07-21 23:02
423 查看
A Simple OpenGL Shader Example II
eryar@163.comAbstract. 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,
[b]1. Introduction [/b]
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也是一个重要内容。虽然当时听得云里雾里,还是要感谢公司提供这样的培训机会。
[b]2.GLSL Data Types [/b]
GLSL内置了许多数据类型,使图形操作的表达式计算更方便。布尔类型、整型、矩阵、向量及结构、数组等都包括在内。
Scalars | |
float | Declares a single floating-point number. |
int | Declares a single integer number. |
bool | Declares a single Boolean number. |
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 |
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 |
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 |
attribute限定符标记的是一种全局变量,该变量被用作从OpenGL应用程序向顶点着色器中传递参数,因此该限定符仅用于顶点着色器。
uniform限定符也标也一种全局变量,该变量对于一个图元来说是不可改变的。同attribute限定符一样,uniform可以从OpenGL应用程序中接收传递过来的数据。uniform限定符可以用于顶点着色器和像素着色器。
最后GLSL还提供了从顶点着色器向片段着色器传递数据的方法,即使用varying限定符。
[b]4.Code Example [/b]
在《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已经起作用了。
[b]5.Conclusion [/b]
综上所述,GLSL中通过限定符Qualifiers来实现OpenGL程序与GLSL的数据传递。其中uniform变量可以用来从OpenGL程序向片段着色器和顶点传递数据,是很常用的一种方式。
本文在Qt中测试了uniform变量效果,可以发现Qt对OpenGL的面向对象封装还是很方便使用,也很容易找到与之对应的OpenGL函数。通过学习使用Qt中的OpenGL来方便学习理解OpenGL相关知识点。
[b]6. References [/b]
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
相关文章推荐
- linux常用c函数 文件操作篇
- 软件架构百度百科
- Openssl base64命令
- linux常用c函数 常用数学函数篇
- linux静态库和动态库分析
- 阿里云服务器centos6安装vncserver
- linux下检测网卡与网线连通状态
- 解决Linux下AES解密失败
- ARM架构
- 计算100以内所有奇数的和以及所有偶数的和
- hadoop 常用命令
- 如何搭建轻量级架构-敏捷开发普及篇
- Linux的mmap文件内存映射机制
- linux 启动过程详解
- OpenGIS全面综述
- linux /etc/init.d/functions详解
- Linux kernel 分析之八:系统调用参数
- Linux kernel 分析之七:内核启动-链接脚本
- Linux kernel 分析之六:内核启动-开启页面映射
- 【树形dp】hdu 1011 Starship Troopers