Page 16 of 33

Re: Share a Shader!

Posted: Wed Mar 27, 2013 12:07 am
by Jasoco
I can't figure out how to properly implement it into my game. Never comes out right. But that might be my fault.

Re: Share a Shader!

Posted: Sat Mar 30, 2013 1:02 am
by retrotails
Warps UVs with a normal map.
It also adds a gradient to make the sphere look nicer but that's not necessary.
edf.png
edf.png (528.67 KiB) Viewed 2718 times

Re: Share a Shader!

Posted: Sun Mar 31, 2013 1:52 pm
by mikeisinlove
slime wrote:Bloom.

Code: Select all

local math, love = math, love

local function FindSmallestPO2(num)
	return 2 ^ math.ceil(math.log(num)/math.log(2))
end

local function ScaleToPO2(xsize, ysize)
	if love.graphics.isSupported("npot") then return xsize, ysize end
	return FindSmallestPO2(xsize), FindSmallestPO2(ysize)
end

-- i've found xsize and ysize of 1/2 - 1/4 the screen resolution to be nice
-- smaller values make the bloom more apparent and give much better performance, but can make it look bad if too small
function CreateBloomEffect(xsize, ysize) 
	if not love.graphics.newPixelEffect
	or not love.graphics.isSupported
	or not love.graphics.isSupported("pixeleffect")
	or not love.graphics.isSupported("canvas") then
		return
	end
	
	local function newPixelEffect(code)
		local success, result = pcall(love.graphics.newPixelEffect, code)
		if success then
			return result
		else
			print("Error compiling shader!\n"..result)
		end
	end
	
	local bloom = {}
	
	local shaders = {
		blur_vert = [[
			extern number canvas_h = 256.0;
			
			const number offset_1 = 1.3846153846;
			const number offset_2 = 3.2307692308;
			
			const number weight_0 = 0.2270270270;
			const number weight_1 = 0.3162162162;
			const number weight_2 = 0.0702702703;
			
			vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
			{
				vec4 texcolor = Texel(texture, texture_coords);
				vec3 tc = texcolor.rgb * weight_0;
				
				tc += Texel(texture, texture_coords + vec2(0.0, offset_1)/canvas_h).rgb * weight_1;
				tc += Texel(texture, texture_coords - vec2(0.0, offset_1)/canvas_h).rgb * weight_1;
				
				tc += Texel(texture, texture_coords + vec2(0.0, offset_2)/canvas_h).rgb * weight_2;
				tc += Texel(texture, texture_coords - vec2(0.0, offset_2)/canvas_h).rgb * weight_2;
				
				return color * vec4(tc, 1.0);
			}
		]],
		blur_horiz = [[
			extern number canvas_w = 256.0;

			const number offset_1 = 1.3846153846;
			const number offset_2 = 3.2307692308;
			
			const number weight_0 = 0.2270270270;
			const number weight_1 = 0.3162162162;
			const number weight_2 = 0.0702702703;

			vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
			{
				vec4 texcolor = Texel(texture, texture_coords);
				vec3 tc = texcolor.rgb * weight_0;
				
				tc += Texel(texture, texture_coords + vec2(offset_1, 0.0)/canvas_w).rgb * weight_1;
				tc += Texel(texture, texture_coords - vec2(offset_1, 0.0)/canvas_w).rgb * weight_1;
				
				tc += Texel(texture, texture_coords + vec2(offset_2, 0.0)/canvas_w).rgb * weight_2;
				tc += Texel(texture, texture_coords - vec2(offset_2, 0.0)/canvas_w).rgb * weight_2;
				
				return color * vec4(tc, 1.0);
			}
		]],
		bloom = [[
			extern number threshold = 1.0;
			
			float luminance(vec3 color)
			{
				// numbers make 'true grey' on most monitors, apparently
				return (0.212671 * color.r) + (0.715160 * color.g) + (0.072169 * color.b);
			}
			
			vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
			{
				vec4 texcolor = Texel(texture, texture_coords);
				
				vec3 extract = smoothstep(threshold * 0.7, threshold, luminance(texcolor.rgb)) * texcolor.rgb;
				return vec4(extract, 1.0);
			}
		]],
		
		combine = [[
			extern Image bloomtex;
			
			extern number basesaturation = 1.0;
			extern number bloomsaturation = 1.0;
			
			extern number baseintensity = 1.0;
			extern number bloomintensity = 1.0;
			
			vec3 AdjustSaturation(vec3 color, number saturation)
			{
    			vec3 grey = vec3(dot(color, vec3(0.212671, 0.715160, 0.072169)));
    			return mix(grey, color, saturation);
			}
		
			vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
			{
				vec4 basecolor = Texel(texture, texture_coords);
				vec4 bloomcolor = Texel(bloomtex, texture_coords);
				
				bloomcolor.rgb = AdjustSaturation(bloomcolor.rgb, bloomsaturation) * bloomintensity;
				basecolor.rgb = AdjustSaturation(basecolor.rgb, basesaturation) * baseintensity;
				
				basecolor.rgb *= (1.0 - clamp(bloomcolor.rgb, 0.0, 1.0));
				
				bloomcolor.a = 0.0;
				
				return clamp(basecolor + bloomcolor, 0.0, 1.0);
			}
		]]
	}
	
	for k,v in pairs(shaders) do
		local shader = newPixelEffect(v)
		if shader then
			shaders[k] = shader
		else
			return
		end
	end
	
	if not shaders.blur_vert or not shaders.blur_horiz or not shaders.bloom or not shaders.combine then
		return
	end

	
	local intensity_base, intensity_bloom = 1, 1
	local saturation_base, saturation_bloom = 1, 1
	local threshold_bloom = 0.5
	
	local debugdraw = false
	
	function bloom:refresh(xs, ys)
		xs, ys = math.floor(xs+0.5), math.floor(ys+0.5)
		
		local renderingtoscene = false

		self.xsize, self.ysize = xs, ys
		
		self.po2xsize, self.po2ysize = ScaleToPO2(self.xsize, self.ysize) -- scales x and y to next power of 2 if npot is false
		
		self.xres, self.yres = love.graphics.getWidth(), love.graphics.getHeight()
		self.po2xres, self.po2yres = ScaleToPO2(self.xres, self.yres)

	
		self.quad = love.graphics.newQuad(0, 0, self.xsize, self.ysize, self.po2xsize, self.po2ysize)
		self.scenequad = love.graphics.newQuad(0, 0, self.xres, self.yres, self.po2xres, self.po2yres)
	
		self.canvas = {
			bloom = love.graphics.newCanvas(self.po2xsize, self.po2ysize),
			blur_horiz = love.graphics.newCanvas(self.po2xsize, self.po2ysize),
			blur_vert = love.graphics.newCanvas(self.po2xsize, self.po2ysize),
			scene = love.graphics.newCanvas(self.po2xres, self.po2yres),
			bloomscene = love.graphics.newCanvas(self.po2xres, self.po2yres),
		}
				
		for k,v in pairs(self.canvas) do
			v:clear()
		end
		
		shaders.blur_horiz:send("canvas_w", self.po2xsize)
		shaders.blur_vert:send("canvas_h", self.po2ysize)
		self:setThreshold(self:getThreshold())
		self:setIntensity(self:getIntensity())
		self:setSaturation(self:getSaturation())
		
		if renderingtoscene then
			love.graphics.setCanvas(self.canvas.scene)
		end
		
		collectgarbage("collect")
	end
	
	function bloom:debugDraw(shoulddebugdraw)
		debugdraw = not not shoulddebugdraw
	end
	
	function bloom:setIntensity(ibase, ibloom)
		intensity_base = ibase
		intensity_bloom = ibloom
		
		shaders.combine:send("baseintensity", ibase)
		shaders.combine:send("bloomintensity", ibloom)
	end
	function bloom:getIntensity()
		return intensity_base, intensity_bloom
	end
	
	function bloom:setSaturation(sbase, sbloom)
		saturation_base = sbase
		saturation_bloom = sbloom
		
		shaders.combine:send("basesaturation", sbase)
		shaders.combine:send("bloomsaturation", sbloom)
	end
	function bloom:getSaturation()
		return saturation_base, saturation_bloom
	end
	
	function bloom:setThreshold(threshold)
		threshold_bloom = threshold
		
		shaders.bloom:send("threshold", threshold)
	end
	function bloom:getThreshold()
		return threshold_bloom
	end
	
	
	-- call right before drawing the stuff you want bloomed
	function bloom:predraw()
		for k,v in pairs(self.canvas) do
			v:clear()
		end
		love.graphics.setCanvas(self.canvas.scene)
		
		self.drawing = true
	end
	
	function bloom:enabledrawtobloom()
		love.graphics.setCanvas(self.canvas.bloomscene)
	end
	
	-- call after drawing the stuff you want bloomed
	function bloom:postdraw()			
		love.graphics.setColor(255, 255, 255)
		local blendmode = love.graphics.getBlendMode()
		love.graphics.setBlendMode("premultiplied")
		
		love.graphics.push()
		love.graphics.scale(self.po2xsize/self.po2xres, self.po2ysize/self.po2yres)
		
		-- apply bloom extract shader
		love.graphics.setCanvas(self.canvas.bloom)
		love.graphics.setPixelEffect(shaders.bloom)
		love.graphics.drawq(self.canvas.bloomscene, self.scenequad, 0, 0)
		
		love.graphics.pop()
					
		-- apply horizontal blur shader to extracted bloom
		love.graphics.setCanvas(self.canvas.blur_horiz)
		love.graphics.setPixelEffect(shaders.blur_horiz)
		love.graphics.drawq(self.canvas.bloom, self.quad, 0, 0)
		
		-- apply vertical blur shader to blurred bloom
		love.graphics.setCanvas(self.canvas.blur_vert)
		love.graphics.setPixelEffect(shaders.blur_vert)
		love.graphics.drawq(self.canvas.blur_horiz, self.quad, 0, 0)
		
		-- render final scene combined with bloom canvas
		love.graphics.setCanvas()
		shaders.combine:send("bloomtex", self.canvas.blur_vert)
		love.graphics.setPixelEffect(shaders.combine)
		love.graphics.drawq(self.canvas.scene, self.scenequad, 0, 0)
		
		love.graphics.setPixelEffect()
		
		if debugdraw then
			-- love.graphics.setColor(255, 255, 255, 128)
			love.graphics.draw(self.canvas.bloom, 0, 0)
			love.graphics.draw(self.canvas.blur_horiz, self.po2xsize+4, 0)
			love.graphics.draw(self.canvas.blur_vert, self.po2xsize*2+8, 0)
			-- love.graphics.draw(self.canvas.blur_vert, 0, 0, 0, self.po2xres/self.po2xsize, self.po2yres/self.po2ysize)
		end
		
		love.graphics.setBlendMode(blendmode)
		
		self.drawing = false
	end
	
	function bloom:isDrawing()
		return not not self.drawing
	end
	
	bloom:refresh(xsize, ysize)
	
	bloom:setIntensity(1, 1)
	bloom:setSaturation(1, 1)
	bloom:setThreshold(0.35)
	
	return bloom
end
Hey this looked pretty cool so I tried it out but the line
shaders.combine:send("bloomtex", self.canvas.blur_vert)
crashes it with no error message so I'm assuming there is a problem with sending canvases to a shader or something? Can someone help me understand the problem? I'd like to be able to write my own shaders but I can't even tell what the problem really is here.

Re: Share a Shader!

Posted: Mon Apr 29, 2013 1:41 pm
by Germanunkol
Useless first distortion shader of mine.
...
Scroll wheel to change number of squares.

Re: Share a Shader!

Posted: Tue Apr 30, 2013 8:57 am
by Germanunkol
Still just as useless, but a little prettier :P

Re: Share a Shader!

Posted: Fri May 03, 2013 12:39 am
by shatterblast
Germanunkol wrote:Still just as useless, but a little prettier :P
Kind of odd on this last one if you zoom out all the way. From a top-down view, it looks like a whirlwind, a fractal in motion, or something similar.

Re: Share a Shader!

Posted: Fri May 03, 2013 10:14 am
by Germanunkol
shatterblast wrote: Kind of odd on this last one if you zoom out all the way. From a top-down view, it looks like a whirlwind, a fractal in motion, or something similar.
True, I think the problem is that the square's borders are "cut off", a pixel is either part of the square or not, there's no smooth transitions. That's why the growing and shrinking of the squares doesn't look all that great...

Re: Share a Shader!

Posted: Sun May 05, 2013 4:29 pm
by Ref
Would like a peek at version 0.9 shader syntax.
Got everything working except Shader:send.
What is the new syntax?

Re: Share a Shader!

Posted: Sun May 05, 2013 5:16 pm
by slime
It works fine for me. What happens for you?

Re: Share a Shader!

Posted: Sun May 05, 2013 5:25 pm
by Ref
For version 0.9, I get solid yellow triangles (no error messages) - not the shaded triangles I get with 0.8.