Page 30 of 33

Re: Share a Shader!

Posted: Thu Jun 09, 2016 11:27 pm
by Nuthen224
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!

Posted: Fri Jun 10, 2016 12:32 am
by rmcode
4aiman wrote:It may be a little off-topic, 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().
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 wave-transformation on the level previews.

Re: Share a Shader!

Posted: Fri Jun 10, 2016 6:27 am
by 4aiman
Thanks! I'll try ^_^

Re: Share a Shader!

Posted: Sat Jul 30, 2016 1:12 pm
by Sheepolution

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 = 1-finTex.r;
			finTex.g = 1-finTex.g;
			finTex.b = 1-finTex.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
I made this a while back when learning shaders, and I thought it would be nice to share it. Note that my knowledge about shaders is still pretty limited so it can probably be improved in some way. Also as I'm writing this I'm learning that shine exists, which from what I understand has the same goal? Anyway, I couldn't really turn this into a library so I thought I'd share it here.

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:
Image

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);
You can add your own shaders of course, just make sure you get the variable names right (look at the header).

Enjoy?

Re: Share a Shader!

Posted: Sat Jul 30, 2016 3:27 pm
by Ulydev
Sheepolution wrote:-snip-
Hey Sheepolution, that looks amazing!

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... :death:

Re: Share a Shader!

Posted: Wed Dec 07, 2016 7:05 am
by rungo73
@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.

Re: Share a Shader!

Posted: Sat Dec 10, 2016 11:51 pm
by Tanner
Not a useful shader but it's got some colors in it at least. https://www.shadertoy.com/view/MlcXDB

Re: Share a Shader!

Posted: Sun Mar 26, 2017 12:47 am
by creeper9207
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

Image

Re: Share a Shader!

Posted: Sun Mar 26, 2017 8:54 am
by Imaculata
Loving that wave shader! I'm going to give that a try for the water in my 2d platformer.

Re: Share a Shader!

Posted: Mon Apr 17, 2017 2:04 am
by Drak
Just got into writing some shaders, and I'm trying to dry a "overlay" texture on an existing image.

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;
        }
    ]]
    
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?