## [library] moonshine – Chainable post-processing shaders for LÖVE.

vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

### [library] moonshine – Chainable post-processing shaders for LÖVE.

TL;DR: shine version 2.0: Better API, better performance, better name.

Less than 10 lines of code to transform this:
noonshine.jpg (66.89 KiB) Viewed 3063 times
into this:
moonshine.jpg (87.09 KiB) Viewed 3063 times

Lövers,

ever since shaders were first added to LÖVE, I had this idea of a vast repository of common post-processing shaders that you could just staple on top of your game with a few lines of code. This repository would be open, so that anybody that cared and could would contribute to it.

Unfortunately, this idea would require abstractions and restrictions. Unfortunately, because this clashes with the goal and scope of LÖVE. LÖVE provides the tools you need to make great games, without imposing any artificial limits on what you can and cant do. This is the reason why LÖVE is great, but it means that sometimes things are not as easy as they could be.

A few years back I released shine to fill the gap. You can see how my vision influenced the design : adding post processing shaders to your game requires only a few lines of code. However, the backend, that is, the actual implementation of the shaders, was horrible. Just horrible. The API was a nightmare. I mean, look at this! Who is supposed to write this, let alone understand whats going on? Yuck. Still, awesome people contributed cool effects like pixelate and scanlines, light scattering and gameboy color emulation, or barrel distortion and a sketch effect.

Recently, josefnpat and I worked on a thing which used shine. As the machine we were given was not all that powerful, I ended up re-implemented the effects in two custom shaders. When done, I realized that this new code could be abstracted and be the basis for a rewrite of shine. That day was the birthday of shine 2.0, or, as it should henceforth be known: moonshine*.

Moonshine does everything shine does, but better. It is (way) easier to write effects (example), chaining multiple effects (what you normally do) is much more performant, and some idiocies were fixed. The README documents all effects and contains small tutorials on both how to use the lib and how to contribute effects.

There is also a demo to show off and experiment with the effects. It is attached to this post, but I don't recommend looking at the code to learn moonshine: most of it is used to construct the GUI (though you might learn a thing or two about suit).

Anyway, enough with the wall of text already. Here is the code: moonshine

Enjoy!

* I realize there is also moonshine, the Lua interpreter for the browser, but the name just fits
Attachments
moonshine.love
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine

master both
Party member
Posts: 249
Joined: Tue Nov 08, 2011 12:39 am
Location: Chile

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

Awesome, this sure is a huge upgrade from shine, it's really clean and simple. Congrats!

Fuzzlix
Citizen
Posts: 53
Joined: Thu Oct 13, 2016 5:36 pm

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

Well done!
But now comes the beginner question :
Is it possible to use your library with fonts too? (I ask because i have seen the nice effects grump created in his nice game animal factory)

vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

Fuzzlix wrote:
Tue Oct 31, 2017 5:46 pm
Is it possible to use your library with fonts too?
I am unsure what you mean by that, but the shaders apply to everything drawn inside the effect.draw(...) call.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine

Fuzzlix
Citizen
Posts: 53
Joined: Thu Oct 13, 2016 5:36 pm

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

vrld wrote:
Tue Oct 31, 2017 5:55 pm
Fuzzlix wrote:
Tue Oct 31, 2017 5:46 pm
Is it possible to use your library with fonts too?
I am unsure what you mean by that, but the shaders apply to everything drawn inside the effect.draw(...) call.
Please take a look at the text "Animal Factory" on the start screen. The letter color inside a letter changes and the letter got a black border for instance. The source font is a normal ttf font.
I could draw the letter into a new image and manipulate the color with your filters easily but how to create the black border?

zorg
Party member
Posts: 2373
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

Fuzzlix wrote:
Tue Oct 31, 2017 6:27 pm
vrld wrote:
Tue Oct 31, 2017 5:55 pm
Fuzzlix wrote:
Tue Oct 31, 2017 5:46 pm
Is it possible to use your library with fonts too?
I am unsure what you mean by that, but the shaders apply to everything drawn inside the effect.draw(...) call.
Please take a look at the text "Animal Factory" on the start screen. The letter color inside a letter changes and the letter got a black border for instance. The source font is a normal ttf font.
I could draw the letter into a new image and manipulate the color with your filters easily but how to create the black border?
You probably want an outline shader then, something like explained in one of the löve related blog posts.
Iirc that's usually not a "post-processing" related shader though. (But could probably be implemented by you using moonshine, anyway)
Me and my stuff True 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.

Fuzzlix
Citizen
Posts: 53
Joined: Thu Oct 13, 2016 5:36 pm

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

zorg wrote:
Tue Oct 31, 2017 6:42 pm
You probably want an outline shader then, something like explained in one of the löve related blog posts.
Iirc that's usually not a "post-processing" related shader though. (But could probably be implemented by you using moonshine, anyway)
I will look at it.
Thank you.

modiX
Citizen
Posts: 86
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

Hi vrld,

Problem 1 ~ solved

I'm on the point where I want to build and use shaders and your lib looks very interesting to me, however there seems to be a problem when you scale the graphics:

Code: Select all

local moonshine = require 'moonshine'

effect = moonshine(moonshine.effects.glow)
effect.glow.min_luma = 1
effect.glow.strength = 50
end

function love.draw()
love.graphics.scale(1.2, 1.2)
effect(function()
love.graphics.rectangle("fill", 100,100, 100,100)
end)
end
https://dl.dropbox.com/s/cb1n3v5ikktl4a ... .45.40.png

The glow effect in this example will be scaled another time, so that it's off its position. I've not looked into your source code so far, but I expect this to happen, because you create an additional canvas you draw into, so the scaling with be applied two times. Is there an elegant solution to this?

UPDATE: So I found the solution by myself. I should've looked into canvas objects way earlier, my bad. My objects (I want the effect apply to) should all be rendered in a canvas that is large enough to render the glow around it:

Code: Select all

local moonshine = require 'moonshine'

canvas = love.graphics.newCanvas(800, 600)
effect = moonshine(moonshine.effects.glow)
effect.glow.min_luma = 1
effect.glow.strength = 50
end

function love.draw()
love.graphics.setCanvas(canvas)
love.graphics.clear()
effect(function()
love.graphics.rectangle("fill", 100,100, 100,100)

love.graphics.setCanvas()
love.graphics.draw(canvas, 0, 0, 0, 1.2, 1.2, 0, 0, 0, 0)
end)
end
This can be scaled up without messing up. However, as I understood, I better have only one master canvas I scale up to fit my game window. However, the 2nd issue is still present. (see below)

Problem 2 ~ partially solved

Also, it seems there is an issue with moonshine.effects.glow on non textured shapes. Unless my draw color of my rectangle is white, the glow effect will not work and the rectangle will be transparent:

Code: Select all

local moonshine = require 'moonshine'

canvas = love.graphics.newCanvas(800, 600)
effect = moonshine(moonshine.effects.glow)
effect.glow.min_luma = 1
effect.glow.strength = 50
sprite = love.graphics.newImage("background.png")
sprite:setWrap("repeat", "repeat")
end

function love.draw()
love.graphics.setCanvas(canvas)
love.graphics.clear()
love.graphics.setColor({ 255, 0, 0 })
love.graphics.rectangle("fill", 100,100, 100,100)
love.graphics.setColor({ 255, 255, 255 })
love.graphics.rectangle("fill", 300,300, 100,100)

love.graphics.setCanvas()
love.graphics.setColor({ 255, 255, 255 })
love.graphics.draw(sprite, quad, 0, 0, 0, 1, 1)
effect(function()
love.graphics.setColor({ 255, 255, 255 })
love.graphics.draw(canvas, 0, 0)
end)
end

See how the red shape that is transparent is not glowing at all? It shouldn't be transparent and it should glow. It would be great if you could look into it or tell me how I can fix it. Thank you.

UPDATE: Thanks to slime now I know the glow was not working, because of min_luma. If I change it to 0 I get this:

The transparency is still an issue I don't understand. Any help is appreciated.
Attachments
GlowBug.love
Last edited by modiX on Wed Dec 27, 2017 11:31 pm, edited 9 times in total.

───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

drunken_munki
Party member
Posts: 134
Joined: Tue Mar 29, 2011 11:05 pm

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

At a glance this is the normal functionality when using pixel shaders on shapes (lines, ellipses, rectangles, etc).

If you want this to work in the simplest way you will need to draw the red shape into a canvas and then enable the shader when you draw the canvas to screen. This may also be useful if you want to group objects into one shader pass by drawing them all to this canvas.

^ You could take a look at the vertex shader, however, if you want to apply a shader to a shape. Though I've never understood this myself or used it.

modiX
Citizen
Posts: 86
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

### Re: [library] moonshine – Chainable post-processing shaders for LÖVE.

drunken_munki wrote:
Wed Dec 27, 2017 4:42 pm
At a glance this is the normal functionality when using pixel shaders on shapes (lines, ellipses, rectangles, etc).

If you want this to work in the simplest way you will need to draw the red shape into a canvas and then enable the shader when you draw the canvas to screen. This may also be useful if you want to group objects into one shader pass by drawing them all to this canvas.

Regarding my first problem, this is the solution. Please check my EDIT. I, eventually, modified the 2nd problem to use a canvas, too. However, the issue persists. Please check my 2nd problem with the red and the white rectangle. I already draw the red and the white rectangle on one canvas and draw it with color { 255, 255, 255 } using the effect function of moonshine.

This library already does the work when it comes to creating new shaders. The desired shader is created and set under the hood of the effect function call. It works with the white rectangle but not with the red, even when both rectangles have been drawn in the same canvas, I draw.

Problem 3

@vrld, here is another thing I don't get. I want to migrate a shader to moonshine to be able to chain it with other shaders that are already included, but there seems to be an issue with alpha and I don't get why this is happening.

Here is my test shader I created in the moonshine folder:

Code: Select all

return function(moonshine)
vec4 effect(vec4 color, Image texture, vec2 texturePos, vec2 screenPos)
{
return vec4(1.0f, 0.0f, 0.0f, 0.0f);
}
]]

local setters = {}

return moonshine.Effect{
name = "test",
setters = setters,
defaults = {}
}
end
As you can see, it simply returns one color, which is red, but fully transparent. So when I use the shader like this:

Code: Select all

local moonshine = require 'moonshine'

effect = moonshine(moonshine.effects.test)
canvas = love.graphics.newCanvas(800, 600)
end

function love.draw()
effect(function()
love.graphics.draw(canvas, 0, 0, 0)
end)
end
... I expect it to draw a black window, since every returned color is transparent. Instead, it ignores the alpha and draws a fully red window. Why is this happening?