class Eagle::Shader

Overview

A GPU program for custom visual effects: glows, color grading, waves, outlines and more.

The easiest way in is Shader.effect, where you write a single GLSL function that decides the color of each pixel, in the style of LÖVE. Eagle supplies the vertex shader and the uniforms u_time, u_resolution and u_texture.

wave = Shader.effect(<<-GLSL)
  vec4 effect(vec4 color, sampler2D tex, vec2 uv, vec2 screen) {
    uv.x += sin(uv.y * 20.0 + u_time * 3.0) * 0.01;
    return texture(tex, uv) * color;
  }
  GLSL

canvas = Canvas.new(320, 180)
g.with_shader(wave) { g.draw(canvas, Window.rect) }

tint = Shader.effect("uniform vec3 u_tint; vec4 effect(vec4 c, sampler2D t, vec2 uv, vec2 s) { return texture(t, uv) * c * vec4(u_tint, 1.0); }")
tint["u_tint"] = Vec3.new(1, 0.5, 0.5)

Write GLSL in the common subset of desktop GLSL 3.30 and WebGL2 GLSL ES 3.00, so the same shader runs natively and in the browser. Eagle adds the #version line. For full control, pass both stages to Shader.new or load a file with #vertex and #fragment sections.

Defined in:

eagle/graphics/shader.cr

Constant Summary

ATTRIBS_2D = ["a_position", "a_uv", "a_color"] of ::String

Vertex attribute names, in order, for Eagle's 2D batches.

ATTRIBS_3D = ["a_position", "a_normal", "a_uv", "a_color", "a_tangent"] of ::String

Vertex attribute names, in order, for 3D meshes.

DEFAULT_2D_FRAGMENT = "precision mediump float;\nuniform sampler2D u_texture;\nin vec2 v_uv;\nin vec4 v_color;\nout vec4 frag_color;\nvoid main() {\n frag_color = texture(u_texture, v_uv) * v_color;\n}"

Source of the built-in 2D fragment shader.

DEFAULT_2D_VERTEX = "in vec2 a_position;\nin vec2 a_uv;\nin vec4 a_color;\nuniform mat4 u_projection;\nout vec2 v_uv;\nout vec4 v_color;\nvoid main() {\n v_uv = a_uv;\n v_color = a_color;\n gl_Position = u_projection * vec4(a_position, 0.0, 1.0);\n}"

Source of the built-in 2D vertex shader. Pair your own fragment shader with it.

Constructors

Instance Method Summary

Constructor Detail

def self.default_2d : Shader #

The built-in shader Eagle uses for 2D drawing.


def self.effect(body : String) : Shader #

Builds a 2D pixel effect from a function with this signature:

vec4 effect(vec4 color, sampler2D tex, vec2 uv, vec2 screen_coords)

color is the draw color, tex the texture being drawn, uv its texture coordinate and screen_coords the pixel position. Declare your own uniforms above the function.


def self.load(path : String) : Shader #

Loads a shader file through the asset cache. See .parse for the file format.


def self.new(vertex_source : String, fragment_source : String, attribs : Array(String) = ATTRIBS_2D) #

Compiles and links a program from vertex and fragment sources. Raises ShaderError with the driver's log if either fails.


def self.parse(source : String, attribs : Array(String) = ATTRIBS_2D) : Shader #

Builds a shader from one source string with #vertex and #fragment section markers, or an #effect section for the .effect style.


Instance Method Detail

def []=(name : String, value : GPU::UniformValue) : Nil #

Sets a uniform. Accepts numbers, Vec2, Vec3, Vec4, Color and Mat4. Setting a uniform the shader doesn't use is a no-op.


def []=(name : String, value : Float64) #

Sets a float uniform from a Float64.


def []=(name : String, value : Int) #

Sets an int uniform.


def dispose : Nil #

Frees the GPU program.


def fragment_source : String #

The fragment shader source as compiled.


def has_uniform?(name : String) : Bool #

True when the shader declares and uses the uniform name.


def id : UInt32 #

The GPU program handle.


def location(name : String) : Int32 #

The uniform location for name, or -1 if the shader doesn't use it.


def set(name : String, value : GPU::UniformValue) : Nil #

Same as #[]=.


def set(name : String, value : Float64) #

Sets a float uniform from a Float64.


def set(name : String, value : Int) #

Sets an int uniform.


def set_texture(name : String, texture : Texture, unit : Int32 = 0) : Nil #

Binds texture to sampler unit unit and points the uniform name at it, for shaders that read more than one texture.


def use : Nil #

Makes this the active program, for custom rendering code.


def vertex_source : String #

The vertex shader source as compiled, without Eagle's version prelude.