build_shader(3)

πŸ“¦
version 0.7.1 Β· 2 versions
, in nixos 26.05

okay so bestie, this is the build_shader(3) page from the Arcan Lua API manual, and we’re about to make shader construction make sense. The NAME section says build_shader - using, which is lowkey iconic and also extremely β€œthe vibes will explain themselves” πŸŽ€βœ¨


🌸 NAME 🌸

build_shader - using. That’s the whole NAME section, bestie, no cap. It’s giving β€œmysterious but useful” πŸ’…

✨ SYNOPSIS ✨

uint:shader_id
build_shader( string/nil:vertex_program, string/nil:fragment_program,
string:label )

πŸ’– DESCRIPTION πŸ’–

okay so picture this: every video object can have a whole series of processing/rendering instructions attached to it 🫢 These are platform dependent, so you can check (GL_VERSION, SHADER_LANGUAGE) for identification strings to help support your choice β€” and the most commonly supported shader language is currently GLSL 120 ✨

This function is literally the glow-up from a higher level description (like a string) to some implementation defined internal interpretation that can later be referenced and connected to VIDs using the returned shader_id or the label πŸ’–

vertex_program describes the processing stage that determines the shape of the object to be drawn, and fragment_program describes the content that will be filled inside the shape. Both of these are allowed to be nil, and the engine will then use whatever platform specific default is defined πŸ‘‘

A shader can also have a set of limited user-defined variables, called uniforms (see shader_uniform for the details) along with a number of built in ones (see the notes below) 🧚

If the contents of the supplied vertex_program or fragment_program could not be interpreted, or there was insufficient shader slots left to create another one, the returned shader_id will be nil 😭 To associate a successfully built shader to a vid, see image_shader.

bestie, that nil return is your vibe check β€” if the shader didn’t build or there were no slots left, you get nil instead of a shader_id. periodt πŸ’…

🧚 NOTES 🧚

  1. For GLSL 120, reserved attributes are: vertex (vec4), normal (vec3), color (vec4), texcoord (vec2), texcoord1 (vec2), tangent (vec3), bitangent (vec3), joints (ivec4), weights (vec4)
  2. For GLSL 120, reserved uniforms are: modelview (mat4), projection (mat4), texturem (mat4), trans_move (float, 0.0 .. 1.0), trans_scale (float, 0.0 .. 1.0) trans_rotate (float, 0.0 .. 1.0), obj_input_sz (vec2, orig w/h) obj_output_sz (vec2, current w/h), obj_storage_sz (vec2, texture storage w/h), obj_opacity(float, 0.0 .. 1.0), obj_col (vec3, 0.0 .. 1.0), rtgt_id (uint), fract_timestamp (float), timestamp (int)

🌈 EXAMPLE 🌈

Here’s the EXAMPLE, and it’s kind of the main character: it looks up the shader format for SHADER_LANGUAGE, shuts down with shutdown(...) if there’s no match, then calls build_shader(sh.vertex, sh.fragment, "default") πŸ¦‹

local shfmt = {};
shfmt["GLSL120"].vertex = [[
uniform mat4 modelview;
uniform mat4 projection;
attribute vec4 vertex;
attribute vec2 texcoord;
varying vec2 texco;
void build_shader0(void)
{
      texco = texcoord;
      gl_Position = (projection * modelview) * vertex;
}
]];
shfmt["GLSL120"].fragment = [[
uniform sampler2D map_diffuse;
uniform float obj_opacity;
varying vec2 texco;
void build_shader0(){
            vec4 col = texture2D(map_diffuse, texco);
            col.a = col.a * obj_opacity;
            gl_FragColor = col;
}
]];
function build_shader0()
      local sh = shfmt[SHADER_LANGUAGE];
      if (sh == nil) then
            return shutdown("no matching shader for the platform language:" ..
                  SHADER_LANGUAGE, EXIT_FAILURE);
      end
      build_shader(sh.vertex, sh.fragment, "default");
end

πŸ’€ MISUSE πŸ’€

and now the MISUSE section, aka the β€œdo not copy this” corner πŸ’€ The page literally labels this MISUSE, so keep that energy in mind.

local shfmt = {};
shfmt["GLSL120"].vertex = [[
uniform mat4 modelview;
uniform mat4 projection;
attribute vec4 vertex;
attribute vec2 texcoord;
varying vec2 texco;
void build_shader0(void)
{
      texco = texcoord;
      gl_Position = (projection * modelview) * vertex;
}
]];
shfmt["GLSL120"].fragment = [[
uniform sampler2D map_diffuse;
uniform float obj_opacity;
varying vec2 texco;
void build_shader0(){
            vec4 col = texture2D(map_diffuse, texco);
            col.a = col.a * obj_opacity;
            gl_FragColor = col;
}
]];
function build_shader0()
      local sh = shfmt[SHADER_LANGUAGE];
      if (sh == nil) then
            return shutdown("no matching shader for the platform language:" ..
                  SHADER_LANGUAGE, EXIT_FAILURE);
      end
      build_shader(nil, nil, nil);
end

πŸ’€ MISUSE πŸ’€

another MISUSE, another β€œbestie no” πŸ’€ This one’s still filed under MISUSE, so don’t let the cute code block fool you.

local shfmt = {};
shfmt["GLSL120"].vertex = [[
uniform mat4 modelview;
uniform mat4 projection;
attribute vec4 vertex;
attribute vec2 texcoord;
varying vec2 texco;
void build_shader1(void)
{
      texco = texcoord;
      gl_Position = (projection * modelview) * vertex;
}
]];
shfmt["GLSL120"].fragment = [[
uniform sampler2D map_diffuse;
uniform float obj_opacity;
varying vec2 texco;
void build_shader1(){
            vec4 col = texture2D(map_diffuse, texco);
            col.a = col.a * obj_opacity;
            gl_FragColor = col;
}
]];
function build_shader1()
      local sh = shfmt[SHADER_LANGUAGE];
      if (sh == nil) then
            return shutdown("no matching shader for the platform language:" ..
                  SHADER_LANGUAGE, EXIT_FAILURE);
      end
      build_shader(vshader, fshader, 0.5);
end

πŸ‘‘ SEE ALSO πŸ‘‘

mwah πŸ’‹ β€” this page comes from source/version vidsys, dated October 2026, and yes babes, it’s the build_shader(3) manpage.

πŸ“¦ where this page comes from