I'm working on a Mandelbrot fractal generator. It generates a certain number of pixels on the screen, then iterates through a function to produce color. Once the whole screen is filled with pixels, I use the screenshot function and create an image of that screenshot. Next, I stop drawing each pixel to the screen, and I draw the screenshot, to stop the lag. This is what it looks like:
https://love2d.org/imgmirrur/blJRoQu.png
I added the ability to zoom in using your mouse wheel, and to pan using WASD. However, when you zoom in, the fractal gets blurry. How would I go about re-rendering the fractal when you zoom in, so it appears high quality? I only want to re-render the pixels visible on the screen, to prevent lag.
How would I go about this?
Re: How would I go about this?
Upload your love file and we can help you.
We can make all the suggestions in the world but without the source its a waste of time.
We can make all the suggestions in the world but without the source its a waste of time.
- zorg
- Party member
- Posts: 3470
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: How would I go about this?
From what you wrote, i believe you want something like this:
when zooming in, you probably have a set scale that you use; you can use that, and the panning values to calculate the area you would need to re-render that one "view".
Problem is, you're trying to draw an infinitely detailed... thing, so you can't store that in its entirety.
What you can do, is to cache (save) separate parts of it at different detail levels, and if you are at a place rendered previously, it can display that without the need to calculate every pixel again, but sooner or later, this will eat up your ram, and even your hdd if you decide to utilize that as well.
when zooming in, you probably have a set scale that you use; you can use that, and the panning values to calculate the area you would need to re-render that one "view".
Problem is, you're trying to draw an infinitely detailed... thing, so you can't store that in its entirety.
What you can do, is to cache (save) separate parts of it at different detail levels, and if you are at a place rendered previously, it can display that without the need to calculate every pixel again, but sooner or later, this will eat up your ram, and even your hdd if you decide to utilize that as well.
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.
-
- Prole
- Posts: 9
- Joined: Sat Sep 13, 2014 10:20 pm
Re: How would I go about this?
Here is my code. It's kind of messy considering I did a lot of playing around with itartofwork wrote:Upload your love file and we can help you.
We can make all the suggestions in the world but without the source its a waste of time.
Code: Select all
--[[
Mandelbrot set: Iterate through the following function
fc(z) z^2 + c
Case1, blows up:
c = 1
f1(0) 0^2 + 1 --> 1
f1(1) 1^2 + 1 --> 2
f1(2) 2^2 + 1 --> 5
f1(5) 5^2 + 1 --> 26
Case2, is always <= 2:
c = -1
f-1(0) 0^2 - 1 --> -1
f-1(-1) -1^2 - 1 --> 0
f-1(0) 0^2 - 1 --> -1
]]
function love.load()
maxIter = 1000
gridSize = 50
default = 10
default2 = 5
box = 1
colorScale = 8
scale = 1
transX = 0
transY = 0
power = 2
iterationCount = 0
pixelCount = 0
love.graphics.setBackgroundColor(255, 255, 255)
screenshot = nil
points = {}
loops = 0
width, height = love.graphics.getWidth(), love.graphics.getHeight()
processing = true
zoomCol = width / 2
zoomRow = height / 2
nowH, nowW = 10, 10
function love.keypressed(key)
if key == "escape" then
love.event.quit()
end
end
function love.mousepressed(x, y, button)
if button == "wu" and not processing then
scale = scale + (scale / 4)
elseif button == "wd" and not processing then
scale = scale - (scale / 4)
end
end
--i = root(-1), so by squaring i, you get a real number to graph (-1)
function toRealNumber(imaginary)
return imaginary ^ 2
end
function f(z, c)
return z ^ power + c
end
function comma(number)
repeat number, count = tostring(number):gsub("^(%d+)(%d%d%d)", "%1,%2") until count == 0
return number
end
function redraw(zoom)
end
end
function love.draw()
love.graphics.scale(scale, scale)
love.graphics.translate(transX, transY)
if loops == 0 then
for _, point in ipairs(points) do
love.graphics.setColor(point[3] == "white" and {point[4] * colorScale, point[4] * colorScale, point[4] * colorScale} or {0, 0, 0})
love.graphics.rectangle("fill", point[1], point[2], default, default)
end
elseif loops == 1 or loops == 2 then
love.graphics.draw(screenshot, 0, 0)
for _, point in ipairs(points) do
love.graphics.setColor(point[3] == "white" and {point[4] * colorScale, point[4] * colorScale, point[4] * colorScale} or {0, 0, 0})
love.graphics.rectangle("fill", point[1], point[2], default, default)
end
else
love.graphics.draw(screenshot, 0, 0)
end
love.graphics.setColor(255, 255, 255)
love.graphics.rectangle("line", nowW - gridSize, nowH - gridSize, gridSize, gridSize)
if loops < 3 then
love.graphics.printf("Iterations: " .. comma(iterationCount), 25, 25, 500, "left")
love.graphics.printf("Pixels: " .. comma(pixelCount), 25, 50, 500, "left")
end
end
function love.update()
if processing then
for row = nowH - gridSize, nowH, default do
for col = nowW - gridSize, nowW, default do
pixelCount = pixelCount + 1
local real = (col - zoomCol) * 4 / width --- (love.mouse.getX() / width)--x axis (real numbers)
local imaginary = (row - zoomRow) * 4 / width --- (love.mouse.getY() / width)--y axis (imaginary numbers) (i = root(-1))
local z, c, iter = 0, 0, 0
while (f(z, toRealNumber(c)) <= 4 and iter < maxIter) do --f(x, z) z^2 + c
iterationCount = iterationCount + 1
local zNew = z^2 - toRealNumber(c) + real
c = 2*z*c + imaginary
z = zNew
iter = iter + 1
end
if iter < maxIter then
table.insert(points, {col, row, "white", iter})
else
table.insert(points, {col, row, "black"})
end
end
end
nowW = nowW + gridSize
if nowW >= width + (gridSize * 3) then
nowW = 1
nowH = nowH + gridSize
end
if nowH - gridSize >= height then
nowW = 1
nowH = 1
screenshot = love.graphics.newImage(love.graphics.newScreenshot(true))
points = {}
loops = loops + 1
if loops == 1 then
pixelCount = 0
iterationCount = 0
processing = true
default = default2
elseif loops == 2 then
pixelCount = 0
iterationCount = 0
default = box
else
processing = false
end
end
else
if love.keyboard.isDown("w") then
transY = transY + (5*(1/scale))
end
if love.keyboard.isDown("s") then
transY = transY - (5*(1/scale))
end
if love.keyboard.isDown("d") then
transX = transX - (5*(1/scale))
end
if love.keyboard.isDown("a") then
transX = transX + (5*(1/scale))
end
end
end
Re: How would I go about this?
I went over the code and didn't find a solution, although it was late when i read the initial thread.
The problem you said your having is when you zoom the image becomes pixelated, there are a few reasons for this, your not actually drawing out the image in terms of pixels example below
What you are doing however is drawing out rectangles in specific dimensions which are a series of pixels so when you zoom in your stretching the rectangles increasing the pixel count which creates a blurred image.
The next issue is your taking a screenshot of the screen which is saved into memory as a raster image which sets you up for failure when you want to zoom in.
You need to find a way to draw out your rectangles using a grid system, where they are saved into memory and then can be rebuilt as a vector, this will allow you to easily rebuild the image when you zoom in.
That is just my thoughts on this, hope it was a little helpful.
The problem you said your having is when you zoom the image becomes pixelated, there are a few reasons for this, your not actually drawing out the image in terms of pixels example below
Code: Select all
love.graphics.rectangle("fill", point[1], point[2], default, default)
The next issue is your taking a screenshot of the screen which is saved into memory as a raster image which sets you up for failure when you want to zoom in.
You need to find a way to draw out your rectangles using a grid system, where they are saved into memory and then can be rebuilt as a vector, this will allow you to easily rebuild the image when you zoom in.
That is just my thoughts on this, hope it was a little helpful.
Who is online
Users browsing this forum: Ahrefs [Bot] and 11 guests