Idea Review: Better than Pixel Perfect ?

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

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.

GOAL:
- 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
ReFreezed
Party member
Posts: 612
Joined: Sun Oct 25, 2015 11:32 pm
Location: Sweden
Contact:

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 = love.graphics.newCanvas(WORLD_WIDTH, WORLD_HEIGHT)
	worldCanvas:setFilter("nearest", "nearest") -- Only for this example - use linear if your shader requires it.

	worldCanvasShader = love.graphics.newShader[[
	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;
	}
	]]
end

function love.draw()
	-- Render the world.
	love.graphics.setCanvas(worldCanvas)
	love.graphics.clear(.2, .4, .2, 1) -- Green background.

	love.graphics.setColor(0, 0, 0, .2) -- Dark stripe.
	love.graphics.rectangle("fill", .4*WORLD_WIDTH, 0, .2*WORLD_WIDTH, WORLD_HEIGHT)

	love.graphics.setColor(0, 1, 1, .7) -- Cyan rings.
	love.graphics.setLineStyle("rough")
	love.graphics.setLineWidth(4)
	love.graphics.circle("line", .42*WORLD_WIDTH, .43*WORLD_HEIGHT, 12, 32)
	love.graphics.circle("line", .58*WORLD_WIDTH, .57*WORLD_HEIGHT, 12, 32)

	love.graphics.setCanvas(nil)

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

	worldCanvasShader:send("time", love.timer.getTime())

	love.graphics.setShader(worldCanvasShader)
	love.graphics.setColor(1, 1, 1, 1)
	love.graphics.draw(worldCanvas, (ww-cw*scale)/2, (wh-ch*scale)/2, 0, scale)
	love.graphics.setShader(nil)

	-- Show what worldCanvas contains in a corner.
	love.graphics.draw(worldCanvas)
end
Tools: Hot Particles, LuaPreprocess, InputField, (more) Games: Momento Temporis
"If each mistake being made is a new one, then progress is being made."
Post Reply

Who is online

Users browsing this forum: No registered users and 56 guests