Idea Review: Better than Pixel Perfect ?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
Posts: 2
Joined: Wed Sep 15, 2021 10:18 am

Idea Review: Better than Pixel Perfect ?

Post by pixelprato »

Hi guys, I'm new to löve.

I'm starting to recreate a type of rendering render-to-texture that I did in C# with Unity back then.

Thx to comment and maybe proposing me other solution. For the moment I'm satisfied with what I ended up, but there's always room to do differently.

- Getting pixelated rendering.
- with smooth "crt" distortion.
- and not jaggy pixel contours.
* I could dig into some librairies as the "push" one, but I want to code lot of thing myself to 1)learn and 2)own more what I'm doing.

I don't want a complex shader that smooth-out pixels with costly blur thing. I did:

1. Drawing on a firstCanvas of 360x204
-- scale x1, nearest...
2. Storing that result in a image of 360x204 (pre-render)
-- scale x1, and nearest)
-- image = firstCanvas

3. Than rendering in a finalCanvas, the image "pre-render").
-- scaling this one as I want
-- linear filtering (getting for free, smooth (fake AA) pixel edges)
-- shader applied here, to distort and play with the upscaled low-pixels pre-render

WHY I do not just render low-resolution on a canvas and right-away rendering a second time in another canvas ?
I did not succeed only using 2 canvas in a row without storing some result in a buffer(image). Scaling up the second one doesn't "store" the first one as "printed" and the trick using "linear" filtering on the last Canvas won't work.
User avatar
Party member
Posts: 304
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden

Re: Idea Review: Better than Pixel Perfect ?

Post by ReFreezed »

You can definitively get rid of the middle step involving an image (which seem highly inefficient), and probably the finalCanvas step too (if you don't have more post-processing to do or something).

Example using only one canvas:

Code: Select all

local WORLD_WIDTH  = 80
local WORLD_HEIGHT = 100

local worldCanvas, worldCanvasShader

function love.load()
	worldCanvas =, WORLD_HEIGHT)
	worldCanvas:setFilter("nearest", "nearest") -- Only for this example - use linear if your shader requires it.

	worldCanvasShader =[[
	uniform float time;

	vec4 effect(vec4 color, Image tex, vec2 texCoords, vec2 screenCoords) {
		texCoords.x += 0.005 * sin(50.0*texCoords.y + 2.5*time); // Add a wave effect.
		vec4 pixel   = Texel(tex, texCoords);
		return pixel * color;

function love.draw()
	-- Render the world., .4, .2, 1) -- Green background., 0, 0, .2) -- Dark stripe."fill", .4*WORLD_WIDTH, 0, .2*WORLD_WIDTH, WORLD_HEIGHT), 1, 1, .7) -- Cyan rings."rough")"line", .42*WORLD_WIDTH, .43*WORLD_HEIGHT, 12, 32)"line", .58*WORLD_WIDTH, .57*WORLD_HEIGHT, 12, 32)

	-- Render worldCanvas centered on and filling the screen, with effects.
	local ww, wh =
	local cw, ch = worldCanvas:getDimensions()
	local scale  = math.min(ww/cw, wh/ch)

	worldCanvasShader:send("time", love.timer.getTime()), 1, 1, 1), (ww-cw*scale)/2, (wh-ch*scale)/2, 0, scale)

	-- Show what worldCanvas contains in a corner.
Tools: Hot Particles, LuaPreprocess, (more) Games: Momento Temporis: Light from the Deep, Energize!
"If each mistake being made is a new one, then progress is being made."
Post Reply

Who is online

Users browsing this forum: veethree and 39 guests