Hi !
For my current project I need to use a "glitch effect" shader. I found a few of them on a website called shadertoy, but I don't understand how to use them in Love2D.
I've used shaders before but they were all designed to work on Love2D in the first place, which is not the case here.
Usually I make a new shader using love.graphics.newShader () and then send a few variable the shader needs with shader:send () but I guess there are a few other things to do in order to make it work when the shader is not specifically designed for Love2D ?
An example of the kind of shader I want to use on my project : https://www.shadertoy.com/view/XtK3W3
(It uses a video but it can use a simple image - which is the way I plan to use it in my project)
Can someone please explain to me what I'm supposed to do in order to make a shader work if it's not designed to be used in Love2D in the first place ?
Maybe share an example of the kind of "conversion" I need to do in order to make it work properly ?
Thanks for your help
Using shader in Love2D
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Using shader in Love2D
See the "Shader language" part of love.graphics.newShader for basic differences. The variables provided by the Shadertoy runtime (buffers, time, etc.) should be documented on their site somewhere - you have to implement most of those yourself in LÖVE.
Re: Using shader in Love2D
I can walk you through the steps to port this shader:
1. The main body of a shader such as
typically becomes
2. You'll want to switch out fragColor for color and fragCoord's for texture_coords
3. Often shadertoy shaders use normalized coordinates, probably dont need those;
so you can remove
and instead just define
4. iChannel0 would be the input texture from shadertoy, so use tex here for love2d
5. then to pass in the iTime attribute something like;
along with a input
6. texture() would also become Texel()
7. then you'll also want to make sure color is returned at the end
So with those changes in mind, you would get something like this:
and also, a working example/love file here:
1. The main body of a shader such as
Code: Select all
void main()
Code: Select all
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
3. Often shadertoy shaders use normalized coordinates, probably dont need those;
so you can remove
Code: Select all
vec2 uv = fragCoord.xy / iResolution.xy;
Code: Select all
vec2 uv = texture_coords;
5. then to pass in the iTime attribute something like;
Code: Select all
shader:send("millis", love.timer.getTime())
Code: Select all
uniform float millis;
6. texture() would also become Texel()
7. then you'll also want to make sure color is returned at the end
Code: Select all
return color
So with those changes in mind, you would get something like this:
Code: Select all
shader = [[
uniform float millis;
//
// Description : Array and textureless GLSL 2D simplex noise function.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : stegu
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com/ashima/webgl-noise
// https://github.com/stegu/webgl-noise
//
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec2 mod289(vec2 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec3 permute(vec3 x) {
return mod289(((x*34.0)+1.0)*x);
}
float snoise(vec2 v)
{
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//i1.y = 1.0 - i1.x;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
// x0 = x0 - 0.0 + 0.0 * C.xx ;
// x1 = x0 - i1 + 1.0 * C.xx ;
// x2 = x0 - 1.0 + 2.0 * C.xx ;
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
// Permutations
i = mod289(i); // Avoid truncation effects in permutation
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
float rand(vec2 co)
{
return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
vec4 effect( vec4 color, Image tex, vec2 texture_coords, vec2 screen_coords )
{
vec2 uv = texture_coords;
float time = millis * 2.0;
// Create large, incidental noise waves
float noise = max(0.0, snoise(vec2(time, uv.y * 0.3)) - 0.3) * (1.0 / 0.7);
// Offset by smaller, constant noise waves
noise = noise + (snoise(vec2(time*10.0, uv.y * 2.4)) - 0.5) * 0.15;
// Apply the noise as x displacement for every line
float xpos = uv.x - noise * noise * 0.25;
vec4 c = Texel(tex, vec2(xpos, uv.y));
// Mix in some random interference for lines
color.rgb = mix(c.rgb, vec3(rand(vec2(uv.y * time))), noise * 0.3).rgb;
// Apply a line pattern every 4 pixels
if (floor(mod(texture_coords.y * 0.25, 2.0)) == 0.0)
{
color.rgb *= 1.0 - (0.15 * noise);
}
// Shift green/blue channels (using the red channel)
color.g = mix(color.r, Texel(tex, vec2(xpos + noise * 0.05, uv.y)).g, 0.25);
color.b = mix(color.r, Texel(tex, vec2(xpos - noise * 0.05, uv.y)).b, 0.25);
color.a = c.a //preserve alpha channel
return color;
}
]]
Re: Using shader in Love2D
Due to precision errors after long uptime, passing the time like this can result in laggy animation. Get the timer value from love.timer.getTime() when the game starts, and subtract it from the current time when passing it to the shader.unixfreak wrote: ↑Wed Oct 28, 2020 12:42 pm 5. then to pass in the iTime attribute something like;Code: Select all
shader:send("millis", love.timer.getTime())
Code: Select all
-- when game starts
local startTime = love.timer.getTime()
-- when sending the time
shader:send("iTime", love.timer.getTime() - startTime)
Re: Using shader in Love2D
Hmm, interesting. Never thought about that one.
Who is online
Users browsing this forum: Ahrefs [Bot], Google [Bot] and 1 guest