Help with shader

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Autophoenix
Prole
Posts: 40
Joined: Thu Mar 06, 2014 4:18 pm
Location: Rio de Janeiro, Brazil

Help with shader

Post by Autophoenix »

Hi!

I'm trying to import this shader from Shadertoy, with no success
I'm stuck with this "iChannel" variable that came up when I converted the shader to Love2D shader language using this tool

Here's my main.lua, with converted shader code:

Code: Select all

ntsc=[[
extern vec3 iResolution;
extern Image iChannel;


//Composite color artifact simulator
//Change Buf A to change the input image.

#define HUE 0.0
#define SATURATION 30.0
#define BRIGHTNESS 1.0

#define COMPOSITE 0 //Composite demodulated image
#define RGB 1 //Raw RGB input image
#define LUMA 2 //Luma component
#define CHROMA 3 //Chroma component
#define SIGNAL 4 //Modulated image
#define SPLIT 5 //Left = Input RGB, Right = Output composite

#define VIEW_MODE SPLIT

#define F_COL (1.0 / 4.0)
#define F_LUMA_LP (1.0 / 6.0)

#define FIR_SIZE 29

number pi = atan(1.0)*4.0;
number tau = atan(1.0)*8.0;

mat3 yiq2rgb = mat3(1.000, 1.000, 1.000,
                    0.956,-0.272,-1.106,
                    0.621,-0.647, 1.703);

//Angle -> 2D rotation matrix
mat2 rotate(number a)
{
    return mat2( cos(a), sin(a),
                -sin(a), cos(a));
}

//Non-normalized texture sampling.
vec4 sample2D(sampler2D sampler,vec2 resolution, vec2 uv)
{
    return texture(sampler, uv / resolution);
}

number sinc(number x)
{
	return (x == 0.0) ? 1.0 : sin(x*pi)/(x*pi);
}

//https://en.wikipedia.org/wiki/Window_function
number WindowBlackman(number a, int N, int i)
{
    number a0 = (1.0 - a) / 2.0;
    number a1 = 0.5;
    number a2 = a / 2.0;

    number wnd = a0;
    wnd -= a1 * cos(2.0 * pi * (number(i) / number(N - 1)));
    wnd += a2 * cos(4.0 * pi * (number(i) / number(N - 1)));

    return wnd;
}

//FIR lowpass filter
//Fc = Cutoff freq., Fs = Sample freq., N = # of taps, i = Tap index
number Lowpass(number Fc, number Fs, int N, int i)
{
    number wc = (Fc/Fs);

    number wnd = WindowBlackman(0.16, N, i);

    return 2.0*wc * wnd * sinc(2.0*wc * number(i - N/2));
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    number Fs = iResolution.x;
    number Fcol = Fs * F_COL;
    number Flumlp = Fs * F_LUMA_LP;
    number n = floor(fragCoord.x);

	vec2 uv = fragCoord.xy;

    number luma = sample2D(iChannel0, iResolution.xy, uv).r;
    vec2 chroma = vec2(0);

    //Filtering out unwanted high freqency content from the chroma(IQ) signal.
    for(int i = 0;i < FIR_SIZE;i++)
    {
        int tpidx = FIR_SIZE - i - 1;
        number lp = Lowpass(Flumlp, Fs, FIR_SIZE, tpidx);
        chroma += sample2D(iChannel0, iResolution.xy, uv - vec2(i - FIR_SIZE / 2, 0)).yz * lp;
    }

    chroma *= rotate(tau * HUE);

    vec3 color = yiq2rgb * vec3(BRIGHTNESS * luma, chroma * SATURATION);

    #if(VIEW_MODE == COMPOSITE)
    	fragColor = vec4(color, 0);

    #elif(VIEW_MODE == RGB)
   		fragColor = texture(iChannel1, uv / iResolution.xy);

    #elif(VIEW_MODE == LUMA)
    	fragColor = vec4(luma);

    #elif(VIEW_MODE == CHROMA)
    	fragColor = vec4(40.0*chroma+0.5,0,0);

    #elif(VIEW_MODE == SIGNAL)
    	fragColor = 0.5 * texture(iChannel2, uv / iResolution.xy).rrrr+0.25;

    #elif(VIEW_MODE == SPLIT)
    	if(uv.x < iResolution.x/2.0)
        {
            fragColor = texture(iChannel1, uv / iResolution.xy);
        }
        else
        {
    		fragColor = vec4(color, 0);
        }
    #endif
}


vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords){
    vec2 fragCoord = texture_coords * iResolution.xy;
    mainImage( color, fragCoord );
    return color;
}
]]

function love.load()
  disk = love.graphics.newImage("disk.png")
  x=400-disk:getWidth()/2
  y=300-disk:getHeight()/2

  --canvas = love.graphics.newCanvas()
  shader = love.graphics.newShader(ntsc)
end

function love.update(dt)
  shader:send('iResolution', { love.window.getWidth(), love.window.getHeight(), 1 })

  local v=10
  if love.keyboard.isDown("w") then
    y=y-v
  end
  if love.keyboard.isDown("a") then
    x=x-v
  end
  if love.keyboard.isDown("s") then
    y=y+v
  end
  if love.keyboard.isDown("d") then
    x=x+v
  end
end

function love.draw()
  love.graphics.setShader(shader)
  love.graphics.draw(disk, x, y)
  love.graphics.setShader()
end
Any thoughts?
a² = b² + c²
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with shader

Post by pgimeno »

Try iChannel0 instead. You may need iChannel1 as well, especially since you're setting VIEW_MODE to SPLIT.

That's for LÖVE 0.9, right? It would've been nice to specify that.
User avatar
Autophoenix
Prole
Posts: 40
Joined: Thu Mar 06, 2014 4:18 pm
Location: Rio de Janeiro, Brazil

Re: Help with shader

Post by Autophoenix »

pgimeno wrote: Thu Aug 02, 2018 11:27 pm Try iChannel0 instead. You may need iChannel1 as well, especially since you're setting VIEW_MODE to SPLIT.

That's for LÖVE 0.9, right? It would've been nice to specify that.
I tried commenting extern Image iChannel; out but I get a undeclared identifier error. Also, what are those channels? My ideia is to apply the shader to the screen, not to an image or a canvas.
I also forgot to replace the texture() function with Texel(), that was giving me an error

I'm using LÖVE 11.1
a² = b² + c²
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with shader

Post by pgimeno »

Well, the shader requires two external images, iChannel0 and iChannel1. Once I add those and replace texture() with Texel(), the above code no longer gives errors (but I get a black screen).

These images seem to be the input images in ShaderToy. I can't help you figure out what they are for, sorry.
User avatar
Autophoenix
Prole
Posts: 40
Joined: Thu Mar 06, 2014 4:18 pm
Location: Rio de Janeiro, Brazil

Re: Help with shader

Post by Autophoenix »

pgimeno wrote: Fri Aug 03, 2018 1:58 pm Well, the shader requires two external images, iChannel0 and iChannel1. Once I add those and replace texture() with Texel(), the above code no longer gives errors (but I get a black screen).

These images seem to be the input images in ShaderToy. I can't help you figure out what they are for, sorry.
What did you send to iChannel0 and iChannel1? canvases?
a² = b² + c²
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with shader

Post by pgimeno »

I sent nothing, the shader simply did no longer err out.

You can send an object of type Texture, be it a canvas or an image.
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Help with shader

Post by zorg »

Also, as far as i've seen, shadertoy inputs are usually static images or videos, basically either sending the image once, or updating the texel each frame in case of a video... is my guess on how you'd replicate those behaviours in löve (with either images or a canvas in the latter case). (maybe it can even be audio, although i'm not sure how the site encodes those into Texel data)
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Post Reply

Who is online

Users browsing this forum: No registered users and 48 guests