Per-pixel plasma / copperbars

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
NÖÖB
Prole
Posts: 41
Joined: Thu Jul 31, 2008 10:57 pm
Location: Norway

Per-pixel plasma / copperbars

Post by NÖÖB » Thu Mar 03, 2011 10:53 pm

Branching off my previous topic http://love2d.org/forums/viewtopic.php?f=4&t=2547 about per pixel manipulation speed; after taking into consideration that framebuffers won't work on all computers, I looked into the newImageData function to use that as a sort of buffer.
It's not fast, but at least it seems faster than love.graphics.point.

Please excuse the code, I've only learned the bare minimum of love to create this, if that..

MAIN.LUA

Code: Select all

initScreen = love.graphics.setMode( 800, 600, false, true, 0 )

pixBuf		= love.image.newImageData( 512, 256 ) -- initialize PO2 buffer
pix		= love.graphics.newImage( pixBuf )

pixUpdate	= 0;	pixOffsetX	= 0;	pixOffsetY	= 0
f1		= 0;	f2		= 0;	f3		= 0
av		= 0;	av2		= 0;	av3		= 0
l1		= 0;	l2		= 0;	b1		= 0
pm		= 3.14 / 180

-- ---------------------------------------------------------------------
function love.update( dt )
	pixUpdate = pixUpdate + 1
	if pixUpdate > 1 then -- limit render FPS
		plasma()
		pixUpdate = 0
	end
	love.timer.sleep( 1 )
end

-- ---------------------------------------------------------------------
function love.draw()
	love.graphics.draw( pix, pixOffsetX, pixOffsetY, 0, 2, 2, 0, 0 )
	love.graphics.print("FPS: " .. love.timer.getFPS(), 1, 1 )
end

-- ---------------------------------------------------------------------
function preparePix()
	collectgarbage('collect')
	pixBuf = love.image.newImageData( 512, 256 )
end

-- ---------------------------------------------------------------------
function updatePix( pOX, pOY )
	pixOffsetX = pOX; pixOffsetY = pOY
	pix = love.graphics.newImage( pixBuf )
	pix:setFilter( "nearest", "nearest" )
end

-- ---------------------------------------------------------------------
function plasma()
	preparePix()
	f1 = f1 + 1
	f2 = f2 - 7
	f3 = f3 + 3
	for l1 = 0, 180 do -- plasma size 320 x 180 ( rendered 640 x 360 )
		av = 50 * math.sin(( l1 + f1 ) * pm )
		av2 = 60 + av * math.cos(( f2 + l1 ) * pm )
		av3 = 100 + 10 * math.sin(( f1 + l1 ) / 10 )
		b1 = 100 + 70 * ( math.cos( av2 + l1 )) / 8
		for l2 = 0, 320 do
			r = 140 + av2 * math.sin(( l2 + av2 + l1 ) / av3 )
			pixBuf:setPixel(l2, l1, r, av2, b1, 255 )
		end
	end
	updatePix( 80, 120 )
end
[edit] the plasma code is heavily based on a freebasic plasma a guy name Shockwave @ dbfinteractive.com wrote [/edit]

User avatar
RPG
Party member
Posts: 157
Joined: Wed Mar 02, 2011 5:02 am
Location: Russia
Contact:

Re: Per-pixel plasma / copperbars

Post by RPG » Thu Mar 03, 2011 11:30 pm

Slow as hell:(

User avatar
NÖÖB
Prole
Posts: 41
Joined: Thu Jul 31, 2008 10:57 pm
Location: Norway

Re: Per-pixel plasma / copperbars

Post by NÖÖB » Thu Mar 03, 2011 11:38 pm

Well, yeah..
What FPS were you getting? I get 20FPS on my Acer AS3810t

User avatar
EmmanuelOga
Citizen
Posts: 56
Joined: Thu Apr 22, 2010 9:42 pm
Location: Buenos Aires, Argentina
Contact:

Re: Per-pixel plasma / copperbars

Post by EmmanuelOga » Thu Mar 03, 2011 11:41 pm

AFAICT in your example you only need to initialize the pixBuf once, no need to create it again and again.

Code: Select all

 pixBuf = love.image.newImageData( 512, 256 )
Calling that only once won't give you any noticeable speed up though.

IMHO löve is not very well suited for this kind of old school effect because, as your examples show, its ability to push raw pixels is limited. Not sure if that's because of being opengl based or because doing getpixel/putpixel stuff in lua is inherently slow. It is much faster to draw a thousand triangles that it is to draw a thousand pixels. The modern way of doing that kind of stuff is using shaders, and I'm not sure when (If?) love will support shaders (someone did implement shaders for löve in a fork, but I haven't heard anything about löve authors going to merge that fork).

On a different note, to me, the main utility of framebuffers is not that they are faster (http://pastie.org/1630601), but that fbs allow you to draw the stuff you would normally draw to the screen to a surface, which you then can further manipulate. They are cool for overlay effects (fade outs, crops, etc...). But they are not necessarily faster.

On a last note, is it really common that video cards do not support framebuffers? I thought that was a really old feature of video cards. In my laptop I have a crappy Intel Mobile 4 video card and framebuffers work just fine.
--------------------------------------------------------------------------------------------------------
http://EmmanuelOga.com

User avatar
NÖÖB
Prole
Posts: 41
Joined: Thu Jul 31, 2008 10:57 pm
Location: Norway

Re: Per-pixel plasma / copperbars

Post by NÖÖB » Thu Mar 03, 2011 11:55 pm

Thanks for the heads up on the pixBuf!
I just read on another thread that framebuffers may not work on some computers.. I dunno - I tried your version of the program, and the framebuffer works here on an intel GMA4500 integrated card, although it ran a bit slower than mine; 7FPS vs 20FPS

User avatar
TechnoCat
Inner party member
Posts: 1611
Joined: Thu Jul 30, 2009 12:31 am
Location: Denver, CO
Contact:

Re: Per-pixel plasma / copperbars

Post by TechnoCat » Thu Mar 03, 2011 11:59 pm

EmmanuelOga wrote:AFAICT in your example you only need to initialize the pixBuf once, no need to create it again and again.

Code: Select all

 pixBuf = love.image.newImageData( 512, 256 )
Calling that only once won't give you any noticeable speed up though.
I actually got bumped from 36fps to 38fps when I made it reuse the ImageData object.

User avatar
EmmanuelOga
Citizen
Posts: 56
Joined: Thu Apr 22, 2010 9:42 pm
Location: Buenos Aires, Argentina
Contact:

Re: Per-pixel plasma / copperbars

Post by EmmanuelOga » Fri Mar 04, 2011 12:00 am

NÖÖB wrote:Thanks for the heads up on the pixBuf!
I just read on another thread that framebuffers may not work on some computers.. I dunno - I tried your version of the program, and the framebuffer works here on an intel GMA4500 integrated card, although it ran a bit slower than mine; 7FPS vs 20FPS
That may be because I changed the frame limiting code. Try using the same love.update function from your example. In the best case, I'm getting around the same fps for both versions (between 27-32).
--------------------------------------------------------------------------------------------------------
http://EmmanuelOga.com

User avatar
TechnoCat
Inner party member
Posts: 1611
Joined: Thu Jul 30, 2009 12:31 am
Location: Denver, CO
Contact:

Re: Per-pixel plasma / copperbars

Post by TechnoCat » Fri Mar 04, 2011 12:06 am

I bumped it up to 60fps from 36fps just by putting "local" in places.

Code: Select all

function love.load()
  pixBuf = love.image.newImageData( 512, 256 ) -- initialize PO2 buffer
  pix = love.graphics.newImage( pixBuf )

  pixUpdate = 0
  pixOffsetX = 0
  pixOffsetY = 0
  f1 = 0
  f2 = 0
  f3 = 0
  av = 0
  av2 = 0
  av3 = 0
  l1 = 0
  l2 = 0
  b1 = 0
  pm = 3.14 / 180

  preparePix()
end

-- ---------------------------------------------------------------------
function love.update( dt )
   pixUpdate = pixUpdate + 1
   if pixUpdate > 1 then -- limit render FPS
      plasma()
      pixUpdate = 0
   end
   love.timer.sleep( 1 )
end

-- ---------------------------------------------------------------------
function love.draw()
   love.graphics.draw( pix, pixOffsetX, pixOffsetY, 0, 2, 2, 0, 0 )
   love.graphics.print("FPS: " .. love.timer.getFPS(), 1, 1 )
end

-- ---------------------------------------------------------------------
function preparePix()
   collectgarbage('collect')
   pixBuf = love.image.newImageData( 512, 256 )
end

-- ---------------------------------------------------------------------
function updatePix( pOX, pOY )
   pixOffsetX = pOX; pixOffsetY = pOY
   pix = love.graphics.newImage( pixBuf )
   pix:setFilter( "nearest", "nearest" )
end

-- ---------------------------------------------------------------------
function plasma()
  f1 = f1 + 1
  f2 = f2 - 7
  f3 = f3 + 3
  local sin = math.sin
  local cos = math.cos
  for l1 = 0, 180 do -- plasma size 320 x 180 ( rendered 640 x 360 )
    local av = 50 * sin(( l1 + f1 ) * pm )
    local av2 = 60 + av * cos(( f2 + l1 ) * pm )
    local av3 = 100 + 10 * sin(( f1 + l1 ) / 10 )
    local b1 = 100 + 70 * ( cos( av2 + l1 )) / 8
    for l2 = 0, 320 do
       local r = 140 + av2 * sin(( l2 + av2 + l1 ) / av3 )
       pixBuf:setPixel(l2, l1, r, av2, b1, 255 )
    end
  end
  updatePix( 80, 120 )
end
Last edited by TechnoCat on Fri Mar 04, 2011 12:09 am, edited 1 time in total.

User avatar
NÖÖB
Prole
Posts: 41
Joined: Thu Jul 31, 2008 10:57 pm
Location: Norway

Re: Per-pixel plasma / copperbars

Post by NÖÖB » Fri Mar 04, 2011 12:08 am

EmmanuelOga wrote:That may be because I changed the frame limiting code. Try using the same love.update function from your example. In the best case, I'm getting around the same fps for both versions (between 27-32).
Yeah, that did it; getting 14FPS on your version now :)

@Technocat: woah! :awesome: You need the preparePix call in the plasma function, though.. if not, your ram gets eaten
Last edited by NÖÖB on Fri Mar 04, 2011 12:24 am, edited 1 time in total.

User avatar
RPG
Party member
Posts: 157
Joined: Wed Mar 02, 2011 5:02 am
Location: Russia
Contact:

Re: Per-pixel plasma / copperbars

Post by RPG » Fri Mar 04, 2011 12:14 am

20-25 fps on nvidia GF6200. May be much better.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest