17 KiB
F.O.R.G.E. (Steel)
Fusion Of Real-time Generative Effects
Steel version (PC executable)
Discover an engine where user-defined fragment shaders collide to produce stunning visuals.
See Demo #1 - 1H and Demo #2 - Monitor View on YouTube.
Quick Start
FORGE default project is controlled with a KORG nanoKONTROL2.
Don't worry if you don't have one, the demo mode will still run great.
After you install the project, you can test run the following commands:
# demo mode, works out of the box
forge --demo
# see the monitor output
forge --demo --monitor-only
# open to another screen
forge --demo --screen=1
# open both output and monitor
forge --demo -screen=0 --monitor=1
# nanoKONTROL2 plugged, control the default project
forge
# nanoKONTROL2 plugged, add video devices
forge --video-in=/dev/video0 --video-in=/dev/video1
# run the sample projet and work on it
forge --project=./sample --hot-reload
What to do next
Here are some pointers if you want to customize your FORGE experience:
- Discover the hotkeys
- Familiarize with the CLI arguments
- Discover how to use the default project
- Make your own FORGE project
Table of Contents
- Quick Start
- What is FORGE ?
- Install
- Usage
- Default Project
- Making your own FORGE project
- Frequently Asked Questions
What is FORGE ?
FORGE is an engine rendering a project into visuals.
Using OpenGL GLSL language, it talks to your graphic card to generate layers of textures defined by the fragment shaders and outputs it to your screen.
Here's a quick rundown of the process:
- Reads the
forge_project.cfgdefined in the project folder. - Reads the
.glslfiles, including common parts while parsing them. - Creates and links all the OpenGL elements (programs, uniforms, textures, framebuffers, etc.)
- Creates a GLFW window
- (optional) Connects to a MIDI controller (ALSA library) and read events to the background
- (optional) Opens a video device stream (V4L2 library) and read buffers in the background
- Updates context and pass it to the OpenGL programs (time, resolution, state, etc.)
- Renders each texture from its OpenGL program
- Renders window
- Repeat at step 7
Install
Requirements
| library | apt | pacman |
|---|---|---|
| libglfw | libglfw3-dev | extra/glfw |
| libGL | libgl-dev | extra/libglvnd |
| libasound | libasound2-dev | extra/alsa-lib |
| libv4l2 | libv4l-dev | extra/v4l-utils |
| libbsd | libbsd-dev | extra/libbsd |
From release
See Releases
tar xvzf forge-steel-x.y.z.tar.gz
cd forge-steel-x.y.z
./configure
make
make install
From repository (PKGBUILD)
git clone --recursive https://github.com/klemek/forge-steel
cd forge
makepkg -si
From repository (dev version)
git clone --recursive https://github.com/klemek/forge-steel
cd forge
aclocal
autoconf
automake --add-missing
./configure
make
make install
Usage
Runtime hotkeys
When running, the following hotkeys are available:
- Esc: Exit window
- R: Randomize internal values
- 0: Reset internal values to 0
- D: Demo mode On/Off
- A: Auto Random mode On/Off
CLI arguments
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-v=FILE] [-vs=SIZE] [-is=SIZE] [-sf=STATE_PATH] [-ls / -nls] [-ss / -nss] [-tm] [-tf]
Fusion Of Real-time Generative Effects.
options:
-h, --help show this help message and exit
-v, --version print version
-p, --project forge project directory (default: /usr/share/forge/default)
-c, --config config file name (default: forge_project.cfg)
-hr, --hot-reload hot reload of shaders scripts
-s, --screen output screen number (default: primary)
-m, --monitor monitor screen number (default: none)
-mo, --monitor-only no output screen
-w, --windowed not fullscreen
-t, --tempo base tempo (default: 60)
-d, --demo demonstration mode (assume --no-save-state, --no-load-state, --auto-random)
-ar, --auto-random randomize state every 4 beats
-nar, --no-auto-random do not randomize state (default)
-v, --video-in path to video capture device (multiple allowed)
-vs, --video-size video capture desired height (default: internal texture height)
-is, --internal-size internal texture height (default: 720)
-sf, --state-file saved state file (default: forge_saved_state.txt)
-ls, --load-state load saved state (default)
-nls, --no-load-state do not load saved state
-ss, --save-state save state (default)
-nss, --no-save-state do not save state
-tm, --trace-midi print midi code and values
-tf, --trace-fps print fps status of subsystems
Default Project
A.K.A Kleπek's shaders
FORGE come pre-loaded with a default project, the following explains how to use it.
Monitor and debug view
When opening the monitor view, here's what to expect:
On the bottom left corner, here's how to read the internal state:
nanoKONTROL2 layout for the default project
In order to control the default project, you can expect it to work with this layout:
In blue is a sample "stage" as most sources/effects use a combination of 4 stages (see table below)
⚠️ you'll need to change your nanoKONTROL2 settings to remove the "toggle" behavior of the buttons and use "external" led control. (Use the KORG KONTROL Editor and the provided data file to setup your controller.)
Available sources and effects
Working with pages and items, you can use the following predefined sources and effects:
| P | # | SRC | COL2 | COL3 | COL4 | FX | COL6 | COL7 | COL8 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | Feedback + Thru | Hue | Saturation | Light | Thru | Hue | Saturation | Light |
| 1 | Lines | Thick. / Dezoom | Rotation | Distortion | Feedback + Shift | Zoom / Dezoom | X Shift | Y Shift | |
| 2 | Dots | Zoom | Rotation | Lens | Shift | Zoom / Dezoom | X Shift | Y Shift | |
| 3 | Waves | Spacing | Thickness | Vert. Scroll (R) | Colorize | Black Color | White Color | Shift | |
| 4 | Noise | Zoom | Voronoi dist. | Details | Quantize | Pixel Size | Bit Depth | Blur | |
| 2 | 5 | Video In 1 + Thru | Hue | Saturation | Light | Dithering | Pixel Size | Bit Depth | Blur |
| 6 | CP437 | Zoom | Charset | Char. Delta | TV | Lens | Horz. Noise | Dezoom | |
| 7 | Sentences | Zoom | Sentence | Vertical repeat | Kaleidoscope | Axes | Rotation | Horz. Scroll | |
| 8 | Sentences repeat | X Shift | Sentence | Vertical repeat | CP437 | Zoom | Charset | Char. Delta | |
| 9 | Isometric grid | Zoom | Scroll | Elevation | Lens | Lens limit | Lens power | Pre Zoom | |
| 3 | A | Video In 2 + Thru | Hue | Saturation | Light | Spill | Bottom limit | Top Limit | Rotation |
| B | Scales | Zoom | Shape | Ripples | Game Of Life | Pixel Size | Ruleset/Threshold | Feedback | |
| C | Credenza | Zoom | Shape | Ripples | Sobel Filter | Horz. filter | Vert. filter | Filter Size | |
| D | Cursor | Size | Pos X | Pos Y | Isometric | Zoom | Scroll | Rotate | |
| E | (Random source) | --- | --- | --- | (Random effect) | --- | --- | --- |
See the printable version.
Making your own FORGE project
You want to embrace the "user" in "user-defined"? It's time to make your own project.
Starts with copying the sample project and make it your own with the following guide.
Then, writing code you can use the --hot-reload to watch your visuals as you design them.
forge --project=<project_dir> --hot-reload
forge_project.cfg
Every FORGE project starts with a forge_project.cfg.
We will not dig down all the variables here but feel free to read either:
- sample/forge_project.cfg (beginner oriented)
- default/forge_project.cfg (more complete)
Midi groups
FORGE allows you to send the midi data in the form of groups.
Each group has the following properties:
- A number of layers with
MIDI_X_ACTIVE_COUNT(default:1) - Each midi code controlling how to change the active layer with
MIDI_X_ACTIVE_Y - A number of codes with
MIDI_X_COUNT - Each midi code controlling the active layer with
MIDI_X_Y(as avec3:_X/_Y/_Z)
States
FORGE allows to define a "state" to a fragment shader.
This combines several parameters:
SELECT_PAGE_COUNT(default:1) +SELECT_PAGE_X: define midi codes for pages of item.SELECT_ITEM_COUNT+SELECT_ITEM_X: define midi codes for items per page.SELECT_FRAG_X: define midi codes to "select" a fragment shader.
The selected fragment shader will have its state updated with either:
iStateXint uniform- Your defined subroutines
Writing your fragment shaders
The core concept behind FORGE is the fragment shaders, here's how to write them.
Naming
Depending on your FRAG_COUNT (default: 1) and FRAG_FILE_PREFIX (default: frag), you will have to write files frag1.glsl up to fragX.glsl.
Minimal working code
Here is the minimal working fragment shader code, only outputting a black screen:
#version 460
in vec2 vUV;
out vec4 fragColor;
void main() {
fragColor = vec4(0);
}
You don't have to consider the output, as long as its a out vec4 it will be either rendered to a framebuffer (then to a texture) or the output window, depending on your forge_project.cfg.
Uniforms
Every UNIFORM_XXX defined in the forge_project.cfg is injected into your code at runtime.
uniform float iTime; // the current time
uniform sampler2D iTex0; // texture 1 (0-based)
uniform sampler2D iTex9; // texture 10
uniform int iSeed1;
uniform vec3 iMidi2_3[7]; // midi group 2, layer 3, size 7
uniform vec3 iMidi3_1[2];
Working with #include
You dreamt it, FORGE made it real, you can now include glsl files to reduce their lengths.
Suppose you have a time.glsl file along side your frag1.glsl like so:
project/time.glsl
#define PI 3.1415927
uniform float iBeats;
float sinTime()
{
return sin(iBeats * 2 * PI);
}
project/frag1.glsl
#version 460
in vec2 vUV;
out vec4 fragColor;
#include time.glsl
void main() {
fragColor = vec4(sinTime());
}
Internally, FORGE will create the following fragment shader code:
#version 460
in vec2 vUV;
out vec4 fragColor;
#define PI 3.1415927
uniform float iBeats;
float sinTime()
{
return sin(iBeats * 2 * PI);
}
void main() {
fragColor = vec4(sinTime());
}
You can stack up to 63 #include as deeply as you want.
You're not sure you already included a file? Use preprocessors:
#ifndef TIME
#define TIME
// your code
#endif
Working with subroutines
Starting from OpenGL 4.6, GLSL language allows subroutine:
#version 460
in vec2 vUV;
out vec4 fragColor;
// SUB_TYPE_COUNT=1
// SUB_1_PREFIX=sub_
subroutine vec4 sub_function(vec2 vUV);
subroutine(sub_function) vec4 sub_1(vec2 vUV) {
return vec4(0);
}
subroutine(sub_function) vec4 sub_2(vec2 vUV) {
return vec4(1);
}
subroutine uniform sub_function current_sub;
// equivalent to this, but with function injection
uniform int iState1; // considering this is frag1.glsl
void main() {
// current_sub will be either sub_1 or sub_2 depending
// on the current "state" of this fragment shader
fragColor = current_sub(vUV);
}
Frequently Asked Questions
Why "steel"?
FORGE is a concept which is intended to be derived onto other forms (like Raspberry PI). In order to differentiate between them each would be name after a different alloy.
FORGE (steel) describe the linux version.
I couldn't install FORGE on my computer
Verify you have the correct requirements installed.
Then if you continue to have problems, you can open an issue.
I didn't understand everything about your tutorial
Please open an issue describing what your having trouble with, I'll try to answer and update the README.
My nanoKontrol2 is acting strange
You may need to change your NanoKontrol2 settings to remove the "toggle" behavior of the buttons and use "external" led control.
Use the KORG KONTROL Editor and the provided data file to setup your controller.
How do I report a bug?
You're free to open a new issue in the Issues page.
Don't forget to add all information available to your bug (version, operating system, etc.).
Help I got low FPS on my video device
There's already an open issue on this subject.
How do I change the default project built-in sentences?
The sentences are defined in default/inc_sentences.glsl.
The script scripts/sentences.py can help you update them.




