Old 5th September 2017, 21:40   #1
LamersAss
Junior Member
 
Join Date: Oct 2015
Posts: 21
WebGL Shader

Question!

Is it possible to convert this JS shading to Milkdrop shading?



In Action:
http://js1k.com/2016-elemental/demo/2552

Code:
http://js1k.com/2016-elemental/details/2552

code:
// 35633 = gl.VERTEX_SHADER
// 35632 = gl.FRAGMENT_SHADER
// 35044 = gl.STATIC_DRAW
// 34962 = gl.ARRAY_BUFFER
// 05120 = gl.BYTE
// 00006 = gl.TRIANGLE_FAN

// Code may look unnecessarily complicated here and there,
// but that's all part of the compression optimization, the more patterns, the better.

P = g.createProgram()

g.shaderSource(A=g.createShader(35633),"attribute vec2 P;void main(){gl_Position=vec4(P,0,1);}")
g.compileShader(A);g.attachShader(P,A)

g.shaderSource(A=g.createShader(35632),"precision mediump float;uniform vec2 R,M;uniform float T; float t=5e-3;void main(){for( float i=0.;i<64.;i++){vec3 p=vec3((2.*gl_FragCoord.xy-R)/R.yy,t-1.),b=vec3(.707,.707,0); float a=T;p.xz*=mat2(cos(a),-sin(a),sin(a),cos(a));for( float i=0.;i<20.;i++){ a=(M/R*6.).x;p.xz*=mat2(cos(a),-sin(a),sin(a),cos(a)); a=(M/R*6.).y;p.xy*=mat2(cos(a),-sin(a),sin(a),cos(a));p-=min(0.,dot(p,b))*b*2.;b=b.zxx;p-=min(0.,dot(p,b))*b*2.;b=b.zxz;p-=min(0.,dot(p,b))*b*2.;b=b.xxy;p=p*1.5-.25;}t+=length(p)/3325.;if(length(p)/3325.<5e-3||t>2.){b=vec3(1);p*=.5;gl_FragColor=vec4(p/length(p)*(t<2.?5./i:i/64.),dot(p,b));break;}}}")

g.compileShader(A);g.attachShader(P,A)
g.linkProgram(P);g.useProgram(P)

g.bindBuffer(A=34962,g.createBuffer())
g.bufferData(A,new Int8Array([-3,1,1,-3,1,1]),35044)

g.enableVertexAttribArray(0)
g.vertexAttribPointer(b=0,2,5120,0,0,0)

g.uniform2f(g.getUniformLocation(P,"R"),a.width*=.8,a.height*=.8)
g.uniform2f(g.getUniformLocation(P,"M"),0,0)

onmousemove=function(e){g.uniform2f(g.getUniformLocation(P,"M"),b=e.pageX,e.pageY)};
(s=function(e){g.uniform1f(g.getUniformLocation(P,"T"),A+=.01);g.drawArrays(6,0,3);requestAnimationFrame(s)})();

f = new AudioContext();
a = f.createScriptProcessor(8192,1,1);
a.connect(f.destination);

a.onaudioprocess = function(e)
{
q = e.outputBuffer.getChannelData(0);

for(i=8192;i--
{
q[i] *= .8
for(j=7;--j q[i] += Math.sin(i*(A*50%j)*Math.floor(b/150)*j/326) * Math.sin(i/2606) * Math.sin(A)/j/4;
}
}

LamersAss is offline   Reply With Quote
Old 6th September 2017, 15:11   #2
Nitorami
Major Dude
 
Join Date: Mar 2008
Location: Erlangen
Posts: 770
Send a message via ICQ to Nitorami
Milkdrop's shader access is entirely based on a flat mesh - not feasible.
Nitorami is online now   Reply With Quote
Old 10th September 2017, 11:07   #3
Flexi
wellspring of milk
Major Dude
 
Flexi's Avatar
 
Join Date: Apr 2007
Location: 54.085108,12.127497
Posts: 2,045
Send a message via ICQ to Flexi
The WebGL setup is really just one triangle that spans over the full viewport, and the fractal is rendered just like with a Milkdrop shader. So the challenge is only a couple of replacements for the different shader syntax: vec3 -> float3, etc.

By the way, that sound code below was programmed by my friend and neighbor Helmut.
Flexi is offline   Reply With Quote
Old 10th September 2017, 18:14   #4
Nitorami
Major Dude
 
Join Date: Mar 2008
Location: Erlangen
Posts: 770
Send a message via ICQ to Nitorami
The world is small
But I would be very surprised if that could be done in milkdrop. I cannot read WebGL, but simply replacing a few identifiers by others won't do the job. We don't have vertices in MD, neither persistent variables.
Nitorami is online now   Reply With Quote
Old 11th September 2017, 15:59   #5
Flexi
wellspring of milk
Major Dude
 
Flexi's Avatar
 
Join Date: Apr 2007
Location: 54.085108,12.127497
Posts: 2,045
Send a message via ICQ to Flexi
Really, all geometry vertex data is this little array of 3 2D coordinates that spans over the whole screen (from -1,-1 to 1,1):

Quote:
g.bufferData(A,new Int8Array([-3,1,1,-3,1,1]),35044)
Apparently that line seems to be a copy of an entry by my humble self from two years before. I won the competition in 2014 but with my other "DragonDrop" entry which didn't even use WebGL. It's only fair to say that I learned this trick from someone else in the first place. There's this funny adage: "2 triangles ought to be enough for anybody". I think it was https://twitter.com/paniq who pointed me at the optimization with only one triangle. Check this out: https://twitter.com/thespite/status/744611176735186945
"Edgy The Pit Minder" got rejected anyway, because I didn't read the rules properly and 2k + WebGL were not allowed. You can find my step-by-step progress on both entries here: http://www.cake23.de/hereBeDragons/

In the animation loop
Quote:
g.drawArrays(6,0,3)
is the single WebGL draw call. The 6 is for the triangle strip geometry, the 0 is the starting index, and the 3 the number of vertices.

Let's break down the shader program:

code:

precision mediump float;
uniform vec2 R,M;
uniform float T;
float t=5e-3;
void main(){
for( float i=0.;i<64.;i++){
vec3 p=vec3((2.*gl_FragCoord.xy-R)/R.yy,t-1.),b=vec3(.707,.707,0);
float a=T;
p.xz*=mat2(cos(a),-sin(a),sin(a),cos(a));
for( float i=0.;i<20.;i++){
a=(M/R*6.).x;
p.xz*=mat2(cos(a),-sin(a),sin(a),cos(a));
a=(M/R*6.).y;
p.xy*=mat2(cos(a),-sin(a),sin(a),cos(a));
p-=min(0.,dot(p,b))*b*2.;
b=b.zxx;
p-=min(0.,dot(p,b))*b*2.;
b=b.zxz;
p-=min(0.,dot(p,b))*b*2.;
b=b.xxy;
p=p*1.5-.25;
}
t+=length(p)/3325.;
if(length(p)/3325.<5e-3||t>2.){
b=vec3(1);
p*=.5;
gl_FragColor=vec4(p/length(p)*(t<2.?5./i:i/64.),dot(p,b));
break;
}
}
}



gl_FragColor is the equivalent for ret in Milkdrop, and you can understand gl_FragCoord.xy as the uv vector in Milkdrop. The two uniform variables could be understood as the q_ variables to contain (CPU) scripted values (here: the mouse pointer position and the scaled down texture resolution). Please don't expect me to explain the maths though. And this is supposed to be a composite shader that doesn't work with any render-to-texture feedback loop. I barely fitted render-to-texture in 1k without any effects in then. I just ran with it to the 2k mark.
Flexi is offline   Reply With Quote
Old 12th September 2017, 17:55   #6
Nitorami
Major Dude
 
Join Date: Mar 2008
Location: Erlangen
Posts: 770
Send a message via ICQ to Nitorami
The problem in Milkdrop is that the code within the shader_body {} section is always executed for the entire screen, only depending on uv. There is no way to limit this to small fragments, which would be required to run loops of depth 64 x 20.
I would delve into that more deeply if I would see a chance to do it but I don't. I had the issue with my own presets that I wanted to do a calculation only for a part of the screen - nope, you have to do it for all pixels, and then apply masks to hide the part you don't want to show.
Nitorami is online now   Reply With Quote
Old 12th September 2017, 18:49   #7
Flexi
wellspring of milk
Major Dude
 
Flexi's Avatar
 
Join Date: Apr 2007
Location: 54.085108,12.127497
Posts: 2,045
Send a message via ICQ to Flexi
There's always a trade-off. Perhaps the compilers could be more clever to optimize masks, but that's not what they were built for in the first place anyway, and it would also bloat up the compile time. Of course specifying certain areas by geometry is also more descriptive. But that's really not the point of code golfing challenges. Wasting performance is tolerable in size coding. Optimization for performance is a whole other story. What counts is the performance at a demoscene event, where there's usually a powerful PC with fast processors and a Titan class graphics card, and how you engage with the crowd. There are some standards that I find overused, but the audience tends to cheer for such effects as rgb channel splits and tv scan lines, so every high-ranked entry has them. Those are my two cents: https://twitter.com/Flexi23/status/647007953971752960

But apparently you can pull off some nasty long running loops for every pixels on graphics cards nowadays. That WebGL demo doesn't even run with full native performance since its glsl shader code is indirectly executed as DirectX shader at least under Windows (read: https://en.wikipedia.org/wiki/ANGLE_(software) ), but I'm getting good frame rates anyway. I'd expect the direct manual translation to run slightly faster. I actually went the other way around and started porting some of my effects from Milkdrop to WebGL and glsl.

Then there's Jordan Berg who wrote a clojure script to trans-compile Milkdrop presets from the original source directly in the browser: https://butterchurnviz.com/ I met him when I visited San Francisco last year, but he doesn't seem to be working on it anymore.
Flexi is offline   Reply With Quote
Old 12th September 2017, 19:56   #8
Flexi
wellspring of milk
Major Dude
 
Flexi's Avatar
 
Join Date: Apr 2007
Location: 54.085108,12.127497
Posts: 2,045
Send a message via ICQ to Flexi
>> https://www.shadertoy.com/view/ltXyRS
Flexi is offline   Reply With Quote
Reply
Go Back   Winamp & SHOUTcast Forums > Visualizations > MilkDrop > MilkDrop Presets

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump