A Simple OpenGL Shader Example II

A Simple OpenGL Shader Example II

eryar@163.comphp

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. html

Key Words. OpenGL, GLSL, Qualifiers, node

1. Introduction 編程

GLSL的特性與C/C++很是相似,包括它的數據類型。GLSL有三種基本數據類型:float, int和bool,及由這些數據類型組成的數組和結構體。須要注意的是GLSL並不支持指針。數組

GLSL 中有4個限定符(Qualifier)可供使用,它們限定了被標記的變量不能被更改的「範圍」。及經過這幾個限定符能夠與OpenGL的程序來通訊,即爲 OpenGL程序提供了一個將數據傳遞給Shader的界面(Interface to a Shader)。app

OpenCASCADE中使用GLSL實現了Ray Tracing效果,剛開始使用第三方庫OpenCL來使用GPU加速,最新版本統一使用GLSL。curl

wps_clip_image-26489

Figure 1.1 OpenGL Trainingide

在《OpenGL高級編程技術培訓教材》中,GLSL也是一個重要內容。雖然當時聽得雲裏霧裏,仍是要感謝公司提供這樣的培訓機會。函數

2.GLSL Data Types post

  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);
}
運行程序,當程序視圖重繪時就會改變茶壺的顏色,以下圖所示:

wps_clip_image-2645wps_clip_image-5687

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

相關文章
相關標籤/搜索