En este aparato gl_FragCoord.y = 0 cae ARRIBA en un 0-input. Y la captura de glslViewer coincide con el aparato: NO hay que voltearla, que es lo contrario de lo que decia la version anterior de esta guia. Ademas, check_port.py ya no cuenta las llamadas que aparecen dentro de los comentarios. Generado con generar-agente-portable.py. No editar aqui. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
13 KiB
doc, rev, canonical_language, canonical_source, translations
| doc | rev | canonical_language | canonical_source | translations | |||
|---|---|---|---|---|---|---|---|
| RECUR-SHADER-REF | 03 | en | docs/recur-shader-reference.en.md |
|
Com funcionen de debò els shaders a r_e_c_u_r
Tot el que hi ha aquí està comprovat llegint el codi font dels tres repositoris
implicats, no llegint fòrums. Cada afirmació porta fitxer:línia. Allò que no es pot
tancar llegint codi va marcat com a [PER VERIFICAR A LA MÀQUINA].
Verificat el 2026-08-28 contra el commit 16e1fae de r_e_c_u_r.
La cadena: qui dibuixa què
No és un sol programa. Són tres peces, i confondre-les fa perdre el temps:
r_e_c_u_r (Python, la interfície)
│ navega Shaders/, llegeix el fitxer, decideix què enviar
│ OSC → port local
▼
c_o_n_j_u_r (aplicació d'openFrameworks, C++)
│ rep /shader/N/load, /param, /speed
▼
la classe conjur (addon ofxVideoArtTools)
│ fa shader.begin(), enllaça els uniforms, dibuixa
▼
OpenGL ES 2.0 / GLSL ES 1.00 ← aquí corre el teu .frag
- r_e_c_u_r no renderitza res. Només envia missatges OSC.
- Els uniforms s'enllacen a
ofxVideoArtTools/src/conjur.cpp. Aquell fitxer és la font de veritat sobre quines variables existeixen. - Repositoris: r_e_c_u_r, c_o_n_j_u_r, ofxVideoArtTools. Tots tres GPL-3.0.
On van els fitxers
data_centre/data.py:34 — r_e_c_u_r busca shaders en aquest ordre:
- L'USB o dispositiu extern muntat (
PATH_TO_EXTERNAL_DEVICES) /home/pi/r_e_c_u_r/Shaders/home/pi/Shaders
Extensions que mostra el navegador: .frag, .shader, .glsl, .glslf, .fsh.
El vertex shader està fixat al codi. ofApp.cpp:317 carrega sempre
/home/pi/r_e_c_u_r/Shaders/default.vert, passi el que passi. No pots donar el teu propi
vertex shader sense tocar C++. Només escrivim fragment shaders.
Els uniforms que existeixen de debò
De ofxVideoArtTools/src/conjur.cpp:50-73. Aquesta és la llista completa; no n'hi ha
més.
Els que fem servir (format Book of Shaders)
| Uniform | Tipus | Què és | Font |
|---|---|---|---|
u_time |
float |
Segons des que va arrencar el shader, escalat per la velocitat | conjur.cpp:51 |
u_resolution |
vec2 |
Mida de la finestra en píxels | conjur.cpp:52 |
u_x0…u_x3 |
float |
Els quatre paràmetres de la interfície. Sempre 0.0–1.0 | conjur.cpp:54 |
u_tex0 |
sampler2D |
Textura d'entrada (vídeo, o sortida del shader anterior) | conjur.cpp:57 |
u_tex1 |
sampler2D |
Segona entrada, si existeix a la cadena | conjur.cpp:57 |
I del default.vert, disponibles com a varyings:
| Varying | Tipus | Què és |
|---|---|---|
v_texcoord |
vec2 |
Coordenada UV normalitzada, 0.0–1.0. És el que es fa servir sempre |
tcoord |
vec2 |
Àlies exacte de v_texcoord (suport de dos formats) |
v_position, v_color, v_normal |
Existeixen, però els shaders del repositori no els fan servir |
Els legacy (existeixen, però no els facis servir en codi nou)
conjur.cpp:61-73 enllaça a més un joc de noms més antic:
| Uniform | Tipus | Què és |
|---|---|---|
ftime |
float |
Només la part decimal de u_time — va de 0 a 1 i salta. No és un rellotge continu |
itime |
int |
ceil(u_time), comptador de segons enters |
tres |
vec2 |
Igual que u_resolution |
fparams |
vec4 |
Els quatre params junts: fparams[0] == u_x0 |
iparams |
ivec4 |
Sempre (0,0,0,0). Està mort — conjur.cpp:66 el fixa a zero |
tex, tex2 |
sampler2D |
Àlies d'u_tex0 i u_tex1 |
Compte amb ftime: Shaders/0-input/colour_sine.frag el fa servir i és fàcil copiar-lo
creient que és el rellotge. Serra cada segon.
D'on surt aquest joc de noms antic
No és un invent de r_e_c_u_r: és la convenció nativa del Structure, el mòdul Eurorack
de vídeo d'Erogenous Tones. El default.vert declara tcoord i v_texcoord alhora, amb
el comentari literal // twice because supporting two shader formats, precisament per
servir les dues comunitats.
Es veu clar a l'únic tutorial de conversió que hi ha a la wiki oficial, tutorial_converting_simple_1input_shader_from_shadertoy: està escrit sencer en la convenció antiga, parla dels «noms que structure/recur esperen» i envia al sandbox d'Erogenous Tones.
Els dos formats funcionen de debò. conjur.cpp:50-73 enllaça els dos jocs sense
condicions, i com que fparams s'alimenta del mateix array shaderParams que
u_x0..u_x3, un shader escrit a l'estil antic també respon als comandaments. Tot i així,
en codi nou convé el joc modern per tres raons concretes: iparams està mort, ftime no
és un rellotge continu, i el modern és el que fan servir els shaders d'exemple del
repositori.
Si segueixes el tutorial de la wiki: reconstrueix el temps amb
float time = float(itime) + ftime;. Com queitimeésceil()i nofloor(), això va gairebé un segon avançat respecte au_time. Tant se val per a un efecte visual, però no és el mateix rellotge.
El que NO existeix
- No hi ha
u_mouse. Les notes de l'autor l'esmenten, però només com a manera de desenvolupar amb glslViewer a l'escriptori;conjur.cppno l'enllaça mai. Amb l'historial complet al davant es pot afirmar fort:git log -S "u_mouse"sobresrc/no retorna cap commit dels 47 del repositori. No es va treure: no hi va ser mai. - No hi ha equivalent d'
iTimeDelta,iFrame,iDate,iChannelResolution, ni entrada d'àudio. - No hi ha multipassada (els
Buffer A/B/C/Dde Shadertoy).
La marca //N-input: què fa realment
Tots els shaders del repositori comencen amb //0-input, //1-input o //2-input.
video_centre/shaders.py:48-57 busca aquella cadena en qualsevol part del fitxer i la
tradueix a 0in/1in/2in; si no en troba cap, el tipus és -.
Però la marca és purament informativa. Seguint la dada fins al final:
shaders.py:76l'envia per OSC com a segon argument de/shader/N/load.ofApp.cpp:317només llegeix l'argument 0 (la ruta). Ignora el tipus i el nombre de paràmetres.- L'únic altre ús és
display.py:174, que pinta la primera lletra a la pantalla.
O sia que la marca canvia l'etiqueta del menú i res més. u_tex0 està enllaçat sempre que
hi hagi almenys una textura a la cadena, fins i tot en un //0-input. Escriu-la
igualment: és el que et diu d'un cop d'ull què fa un shader quan en tens trenta a la
llista.
La documentació del mateix autor (
c_o_n_j_u_r/notes_on_shader_formats.md) parla de//gen-shaderi//pro-shader, i diu que un gen-shader pausa el vídeo. Aquell document està desactualitzat: el codi actual busca//N-inputi no fa res amb el resultat. Si segueixes les notes de l'autor al peu de la lletra, el teu shader apareix com a tipus-.
El mateix amb el nombre de paràmetres: les notes diuen que es detecta comptant
uniform float u_xN, però shaders.py:61 té un if True: que retorna 4 sempre. Els
quatre params estan disponibles declaris els que declaris.
La interfície no informa d'errors del shader
video_centre/shaders.py:18 documenta '!' com a estat d'error, però no hi ha cap camí
del codi que l'assigni. Un shader que no compila mostra el mateix estat de «en marxa» que
un que funciona. El registre de GLSL només existeix a la sortida estàndard de
c_o_n_j_u_r.
Com encadena les tres capes
ofApp.cpp:115-129 — hi ha 3 capes de shader, s'apliquen en ordre, i cadascuna fica la
seva sortida al principi de la llista de textures:
if(effectShader0active){
fbo = effectShader0.apply(effectInput);
effectInput.insert(effectInput.begin(), fbo.getTexture());
}
// ...igual per a 1 i 2
Conseqüència pràctica: a la capa 1, u_tex0 és la sortida de la capa 0, i u_tex1 és
el que la capa 0 tenia d'entrada. Aquí hi ha el truc per barrejar una imatge amb la seva
pròpia versió processada.
Temps i velocitat
conjur.cpp:74-77:
void conjur::setSpeed(float value){
speed = -2.0 + 4.0*value;
}
El valor de la interfície (0–1) es mapa a un multiplicador de −2 a +2:
| Valor UI | Velocitat | Efecte |
|---|---|---|
| 0.0 | −2.0 | El temps corre enrere, al doble |
| 0.5 | 0.0 | Congelat |
| 0.75 | 1.0 | Normal |
| 1.0 | 2.0 | El doble de ràpid |
El botó de velocitat de r_e_c_u_r (shaders.py:136-140) només alterna entre 0.5 i 0.75, o
sia congelat / normal. Per al rang complet cal activar l'ajust X3_AS_SPEED, que
segresta u_x3: amb ell activat, u_x3 deixa d'arribar al shader i passa a ser el
control de velocitat (shaders.py:157-160). Si el teu shader fa servir els quatre params,
compta que el quart pot faltar.
I u_time és acumulat, no absolut (conjur.cpp:88-94): en canviar la velocitat no salta,
segueix des d'on anava. Pot ser negatiu si el poses marxa enrere — si el teu shader fa
sqrt(u_time) o semblant, es trenca.
Estabilitat d'aquesta llista
Els noms dels uniforms no canvien des del 2019-08-03, commit 4c7312c
(«added alt shader mode»), que va introduir els dos jocs alhora. Cap commit posterior toca
ni un sol nom. El que sí que va canviar després va ser d'on surt el temps:
| Commit | Data | Què va fer |
|---|---|---|
4c7312c |
2019-08-03 | Fixa els noms dels uniforms, els dos jocs |
0483d54 |
2019-08-30 | u_time, ftime i itime deixen de llegir ofGetElapsedTimef() directament i passen pel rellotge virtual getTime(). Aquí neix speed = -2.0 + 4.0*value, i amb ella poder congelar el temps o córrer-lo enrere |
b8f4bd4 |
2019-09-27 | Retocs sense efecte sobre els uniforms |
4fd0559 |
2025-04-04 | «changing a few things for recurboy update»: només dues línies d'ofLog |
Dit d'una altra manera: des del setembre del 2019 no s'ha mogut res que afecti com s'escriu un shader.
Compte amb les branques
master està congelada al commit 16e1fae, del 2020-07-23, i és el que descriu
aquest document. Però el repositori va seguir viu en altres branques:
| Branca | Últim commit | Què afegeix |
|---|---|---|
master |
2020-07-23 | La base. És el documentat aquí |
dev |
2022-01-11 | Sistema de modulació dels 4 params, ajust USE_SHADER_MOD i shaders nous (chroma_key, luma_key_black/white, displace2in, spotlight) |
feature_plugins |
2020-03-15 | Sistema de connectors |
pre-plugin-dev |
2020-03-14 |
La bona notícia: el format de shader no canvia. video_centre/shaders.py a dev
segueix buscant //0-input///1-input///2-input, i
determine_shader_parameter_number conserva el mateix if True: return 4. Tot el
d'aquest document val igual a dev.
El que sí que canvia és el que es pot fer amb els params: a dev es poden modular,
sumant un valor de −1 a +1 al valor base i retallant el resultat a 0–1. La wiki documenta
a sobre d'això connectors d'LFO i de reacció a àudio.
[PER VERIFICAR A LA MÀQUINA] quina branca corre el teu aparell:
git -C ~/r_e_c_u_r branch --show-current.
Ajustos de r_e_c_u_r que afecten els shaders
De json_objects/settings_default.json:
X3_AS_SPEED— el dit més amunt:u_x3passa a ser el control de velocitat.FIX_PARAM_OFFSET_LAYER— canvia a quina capa es dirigeixen els comandaments.SHADER_POSITION(input/output) — si la cadena de shaders s'aplica abans o després del bucle de realimentaciódetour.
Limitacions de la màquina
- OpenGL ES 2.0 / GLSL ES 1.00. Ho diu l'autor a
notes_on_shader_formats.md(«currently the conjur openframeworks application is running gles 2»). És el que més mana en portar des de Shadertoy; vegeu la guia de conversió. - No es declara
#versiona dalt. Es fa servir el bloc#ifdef GL_ES / precision mediump float; / #endifque porten tots els shaders del repositori. - El maquinari objectiu és la Raspberry Pi 3.
- [PER VERIFICAR A LA MÀQUINA] la resolució real de treball:
u_resolutionsurt d'ofGetWidth()/ofGetHeight(), que depèn de com estigui configurada la sortida de vídeo de la Pi. - Mesurat el 2026-09-05: per a un shader
0-input,gl_FragCoord.y = 0cau A DALT de la pantalla en aquest aparell, al reves que en un escriptori. Aixo va degl_FragCoord, no dev_texcoord; el punt seguent segueix obert. - [PER VERIFICAR A LA MÀQUINA] si
v_texcoordté l'eix Y invertit respecte a Shadertoy. Els shaders del repositori el fan servir directament sense capgirar, cosa que suggereix que no, però amb textures de vídeo en un FBO convé comprovar-ho ambtest-orientation.fragabans de barallar-se amb un port.
Errates al repositori original
Trobades en llegir-lo, per si te'n copies (comprovades sobre el commit 16e1fae):
Shaders/0-input/colour_sine.frag:9—uniform vec4 fparamssense punt i coma. Aquell fitxer no compila. No el facis servir de plantilla.Shaders/1-input/invert_effect.frag— no porta bloc de precisió.Shaders/2-input/mix_lumaKey.frag— ni marca//N-inputni bloc de precisió, i està escrit sencer amb els noms legacy (tcoord,tex,tex2,tres,fparams). És l'exemple viu del format antic, útil per reconèixer-lo.