Skip to content
Dmitry Mamontov edited this page Jan 14, 2020 · 7 revisions

Shaders

Started from 1.7.1, Saddy will support shaders if OpenGL version larger than 3.0. To support them two new classes are introduced, sad::Shader, which stores shader programs and compiles them, and sad::ShaderFunction (sad::FontShaderFunction for fonts), which is used to set uniforms and change uniform variable in shaders. sad::ShaderFunction stores a reference to sad::Shader, thus allowing to use the same shader with several functions (an having several separate states). You also can share sad::ShaderFunction between nodes.

Please, note, that when creating shader you need to explicitly set it's renderer via sad::Shader::setRenderer, so it will work properly.

Relations between nodes and shaders.

You can attach shader via setShaderFunction(sad::ShaderFunction*) to any node . However, there is only one exception to it - sad::Label and it's descendants, in which you should pass sad::FontShaderFunction* to setShaderFunction. Also, it has additional setLineShaderFunction, which defines a shader for lines, used, when rendering underlined text and strikethrough.

Requirements for shaders.

Please, note that for the most shaders you need to have block like

layout (std140) uniform _SGLCameraInfo
{
    mat4 _sglModelViewMatrix;
    mat4 _sglProjectionMatrix;
}

This uniform parameter for UBO is used to pass modelview and projection matrices into shaders, so it can be used to transform coordinates of the points to correct coordinates.

The other used uniform parameter is

uniform vec4 _gl_Color;

Which will be used to pass color of sprite/font to a shader. Use it in your vertex or fragment shader to implement correct blending.

When rendering textured quads, or fonts, fragment shader should declare:

uniform sampler2D _defaultTexture;\n

to get access to bound texture.

For font and font lines shaders, the two following uniforms are defining center of label and angle of rotation for label to ensure, that they are properly rendered:

uniform vec2 center;
uniform float angle;

Default shader implementation for reference

Default shader for Sprite3D

When using valid texture:

Vertex program:

#version 300 es
layout(location = 0) in vec3 position;
layout (std140) uniform _SGLCameraInfo
{
	mat4 _sglModelViewMatrix;
	mat4 _sglProjectionMatrix;
};
in vec2 vertTexCoord;
out vec2 fragTexCoord;

void main()
{
	fragTexCoord = vertTexCoord;
	vec4 tmp = vec4(position.x, position.y, position.z, 1.0);
	gl_Position = (_sglProjectionMatrix * _sglModelViewMatrix) * tmp;
}

Fragment program:

#version 300 es
precision mediump float;
in vec2 fragTexCoord;
out vec4 color;
uniform sampler2D _defaultTexture;
uniform vec4 _gl_Color;
void main()
{
    color = texture(_defaultTexture, fragTexCoord) * _gl_Color;
}

Without texture:

Vertex program:

#version 300 es
layout(location = 0) in vec3 position;
layout (std140) uniform _SGLCameraInfo
{
    mat4 _sglModelViewMatrix;
    mat4 _sglProjectionMatrix;
};

void main()
{
    vec4 tmp = vec4(position.x, position.y, position.z, 1.0);
    gl_Position = (_sglProjectionMatrix *_sglModelViewMatrix)  * tmp;
}

Fragment program:

#version 300 es
precision mediump float;
uniform vec4 _gl_Color;
out vec4 color;
void main()
{
    color = _gl_Color;
}

Default shader for Sprite2D (or any other quad)

When using valid texture:

Vertex program:

#version 300 es
layout(location = 0) in vec2 position;
layout (std140) uniform _SGLCameraInfo
{
	mat4 _sglModelViewMatrix;
	mat4 _sglProjectionMatrix;
};
in vec2 vertTexCoord;
out vec2 fragTexCoord;

void main()
{
    fragTexCoord = vertTexCoord;
    vec4 tmp = vec4(position.x, position.y, 0.0, 1.0);
    gl_Position = (_sglProjectionMatrix * _sglModelViewMatrix) * tmp;
}

Fragment program:

#version 300 es
precision mediump float;
in vec2 fragTexCoord;
out vec4 color;
uniform sampler2D _defaultTexture;
uniform vec4 _gl_Color;
void main()
{
    color = texture(_defaultTexture, fragTexCoord) * _gl_Color;
}

Without texture:

Vertex program:

#version 300 es
layout(location = 0) in vec2 position;
layout (std140) uniform _SGLCameraInfo
{
	mat4 _sglModelViewMatrix;
	mat4 _sglProjectionMatrix;
};

void main()
{
    vec4 tmp = vec4(position.x, position.y, 0.0, 1.0);
    gl_Position = (_sglProjectionMatrix *_sglModelViewMatrix)  * tmp;
}

Fragment program:

#version 300 es\n
precision mediump float;
uniform vec4 _gl_Color;
out vec4 color;
void main()
{
    color = _gl_Color;
}

Shaders for labels and rendering text

Vertex program:

#version 300 es
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 vertTexCoord;
layout (std140) uniform _SGLCameraInfo
{
	mat4 _sglModelViewMatrix;
	mat4 _sglProjectionMatrix;
};
out vec2 fragTexCoord;
out vec4 fragColorData;
uniform vec2 center;
uniform float angle;
uniform vec4 _gl_Color;

void main()
{
    fragTexCoord = vertTexCoord;
    fragColorData = _gl_Color;
    float dx = position.x;
    float dy = position.y;
    float x  = center.x + (dx * cos(angle) - dy * sin(angle));
    float y  = center.y + (dx * sin(angle) + dy * cos(angle));
    vec4 tmp = vec4(x, y, 0.0, 1.0);
    gl_Position = (_sglProjectionMatrix * _sglModelViewMatrix) * tmp;
}

Fragment program:

#version 300 es
precision mediump float;
in vec2 fragTexCoord;
in vec4 fragColorData;
out vec4 color;
uniform sampler2D _defaultTexture;
void main()
{
    color = texture(_defaultTexture, fragTexCoord) * fragColorData;
}

Shaders for labels and rendering lines for underlined text and strikethrough

Vertex program:

#version 300 es
layout(location = 0) in vec2 position;
layout (std140) uniform _SGLCameraInfo
{
	mat4 _sglModelViewMatrix;
	mat4 _sglProjectionMatrix;
};
uniform vec2 center;
uniform float angle;

void main()
{
    float dx = position.x;
    float dy = position.y;
    float x  = center.x + (dx * cos(angle) - dy * sin(angle));
    float y  = center.y + (dx * sin(angle) + dy * cos(angle));
    vec4 tmp = vec4(x, y, 0.0, 1.0);
    gl_Position = (_sglProjectionMatrix * _sglModelViewMatrix) * tmp;
}

Fragment program:

#version 300 es
precision mediump float;
uniform vec4 _gl_Color;
out vec4 color;
void main()
{
    color = _gl_Color;
}