commit 527e79cef3a9aab69b7f66059113efd624ec984d Author: klemek Date: Wed Aug 26 17:32:51 2026 +0200 initial commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6f633de --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{*.c,*.h}] +indent_size = 2 + +[{Makefile.*,Makefile}] +indent_style = tab +indent_size = 2 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6c54f48 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "forge-steel"] + path = forge-steel + url = https://git.klemek.fr/klemek/forge-steel diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ebf0739 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +# ENV + +FORGE_MAKE ?= $(MAKE) -C forge-steel -f Makefile.dev +RUN_ARGS ?= -tf --project=project -is=1080 --demo + +# FILES + +forge-steel/build/forge: + $(FORGE_MAKE) build-no-video + +# ACTIONS + +.PHONY: clean +clean: + $(FORGE_MAKE) clean + +.PHONY: build +build: forge-steel/build/forge + +.PHONY: run +run: + LIBGL_ALWAYS_SOFTWARE=true forge-steel/build/forge $(RUN_ARGS) diff --git a/forge-steel b/forge-steel new file mode 160000 index 0000000..73dd4b7 --- /dev/null +++ b/forge-steel @@ -0,0 +1 @@ +Subproject commit 73dd4b75d323b02f357a9cf62ae8be4f69898af2 diff --git a/forge_default_save.txt b/forge_default_save.txt new file mode 100644 index 0000000..e851335 --- /dev/null +++ b/forge_default_save.txt @@ -0,0 +1,123 @@ +tempo=60 +page=0 +selected=3 +seed_0=355 +state_0=5 +seed_1=247 +state_1=11 +seed_2=74 +state_2=10 +seed_3=251 +state_3=3 +seed_4=799 +state_4=5 +seed_5=80 +state_5=3 +active_0=1 +active_1=0 +active_2=0 +value_0_x=127 +value_0_y=127 +value_0_z=127 +value_1_x=34 +value_1_y=59 +value_1_z=127 +value_2_x=127 +value_2_y=127 +value_2_z=0 +value_3_x=56 +value_3_y=32 +value_3_z=69 +value_4_x=0 +value_4_y=127 +value_4_z=0 +value_5_x=55 +value_5_y=67 +value_5_z=18 +value_6_x=127 +value_6_y=0 +value_6_z=0 +value_7_x=75 +value_7_y=102 +value_7_z=20 +value_8_x=0 +value_8_y=0 +value_8_z=127 +value_9_x=89 +value_9_y=93 +value_9_z=72 +value_10_x=127 +value_10_y=0 +value_10_z=127 +value_11_x=92 +value_11_y=49 +value_11_z=69 +value_12_x=127 +value_12_y=127 +value_12_z=127 +value_13_x=72 +value_13_y=61 +value_13_z=104 +value_14_x=0 +value_14_y=0 +value_14_z=127 +value_15_x=74 +value_15_y=18 +value_15_z=63 +value_16_x=127 +value_16_y=127 +value_16_z=0 +value_17_x=127 +value_17_y=85 +value_17_z=6 +value_18_x=110 +value_18_y=26 +value_18_z=0 +value_19_x=127 +value_19_y=0 +value_19_z=0 +value_20_x=17 +value_20_y=34 +value_20_z=53 +value_21_x=0 +value_21_y=0 +value_21_z=0 +value_22_x=39 +value_22_y=25 +value_22_z=112 +value_23_x=0 +value_23_y=127 +value_23_z=0 +value_24_x=49 +value_24_y=57 +value_24_z=92 +value_25_x=99 +value_25_y=53 +value_25_z=127 +value_26_x=0 +value_26_y=0 +value_26_z=127 +value_27_x=30 +value_27_y=82 +value_27_z=25 +value_28_x=127 +value_28_y=0 +value_28_z=0 +value_29_x=115 +value_29_y=126 +value_29_z=84 +value_30_x=127 +value_30_y=127 +value_30_z=0 +value_31_x=4 +value_31_y=122 +value_31_z=100 +value_32_x=52 +value_32_y=6 +value_32_z=127 +value_33_x=0 +value_33_y=0 +value_33_z=127 +value_34_x=127 +value_34_y=15 +value_34_z=0 diff --git a/project/forge_project.cfg b/project/forge_project.cfg new file mode 100644 index 0000000..d157706 --- /dev/null +++ b/project/forge_project.cfg @@ -0,0 +1,320 @@ +################################ +## FORGE INVAR PROJECT CONFIG ## +################################ +# Your reading a FORGE configuration file, don't panic +# Everything here is designed to link elements between them +# (shaders, video devices, textures, midi inputs, etc.) +# Every number based constant will be "one-based" (1,2,3,etc.) +# To read more, go to +# https://git.klemek.fr/klemek/forge-invar + + +# ================ +# FRAGMENT SHADERS +# ================ + + +# === UNIFORMS === +# GLSL uniform names or prefixes +# Prefixed uniforms are "iVariableX" with a number + +# --- uniform float --- + +# Elapsed time +UNIFORM_TIME=iTime +# Current tempo +UNIFORM_TEMPO=iTempo +# Current total beats +UNIFORM_BEATS=iBeats + +# --- uniform int --- + +# Output frame per second +UNIFORM_FPS=iFPS +# Input X frame per second +UNIFORM_IN_FPS_PREFIX=iInputFPS +# 0/1 if demo +UNIFORM_DEMO=iDemo +# 0/1 if auto random +UNIFORM_AUTORAND=iAutoRand +# auto random cycle length +UNIFORM_AUTORANDCYCLE=iAutoRandCycle +# Current page +UNIFORM_PAGE=iPage +# Current selected shader +UNIFORM_SELECTED=iSelected +# Seed for shader X +UNIFORM_SEED_PREFIX=iSeed +# State for shader X +UNIFORM_STATE_PREFIX=iState +# Midi group X active layer number +UNIFORM_ACTIVE_PREFIX=iActive + +# --- uniform vec2 --- + +# Output resolution +UNIFORM_RESOLUTION=iResolution +# Internal textures resolution +UNIFORM_TEX_RESOLUTION=iTexResolution + +# --- uniform vec3 --- + +# Midi group X layer Y (beware of group size) +# Injected as "iGroupX_Y[Z]" +UNIFORM_GROUP_PREFIX=iGroup + +# --- uniform sampler2D --- + +# Internal texture X +UNIFORM_TEX_PREFIX=iTex + +# === SUBROUTINES === +# GLSL subroutines prefixes +# You can then use them as: +# subroutine() () {} +# (see: https://wikis.khronos.org/opengl/Shader_Subroutine) +# Numbers go from 1 to SELECT_PAGE_COUNT * SELECT_ITEM_COUNT +# Each fragment shader is injected its current state subroutine + +# Total subroutine variants +SUB_TYPE_COUNT=2 +# Each subroutine variant prefix +SUB_1_PREFIX=src_ +SUB_2_PREFIX=fx_ + + +# =========== +# TEXTURE I/O +# =========== + + +# Total number of internal textures +TEX_COUNT=6 + +# === FRAGMENT SHADERS +# Fragment shaders will be read from the CLI directory as "fragX.glsl" + +# Prefix of fragment shaders to detect +FRAG_FILE_PREFIX=frag + +# Total number of fragment shaders (excluding frag0.glsl) +FRAG_COUNT=7 + +# To which texture will the shader fragX.glsl will render to +FRAG_1_OUT=1 +FRAG_2_OUT=2 +FRAG_3_OUT=3 +FRAG_4_OUT=4 +FRAG_5_OUT=5 +FRAG_6_OUT=0 +# Which fragment shader renders to output window +FRAG_OUTPUT=7 +# Which fragment shader renders to monitor window +FRAG_MONITOR=7 + + +# ========== +# I/O Inputs +# ========== +# Each code either maps to a midi event or a key code +# 0 - 999 -> midi event +# Keyboard modifiers are encoded like this: +# 1000 -> keyboard event +# 10000 -> shift +# 100000 -> control +# 1000000 -> alt +# This means 111082 is control+alt+R + +# The recognized ALSA name of the midi device +MIDI_HW=hw:CARD=nanoKONTROL2 + +# === TYPES OF EVENTS +# FORGE needs to differentiate between fader and buttons +# In the next configurations, when an event is not configured, +# it will be skipped + +# Total number of faders +FADER_COUNT=16 +# Midi codes of faders +FADER_1=0 +FADER_2=1 +FADER_3=2 +FADER_4=3 +FADER_5=4 +FADER_6=5 +FADER_7=6 +FADER_8=7 +FADER_9=16 +FADER_10=17 +FADER_11=18 +FADER_12=19 +FADER_13=20 +FADER_14=21 +FADER_15=22 +FADER_16=23 +# Midi code for tap tempo +TAP_TEMPO=46 + +# === FRAGMENT SUBROUTINE SELECT +# You can manipulate which subroutine is sent to which fragment shader + +# Midi codes to select fragment X +SELECT_FRAG_3=32 +SELECT_FRAG_4=64 +SELECT_FRAG_5=36 +SELECT_FRAG_6=68 +SELECT_FRAG_8=52 +# Total number of pages (can be 1) +SELECT_PAGE_COUNT=3 +# Midi codes to select page X +SELECT_PAGE_1=60 +SELECT_PAGE_2=61 +SELECT_PAGE_3=62 +# Total number of items per page +SELECT_ITEM_COUNT=5 +# Midi codes to select item Y on page X +SELECT_ITEM_1=43 +SELECT_ITEM_2=44 +SELECT_ITEM_3=42 +SELECT_ITEM_4=41 +SELECT_ITEM_5=45 + +# === GROUP INPUT STATES +# Inputs will control FORGE's state as follows +# X groups of Y layers sized Z +# You can manipulate only 1 layer at a time +# Every layer of every groups will be send as uniforms +# Each active layer will be sent back to the device +# with the same codes for nice display + +# Total number of groups +GROUP_COUNT=3 + +# Total number of layers of group 1 +GROUP_1_ACTIVE_COUNT=2 +# Midi codes to change layer of group 1 +GROUP_1_ACTIVE_1=32 +GROUP_1_ACTIVE_2=64 + +# Size of group 1 +GROUP_1_COUNT=6 +# Every code of active layer manipulation of group 1 +GROUP_1_1_X=33 +GROUP_1_1_Y=49 +GROUP_1_1_Z=65 +GROUP_1_2_X=1 +GROUP_1_2_Y=17 +GROUP_1_2_Z= +GROUP_1_3_X=34 +GROUP_1_3_Y=50 +GROUP_1_3_Z=66 +GROUP_1_4_X=2 +GROUP_1_4_Y=18 +GROUP_1_4_Z= +GROUP_1_5_X=35 +GROUP_1_5_Y=51 +GROUP_1_5_Z=67 +GROUP_1_6_X=3 +GROUP_1_6_Y=19 +GROUP_1_6_Z= + +# Same for group 2 +GROUP_2_ACTIVE_COUNT=3 +GROUP_2_ACTIVE_1=36 +GROUP_2_ACTIVE_2=68 +GROUP_2_ACTIVE_3=52 +GROUP_2_COUNT=7 +GROUP_2_1_X=37 +GROUP_2_1_Y=53 +GROUP_2_1_Z=69 +GROUP_2_2_X=5 +GROUP_2_2_Y=21 +GROUP_2_2_Z= +GROUP_2_3_X=38 +GROUP_2_3_Y=54 +GROUP_2_3_Z=70 +GROUP_2_4_X=6 +GROUP_2_4_Y=22 +GROUP_2_4_Z= +GROUP_2_5_X=39 +GROUP_2_5_Y=55 +GROUP_2_5_Z=71 +GROUP_2_6_X=7 +GROUP_2_6_Y=23 +GROUP_2_6_Z= +GROUP_2_7_X=4 +GROUP_2_7_Y=20 +GROUP_2_7_Z=59 + +# Same for group 3 +GROUP_3_COUNT=2 +GROUP_3_1_X=48 +GROUP_3_1_Y=58 +GROUP_3_1_Z= +GROUP_3_2_X=0 +GROUP_3_2_Y= +GROUP_3_2_Z= + +# Auto-Random Ignore (ARI) prefixes +ARI_COUNT=2 +ARI_1=GROUP_3_1_Y +ARI_2=GROUP_3_2_Z + +# ===== +# OTHER +# ===== + +# === SAVE FILES +# When loading/saving from last run or using save states +SAVE_FILE_PREFIX=forge_default_save + +# === HOTKEYS +# You can change the default keycodes used on runtime + + +# R on (qwerty) +KEY_RANDOMIZE=1082 +# SHIFT+R (qwerty) +KEY_RESET=11082 +# D (qwerty) +KEY_DEMO=1068 +# A (qwerty) +KEY_AUTORAND=1065 +# Left arrow +KEY_AUTORAND_DOWN=1263 +# Right arrow +KEY_AUTORAND_UP=1262 +# Down arrow +KEY_TEMPO_DOWN=1264 +# Up arrow +KEY_TEMPO_UP=1265 + +# Number of load states keys +KEY_LOAD_COUNT=10 + +# 1 to 9 then 0 keys +KEY_LOAD_1=1049 +KEY_LOAD_2=1050 +KEY_LOAD_3=1051 +KEY_LOAD_4=1052 +KEY_LOAD_5=1053 +KEY_LOAD_6=1054 +KEY_LOAD_7=1055 +KEY_LOAD_8=1056 +KEY_LOAD_9=1057 +KEY_LOAD_10=1048 + +# Number of save states keys +KEY_SAVE_COUNT=10 + +# 1 to 9 then 0 keys with shift +KEY_SAVE_1=11049 +KEY_SAVE_2=11050 +KEY_SAVE_3=11051 +KEY_SAVE_4=11052 +KEY_SAVE_5=11053 +KEY_SAVE_6=11054 +KEY_SAVE_7=11055 +KEY_SAVE_8=11056 +KEY_SAVE_9=11057 +KEY_SAVE_10=11048 diff --git a/project/frag1.glsl b/project/frag1.glsl new file mode 100644 index 0000000..ec1d104 --- /dev/null +++ b/project/frag1.glsl @@ -0,0 +1,20 @@ + +#version 460 + +// SRC A +// ----------- +// OUT: 2 (FX A) + +in vec2 vUV; +out vec4 fragColor; + +#include inc_src.glsl + +subroutine uniform src_stage_sub src_stage; + +uniform int iSeed1; +uniform vec3 iGroup1_1[6]; + +void main() { + fragColor = src_stage(vUV, iSeed1, iGroup1_1[0], iGroup1_1[1].xy, iGroup1_1[2], iGroup1_1[3].xy, iGroup1_1[4], iGroup1_1[5].xy); +} diff --git a/project/frag2.glsl b/project/frag2.glsl new file mode 100644 index 0000000..6bdf661 --- /dev/null +++ b/project/frag2.glsl @@ -0,0 +1,19 @@ +#version 460 + +// SRC B +// ----------- +// OUT: 4 (FX B) + +in vec2 vUV; +out vec4 fragColor; + +#include inc_src.glsl + +subroutine uniform src_stage_sub src_stage; + +uniform int iSeed2; +uniform vec3 iGroup1_2[6]; + +void main() { + fragColor = src_stage(vUV, iSeed2, iGroup1_2[0], iGroup1_2[1].xy, iGroup1_2[2], iGroup1_2[3].xy, iGroup1_2[4], iGroup1_2[5].xy); +} diff --git a/project/frag3.glsl b/project/frag3.glsl new file mode 100644 index 0000000..eed41a6 --- /dev/null +++ b/project/frag3.glsl @@ -0,0 +1,21 @@ +#version 460 + +// FX A +// ------------- +// IN: 1 (SRC A) +// IN: 3 (FX A) +// OUT: 5 (A+B) + +in vec2 vUV; +out vec4 fragColor; + +#include inc_fx.glsl + +uniform sampler2D iTex1; +uniform sampler2D iTex3; +uniform int iSeed3; +uniform vec3 iGroup2_1[7]; + +void main() { + fragColor = fx_stage(vUV, iTex1, iTex3, iSeed3, iGroup2_1[0], iGroup2_1[1].xy, iGroup2_1[2], iGroup2_1[3].xy, iGroup2_1[4], iGroup2_1[5].xy, iGroup2_1[6]); +} diff --git a/project/frag4.glsl b/project/frag4.glsl new file mode 100644 index 0000000..f150c8c --- /dev/null +++ b/project/frag4.glsl @@ -0,0 +1,21 @@ +#version 460 + +// FX B +// ------------- +// IN: 2 (SRC B) +// IN: 4 (FX B) +// OUT: 5 (A+B) + +in vec2 vUV; +out vec4 fragColor; + +#include inc_fx.glsl + +uniform sampler2D iTex2; +uniform sampler2D iTex4; +uniform int iSeed4; +uniform vec3 iGroup2_2[7]; + +void main() { + fragColor = fx_stage(vUV, iTex2, iTex4, iSeed4, iGroup2_2[0], iGroup2_2[1].xy, iGroup2_2[2], iGroup2_2[3].xy, iGroup2_2[4], iGroup2_2[5].xy, iGroup2_2[6]); +} diff --git a/project/frag5.glsl b/project/frag5.glsl new file mode 100644 index 0000000..7d4af38 --- /dev/null +++ b/project/frag5.glsl @@ -0,0 +1,37 @@ +#version 460 + +// A+B +// ------------ +// IN: 3 (FX A) +// IN: 4 (FX B) +// OUT: 6 (MFX) + +in vec2 vUV; +out vec4 fragColor; + +#include inc_magic.glsl +#include inc_functions.glsl + +uniform int iDemo; +uniform sampler2D iTex3; +uniform sampler2D iTex4; +uniform int iSeed5; +uniform vec3 iGroup3_1[2]; + +void main() { + float mix_value = magic(iGroup3_1[1].xy, vec3(1, 0, 0), iSeed5); + bool mix_type = magic_trigger(vec3(iGroup3_1[0].x, 0, 0), iSeed5 + 10); + + vec4 color_a = texture(iTex3, vUV); + vec4 color_b = texture(iTex4, vUV); + + float k = mean(color_a); + + mix_value = mix(mix_value, mix_value * 0.9 + 0.05, iDemo); + + if (mix_type) { + fragColor = mix(color_a, color_b, step(mix_value, k)); + } else { + fragColor = mix(color_b, color_a, mix_value); + } +} diff --git a/project/frag6.glsl b/project/frag6.glsl new file mode 100644 index 0000000..c79afd1 --- /dev/null +++ b/project/frag6.glsl @@ -0,0 +1,26 @@ +#version 460 + +// MFX +// ------------ +// IN: 5 (A+B) +// IN: 0 (OUT) +// OUT: 0 (OUT) + +in vec2 vUV; +out vec4 fragColor; + +#include inc_fx.glsl + +uniform sampler2D iTex5; +uniform sampler2D iTex0; +uniform int iSeed6; +uniform vec3 iGroup2_3[7]; +uniform vec3 iGroup3_1[2]; + +void main() { + vec4 color = fx_stage(vUV, iTex5, iTex0, iSeed6, iGroup2_3[0], iGroup2_3[1].xy, iGroup2_3[2], iGroup2_3[3].xy, iGroup2_3[4], iGroup2_3[5].xy, iGroup2_3[6]); + + color = mix(color, vec4(0), iGroup3_1[0].y); + + fragColor = color; +} diff --git a/project/frag7.glsl b/project/frag7.glsl new file mode 100644 index 0000000..f9e7761 --- /dev/null +++ b/project/frag7.glsl @@ -0,0 +1,12 @@ +#version 460 + +// OUT + +in vec2 vUV; +out vec4 fragColor; + +uniform sampler2D iTex0; + +void main() { + fragColor = texture(iTex0, vUV); +} diff --git a/project/inc_cp437.glsl b/project/inc_cp437.glsl new file mode 100644 index 0000000..bb4cc76 --- /dev/null +++ b/project/inc_cp437.glsl @@ -0,0 +1,447 @@ +#ifndef INC_CP437 +#define INC_CP437 + +const int cp437[] = { + 0x0000, 0x0000, 0x0000, 0x0000, // 0x00, NUL + 0x151E, 0x8A87, 0xE19D, 0x789B, // 0x01, SOH, SMILEY BLACK + 0xFBFE, 0xFDF7, 0xEF73, 0x7FEC, // 0x02, STX, SMILEY LIGHT + 0xFFF6, 0x7773, 0x08CE, 0x0013, // 0x03, ETX, HEART + 0xFEC8, 0x7310, 0x08CE, 0x0013, // 0x04, EOT, DIAMOND + 0xFCEC, 0x7131, 0xECEF, 0x3137, // 0x05, ENQ, CLUB + 0xEC88, 0x3100, 0xECEF, 0x3137, // 0x06, ACK, SPADE + 0xC800, 0x3100, 0x008C, 0x0013, // 0x07, BEL, DOT + 0x37FF, 0xCEFF, 0xFF73, 0xFFEC, // 0x08, BS, INVERT DOT + 0x26C0, 0x4630, 0x0C62, 0x0364, // 0x09, HT, CIRCLE + 0xD93F, 0xB9CF, 0xF39D, 0xFC9B, // 0x0A, LF, INVERT CIRCLE + 0xE000, 0xBFEF, 0xE333, 0x1333, // 0x0B, VT, MALE + 0x666C, 0x6663, 0x8E8C, 0x1713, // 0x0C, FF, FEMALE + 0xCCCC, 0x0FCF, 0x7FEC, 0x0000, // 0x0D, CR, NOTE + 0x6E6E, 0xCFCF, 0x3766, 0x06EC, // 0x0E, SO, DOUBLE NOTE + 0x7CA9, 0xE359, 0x9AC7, 0x953E, // 0x0F, SI, SUN + 0xFF71, 0x7100, 0x017F, 0x0001, // 0x10, DLE, RIGHT TRIANGLE + 0xFC00, 0x7774, 0x000C, 0x0477, // 0x11, DC1, LEFT TRIANGLE + 0x8EC8, 0x1731, 0x8CE8, 0x1371, // 0x12, DC2, ARROW UP DOWN + 0x6666, 0x6666, 0x0606, 0x0606, // 0x13, DC3, DOUBLE EXCLAMATION + 0xEBBE, 0xDDDF, 0x0888, 0x0DDD, // 0x14, DC4, PARAGRAPH + 0x6C6C, 0x31C7, 0xE3C6, 0x1313, // 0x15, NAK, ? + 0x0000, 0x0000, 0x0EEE, 0x0777, // 0x16, SYN, HALF SQUARE BOTTOM + 0x8EC8, 0x1731, 0xF8CE, 0xF137, // 0x17, ETB, ARROW UP DOWN UNDERLINED + 0x8EC8, 0x1731, 0x0888, 0x0111, // 0x18, CAN, ARROW UP + 0x8888, 0x1111, 0x08CE, 0x0137, // 0x19, EM, ARROW DOWN + 0xF080, 0x7310, 0x0080, 0x0013, // 0x1A, SUB, ARROW RIGHT + 0xF6C0, 0x7000, 0x00C6, 0x0000, // 0x1B, ESC, ARROW LEFT + 0x3300, 0x0000, 0x00F3, 0x0070, // 0x1C, FS, ? + 0xF640, 0xF620, 0x0046, 0x0026, // 0x1D, GS, ARROW LEFT RIGHT + 0xEC80, 0x7310, 0x00FF, 0x00FF, // 0x1E, RS, TRIANGLE UP + 0xEFF0, 0x7FF0, 0x008C, 0x0013, // 0x1F, US, TRIANGLE DOWN + 0x0000, 0x0000, 0x0000, 0x0000, // 0x20, SPACE + 0xCEEC, 0x0110, 0x0C0C, 0x0000, // 0x21, ! + 0x0666, 0x0333, 0x0000, 0x0000, // 0x22, " + 0x6F66, 0x3733, 0x066F, 0x0337, // 0x23, # + 0xE3EC, 0x1030, 0x0CF0, 0x0013, // 0x24, $ + 0x8330, 0x1360, 0x036C, 0x0660, // 0x25, % + 0xEC6C, 0x6131, 0x0E3B, 0x0633, // 0x26, & + 0x0366, 0x0000, 0x0000, 0x0000, // 0x27, ' + 0x66C8, 0x0001, 0x08C6, 0x0100, // 0x28, ( + 0x88C6, 0x1100, 0x06C8, 0x0001, // 0x29, ) + 0xFC60, 0xF360, 0x006C, 0x0063, // 0x2A, * + 0xFCC0, 0x3000, 0x00CC, 0x0000, // 0x2B, + + 0x0000, 0x0000, 0x6CC0, 0x0000, // 0x2C, , + 0xF000, 0x3000, 0x0000, 0x0000, // 0x2D, - + 0x0000, 0x0000, 0x0CC0, 0x0000, // 0x2E, . + 0xC800, 0x0136, 0x0136, 0x0000, // 0x2F, / + 0xB33E, 0x7763, 0x0E7F, 0x0366, // 0x30, 0 + 0xCCEC, 0x0000, 0x0FCC, 0x0300, // 0x31, 1 + 0xC03E, 0x1331, 0x0F36, 0x0330, // 0x32, 2 + 0xC03E, 0x1331, 0x0E30, 0x0133, // 0x33, 3 + 0x36C8, 0x3333, 0x080F, 0x0737, // 0x34, 4 + 0x0F3F, 0x3103, 0x0E30, 0x0133, // 0x35, 5 + 0xF36C, 0x1001, 0x0E33, 0x0133, // 0x36, 6 + 0x803F, 0x1333, 0x0CCC, 0x0000, // 0x37, 7 + 0xE33E, 0x1331, 0x0E33, 0x0133, // 0x38, 8 + 0xE33E, 0x3331, 0x0E80, 0x0013, // 0x39, 9 + 0x0CC0, 0x0000, 0x0CC0, 0x0000, // 0x3A, : + 0x0CC0, 0x0000, 0x6CC0, 0x0000, // 0x3B, ; + 0x36C8, 0x0001, 0x08C6, 0x0100, // 0x3C, < + 0x0F00, 0x0300, 0x00F0, 0x0030, // 0x3D, = + 0x08C6, 0x3100, 0x06C8, 0x0001, // 0x3E, > + 0x803E, 0x1331, 0x0C0C, 0x0000, // 0x3F, ? + 0xBB3E, 0x7763, 0x0E3B, 0x0107, // 0x40, @ + 0x33EC, 0x3310, 0x033F, 0x0333, // 0x41, A + 0xE66F, 0x3663, 0x0F66, 0x0366, // 0x42, B + 0x336C, 0x0063, 0x0C63, 0x0360, // 0x43, C + 0x666F, 0x6631, 0x0F66, 0x0136, // 0x44, D + 0xE66F, 0x1147, 0x0F66, 0x0741, // 0x45, E + 0xE66F, 0x1147, 0x0F66, 0x0001, // 0x46, F + 0x336C, 0x0063, 0x0C63, 0x0767, // 0x47, G + 0xF333, 0x3333, 0x0333, 0x0333, // 0x48, H + 0xCCCE, 0x0001, 0x0ECC, 0x0100, // 0x49, I + 0x0008, 0x3337, 0x0E33, 0x0133, // 0x4A, J + 0xE667, 0x1366, 0x0766, 0x0663, // 0x4B, K + 0x666F, 0x0000, 0x0F66, 0x0764, // 0x4C, L + 0xFF73, 0x7776, 0x033B, 0x0666, // 0x4D, M + 0xBF73, 0x7666, 0x0333, 0x0667, // 0x4E, N + 0x336C, 0x6631, 0x0C63, 0x0136, // 0x4F, O + 0xE66F, 0x3663, 0x0F66, 0x0000, // 0x50, P + 0x333E, 0x3331, 0x08EB, 0x0313, // 0x51, Q + 0xE66F, 0x3663, 0x0766, 0x0663, // 0x52, R + 0xE73E, 0x0031, 0x0E38, 0x0133, // 0x53, S + 0xCCDF, 0x0023, 0x0ECC, 0x0100, // 0x54, T + 0x3333, 0x3333, 0x0F33, 0x0333, // 0x55, U + 0x3333, 0x3333, 0x0CE3, 0x0013, // 0x56, V + 0xB333, 0x6666, 0x037F, 0x0677, // 0x57, W + 0xC633, 0x1366, 0x036C, 0x0631, // 0x58, X + 0xE333, 0x1333, 0x0ECC, 0x0100, // 0x59, Y + 0x813F, 0x1367, 0x0F6C, 0x0764, // 0x5A, Z + 0x666E, 0x0001, 0x0E66, 0x0100, // 0x5B, [ + 0x8C63, 0x1000, 0x0000, 0x0463, // 0x5C, + 0x888E, 0x1111, 0x0E88, 0x0111, // 0x5D, ] + 0x36C8, 0x6310, 0x0000, 0x0000, // 0x5E, ^ + 0x0000, 0x0000, 0xF000, 0xF000, // 0x5F, _ + 0x08CC, 0x0100, 0x0000, 0x0000, // 0x60, ` + 0x0E00, 0x3100, 0x0E3E, 0x0633, // 0x61, a + 0xE667, 0x3000, 0x0B66, 0x0366, // 0x62, b + 0x3E00, 0x3100, 0x0E33, 0x0130, // 0x63, c + 0xE008, 0x3333, 0x0E33, 0x0633, // 0x64, d + 0x3E00, 0x3100, 0x0E3F, 0x0103, // 0x65, e + 0xF66C, 0x0031, 0x0F66, 0x0000, // 0x66, f + 0x3E00, 0x3600, 0xF0E3, 0x1333, // 0x67, g + 0xE667, 0x6300, 0x0766, 0x0666, // 0x68, h + 0xCE0C, 0x0000, 0x0ECC, 0x0100, // 0x69, i + 0x0000, 0x3303, 0xE330, 0x1333, // 0x6A, j + 0x6667, 0x3600, 0x076E, 0x0631, // 0x6B, k + 0xCCCE, 0x0000, 0x0ECC, 0x0100, // 0x6C, l + 0xF300, 0x7300, 0x03BF, 0x0667, // 0x6D, m + 0x3F00, 0x3100, 0x0333, 0x0333, // 0x6E, n + 0x3E00, 0x3100, 0x0E33, 0x0133, // 0x6F, o + 0x6B00, 0x6300, 0xF6E6, 0x0036, // 0x70, p + 0x3E00, 0x3600, 0x80E3, 0x7333, // 0x71, q + 0xEB00, 0x6300, 0x0F66, 0x0006, // 0x72, r + 0x3E00, 0x0300, 0x0F0E, 0x0131, // 0x73, s + 0xCEC8, 0x0300, 0x08CC, 0x0120, // 0x74, t + 0x3300, 0x3300, 0x0E33, 0x0633, // 0x75, u + 0x3300, 0x3300, 0x0CE3, 0x0013, // 0x76, v + 0xB300, 0x6600, 0x06FF, 0x0377, // 0x77, w + 0x6300, 0x3600, 0x036C, 0x0631, // 0x78, x + 0x3300, 0x3300, 0xF0E3, 0x1333, // 0x79, y + 0x9F00, 0x1300, 0x0F6C, 0x0320, // 0x7A, z + 0x7CC8, 0x0003, 0x08CC, 0x0300, // 0x7B, { + 0x0888, 0x0111, 0x0888, 0x0111, // 0x7C, | + 0x8CC7, 0x3000, 0x07CC, 0x0000, // 0x7D, } + 0x00BE, 0x0036, 0x0000, 0x0000, // 0x7E, ~ + 0x6C80, 0x3100, 0x0F33, 0x0766, // 0x7F, DEL, HOUSE + 0x333E, 0x3031, 0xE08E, 0x1311, // 0x80, Ç + 0x3030, 0x3030, 0x0E33, 0x0733, // 0x81, ü + 0x3E08, 0x3103, 0x0E3F, 0x0103, // 0x82, é + 0x0C3E, 0x63C7, 0x0C6C, 0x0F67, // 0x83, â + 0x0E03, 0x3103, 0x0E3E, 0x0733, // 0x84, ä + 0x0E07, 0x3100, 0x0E3E, 0x0733, // 0x85, à + 0x0ECC, 0x3100, 0x0E3E, 0x0733, // 0x86, å + 0x3E00, 0x0100, 0xC0E3, 0x1310, // 0x87, ç + 0x6C3E, 0x63C7, 0x0C6E, 0x0307, // 0x88, ê + 0x3E03, 0x3103, 0x0E3F, 0x0103, // 0x89, ë + 0x3E07, 0x3100, 0x0E3F, 0x0103, // 0x8A, è + 0xCE03, 0x0003, 0x0ECC, 0x0100, // 0x8B, ï + 0x8C3E, 0x1163, 0x0C88, 0x0311, // 0x8C, î + 0xCE07, 0x0000, 0x0ECC, 0x0100, // 0x8D, ì + 0x36C3, 0x6316, 0x033F, 0x0667, // 0x8E, Ä + 0xE0CC, 0x1000, 0x03F3, 0x0333, // 0x8F, Å + 0x6F08, 0x0303, 0x0F6E, 0x0301, // 0x90, É + 0x0E00, 0x3F00, 0x0E3E, 0x0F3F, // 0x91, æ + 0xF36C, 0x7337, 0x0333, 0x0733, // 0x92, Æ + 0xE03E, 0x1031, 0x0E33, 0x0133, // 0x93, ô + 0xE030, 0x1030, 0x0E33, 0x0133, // 0x94, ö + 0xE070, 0x1000, 0x0E33, 0x0133, // 0x95, ò + 0x303E, 0x3031, 0x0E33, 0x0733, // 0x96, û + 0x3070, 0x3000, 0x0E33, 0x0733, // 0x97, ù + 0x3030, 0x3030, 0xF0E3, 0x1333, // 0x98, ÿ + 0x6C83, 0x631C, 0x08C6, 0x0136, // 0x99, Ö + 0x3303, 0x3303, 0x0E33, 0x0133, // 0x9A, Ü + 0x3E88, 0x0711, 0x88E3, 0x1170, // 0x9B, ¢ + 0xF66C, 0x0231, 0x0F76, 0x0360, // 0x9C, £ + 0xFE33, 0x3133, 0xCCFC, 0x0030, // 0x9D, ¥ + 0xF33F, 0x5331, 0x3333, 0xE6F6, // 0x9E, ₧ + 0xC880, 0x31D7, 0xEB88, 0x0111, // 0x9F, ƒ + 0x0E08, 0x3103, 0x0E3E, 0x0733, // 0xA0, á + 0xCE0C, 0x0001, 0x0ECC, 0x0100, // 0xA1, í + 0xE080, 0x1030, 0x0E33, 0x0133, // 0xA2, ó + 0x3080, 0x3030, 0x0E33, 0x0733, // 0xA3, ú + 0xF0F0, 0x1010, 0x0333, 0x0333, // 0xA4, ñ + 0x730F, 0x3303, 0x03BF, 0x0333, // 0xA5, Ñ + 0xC66C, 0x7333, 0x00E0, 0x0070, // 0xA6, ª + 0xC66C, 0x1331, 0x00E0, 0x0030, // 0xA7, º + 0x6C0C, 0x0000, 0x0E33, 0x0130, // 0xA8, ¿ + 0xF000, 0x3000, 0x0033, 0x0000, // 0xA9, ⌐ + 0xF000, 0x3000, 0x0000, 0x0033, // 0xAA, ¬ + 0xB333, 0x736C, 0x036C, 0xF36C, // 0xAB, ½ + 0xB333, 0xD36C, 0x036C, 0xCFFE, // 0xAC, ¼ + 0x8088, 0x1011, 0x0888, 0x0111, // 0xAD, ¡ + 0x36C0, 0x36C0, 0x00C6, 0x00C6, // 0xAE, « + 0xC630, 0xC630, 0x0036, 0x0036, // 0xAF, » + 0x1414, 0x1414, 0x1414, 0x1414, // 0xB0, ░ + 0x5A5A, 0x5A5A, 0x5A5A, 0x5A5A, // 0xB1, ▒ + 0xBEBE, 0xBEBE, 0xBEBE, 0xBEBE, // 0xB2, ▓ + 0x8888, 0x1111, 0x8888, 0x1111, // 0xB3, │ + 0x8888, 0x1111, 0x888F, 0x1111, // 0xB4, ┤ + 0x8F88, 0x1111, 0x888F, 0x1111, // 0xB5, ╡ + 0xCCCC, 0x6666, 0xCCCF, 0x6666, // 0xB6, ╢ + 0x0000, 0x0000, 0xCCCF, 0x6667, // 0xB7, ╖ + 0x8F00, 0x1100, 0x888F, 0x1111, // 0xB8, ╕ + 0x0FCC, 0x6666, 0xCCCF, 0x6666, // 0xB9, ╣ + 0xCCCC, 0x6666, 0xCCCC, 0x6666, // 0xBA, ║ + 0x0F00, 0x6700, 0xCCCF, 0x6666, // 0xBB, ╗ + 0x0FCC, 0x6666, 0x000F, 0x0007, // 0xBC, ╝ + 0xCCCC, 0x6666, 0x000F, 0x0007, // 0xBD, ╜ + 0x8F88, 0x1111, 0x000F, 0x0001, // 0xBE, ╛ + 0x0000, 0x0000, 0x888F, 0x1111, // 0xBF, ┐ + 0x8888, 0x1111, 0x0008, 0x000F, // 0xC0, └ + 0x8888, 0x1111, 0x000F, 0x000F, // 0xC1, ┴ + 0x0000, 0x0000, 0x888F, 0x111F, // 0xC2, ┬ + 0x8888, 0x1111, 0x8888, 0x111F, // 0xC3, ├ + 0x0000, 0x0000, 0x000F, 0x000F, // 0xC4, ─ + 0x8888, 0x1111, 0x888F, 0x111F, // 0xC5, ┼ + 0x8888, 0x1F11, 0x8888, 0x111F, // 0xC6, ╞ + 0xCCCC, 0x6666, 0xCCCC, 0x666E, // 0xC7, ╟ + 0xCCCC, 0x0E66, 0x000C, 0x000F, // 0xC8, ╚ + 0xCC00, 0x0F00, 0xCCCC, 0x666E, // 0xC9, ╔ + 0x0FCC, 0x0E66, 0x000F, 0x000F, // 0xCA, ╩ + 0x0F00, 0x0F00, 0xCCCF, 0x666E, // 0xCB, ╦ + 0xCCCC, 0x0E66, 0xCCCC, 0x666E, // 0xCC, ╠ + 0x0F00, 0x0F00, 0x000F, 0x000F, // 0xCD, ═ + 0x0FCC, 0x0E66, 0xCCCF, 0x666E, // 0xCE, ╬ + 0x0F88, 0x0F11, 0x000F, 0x000F, // 0xCF, ╧ + 0xCCCC, 0x6666, 0x000F, 0x000F, // 0xD0, ╨ + 0x0F00, 0x0F00, 0x888F, 0x111F, // 0xD1, ╤ + 0x0000, 0x0000, 0xCCCF, 0x666F, // 0xD2, ╥ + 0xCCCC, 0x6666, 0x000C, 0x000F, // 0xD3, ╙ + 0x8888, 0x1F11, 0x0008, 0x000F, // 0xD4, ╘ + 0x8800, 0x1F00, 0x8888, 0x111F, // 0xD5, ╒ + 0x0000, 0x0000, 0xCCCC, 0x666F, // 0xD6, ╓ + 0xCCCC, 0x6666, 0xCCCF, 0x666F, // 0xD7, ╫ + 0x8F88, 0x1F11, 0x888F, 0x111F, // 0xD8, ╪ + 0x8888, 0x1111, 0x000F, 0x0001, // 0xD9, ┘ + 0x0000, 0x0000, 0x8888, 0x111F, // 0xDA, ┌ + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0xDB, █ + 0x0000, 0x0000, 0xFFFF, 0xFFFF, // 0xDC, ▄ + 0xFFFF, 0x0000, 0xFFFF, 0x0000, // 0xDD, ▌ + 0x0000, 0xFFFF, 0x0000, 0xFFFF, // 0xDE, ▐ + 0xFFFF, 0xFFFF, 0x0000, 0x0000, // 0xDF, ▀ + 0xBE00, 0x3600, 0x0EB3, 0x0631, // 0xE0, α + 0xF3E0, 0x1310, 0x33F3, 0x0013, // 0xE1, ß + 0x33F0, 0x0330, 0x0333, 0x0000, // 0xE2, Γ + 0x66F0, 0x3370, 0x0666, 0x0333, // 0xE3, π + 0xC63F, 0x0033, 0x0F36, 0x0330, // 0xE4, Σ + 0xBE00, 0x1700, 0x0EBB, 0x0011, // 0xE5, σ + 0x6660, 0x6660, 0x36E6, 0x0036, // 0xE6, µ + 0x8BE0, 0x1360, 0x0888, 0x0111, // 0xE7, τ + 0x3ECF, 0x3103, 0xFCE3, 0x3013, // 0xE8, Φ + 0xF36C, 0x7631, 0x0C63, 0x0136, // 0xE9, Θ + 0x336C, 0x6631, 0x0766, 0x0733, // 0xEA, Ω + 0xE8C8, 0x3103, 0x0E33, 0x0133, // 0xEB, δ + 0xBE00, 0xD700, 0x00EB, 0x007D, // 0xEC, ∞ + 0xBE00, 0xD736, 0x36EB, 0x007D, // 0xED, φ + 0xF36C, 0x1001, 0x0C63, 0x0100, // 0xEE, ε + 0x333E, 0x3331, 0x0333, 0x0333, // 0xEF, ∩ + 0xF0F0, 0x3030, 0x00F0, 0x0030, // 0xF0, ≡ + 0xCFCC, 0x0300, 0x0F0C, 0x0300, // 0xF1, ± + 0xC8C6, 0x0100, 0x0F06, 0x0300, // 0xF2, ≥ + 0xC6C8, 0x0001, 0x0F08, 0x0301, // 0xF3, ≤ + 0x8880, 0x1DD7, 0x8888, 0x1111, // 0xF4, ⌠ + 0x8888, 0x1111, 0xEBB8, 0x0111, // 0xF5, ⌡ + 0xF0CC, 0x3000, 0x0CC0, 0x0000, // 0xF6, ÷ + 0x0BE0, 0x0360, 0x00BE, 0x0036, // 0xF7, ≈ + 0xC66C, 0x1331, 0x0000, 0x0000, // 0xF8, ° + 0x8000, 0x1000, 0x0008, 0x0001, // 0xF9, ∙ + 0x0000, 0x0000, 0x0008, 0x0001, // 0xFA, · + 0x0000, 0x333F, 0x8C67, 0x3333, // 0xFB, √ + 0x666E, 0x3331, 0x0006, 0x0003, // 0xFC, ⁿ + 0x6C8E, 0x0010, 0x000E, 0x0001, // 0xFD, ² + 0xCC00, 0x3300, 0x00CC, 0x0033, // 0xFE, ■ + 0x0000, 0x0000, 0x0000, 0x0000, // 0xFF, NBSP +}; + +const int charsets[] = { + 0x30, 10, // NUMBERS + 0x41, 26, // UPPERCASE LETTERS + 0x61, 26, // LOWERCASE LETTERS + 0x01, 15, // SYMBOLS + 0x18, 4, // ARROWS + 0xB3, 40, // BARS + 0xE0, 16, // GREEK + 0x80, 28, // ACCENTS + 0xB0, 3, // SHADES +}; + +#define CHARSETS 8 + +const int hex_chars[] = { + 0x30, + 0x31, + 0x32, + 0x33, + 0x34, + 0x35, + 0x36, + 0x37, + 0x38, + 0x39, + 0x41, + 0x42, + 0x43, + 0x44, + 0x45, + 0x46, +}; + +bool char(vec2 pos, int code) +{ + if (pos.x < 0.0 || pos.y < 0.0 || pos.x >= 1.0 || pos.y >= 1.0) { + return false; + } + ivec2 pos2 = ivec2(pos.x * 8.0, (1 - pos.y) * 8.0); + ivec2 subpos = pos2 % 4; + int v = int(pow(2, subpos.y * 4 + subpos.x)); + int d = int(pos2.y * 0.25) * 2 + int(pos2.x * 0.25); + return (cp437[code * 4 + d] & v) > 0; +} + +float char_at(vec2 uv, vec2 pos, int code) +{ + return char(uv - pos, code) ? 1 : 0; +} + +float write_5(vec2 uv, vec2 pos, int str[5]) +{ + float d = 0; + int i; + + for (i = 0; i < 5; i++) { + if (str[i] == 0) { + return d; + } + + d += char_at(uv, pos + vec2(i, 0), str[i]); + } + + return d; +} + +float write_10(vec2 uv, vec2 pos, int str[10]) +{ + float d = 0; + int i; + + for (i = 0; i < 10; i++) { + if (str[i] == 0) { + return d; + } + + d += char_at(uv, pos + vec2(i, 0), str[i]); + } + + return d; +} + +float write_20(vec2 uv, vec2 pos, int str[20]) +{ + float d = 0; + int i; + + for (i = 0; i < 20; i++) { + if (str[i] == 0) { + return d; + } + + d += char_at(uv, pos + vec2(i, 0), str[i]); + } + + return d; +} + +float write_int(vec2 uv, vec2 pos, uint value, uint magnitude) +{ + int i; + uint m = 1; + float d = 0; + for (i = 0; i < magnitude; i++) { + if (i == 0 || value >= m) { + d += char_at(uv, pos + vec2(magnitude - i - 1, 0), int(0x30 + (value % (m * 10u)) / m)); + m *= 10u; + } + } + return d; +} + +float write_int_left(vec2 uv, vec2 pos, uint value, uint magnitude) +{ + int i; + uint m = 1; + float d = 0; + for (i = 0; i < magnitude; i++) { + if (i == 0 || value >= m) { + pos.x += 1; + m *= 10u; + } + } + return write_int(uv, pos, value, magnitude); +} + +int read(sampler2D tex, vec2 uv, float k, int d, float t) +{ + float inv_k = 1 / k; + vec2 tex_uv = floor(uv * k) * inv_k; + tex_uv += vec2(d % 2, floor(d * 0.5)) * 0.5 * inv_k; + return + ((mean(reframe(tex, tex_uv + vec2(0, 3) * inv_k * 0.125)) > t) ? 1 : 0) + + ((mean(reframe(tex, tex_uv + vec2(0, 2) * inv_k * 0.125)) > t) ? 2 : 0) + + ((mean(reframe(tex, tex_uv + vec2(0, 1) * inv_k * 0.125)) > t) ? 4 : 0) + + ((mean(reframe(tex, tex_uv + vec2(0, 0) * inv_k * 0.125)) > t) ? 8 : 0) + + ((mean(reframe(tex, tex_uv + vec2(1, 3) * inv_k * 0.125)) > t) ? 16 : 0) + + ((mean(reframe(tex, tex_uv + vec2(1, 2) * inv_k * 0.125)) > t) ? 32 : 0) + + ((mean(reframe(tex, tex_uv + vec2(1, 1) * inv_k * 0.125)) > t) ? 64 : 0) + + ((mean(reframe(tex, tex_uv + vec2(1, 0) * inv_k * 0.125)) > t) ? 128 : 0) + + ((mean(reframe(tex, tex_uv + vec2(2, 3) * inv_k * 0.125)) > t) ? 256 : 0) + + ((mean(reframe(tex, tex_uv + vec2(2, 2) * inv_k * 0.125)) > t) ? 512 : 0) + + ((mean(reframe(tex, tex_uv + vec2(2, 1) * inv_k * 0.125)) > t) ? 1024 : 0) + + ((mean(reframe(tex, tex_uv + vec2(2, 0) * inv_k * 0.125)) > t) ? 2048 : 0) + + ((mean(reframe(tex, tex_uv + vec2(3, 3) * inv_k * 0.125)) > t) ? 4096 : 0) + + ((mean(reframe(tex, tex_uv + vec2(3, 2) * inv_k * 0.125)) > t) ? 8192 : 0) + + ((mean(reframe(tex, tex_uv + vec2(3, 1) * inv_k * 0.125)) > t) ? 16384 : 0) + + ((mean(reframe(tex, tex_uv + vec2(3, 0) * inv_k * 0.125)) > t) ? 32768 : 0); +} + +// https://web.archive.org/web/20151229003112/http://blogs.msdn.com/b/jeuge/archive/2005/06/08/hakmem-bit-count.aspx +int bit_count(int u) +{ + int c; + c = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); + return ((c + (c >> 3)) & 030707070707) % 63; +} + +int guess_char(sampler2D tex, vec2 uv, float k, float t) +{ + int b0 = read(tex, uv, k, 0, t); + int b1 = read(tex, uv, k, 1, t); + int b2 = read(tex, uv, k, 2, t); + int b3 = read(tex, uv, k, 3, t); + + int mc = 0; + int mb = 100; + int i; + int b; + + for (i = 0x01; i <= 0xFF; i++) { + if (i == 0x20 || i == 0xff || i == 0xDB) { + continue; + } + b = bit_count(cp437[i * 4] ^ b0) + bit_count(cp437[i * 4 + 1] ^ b1) + bit_count(cp437[i * 4 + 2] ^ b2) + + bit_count(cp437[i * 4 + 3] ^ b3); + if (b < mb) { + mb = b; + mc = i; + } + } + + return mc; +} + +#endif diff --git a/project/inc_functions.glsl b/project/inc_functions.glsl new file mode 100644 index 0000000..f9c9b6b --- /dev/null +++ b/project/inc_functions.glsl @@ -0,0 +1,405 @@ +#ifndef PI +#define PI 3.1415927 +#endif + +#include inc_time.glsl +#include inc_rand.glsl +#include inc_res.glsl + +#ifndef INC_FUNCTIONS +#define INC_FUNCTIONS + +// BASICS + +float istep(float x, float y) { + return 1 - step(x, y); +} + +float estep(float x, float y) { + return smoothstep(x - 0.0001, x + 0.0001, y); +} + +float iestep(float x, float y) { + return 1 - estep(x, y); +} + +float ease(float x) { + return 0.5 - cos(max(min(x, 1.0), 0.0) * PI) * 0.5; +} + +vec2 ease(vec2 x) { + return 0.5 - cos(max(min(x, 1.0), 0.0) * PI) * 0.5; +} + +vec3 ease(vec3 x) { + return 0.5 - cos(max(min(x, 1.0), 0.0) * PI) * 0.5; +} + +float saw(float x) { + return abs(mod(x + 1, 2) - 1); +} + +vec2 saw(vec2 x) { + return abs(mod(x + 1, 2) - 1); +} + +vec3 saw(vec3 x) { + return abs(mod(x + 1, 2) - 1); +} + +float cmod(float x, float k) { + return mod(x + k * 0.5, k) - k * 0.5; +} + +vec2 cmod(vec2 x, float k) { + return mod(x + k * 0.5, k) - k * 0.5; +} + +vec3 cmod(vec3 x, float k) { + return mod(x + k * 0.5, k) - k * 0.5; +} + +// COLORS + +vec3 col(float x) { + return vec3( + .5 * (sin(x * 2. * PI) + 1.), + .5 * (sin(x * 2. * PI + 2. * PI / 3.) + 1.), + .5 * (sin(x * 2. * PI - 2. * PI / 3.) + 1.) + ); +} + +vec3 shift(vec3 c, float f) { + return vec3( + c.x * (1 - f) + c.y * f, + c.y * (1 - f) + c.z * f, + c.z * (1 - f) + c.x * f + ); +} + +vec3 shift3(vec3 c, float f) { + return shift(shift(shift(c, f), f), f); +} + +vec3 mix3(vec3 c1, vec3 c2, vec3 c3, float x) { + return istep(0.5, x) * mix(c1, c2, x * 2) + + step(0.5, x) * mix(c2, c3, x * 2 - 1); +} + +vec3 mix4(vec3 c1, vec3 c2, vec3 c3, vec3 c4, float x) { + return istep(0.333, x) * mix(c1, c2, x * 3) + + step(0.333, x) * istep(0.667, x) * mix(c2, c3, x * 3 - 1) + + step(0.667, x) * mix(c3, c4, x * 3 - 2); + ; +} + +vec3 mix5(vec3 c1, vec3 c2, vec3 c3, vec3 c4, vec3 c5, float x) { + return istep(0.25, x) * mix(c1, c2, x * 4) + + step(0.25, x) * istep(0.5, x) * mix(c2, c3, x * 4 - 1) + + step(0.5, x) * istep(0.75, x) * mix(c3, c4, x * 4 - 2) + + step(0.75, x) * mix(c4, c5, x * 4 - 3); +} + +vec3 mix6(vec3 c1, vec3 c2, vec3 c3, vec3 c4, vec3 c5, vec3 c6, float x) { + return istep(0.2, x) * mix(c1, c2, x * 5) + + step(0.2, x) * istep(0.4, x) * mix(c2, c3, x * 5 - 1) + + step(0.4, x) * istep(0.6, x) * mix(c3, c4, x * 5 - 2) + + step(0.6, x) * istep(0.8, x) * mix(c4, c5, x * 5 - 3) + + step(0.8, x) * mix(c5, c6, x * 5 - 4); +} + +float mean(vec3 v) +{ + return v.x * 0.3333 + v.y * 0.3333 + v.z * 0.3333; +} + +float mean(vec4 v) +{ + return v.x * 0.3333 + v.y * 0.3333 + v.z * 0.3333; +} + +// OTHER + +mat2 rot(float angle) { + return mat2( + cos(angle * 2. * PI), -sin(angle * 2. * PI), + sin(angle * 2. * PI), cos(angle * 2. * PI) + ); +} + +// EFFECTS + +vec2 lens(vec2 uv, float limit, float power) { + return uv * (1 + limit + length(uv * power)); +} + +vec2 kal(vec2 uv, float n) { + float t = atan(uv.y, uv.x) + PI * 0.5; + float q = 3.0 / (2.0 * PI); + t = abs(mod(t + PI / (n), 2 * PI / n) - PI / (n)); + return length(uv) * vec2( + cos(t), + sin(t) + ); +} + +vec2 kal2(vec2 uv, float n) { + float t = atan(uv.y, uv.x) + PI * 0.5; + float t2 = abs(mod(t + PI / n, 2 * PI / n) - PI / n); + return length(uv) * vec2( + cos(t2), + sin(t2) + ); +} + +// NOISE + +float noise(vec2 n) +{ + const vec2 d = vec2(0, 1); + vec2 b = floor(n); + vec2 f = fract(n); + f *= f * (3 - 2 * f); + return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y); +} + +float noise_f(vec2 n, int f) +{ + float o = noise(n) / 2; + o += mix(o, noise(n * 2), f > 1 ? 1 : 0) / 4; + o += mix(o, noise(n * 4), f > 2 ? 1 : 0) / 8; + o += mix(o, noise(n * 8), f > 3 ? 1 : 0) / 16; + o += mix(o, noise(n * 16), f > 4 ? 1 : 0) / 32; + return o; +} + +// VORONOI + +float v_index(vec2 uv) { + return floor(uv.x) + floor(uv.y) * 45; +} + +vec2 v_pos(float i, int seed, float time) { + int iTimeId = int(time); + float iTimeV = time - iTimeId; + + float x0 = rand(i + seed + iTimeId); + float y0 = rand(i + seed + 10 + iTimeId); + + float x1 = rand(i + seed + iTimeId + 1); + float y1 = rand(i + seed + 10 + iTimeId + 1); + + return vec2( + mix(x0, x1, ease(ease(iTimeV))), + mix(y0, y1, ease(ease(iTimeV))) + ); +} + +vec4 voronoi(vec2 uv, float dist, int seed, float time) { + vec4 o = vec4(0, 0, 2, 0); + vec4 t = vec4(0, 0, 2, 0); + float d, i; + vec2 uv2, p; + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + uv2 = vec2(floor(uv.x) + dx, floor(uv.y) + dy); + i = v_index(uv2); + p = uv2 + v_pos(i, seed, time) * dist; + d = length(p - uv); + if (d < o.z) { + t = o; + o = vec4(p, d, i); + } else if (d < t.z) { + t = vec4(p, d, i); + } + } + } + return vec4(o.z, t.z, o.w, t.w); +} + +// SHAPES + +float circle(vec2 uv, vec2 c, float size) { + return istep(size, length(uv - c)); +} + +float h_circle(vec2 uv, vec2 c, float size, float k) { + return circle(uv, c, size + k * 0.5) - circle(uv, c, size - k * 0.5); +} + +float stripe(float x, float k1, float k2) +{ + return k2 > k1 ? (1 - step(x, k1)) * (step(x, k2)) : ((1 - step(x, k2)) * (step(x, k1))); +} + +float capsule(vec2 uv, float r, float d, float a) +{ + uv *= rot(a); + float f1 = step(uv.x, r) * step(-uv.x, r) * step(uv.y, d - r) * step(-uv.y, d - r); + float f2 = step(length(uv - vec2(0, d - r)), r); + float f3 = step(length(uv + vec2(0, d - r)), r); + return min(1, f1 + f2 + f3); +} + +float rect(vec2 uv, vec2 c, vec2 size) { + uv -= c; + return step(abs(uv.x), size.x) * step(abs(uv.y), size.y); +} + +float h_rect(vec2 uv, vec2 c, vec2 size, float k) { + return rect(uv, c, size + k * 0.5) - rect(uv, c, size - k * 0.5); +} + +float line(vec2 uv, vec2 p1, vec2 p2, float thick) { + vec2 p = p2 - p1; + uv -= p1; + vec2 k; + + if (abs(p.y) > abs(p.x)) { + k = vec2( + uv.x - p.x * uv.y / p.y, + uv.y / p.y + ); + + return step(k.x, thick * 0.5) + * step(-k.x, thick * 0.5) + * step(k.y, 1) + * (1 - step(k.y, 0)); + } else { + k = vec2( + uv.x / p.x, + uv.y - p.y * uv.x / p.x + ); + + return step(k.y, thick * 0.5) + * step(-k.y, thick * 0.5) + * step(k.x, 1) + * (1 - step(k.x, 0)); + } +} + +const mat2x2 ISOMETRIC_MATRIX = { + { + 0.5, + 1 + }, + { + 0.5, + -1 + } + }; + +vec2 iso(vec2 p) { + return p * ISOMETRIC_MATRIX; +} + +vec2 iso_z(float z) { + return vec2( + -z, + z + ); +} + +vec2 iso(vec3 uv) { + return iso(uv.xy) + iso_z(uv.z); +} + +// INPUTS + +vec4 reframe(sampler2D tex, vec2 uv) +{ + uv = uv * vec2(iResolution.y / iResolution.x, 1) + .5; + uv = saw(uv); + return texture(tex, uv); +} + +vec4 reframe_b(sampler2D tex, vec2 uv) +{ + uv = uv * vec2(iResolution.y / iResolution.x, 1) + .5; + return texture(tex, uv); +} + +vec4 kernel(sampler2D tex, vec2 uv, mat3x3 k, float spm) +{ + int x, y; + vec2 offset; + vec4 sum = vec4(0); + for (y = -1; y <= 1; ++y) { + for (x = -1; x <= 1; ++x) { + offset = vec2(x, y) * spm; + if (abs(k[x + 1][y + 1]) > 0) { + sum += k[x + 1][y + 1] * texture(tex, uv + offset); + } + } + } + return sum; +} + +// BLUR + +float gaussian_weight(float x, float sigma) +{ + return exp(-(x * x) / (2.0 * sigma * sigma)); +} + +vec4 gauss(sampler2D tex, vec2 uv, const int kernel_size, float spm, float sigma, float bloom) +{ + int x, y; + vec2 offset; + float w; + vec4 sum = vec4(0); + float weight_sum = 0; + for (y = -kernel_size; y <= kernel_size; ++y) { + for (x = -kernel_size; x <= kernel_size; ++x) { + offset = vec2(x, y) * spm; + w = gaussian_weight(length(vec2(x, y)), sigma); + sum += texture(tex, uv + offset) * w; + weight_sum += w; + } + } + return (sum / weight_sum) * bloom; +} + +vec4 gauss(sampler2D tex, vec2 uv, const int kernel_size, float spm, float sigma) +{ + return gauss(tex, uv, kernel_size, spm, sigma, 1.0); +} + +vec4 gauss(sampler2D tex, vec2 uv, const int kernel_size, float spm) +{ + return gauss(tex, uv, kernel_size, spm, 2.0); +} + +vec4 gauss(sampler2D tex, vec2 uv, const int kernel_size) +{ + return gauss(tex, uv, kernel_size, 1 / max(iResolution.x, iResolution.y)); +} + +vec4 gauss(sampler2D tex, vec2 uv) +{ + return gauss(tex, uv, 3); +} + +float dither(vec2 uv, float x) +{ + bool o = false; + o = o || x * 16 >= 1 && floor(mod(uv.x, 4)) == 0 && floor(mod(uv.y, 4)) == 0; + o = o || x * 16 >= 2 && floor(mod(uv.x, 4)) == 2 && floor(mod(uv.y, 4)) == 2; + o = o || x * 16 >= 3 && floor(mod(uv.x, 4)) == 0 && floor(mod(uv.y, 4)) == 2; + o = o || x * 16 >= 4 && floor(mod(uv.x, 4)) == 2 && floor(mod(uv.y, 4)) == 0; + o = o || x * 16 >= 5 && floor(mod(uv.x, 4)) == 1 && floor(mod(uv.y, 4)) == 1; + o = o || x * 16 >= 6 && floor(mod(uv.x, 4)) == 3 && floor(mod(uv.y, 4)) == 3; + o = o || x * 16 >= 7 && floor(mod(uv.x, 4)) == 1 && floor(mod(uv.y, 4)) == 3; + o = o || x * 16 >= 8 && floor(mod(uv.x, 4)) == 3 && floor(mod(uv.y, 4)) == 1; + o = o || x * 16 >= 9 && floor(mod(uv.x, 4)) == 1 && floor(mod(uv.y, 4)) == 0; + o = o || x * 16 >= 10 && floor(mod(uv.x, 4)) == 3 && floor(mod(uv.y, 4)) == 2; + o = o || x * 16 >= 11 && floor(mod(uv.x, 4)) == 1 && floor(mod(uv.y, 4)) == 2; + o = o || x * 16 >= 12 && floor(mod(uv.x, 4)) == 3 && floor(mod(uv.y, 4)) == 0; + o = o || x * 16 >= 13 && floor(mod(uv.x, 4)) == 0 && floor(mod(uv.y, 4)) == 1; + o = o || x * 16 >= 14 && floor(mod(uv.x, 4)) == 2 && floor(mod(uv.y, 4)) == 3; + o = o || x * 16 >= 15 && floor(mod(uv.x, 4)) == 0 && floor(mod(uv.y, 4)) == 3; + o = o || x * 16 >= 16 && floor(mod(uv.x, 4)) == 2 && floor(mod(uv.y, 4)) == 1; + return o ? 1 : 0; +} + +#endif diff --git a/project/inc_fx.glsl b/project/inc_fx.glsl new file mode 100644 index 0000000..e8aa96a --- /dev/null +++ b/project/inc_fx.glsl @@ -0,0 +1,562 @@ +#include inc_res.glsl +#include inc_magic.glsl +#include inc_functions.glsl + +#ifndef INC_FX +#define INC_FX + +vec4 fx_master(vec3 c0, vec3 c, int seed, vec3 m0) { + float fx = magic(m0.xy, vec3(1,0,0), seed); + bool invert = magic_trigger(vec3(m0.z, 0, 0), seed); + + vec3 c_out = mix(c0, c, fx); + + c_out = mix(c_out, 1 - c_out, invert ? 1 : 0); + + return vec4(c_out, 1.0); +} + +subroutine vec4 fx_stage_sub(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0); + +subroutine uniform fx_stage_sub fx_stage; + +// FX 1 : thru +subroutine(fx_stage_sub) vec4 fx_1(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + + // controls + + float hue = magic(f1, b1, seed + 10); + float saturation = magic(f2, b2, seed + 20); + float light = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + vec3 c = c0; + c = shift3(c, hue); + c *= 1 + saturation; + c = mix(c + light * 2.0, c - (1 - light) * 2.0, step(0.5, light)); + + return fx_master(c0, c, seed, m0); +} + +// FX 2 : feedback + shift +vec4 fx_shift(vec2 vUV, sampler2D src0, sampler2D src1, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = magic(f1, b1, seed + 10); + float x_shift = magic(f2, b2, seed + 20); + float y_shift = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(src0, uv0).xyz; + + vec2 uv2 = uv1; + uv2 = mix(uv2 * (1 + zoom * 2), uv2 * (zoom), step(0.5, zoom)); + uv2 += vec2(x_shift * ratio, y_shift) * 2; + vec3 c = reframe(src1, uv2).xyz; + + return fx_master(c0, c, seed, m0); +} + +subroutine(fx_stage_sub) vec4 fx_2(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + return fx_shift(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); +} + +// FX 3 : shift +subroutine(fx_stage_sub) vec4 fx_3(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + return fx_shift(vUV, previous, previous, seed, b1, f1, b2, f2, b3, f3, m0); +} + +// FX 4 : colorize +subroutine(fx_stage_sub) vec4 fx_4(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + + // controls + + float c_black = magic(f1, b1, seed + 10); + bool c_black_trigger = magic_trigger(b1, seed + 10); + float c_white = magic(f2, b2, seed + 20); + bool c_white_trigger = magic_trigger(b2, seed + 20); + float delta = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + float f = mean(c0); + float c_mix = mix(c_black, c_white, f) + delta; + vec3 c = mix(c_black_trigger ? col(c_mix) : vec3(0), c_white_trigger ? col(c_mix) : vec3(1), f); + + return fx_master(c0, c, seed, m0); +} + +// FX 5 : quantize +subroutine(fx_stage_sub) vec4 fx_5(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float pixel_size = magic(f1, b1, seed + 10); + float quantize = magic(f2, b2, seed + 20); + bool quantize_trigger = magic_trigger(b2, seed + 20); + float blur = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + float pixel = (1 - pixel_size) * 250 + 25; + uv2 = round(uv2 * pixel) / pixel; + vec3 c = gauss(previous, uv2 * vec2(1 / ratio, 1) + .5, 3, 0.005 * blur).xyz; + float colors = (1 - quantize) * 10 + 1; + if (quantize_trigger) { + c = round(c * colors) / colors; + } + // c = mix(c, 1 - c, step(noise_f(uv0 * 10 + vec2(iTime * 0.1, 0), 5), 0.5)); + + return fx_master(c0, c, seed, m0); +} + +// FX 6 : dithering +subroutine(fx_stage_sub) vec4 fx_6(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float pixel_size = magic(f1, b1, seed + 10); + bool pixel_size_trigger = magic_trigger(b1, seed + 10); + float quantize = magic(f2, b2, seed + 20); + bool quantize_trigger = magic_trigger(b2, seed + 20); + float blur = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + float k1 = pow(2, 10 - floor(pixel_size * 5)); + float pixel = (1 - pixel_size) * 250 + 25; + if (pixel_size_trigger) { + uv2 = floor(uv2 * k1) / k1; + } + vec3 c = gauss(previous, uv2 * vec2(1 / ratio, 1) + .5, 3, 0.005 * blur).xyz; + float k3 = pow(2, 5 - floor(quantize * 5)); + if (quantize_trigger) { + c *= k3; + c = vec3( + mix(floor(c.x), ceil(c.x), dither(uv2 * k1, c.x - floor(c.x))), + mix(floor(c.y), ceil(c.y), dither(uv2 * k1, c.y - floor(c.y))), + mix(floor(c.z), ceil(c.z), dither(uv2 * k1, c.z - floor(c.z))) + ); + c /= k3; + } + + return fx_master(c0, c, seed, m0); +} + +// FX 7 : tv +subroutine(fx_stage_sub) vec4 fx_7(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float lens_v = magic(f1, b1, seed + 10); + float horizontal_noise = magic(f2, b2, seed + 20); + float zoom = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + float k1 = lens_v * 0.5; + uv2 *= 1 + zoom * 2; + uv2 = lens(uv2, -k1, k1); + float k = horizontal_noise; + vec3 c = vec3( + reframe_b(previous, uv2 + vec2((rand(uv0.y * 1000 + iTime) - 0.5) * k * 0.1)).x, + reframe_b(previous, uv2 + vec2((rand(uv0.y * 1100 + iTime) - 0.5) * k * 0.1)).y, + reframe_b(previous, uv2).z + ); + + return fx_master(c0, c, seed, m0); +} + +// FX 8 : kaleidoscope +subroutine(fx_stage_sub) vec4 fx_8(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float axes = magic(f1, b1, seed + 10); + float axes_trigger = magic_b(b1, seed + 10).x; + float rotation = magic(f2, b2, seed + 20); + float h_scroll = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + uv2 = mix(uv2, kal2(uv2 * rot(0.25), floor(axes * 9 + 1)) * vec2(1, -2) + vec2(0, -0.5), axes_trigger); + uv2 *= rot(rotation); + uv2.x = (saw(uv2.x / ratio + 0.5 + h_scroll * 2) - 0.5) * ratio; + vec3 c = reframe(previous, uv2).xyz; + + return fx_master(c0, c, seed, m0); +} + +#include inc_cp437.glsl + +// FX 9 : cp437 +subroutine(fx_stage_sub) vec4 fx_9(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = magic(f1, b1, seed + 10); + vec2 charset = magic_f(f2, b2, seed + 20); + vec3 charset_ctrl = magic_b(b2, seed + 20); + float char_delta = magic(f3, b3, seed + 30); + float t = magic(seed + 40); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + float k1 = 100 * (1 - zoom) + 10; + float inv_k = 1 / k1; + uv2 = floor(uv2 * k1) * inv_k; + int start_char = charset_ctrl.x > 0 ? charsets[int(charset.x * CHARSETS) * 2] : 0x01; + int char_span = int((charset_ctrl.x > 0 ? charsets[int(charset.x * CHARSETS) * 2 + 1] : 255)); + char_span = int(char_span * max(1 - charset.y, 1 / (char_span * 0.75))); + ivec2 uv2i = ivec2(uv2 * k1); + int code = ((charset_ctrl.y < 1 || (uv2i.x % 2 ^ uv2i.y % 2) > 0) ? 1 : 0) * (start_char + int((rand(uv2i) + char_delta) * char_span) % char_span); + vec3 c = reframe(previous, uv2 + vec2(0, 0) * inv_k * 0.125).xyz * 0.2 + + reframe(previous, uv2 + vec2(1, 0) * inv_k * 0.125).xyz * 0.2 + + reframe(previous, uv2 + vec2(1, 1) * inv_k * 0.125).xyz * 0.2 + + reframe(previous, uv2 + vec2(0, 1) * inv_k * 0.125).xyz * 0.2 + + reframe(previous, uv2 + vec2(0.5, 0.5) * inv_k * 0.125).xyz * 0.2; + c = char(mod(uv1 * k1, 1), code) ? c : vec3(0); + + return fx_master(c0, c, seed, m0); +} + +// FX 10 : lens +subroutine(fx_stage_sub) vec4 fx_10(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float lens_v1 = magic(f1, b1, seed + 10); + float lens_v2 = magic(f2, b2, seed + 20); + float zoom = magic(f3, b3, seed + 30); + float k = magic(seed + 40); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + uv2 *= 1 + zoom * 2; + uv2 = lens(uv2, -lens_v2 * 10, lens_v1 * 10); + vec3 c = reframe(previous, uv2).xyz; + + return fx_master(c0, c, seed, m0); +} + +// FX 11 : spill +subroutine(fx_stage_sub) vec4 fx_11(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float wall1 = magic(f1, b1, seed + 10); + float wall2 = magic(f2, b2, seed + 20); + float angle = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + uv2 *= rot(angle); + uv2.y = min(uv2.y, 1 - wall1); + uv2.y = -min(-uv2.y, 1 - wall2); + uv2 *= rot(-angle); + vec3 c = reframe(previous, uv2).xyz; + + return fx_master(c0, c, seed, m0); +} + +// FX 12 : Game Of Life +subroutine(fx_stage_sub) vec4 fx_12(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - 0.5) * vec2(ratio, 1); + + // controls + + float pixel_size = magic(f1, b1, seed + 10); + bool pixel_size_trigger = magic_trigger(b1, seed + 10); + f2 = magic_f(f2, b2, seed + 20); + int rule = int(f2.x * 12); + float threshold = f2.y * 0.9 + 0.05; + float fb = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + float k1 = pow(2, 9 - floor(pixel_size * 5)); + float p = 1 / k1; + uv2 = round(uv2 * k1) / k1; + vec3 c1 = mix( + reframe(previous, uv2 + vec2(0.5, 0.5) * p).xyz, + reframe(feedback, uv2 + vec2(0.5, 0.5) * p).xyz, + fb + ); + vec3 c2 = mix( + reframe(previous, uv2 + vec2(1.5, 0.5) * p).xyz, + reframe(feedback, uv2 + vec2(1.5, 0.5) * p).xyz, + fb + ); + vec3 c3 = mix( + reframe(previous, uv2 + vec2(1.5, 1.5) * p).xyz, + reframe(feedback, uv2 + vec2(1.5, 1.5) * p).xyz, + fb + ); + vec3 c4 = mix( + reframe(previous, uv2 + vec2(0.5, 1.5) * p).xyz, + reframe(feedback, uv2 + vec2(0.5, 1.5) * p).xyz, + fb + ); + vec3 c5 = mix( + reframe(previous, uv2 + vec2(-0.5, 1.5) * p).xyz, + reframe(feedback, uv2 + vec2(-0.5, 1.5) * p).xyz, + fb + ); + vec3 c6 = mix( + reframe(previous, uv2 + vec2(-0.5, 0.5) * p).xyz, + reframe(feedback, uv2 + vec2(-0.5, 0.5) * p).xyz, + fb + ); + vec3 c7 = mix( + reframe(previous, uv2 + vec2(-0.5, -0.5) * p).xyz, + reframe(feedback, uv2 + vec2(-0.5, -0.5) * p).xyz, + fb + ); + vec3 c8 = mix( + reframe(previous, uv2 + vec2(0.5, -0.5) * p).xyz, + reframe(feedback, uv2 + vec2(0.5, -0.5) * p).xyz, + fb + ); + vec3 c9 = mix( + reframe(previous, uv2 + vec2(-0.5, -0.5) * p).xyz, + reframe(feedback, uv2 + vec2(-0.5, -0.5) * p).xyz, + fb + ); + bool alive = mean(c1) >= threshold; + int n = 0 + + (mean(c2) >= threshold ? 1 : 0) + + (mean(c3) >= threshold ? 1 : 0) + + (mean(c4) >= threshold ? 1 : 0) + + (mean(c5) >= threshold ? 1 : 0) + + (mean(c6) >= threshold ? 1 : 0) + + (mean(c7) >= threshold ? 1 : 0) + + (mean(c8) >= threshold ? 1 : 0) + + (mean(c9) >= threshold ? 1 : 0) + ; + + if (rule == 0) { // B3/S23 (life) + alive = alive && n == 2 || n == 3; + } else if (rule == 1) { // B1357/S1357 (replicator) + alive = n == 2 || n == 3 || n == 5 || n == 7; + } else if (rule == 2) { // B2/S (seeds) + alive = !alive && n == 2; + } else if (rule == 3) { // B25/S4 + alive = !alive && (n == 2 || n == 5) || alive && n == 4; + } else if (rule == 4) { // B3/S012345678 (life without death) + alive = alive || n == 3; + } else if (rule == 5) { // B34/S34 (34 life) + alive = n == 3 || n ==4; + } else if (rule == 6) { // B35678/S5678 (Diamoeba) + alive = n >= 5 || !alive && n == 3; + } else if (rule == 7) { // B36/S125 (2x2) + alive = !alive && (n == 3 || n == 6) || alive && (n == 1 || n == 2 || n == 5); + } else if (rule == 8) { // B36/S23 (HighLife) + alive = !alive && n == 6 || alive && n == 2 || n == 3; + } else if (rule == 9) { // B3678/S34678 (Day & Night) + alive = n == 3 || n >= 6 || alive && n == 4; + } else if (rule == 10) { // B368/S245 (Morley) + alive = !alive && (n == 3 || n == 6 || n == 8) || alive && (n == 2 || n == 4 || n == 5); + } else if (rule == 11) { // B4678/S35678 (Anneal) + alive = n >= 6 || !alive && n == 4 || alive && (n == 3 || n == 5); + } + + vec3 cout = vec3(alive ? 1 : 0); + + return fx_master(c0, cout, seed, m0); +} + +// FX 13 : Sobel +subroutine(fx_stage_sub) vec4 fx_13(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float sx = magic(f1, b1, seed + 10) * 2; + float sy = magic(f2, b2, seed + 20) * 2; + float disp = 0.005 * magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + const mat3x3 sobelx = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; + const mat3x3 sobely = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; + + mat3x3 sobel = sobelx * sx + sobely * sy; + + vec3 c = abs(kernel(previous, uv0, sobel, disp).xyz); + + return fx_master(c0, c, seed, m0); +} + +// FX 14 : Isometric +subroutine(fx_stage_sub) vec4 fx_14(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = 1 + magic(f1, b1, seed + 10) * 9; + float h_scroll = magic(f2, b2, seed + 20); + float angle = magic(f3, b3, seed + 30); + + // logic + + vec3 c0 = texture(previous, uv0).xyz; + + vec2 uv2 = uv1; + + vec2 uv3 = iso(uv2); + + uv3 *= rot(angle); + + uv3 += vec2(h_scroll, 0); + + uv3 *= round(zoom); + + vec2 umax = vec2(round(zoom), 300); + + vec3 c = reframe(previous, mod(uv3, umax)).xyz; + + return fx_master(c0, c, seed, m0); +} + +// FX 15 : Random +subroutine(fx_stage_sub) vec4 fx_15(vec2 vUV, sampler2D previous, sampler2D feedback, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3, vec3 m0) +{ + int fx = int(randTime(seed + 100) * 14); + + if (fx == 0) { + return fx_1(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 1) { + return fx_2(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 2) { + return fx_3(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 3) { + return fx_4(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 4) { + return fx_5(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 5) { + return fx_6(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 6) { + return fx_7(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 7) { + return fx_8(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 8) { + return fx_9(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 9) { + return fx_10(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 10) { + return fx_11(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 11) { + return fx_12(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else if (fx == 12) { + return fx_13(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } else { + return fx_14(vUV, previous, feedback, seed, b1, f1, b2, f2, b3, f3, m0); + } +} + +#endif diff --git a/project/inc_magic.glsl b/project/inc_magic.glsl new file mode 100644 index 0000000..bf08bab --- /dev/null +++ b/project/inc_magic.glsl @@ -0,0 +1,77 @@ +#include inc_time.glsl + +#ifndef INC_MAGIC +#define INC_MAGIC + +vec2 magic_f(vec2 F, vec3 B, float i) +{ + return vec2( + mix(F.x, randTime(i + 1), min(1, B.z)), + mix(F.y, randTime(i + 2), min(1, B.z)) + ); +} + +vec2 magic_f(float i) +{ + return magic_f(vec2(0), vec3(0, 0, 1), i); +} + +vec3 magic_b(vec3 B, float i) +{ + return vec3( + mix(B.x, step(0.2, randTime(i + 3)), min(1, B.z)), + mix(B.y, step(0.5, randTime(i + 4)), min(1, B.z)), + min(1, B.z) + ); +} + +vec3 magic_b(float i) +{ + return magic_b(vec3(0, 0, 1), i); +} + +bool magic_trigger(vec3 B, float i) +{ + return magic_b(B, i).x > 0; +} + +bool magic_trigger(float i) +{ + return magic_b(i).x > 0; +} + +float magic(vec2 F, vec3 B, float i) +{ + vec2 f = magic_f(F, B, i); + vec3 b = magic_b(B, i); + + return mix(0, f.x * mix(1 - modTime(f.y), cosTime(f.y) * 0.5 + 0.5, b.y), b.x); +} + +float fmagic(vec2 F, vec3 B, float i) +{ + vec2 f = magic_f(F, B, i); + vec3 b = magic_b(B, i); + + return f.x * mix(1 - modTime(f.y), cosTime(f.y) * 0.5 + 0.5, b.y); +} + +float magic(float i) +{ + return magic(vec2(0), vec3(0, 0, 1), i); +} + +float magic_reverse(vec2 F, vec3 B, float i) +{ + vec2 f = magic_f(F, B, i); + vec3 b = magic_b(B, i); + + return mix(0, f.x * mix(1 - modTime(f.y), modTime(f.y), b.y), b.x); +} + +float magic_reverse(float i) +{ + return magic_reverse(vec2(0), vec3(0, 0, 1), i); +} + +#endif diff --git a/project/inc_rand.glsl b/project/inc_rand.glsl new file mode 100644 index 0000000..138b2f9 --- /dev/null +++ b/project/inc_rand.glsl @@ -0,0 +1,14 @@ +#ifndef INC_RAND +#define INC_RAND + +float rand(float seed){ + float v=pow(abs(seed),6./7.); + v*=sin(v)+1.; + return fract(v); +} + +float rand(vec2 n){ + return rand(n.x * 1234 + n.y * 9876); +} + +#endif diff --git a/project/inc_res.glsl b/project/inc_res.glsl new file mode 100644 index 0000000..843597d --- /dev/null +++ b/project/inc_res.glsl @@ -0,0 +1,7 @@ +#ifndef INC_BASE +#define INC_BASE + +uniform vec2 iResolution; +uniform vec2 iTexResolution; + +#endif diff --git a/project/inc_sentences.glsl b/project/inc_sentences.glsl new file mode 100644 index 0000000..7fdb0eb --- /dev/null +++ b/project/inc_sentences.glsl @@ -0,0 +1,29 @@ +#ifndef INC_SENTENCES +#define INC_SENTENCES + +#define SENTENCE_COUNT 17 + +const int sentences[SENTENCE_COUNT][20] = { + {0x66, 0x6F, 0x72, 0x67, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x46, 0x4F, 0x52, 0x47, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x46, 0x2E, 0x4F, 0x2E, 0x52, 0x2E, 0x47, 0x2E, 0x45, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x46, 0x75, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x4F, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x52, 0x65, 0x61, 0x6C, 0x2D, 0x74, 0x69, 0x6D, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x45, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x73, 0x65, 0x65, 0x00, 0x00}, + {0x50, 0x69, 0x78, 0x65, 0x6C, 0x20, 0x62, 0x79, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x4C, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x6C, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x4B, 0x6C, 0x65, 0xE3, 0x65, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x43, 0x6F, 0x64, 0x65, 0x20, 0x61, 0x73, 0x20, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x41, 0x72, 0x74, 0x20, 0x61, 0x73, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, +}; + +const int lengths[SENTENCE_COUNT] = { + 5, 5, 10, 6, 2, 9, 10, 7, 18, 14, 4, 9, 10, 1, 6, 11, 11 +}; +#endif diff --git a/project/inc_src.glsl b/project/inc_src.glsl new file mode 100644 index 0000000..c57f046 --- /dev/null +++ b/project/inc_src.glsl @@ -0,0 +1,615 @@ +#include inc_res.glsl +#include inc_magic.glsl +#include inc_functions.glsl + +#ifndef INC_SRC +#define INC_SRC + +uniform int iDemo; + +uniform sampler2D iTex0; + +subroutine vec4 src_stage_sub(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3); + +vec4 src_thru(vec2 vUV, sampler2D tex, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + + // controls + + float hue = magic(f1, b1, seed + 10); + float saturation = magic(f2, b2, seed + 20); + float light = magic(f3, b3, seed + 30); + + // logic + + vec3 c = texture(tex, uv0).xyz; + + c = shift3(c, hue); + + c *= 1 + saturation; + c = mix(c + light * 2.0, c - (1 - light) * 2.0, step(0.5, light)); + + // output + + return vec4(c, 1.); +} + +// SRC 1: feedback + thru +subroutine ( src_stage_sub ) vec4 src_1(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + return src_thru(vUV, iTex0, seed, b1, f1, b2, f2, b3, f3); +} + +// SRC 2 : lines +subroutine ( src_stage_sub ) vec4 src_2(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float thickness = magic(f1, b1, seed + 10); + float rotation = magic(f2, b2, seed + 20); + float distort = magic(f3, b3, seed + 30); + + // logic + + vec2 uv2 = uv1; + uv2.y *= cos(uv2.x * 5 * distort); + uv2 *= rot(rotation + iBeats / 16); + float k = thickness * 2; + uv2.y = cmod(uv2.y, k * 2 + 0.1); + float f = istep(k * 0.125 + 0.05, uv2.y) * istep(k * 0.125 + 0.01, -uv2.y); + + return vec4(f); +} + +// SRC 3 : dots +subroutine ( src_stage_sub ) vec4 src_3(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = magic(f1, b1, seed + 10); + float rotation = magic(f2, b2, seed + 20); + float lens_v = magic(f3, b3, seed + 30); + + // logic + + vec2 uv2 = uv1; + float k1 = lens_v * 5; + uv2 = lens(uv2, -k1, k1); + uv2 = kal(uv2, 5); + uv2 *= rot(rotation + iBeats / 16); + float k = zoom * 0.1 + 0.05; + uv2 = cmod(uv2, k * 2); + float f = istep(k / (1 + length(uv1) * 2), length(uv2)); + + return vec4(f); +} + +// // SRC 4 : circuit +// subroutine ( src_stage_sub ) vec4 src_4(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +// { +// // start + +// vec2 uv0 = vUV.st; +// float ratio = iResolution.x / iResolution.y; +// vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + +// // controls + +// float z = 10 + magic(f1, b1, 123) * 20; +// float h = magic(f2, b2, seed + 20) * 0.8 + 0.1; +// float v = magic_reverse(f3, b3, seed + 30) * 0.8 + 0.1; + +// // logic + +// uv1 *= z; +// uv1 += iBeats; + +// float s0 = rand(floor(mod(uv1, 1000))) * 1000; +// float s1 = rand(floor(mod(uv1 + vec2(0, 1), 1000))) * 1000; +// float s2 = rand(floor(mod(uv1 - vec2(1, 0), 1000))) * 1000; + +// bool up = rand(s1 + 1) < h; +// bool left = rand(s2 + 2) < v; +// bool down = rand(s0 + 1) < h; +// bool right = rand(s0 + 2) < v; +// bool up_down = up && down; +// bool left_right = left && right; + +// uv1 = mod(uv1, 1.0) - 0.5; + +// const float t = 0.1; + +// float f = 0; +// int c = 0; + +// if (up) { +// f += stripe(uv1.x, -t * 0.5, t * 0.5) * step(-t * 0.5, uv1.y); +// c += 1; +// } + +// if (down) { +// f += stripe(uv1.x, -t * 0.5, t * 0.5) * istep(t * 0.5, uv1.y); +// c += 1; +// } + +// if (left) { +// f += stripe(uv1.y, -t * 0.5, t * 0.5) * istep(t * 0.5, uv1.x); +// c += 1; +// } + +// if (right) { +// f += stripe(uv1.y, -t * 0.5, t * 0.5) * step(-t * 0.5, uv1.x); +// c += 1; +// } + +// if (c == 1) { +// f += istep(t, length(uv1)); +// } + +// f = min(f, 1); + +// if ((up_down ^^ left_right) && c == 2) { +// if (up_down) { +// uv1.xy = uv1.yx; +// } +// if (rand(s0 + 3) < 0.5) { +// uv1.x = -uv1.x; +// } +// float k = rand(s0 + 4) * 60; +// f -= rect(uv1, vec2(0), vec2(t * 3, t)); +// f = max(0, f); +// if (k < 10) { // resistor +// f += line(uv1, vec2(-t * 3.25, -t * 0.5), vec2(-t * 2.5, t * 2), t * 0.75); +// f += line(uv1, vec2(-t * 2.5, t * 2), vec2(-t * 1.5, -t * 2), t * 0.75); +// f += line(uv1, vec2(-t * 1.5, -t * 2), vec2(-t * 0.5, t * 2), t * 0.75); +// f += line(uv1, vec2(-t * 0.5, t * 2), vec2(t * 0.5, -t * 2), t * 0.75); +// f += line(uv1, vec2(t * 0.5, -t * 2), vec2(t * 1.5, t * 2), t * 0.75); +// f += line(uv1, vec2(t * 1.5, t * 2), vec2(t * 2.5, -t * 2), t * 0.75); +// f += line(uv1, vec2(t * 2.5, -t * 2), vec2(t * 3.25, t * 0.5), t * 0.75); +// } else if (k < 20) { // capacitor +// f += rect(uv1, vec2(-t * 2, 0), vec2(t, t * 0.5)); +// f += rect(uv1, vec2(t * 2, 0), vec2(t, t * 0.5)); +// f += rect(uv1, vec2(t, 0), vec2(t * 0.5, t * 3.5)); +// f += rect(uv1, vec2(-t, 0), vec2(t * 0.5, t * 3.5)); +// } else if (k < 30) { // diode +// f += line(uv1, vec2(-t * 2, t * 2.5), vec2(t * 2, 0), t); +// f += line(uv1, vec2(-t * 2, -t * 2.5), vec2(t * 2, 0), t); +// f += rect(uv1, vec2(t * 2.5, 0), vec2(t * 0.5, t * 3)); +// f += rect(uv1, vec2(-t * 2.5, 0), vec2(t * 0.5, t * 3)); +// } else if (k < 40) { // lamp +// f += istep(t * 3.5, length(uv1)); +// f -= istep(t * 2.5, length(uv1)); +// f += line(uv1, vec2(-t * 2), vec2(t * 2), t); +// f += line(uv1, vec2(-t * 2, t * 2), vec2(t * 2, -t * 2), t); +// } else if (k < 50) { // inductor +// f += istep(t * 2, length(uv1 - vec2(t * 2.5, 0))); +// f += istep(t * 2, length(uv1 - vec2(0, 0))); +// f += istep(t * 2, length(uv1 - vec2(-t * 2.5, 0))); +// f -= 2 * istep(t, length(uv1 - vec2(t * 2.5, 0))); +// f -= 2 * istep(t, length(uv1 - vec2(0, 0))); +// f -= 2 * istep(t, length(uv1 - vec2(-t * 2.5, 0))); +// f *= step(-t * 0.5, uv1.y); +// } else if (k < 60) { // switch +// f += istep(t, length(uv1 - vec2(t * 2.5, 0))); +// f += istep(t, length(uv1 + vec2(t * 2.5, 0))); +// f += line(uv1, vec2(t * 2, 0), vec2(-t * 2.5, t * (k < 55 ? 3 : 1)), t); +// } +// } else if (c == 3) { +// if (left_right) { +// uv1.xy = uv1.yx; +// if (up) { +// uv1.x = -uv1.x; +// } +// } else if (right) { +// uv1.x = -uv1.x; +// } +// float k = rand(s0 + 4) * 20; +// if (k < 10) { +// f -= rect(uv1, vec2(0), vec2(t * 3)); +// f = max(0, f); +// f += rect(uv1, vec2(-t * 3, 0), vec2(t * 0.5, t * 3)); +// f += line(uv1, vec2(t * 0.25, t * 3.25), vec2(-t * 3, t), t); +// f += line(uv1, vec2(t * 0.25, -t * 3.25), vec2(-t * 3, -t), t); +// } +// } + +// return vec4(f); +// } + +// SRC 4 : bacteria +subroutine ( src_stage_sub ) vec4 src_4(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = 2 + magic(f1, b1, seed + 10) * 20; + float details = 5 * magic(f2, b2, seed + 20); + float delta = magic(f3, b3, seed + 30); + + // logic + + uv1 *= zoom; + + vec4 data = voronoi(uv1, 1, seed + 40, iBeats * 0.25); + + float f = ease(data.x) + ease(data.y); + + f = saw(f * (1 + data.x * details) - delta * 2.0); + + return vec4(f); +} + +// SRC 5 : noise +subroutine ( src_stage_sub ) vec4 src_5(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = magic(f1, b1, seed + 10); + float voronoi_distort = magic(f2, b2, seed + 20); + float details = magic(f3, b3, seed + 30); + float noise_factor = magic(seed + 40); + + // logic + + vec2 uv2 = uv1; + uv2 *= zoom * 20 + 3; + uv2.x += iBeats; + vec4 data = voronoi(uv2, voronoi_distort, seed + 50, iBeats); + float f = data.x / (data.x + data.y); + f = sin(f * PI * (details * 20)) * 0.5 + 1; + int nf = int(noise_factor * 6); + f *= mix(1, noise_f(uv2, nf - 1), step(0.0, float(nf))); + + return vec4(f); +} + +// SRC 6 : video in 1 + thru +subroutine ( src_stage_sub ) vec4 src_6(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + return src_1(vUV, seed, b1, f1, b2, f2, b3, f3); +} + +#include inc_cp437.glsl + +// SRC 7 : cp437 +subroutine ( src_stage_sub ) vec4 src_7(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = magic(f1, b1, seed + 10); + vec2 charset = magic_f(f2, b2, seed + 20); + vec3 charset_ctrl = magic_b(b2, seed + 20); + float char_delta = magic(f3, b3, seed + 30); + + // logic + + vec2 uv2 = uv1; + uv2 *= zoom * 20 + 3; + uv2 += iBeats; + uv2 = mod(uv2, 100) + 100; + int start_char = charset_ctrl.x > 0 ? charsets[int(charset.x * CHARSETS) * 2] : 0x01; + int char_span = int((charset_ctrl.x > 0 ? charsets[int(charset.x * CHARSETS) * 2 + 1] : 255)); + char_span = int(char_span * max(1 - charset.y, 1 / (char_span * 0.75))); + ivec2 uv2i = ivec2(uv2); + int code = ((charset_ctrl.y < 1 || (uv2i.x % 2 ^ uv2i.y % 2) > 0) ? 1 : 0) * (start_char + int((rand(uv2i) + char_delta) * char_span) % char_span); + uv2 = mod(uv2, 1); + float f = char(uv2, code) ? 1 : 0; + + return vec4(f); +} + +// SRC 8 : sentences + +#include inc_sentences.glsl + +subroutine ( src_stage_sub ) vec4 src_8(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = magic(f1, b1, seed + 10); + float sentence = magic_reverse(f2, b2, seed + 20); + float h_delta = magic(f3, b3, seed + 30); + vec3 h_delta_b = magic_b(b3, seed + 30); + + // logic + + vec2 uv2 = uv1; + uv2 *= (1 + zoom) * 12; + uv2.y += 0.5; + int s = int(sentence * (SENTENCE_COUNT - 1)); + uv2.x += floor(uv2.y) * (h_delta - 0.5) * 2; + uv2.y = mix(uv2.y, mod(uv2.y, 1), h_delta_b.x); + float f = write_20(uv2, vec2(-float(lengths[s]) * 0.5, 0), sentences[s]); + + return vec4(f); +} + +// SRC 9 : sentences repeat +subroutine ( src_stage_sub ) vec4 src_9(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float h_shift = magic(f1, b1, seed + 10); + float sentence = magic_reverse(f2, b2, seed + 20); + float h_delta = magic(f3, b3, seed + 30); + vec3 h_delta_b = magic_b(b3, seed + 30); + + // logic + + vec2 uv2 = uv1; + uv2.x += h_shift; + uv2 *= 15; + uv2.y += 0.5; + int s = int(sentence * (SENTENCE_COUNT - 1)); + float slen = float(lengths[s]); + uv2.x += floor(uv2.y) * (h_delta - 0.5) * 2; + uv2.x = cmod(uv2.x, slen + 1); + vec2 uv3 = uv2; + uv3.y = mix(uv3.y, mod(uv3.y, 1), h_delta_b.x); + float f = write_20(uv3, vec2(-slen * 0.5, 0), sentences[s]); + + f *= (1 - abs(floor(uv2.y) * 0.125)) * (1 - abs(floor(uv2.y) * 0.125)); + + return vec4(f); +} + +// SRC 10 : isometric grid +subroutine ( src_stage_sub ) vec4 src_10(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = 5 + magic(f1, b1, seed + 10) * 15; + float h_scroll = magic(f2, b2, seed + 20); + float max_elevation = magic(f3, b3, seed + 30) * 0.5; + float thick = 0.1; + + // logic + + vec2 uv2 = uv1; + + vec2 uv3 = iso(uv2); + + uv3 += vec2(h_scroll, 0); + + uv3 *= round(zoom); + + vec2 umax = vec2(round(zoom), 300); + + vec2 u0 = mod(floor(uv3), umax); + vec2 u1 = mod(floor(uv3 + vec2(1, 0)), umax); + vec2 u2 = mod(floor(uv3 + vec2(0, 1)), umax); + vec2 u3 = mod(floor(uv3 + vec2(-1, 0)), umax); + vec2 u4 = mod(floor(uv3 + vec2(0, -1)), umax); + + float e0 = (rand(floor(u0)) * 2 - 1) * max_elevation; + float e1 = (rand(floor(u1)) * 2 - 1) * max_elevation; + float e2 = (rand(floor(u2)) * 2 - 1) * max_elevation; + float e3 = (rand(floor(u3)) * 2 - 1) * max_elevation; + float e4 = (rand(floor(u4)) * 2 - 1) * max_elevation; + + uv3 = mod(uv3, 1.0) - 0.5; + + float f = 0; + + f = line(uv3, vec2(0, 0) - iso_z(e0), vec2(1, 0) - iso_z(e1), thick) + + line(uv3, vec2(0, 0) - iso_z(e0), vec2(0, 1) - iso_z(e2), thick) + + line(uv3, vec2(0, 0) - iso_z(e0), vec2(-1, 0) - iso_z(e3), thick) + + line(uv3, vec2(0, 0) - iso_z(e0), vec2(0, -1) - iso_z(e4), thick); + + return vec4(f); +} + +// SRC 11 : video in 2 + thru +subroutine ( src_stage_sub ) vec4 src_11(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + return src_1(vUV, seed, b1, f1, b2, f2, b3, f3); +} + +// SRC 12 : Scales +subroutine ( src_stage_sub ) vec4 src_12(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = 5 + magic(f1, b1, seed + 10) * 15; + float shape = magic(f2, b2, seed + 20); + float repeat = 1 + magic(f3, b3, seed + 30) * 10; + + // logic + + float f = 0; + + vec2 uv2 = uv1; + + uv2 *= zoom; + + uv2 = mod(uv2, 4); + + vec2 uv3 = uv2; + + uv3.y = mix(uv3.y, -uv3.y, step(2, uv2.x) * step(2, uv2.y)); + uv3.y = mix(uv3.y, -uv3.y, istep(2, uv2.x) * istep(2, uv2.y)); + + uv3.y = -uv3.y; + + uv3.x = mix(-uv3.x, uv3.x, istep(3, uv2.x) * step(1, uv2.x)); + uv3.x = mix(-uv3.x, uv3.x, istep(3, uv2.y) * step(1, uv2.y)); + + f = istep(0.5, saw((length(mod(uv3, 1)) + shape + 0.5) * repeat)); + + f = mix(1 - f, f, istep(1, abs(uv2.y - 2)) * istep(2, uv2.x)); + f = mix(1 - f, f, step(1, abs(uv2.y - 2)) * step(2, uv2.x)); + + return vec4(f); +} + +// SRC 13 : Credenza +subroutine ( src_stage_sub ) vec4 src_13(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float zoom = 5 + magic(f1, b1, seed + 10) * 15; + float shape = 0.1 + magic(f2, b2, seed + 20) * 0.9; + float repeat = 1 + magic(f3, b3, seed + 30) * 10; + + // logic + + vec2 uv2 = uv1; + + uv2 *= zoom; + + uv2 = mod(uv2, 2); + + uv2 = abs(uv2 - 1); + + float f = istep(1, length(uv2)) * istep(1, length(1 - uv2)); + + f *= istep(0.5, saw((length(uv2) + shape + 0.5) * repeat)) * istep(0.5, saw((length(1 - uv2) + shape + 0.5) * repeat)); + + return vec4(f); +} + +// SRC 14 : Cursor +subroutine ( src_stage_sub ) vec4 src_14(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + // start + + vec2 uv0 = vUV.st; + float ratio = iResolution.x / iResolution.y; + vec2 uv1 = (uv0 - .5) * vec2(ratio, 1); + + // controls + + float size = magic(f1, b1, seed + 10) * 2 + 0.1; + float dx = (fmagic(f2, b2, seed + 20) * (1 - size * 0.06) - 0.5) * ratio; + bool flip_x = magic_trigger(b2, seed + 20); + float dy = fmagic(f3, b3, seed + 30) * (1 - size * 0.17) - 0.5; + bool flip_y = magic_trigger(b3, seed + 30); + + // logic + + vec2 uv2 = uv1; + + if (flip_x) { + uv2.x = -uv2.x; + } + + if (flip_y) { + uv2.y = -uv2.y; + } + + uv2 -= vec2(dx, -dy); + + uv2 /= size; + + uv2 *= -rot(-PI / 2); + + float f = istep(0, (uv2.x * 2 + uv2.y) * (uv2.x * 2 - uv2.y)) * istep(0, uv2.y); + + uv2.y += 0.1; + + f -= istep(0, (uv2.x + uv2.y * 3) * (uv2.x - uv2.y * 3)) * istep(0, uv2.y); + + f += rect(uv2, vec2(0, -0.04), vec2(0.01, 0.04)); + + return vec4(f); +} + +// SRC 15 : Random +subroutine ( src_stage_sub ) vec4 src_15(vec2 vUV, int seed, vec3 b1, vec2 f1, vec3 b2, vec2 f2, vec3 b3, vec2 f3) +{ + int src = int(randTime(seed + 100) * 14); + + if (src == 0) { + return src_1(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 1) { + return src_2(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 2) { + return src_3(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 3) { + return src_4(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 4) { + return src_5(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 5) { + return src_6(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 6) { + return src_7(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 7) { + return src_8(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 8) { + return src_9(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 9) { + return src_10(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 10) { + return src_11(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 11) { + return src_12(vUV, seed, b1, f1, b2, f2, b3, f3); + } else if (src == 12) { + return src_13(vUV, seed, b1, f1, b2, f2, b3, f3); + } else { + return src_14(vUV, seed, b1, f1, b2, f2, b3, f3); + } +} + +#endif diff --git a/project/inc_time.glsl b/project/inc_time.glsl new file mode 100644 index 0000000..0546a03 --- /dev/null +++ b/project/inc_time.glsl @@ -0,0 +1,53 @@ +#ifndef PI +#define PI 3.1415927 +#endif + +#include inc_rand.glsl + +#ifndef INC_TIME +#define INC_TIME + +uniform float iTime; +uniform float iTempo; +uniform float iBeats; + +float randTime(float seed, int beats){ + return rand(seed + floor(iBeats / beats)); +} + +float randTime(float seed){ + return randTime(seed, 4); +} + +float divider(float x) +{ + if (x < 0.1) return 0; + if (x < 0.2) return 0.125; + if (x < 0.3) return 0.25; + if (x < 0.4) return 0.5; + if (x < 0.6) return 1; + if (x < 0.8) return 2; + return 4; +} + +float modTime(float k, float k2) +{ + return mod(divider(k) * iBeats * k2 / 4, 1); +} + +float modTime(float k) +{ + return modTime(k, 1.0); +} + +float sinTime(float k) +{ + return sin(modTime(k, 0.5) * 2 * PI); +} + +float cosTime(float k) +{ + return cos(modTime(k, 0.5) * 2 * PI); +} + +#endif