Share a Shader!
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
Re: Share a Shader!
4aiman, I think you would want to draw those things to a canvas first. Then apply the shader as you draw the canvas to the screen.
Re: Share a Shader!
You could render the scene to a canvas and then send the canvas to the shader. IIRC that's what I've done in Bomb Dodgers (shameless plug). It allowed me to apply two shaders: One to switch the palette and one to use a wavetransformation on the level previews.4aiman wrote:It may be a little offtopic, but this thread has so many people sharing their shaders...
So, the question is: is there a way to somehow grab what was drawn so far and apply a shader to that?
I've tried using shine (and it worked ok) but failed to understand how to make it respect all my scale() and transform().
 Sheepolution
 Party member
 Posts: 263
 Joined: Mon Mar 04, 2013 9:31 am
 Location: The Netherlands
 Contact:
Re: Share a Shader!
Code: Select all
local list = {
noise = {
body = [[
p += rand(p, noise_rnd)/(1000/noise_amount);
finTex = Texel(tex, p);
]], externs = {amount = 10, rnd = 1}, funcs = {"rand"}},
waves = {
body = [[
p.x += sin(p.y*waves_amount+waves_time*6)*0.03;
finTex = Texel(tex, p);
]], externs = {time = 0, amount = 5}},
bulge = {
body = [[
np = vec2(p.x  bulge_pos.x, p.y  bulge_pos.y);
a = length(np);
b = atan(np.y, np.x);
a = (a*a);
np = a * vec2(cos(b), sin(b));
p = np + bulge_pos;
finTex = Texel(tex, p);
]], externs = {pos = {0.5,0.5}}},
pinch = {
body = [[
np = vec2(p.x  pinch_pos.x, p.y  pinch_pos.y);
a = length(np);
b = atan(np.y, np.x);
a = sqrt(a);
np = a * vec2(cos(b), sin(b));
p = np + pinch_pos;
finTex = Texel(tex, p);
]], externs = {pos = {0.5,0.5}}},
pixel = {
body = [[
p = floor(p*(100/pixel_amount))/(100/pixel_amount);
finTex = Texel(tex, p);
]], externs = {amount = 4}},
sucker = {
body = [[
a = atan(sucker_pos.x  p.y, sucker_pos.y  p.x);
p += vec2(cos(a)/(100/(sucker_amount*sucker_amount)), sin(a)/(100/(sucker_amount*sucker_amount)));
finTex = Texel(tex, p);
]], externs = {amount = 1, pos = {0.5, 0.5} }},
insidespin = {
body = [[
a = atan(0.5  p.y, 0.5  p.x);
p += vec2(cos(a)/insidespin_amount, sin(a)/insidespin_amount);
finTex = Texel(tex, p);
]], externs = {amount = 1}},
curve = {
body = [[
a = abs(p.x  0.5);
p.y = (a*a)*3;
p.x += (p.x > 0.5 ? a : a)*(p.y/2);
finTex = Texel(tex, p);
]], externs = {}},
rgb = {
body = [[
a = 0.0025 * rgb_amount;
finTex.r = texture2D(tex, vec2(p.x + a * rgb_dirs[0], p.y + a * rgb_dirs[1])).r;
finTex.g = texture2D(tex, vec2(p.x + a * rgb_dirs[2], p.y + a * rgb_dirs[3])).g;
finTex.b = texture2D(tex, vec2(p.x + a * rgb_dirs[4], p.y + a * rgb_dirs[5])).b;
]], externs = {dirs = {1,0,0,1,1,1}, amount = 3}},
tvnoise = {
body = [[
finTex.r = tvnoise_light + 1 + rand(p, tvnoise_rnd);
finTex.g = tvnoise_light + 1 + rand(p, tvnoise_rnd);
finTex.b = tvnoise_light + 1 + rand(p, tvnoise_rnd);
]], externs = {light = 1, rnd = 1}, funcs = {"rand"}},
invert = {
body = [[
finTex.r = 1finTex.r;
finTex.g = 1finTex.g;
finTex.b = 1finTex.b;
]], externs = {}},
distortion = {
body = [[
finTex.r = (sin(finTex.r * distortion_amount) + 1.) * .5;
finTex.g = (sin(finTex.g * distortion_amount) + 1.) * .5;
finTex.b = (sin(finTex.b * distortion_amount) + 1.) * .5;
]], externs = {amount = 20}, funcs = {"wave"}},
spinsucker = {
body = [[
a = atan(p.y  0.5, 0.5  p.x);
p.x += sin(a) * spinsucker_amount;
p.y += cos(a) * spinsucker_amount;
finTex = Texel(tex, p);
]], externs = {amount = 1}},
circle = {
body = [[
a = sqrt(abs(p.x  circle_pos[0])*abs(p.x  circle_pos[0]) + abs(p.y  circle_pos[1])*abs(p.y  circle_pos[1]));
if (circle_soft) {
finTex.a = 1  a*2 / circle_amount;
} else {
finTex.a = floor( 1 + (1  a*2 * circle_amount));
}
]], externs = {amount = 1, soft = true, pos = {0.5, 0.5}}},
color = {
body = [[
finTex.r *= color_color[0]/255.0;
finTex.g *= color_color[1]/255.0;
finTex.b *= color_color[2]/255.0;
]], externs = {color = {255, 255, 255}}
},
scan = {
body = [[
if (p.y > scan_y && p.y < scan_y + scan_height) {
finTex.r = scan_light + 1 + rand(p, scan_rnd);
finTex.g = scan_light + 1 + rand(p, scan_rnd);
finTex.b = scan_light + 1 + rand(p, scan_rnd);
}
]], externs = {y = 0, height = 1,light = 1, rnd = 1}, funcs = {"rand"}}
}
}
local functions = {
rand = [[float rand(vec2 co, float v) {
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453 * v);
}]],
wave = [[float wave(float x, float amount) {
return (sin(x * amount) + 1.) * .5;
}]]
}
local function getExternType(a)
local t = type(a)
if t == "number" then return "float" end
if t == "boolean" then return "bool" end
if t == "table" then
local t2 = type(a[1])
if t2 == "number" then
if #a <= 4 then
return "vec" .. #a
else
return "float[" .. #a .. "]"
end
elseif t2 == "table" then
return "vec" .. #a[1] .. "[" .. #a .. "]"
end
end
end
local Shader = {}
function Shader.new(...)
local names = {...}
local funcs = {}
local externs = {}
local header = [[
vec4 effect(vec4 color, Image tex, vec2 p, vec2 pc) {
vec4 finTex = Texel(tex, p);
vec2 np;
float a, b, c;
]]
local bodies = {}
for i,v in ipairs(names) do
local shader = list[v]
table.insert(bodies, shader.body)
for k,ext in pairs(shader.externs) do
table.insert(externs, "extern " .. getExternType(ext) .. " " .. v .. "_" .. k .. ";\n")
end
if shader.funcs then
for i,func in ipairs(shader.funcs) do
table.insert(funcs, functions[shader.funcs[i]])
end
end
end
extern_string = table.concat(externs, "")
funcs_string = table.concat(lume.set(funcs), "")
body_string = table.concat(bodies, "")
local footer = "return finTex;}"
local final = extern_string .. funcs_string .. header .. body_string .. footer
local s = love.graphics.newShader(final)
for i,v in ipairs(names) do
for k,ext in pairs(list[v].externs) do
if type(ext) == "table" and #ext > 4 then
s:send(v.."_"..k, unpack(ext))
else
s:send(v.."_"..k, ext)
end
end
end
return s
end
check whether a shader has a certain extern
function Shader.has(name, extern)
return list[name].externs[extern]
end
return Shader
It's very simple. You use Shader.new to create a new shader. You pass the names of the shaders you want to include.
Example:
You can also use Shader.has to check if a shader has a certain extern.
It is important that you first pass shaders that affect the shape, like "waves" and "noise", and then shaders that affect colors like "rgb" or "invert". This is because a new texture will be made after every shader that affects p.
Code: Select all
finTex = Texel(tex, p);
Enjoy?
Re: Share a Shader!
Hey Sheepolution, that looks amazing!Sheepolution wrote:snip
I'm quite interested in knowing how it runs with multiple shaders/objects. I've had a lot of performance issues with my earlier games which were all linked to using shaders...
Re: Share a Shader!
@Sheepolution
I've been using the shine shader library in my current project pretty much straight outta the box. It doesnt have a wave shader though and today I found this thread.
I'm new to shaders and am not really sure how to adapt your effect to the Shine library. If you have the time, can you show me how I can adapt that effect from your library? Would be a great addition to the library.
Many thanks.
I've been using the shine shader library in my current project pretty much straight outta the box. It doesnt have a wave shader though and today I found this thread.
I'm new to shaders and am not really sure how to adapt your effect to the Shine library. If you have the time, can you show me how I can adapt that effect from your library? Would be a great addition to the library.
Many thanks.
Re: Share a Shader!
Not a useful shader but it's got some colors in it at least. https://www.shadertoy.com/view/MlcXDB

 Prole
 Posts: 2
 Joined: Sat Feb 25, 2017 1:12 am
Re: Share a Shader!
Someone here may find it useful, takes any texture that is drawn while the shader is active and maps it onto a 3d sphere (some distortion but not very noticeable if you don't spin it too fast. stars not included). http://pastebin.com/jRp6LCnz
Re: Share a Shader!
Loving that wave shader! I'm going to give that a try for the water in my 2d platformer.
Re: Share a Shader!
Just got into writing some shaders, and I'm trying to dry a "overlay" texture on an existing image.
I pass the player texture/image, and this draws the texture over the existing image.
Is there anyway to resize the "overlay", it currently stretches over the entire image. Or is what I'm doing not possible in a single pass?
Code: Select all
[[
extern Image player;
vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords )
{
vec4 texcolor = Texel(texture, texture_coords);
vec4 t2 = Texel( player, texture_coords );
if( t2.a > 0 )
return t2 * color;
else
return texcolor * color;
}
]]
Is there anyway to resize the "overlay", it currently stretches over the entire image. Or is what I'm doing not possible in a single pass?
Who is online
Users browsing this forum: Google [Bot], MrFariator and 27 guests