GLSL

Xtreme3D

Lesson 19
GLSL basics

Level: experienced
Version of the Xtreme3D: 3.0.x
Author: Gecko

GLSL (OpenGL Shading Language) is a high-level language description of shaders. With it you can program the graphics pipeline - in other words, to manage the rendering of objects on the ��������� and pixel level. For the processing of peaks is responsible ��������� GLSL program, for processing pixels - �����������.
Work with the GLSL implies knowledge of the principles of the dither and graphics OpenGL pipeline, as well as linear algebra. Since the Xtreme3D does not require such knowledge, the use of GLSL can be a very difficult task for a novice, therefore, it is recommended to pre-read books or manuals on the topic. A very useful will be acquaintance with the principles of the work in OpenGL, as well as at least a basic knowledge of C/C++.

The types of data GLSL



GLSL is strictly �������������� language - any variable, it has a certain type. The language supports the following basic types:

Bool - boolean value
Int - integer
Uint - ����������� integer
Float - a floating point number single precision
Double - a floating point number double-precision
Bvec2, bvec3, bvec4 is a vector of boolean values dimension (2, 3, and 4)
Ivec2, ivec3, ivec4 is a vector of integers
Uvec2, uvec3, uvec4 is a vector of Unsigned integers
The vec2, the vec3, the vec4 is a vector of numbers with a floating point
Dvecn2, dvecn3, dvecn4 is a vector of numbers with a floating point double-precision
Mat2, mat3, mat4 is a matrix of 2x2, 3x3, 4x4
Sampler2D - the texture of the
Sampler2DCube - cubic texture
Sampler2DShadow - Shadow Texture
Void - keyword that indicates the absence of the type (for functions without the returned results).

Vertex Shader


��������� accepts the coordinates of the vertices and their attributes (such as normal the moment and) and, as a rule, puts them out of the object space into the amputation in the world or in species space.

- The Object space (object space) is a local space of object. The center of the coordinate system is the center of the object - top models are defined relative to the center.
- The world space (world space) is another name for the absolute space. The center of the coordinate system, it is the point (0, 0, 0). The total transformation of the object (Transferring, rotation and scaling) puts the tops from the local to the global space. This transformation is typically stored and transmitted in the shader in the form of a matrix 4x4 - the so-called matrix model (model matrix).
- Species space (eye space - a space in which the Center coordinate system is the position of the camera. Translation of the peaks of the world in species space is controlled by the reverse conversion Matrix - the so-called species matrix (view matrix). In OpenGL, as a rule, the model matrix and generic are combined in one ��������-������� (modelview matrix).
- Space amputation (clip space - a space in which the vertices are translated a matrix projection (projection matrix).
It should be noted that the tops of the GLSL is stored in the so-called homogeneous coordinates (homogeneous coordinates) - that is, have an additional fourth coordinate W. Such coordinates, you can express the infinitely distant point where W is equal to zero. Conventional terms have the W is equal to 1.
Peaks in the space of amputation is the main result of the work of the vertex shader. The simplest vertex shader that performs only translation of vertices of the object space into the amputation, is as follows:

Void main()
{
  Gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Gl_Vertex - input the coordinates of vertices
Gl_Position - The output coordinates of the vertices
Gl_ModelViewProjectionMatrix - integrated matrix of 4x4, the combination of The ��������-species and projection matrices of OpenGL.
For this procedure, by the way, in the GLSL has a built-in function to ftransform:

Gl_Position = ftransform();

Vertex Shader are also available from other attributes of the peak - normal, color and texture coordinates: gl_Normal, gl_Color, gl_MultiTexCoordN (where N is a number from 0 to 7). Usually these attributes of the interpolated between the three vertices of triangle, and then come in the ����������� shader. To transfer any value to the interpolation, used in varying intermediate variables. For example, here is the shader communicating to interpolate normal:

Varying the vec3 normal;

Void main()
{
  Normal = gl_NormalMatrix * gl_Normal;
  Gl_Position = ftransform();
}

Please note that we translate normal vertices of the object space for species with a special built-in a matrix of 3x3 gl_NormalMatrix. This is necessary so that the best way to count lights in pixel ������� - this is done in the species space: the fact that the camera is at (0,0,0), greatly facilitates the calculations related to the �������� component of the light.
With the transfer of texture coordinates of the shader will look like this:

Varying the vec3 normal;

Void main()
{
  Normal = gl_NormalMatrix * gl_Normal;
  Gl_TexCoord[0] = gl_MultiTexCoord0;
  Gl_Position = ftransform();
}

Gl_TexCoord - this is a built in varying-variable, array, through which you can transfer any data, not only the texture coordinates.

����������� Shader


����������� accepts the interpolated varying variables (as well as the various options for the status of the OpenGL) and displays as a result of the color pixel. It is performed for each visible on the screen pixels of the object. Please note that checking visibility (Z-test) for pixel graphics is carried out prior to the completed ����������� program - if a pixel is discarded as an invisible, the program is not performed.
The simplest ����������� shader, the painter's object a solid color, looks like this:

Void main()
{
  Gl_FragColor = the vec4(1.0, 0.0, 0.0, 1.0);
}

Gl_FragColor - output color pixel.
In this case, the vec4(1.0, 0.0, 0.0, 1.0) refers to the red color with transparency 1.0 (Full Opacity).

The use of shaders in the Xtreme3D


Create GLSL shaders and connect them to the content is very simple:

Vp = TextRead('my_vertex shader.glsl');
Fp = TextRead('my_fragment_shader.glsl');
Shader = GLSLShaderCreate(vp, fp);
MaterialSetShader('myMaterial', shader);

Lighting on the GLSL


To realize the simplest lighting according to the formula of Lambert, we need the coordinates of the Point surface normal at this point, as well as the coordinates of the source of light. Thus, we need at least two varying variables - normal and interpolated vertex coordinates.
Vertex Shader:

Varying the vec3 normal;
Varying the vec3 position;

Void main()
{
  Normal = gl_NormalMatrix * gl_Normal;
  Position = (gl_ModelViewMatrix * gl_Vertex).xyz;
  Gl_Position = ftransform();
}

Gl_ModelViewMatrix is a built-in matrix of 4x4, The �������� generic matrix of OpenGL. It converts the coordinates of the object space for species in which we will calculate the lighting. As the result of this translation - a homogeneous vector of the vec4, we ����������� coordinate W and charge only the vector of XYZ.
����������� shader:

Varying the vec3 normal;
Varying the vec3 position;

Void main()
{
  The vec3 N = normalize(normal);
  The vec3 L = normalize(gl_LightSource[0].position.xyz - position);
  Float diffuse = clamp(dot(N, L), 0.0, 1.0);
  The vec4 color = gl_FrontMaterial.diffuse * diffuse;
  Color.a = 1.0;
  Gl_FragColor = color;
}

Please note that transfer in the ���������� ������ singular vectors (such as normal) after the interpolation is necessary ����������� - the graphics card does not make it for you. For this in the GLSL is a function normalize.
Access to the coordinates of the source of light is controlled by the position attribute the embedded object of gl_LightSource (array of 8 elements, according to the number of light sources OpenGL). These coordinates in the ����������� ������� is automatically transferred to the species space, which is very convenient - you do not need to do it manually. But if you are, for one reason or another, you need to calculate the lighting in another space - for example, in the space of the tangent - do not forget to transform them. These coordinates as a peer: point source of light, as a rule, has the coordinate of the W is equal to 1, aiming to equal 0.
The operation dot(N, L) - this is the calculation of the light sensor according to the formula: Lambert illumination at the point is determined by the density of the light, and it is linearly dependent on the cosine of angle of incidence of the light. The cosine of the angle between two singular vectors is equal to the product of The ���������� (dot product).
Because the result of this operation - a scalar (float), for transfer to gl_FragColor ��������� need this value to any color. It is better to use Diffuse Color of material - gl_FrontMaterial.diffuse: thus, you can control the color of the object out of the shader, the function of the MaterialSetDiffuseColor.

The textures


In The ����������� ������� can read color from the textures - for this is the function of the texture2D:

The uniform sampler2D diffuseTexture;

Void main()
{
  The vec4 texColor = texture2D(diffuseTexture, gl_TexCoord[0].xy);
  Gl_FragColor = texColor;
}

The textures are declared as uniform objects - that is, the modifiable parameters are transferred to the shader core program. This may be not only the texture, but also any other data types.
The transfer of the textures in the shader is done as follows:

Param GLSLShaderCreateParameter(shader, 'diffuseTexture');
GLSLShaderSetParameterTexture(param, 'myMaterial', 0);


In the function of the GLSLShaderCreateParameter is transferred to the name of the uniform object. In the function of the GLSLShaderSetParameterTexture is transferred to the name of the material, from which you want to read the texture, as well as the texture unit, through which you want to transfer the texture. The OpenGL standard guarantees 8 available texture units (0-7) - the modern video cards they can be and more (up to 16 or even 32), but for the best compatibility it is recommended not to use more than 8. In one ������� cannot transmit two different textures through one and the same texture unit - that is, if you submit multiple textures in different uniform-parameters, use the different blocks.

About the versions of the GLSL


Xtreme3D is based on the OpenGL 1.x and some of the functions of the OpenGL 2.x, which are connected through the expansion of the ARB. Thus, the engine supports GLSL versions 1.1 and 1.2 - later versions of the language defined in the OpenGL specification 3.0.
The default is GLSL 1.1. To switch to 1.2, use the preprocessor directive (on the first line of the shader):

#Version 120

Version 1.2 is built-in support for transposition of matrices (the function transpose), ������������ matrices, as well as arrays.