Plot vs. Writepixel

BlitzMax Forums/BlitzMax Beginners Area/Plot vs. Writepixel

Just reading through the 2D section of the Blitz3D docs in order to increase my general knowledge of possible uh, possibilities, in BlitzMax.

Does anyone have an opinion about the plot command compared to the writepixel command? As far as I understand if I use writepixel i will not change the setcolor parameter which affects all graphics? Is there any difference in speed between the two? Is writepixel even viable in BlitzMax?

Any light shed on the subject would be greatly appreciated.

WritePixel only works on Pixmaps, so youd have to do a DrawPixmap later.

I would imagine Plot being slower, but i havent tested it.

What is it you are trying to do?

It's not so much that I have a specific task I need to do, as I'm trying to get some bearings of the different possibilities.

I do however already have a working paralax-starfield created with the plot-command and was curious whether writepixel would for some reason be a better solution.

Wouldn't it be better to use drawoval? Writepixel would involve too much image manipulation for a parallax starfield while plot is slow.
<edit> It might even be OK to use a single image.

Could be, I have the handicap of owning a 4x3,00Ghz Xeon and it really doesn't show any sign of strugling with this stuff.

In either case, I'm really just experimenting (while creating a small shmup) just to see what's possible.

Another related question: Does plot use OpenGL or is OpenGL only used for commands related to "image" I guess this would make all the diference in the world...

The commands use whatever driver you have specified in the setgraphicsdriver command. Default is DX driver.
Personally, I would use drawoval but, depending on the task and fi you're trying to squeeze every ms out of the process, might use multiple images from the same texture using SetUV. Could be OTT but search using 'setuv' if you're interested.

Nick,
Have a look at the code samples here (which use OpenGL) ..

The first example demonstrates Plot using two methods:

First, using the standard BLitzMax Plot
Then, using an unwrapped version with glBegin and glEnd being called at the start and end of a batch of pixels to plot (instead of every plot)

The speed difference only shows up if you plot 1000's of stars per frame.

' faster plotting

SuperStrict
Framework BRL.GLMax2D
Import BRL.Random


SetGraphicsDriver GLMax2DDriver()
Const width%=640 , height%=480
Const NUMPLOTS%=500000
Local t%

Graphics width,height,0


t=MilliSecs()
FastPlot NUMPLOTS
Local t1%=MilliSecs()-t

t=MilliSecs()
NormalPlot NUMPLOTS
Local t2%=MilliSecs()-t

' _________________________________________________

Cls
DrawText "Number of plots = "+String(NUMPLOTS),10,10
DrawText "  Fast plot (m/secs)= "+String(t1),10,40
DrawText "Normal plot (m/secs)= "+String(t2),10,60
Flip
WaitKey
End

' _________________________________________________

Function FastPlot(num%)
	glDisable GL_TEXTURE_2D	
	glBegin GL_POINTS
	For Local p%=1 To num
		glVertex2f Rand(width),Rand(height)
	Next
	glEnd
	glEnable GL_TEXTURE_2D
	Flip
End Function


Function NormalPlot(num%)
	For Local p%=1 To num
		Plot Rand(width),Rand(height)
	Next
	Flip
End Function





This code is more complicated (using the WritePixel command)
Its certainly pretty damn fast but you need to run it with Debug Off:
Strict

Framework BRL.GLMax2D
Import BRL.Pixmap
Import BRL.Bank
Import BRL.Random
Import BRL.System


SetGraphicsDriver GLMax2DDriver()
Graphics 640,480 , 0


Global particle_list:TList=New TList
Const glevel1=1
Const glevel2=2
Const glevel3=4

Const maxx=239
Const maxy=239

Const particle_life=1000

Global firepix:TPixmap=CreatePixmap(480 , 480 , PF_RGBA8888)
Global cfb:TBank = CreateBank(57600)
Global hfb:TBank = CreateBank(57600)

SeedRnd MilliSecs()

AppTitle = "BlitzMax Firedemo"

Global gradient[256] , col[5]

col[0]=$000000
col[1]=$400040
col[2]=$000080
col[3]=$C00000
col[4]=$FFFF00

SetupGradient()


Local angl:Double = 0

Type Particle
	Field x#,y#
	Field speed#,direction,angle,life
	Global pcount=0
	'
	Method New()
		x=0
		y=0
		speed#=Rnd (.2 , .6)
		direction=Rand(0,359)
		angle=direction
		life=particle_life
		pcount:+1
		particle_list.AddLast(Self)
	End Method
	'
	Method Update()
		If x < -120 Then x = -120
		If x >  119 Then x =  119
		If y < -120 Then y = -120
		If y >  119 Then y =  119

		Local bofs= Int(x+120) + Int(y+120)*240
		Local myPtr:Byte Ptr = BankBuf (cfb)

		Local valu=myPtr[bofs]
		valu=valu+20

		If valu<80
			life:-1
		EndIf

		If life <=0
			x=0
			y=0
			speed#=Rnd (.2 , .6)
			direction=Rand(0,359)
			angle=direction
			life=particle_life
		Else
			If valu>255 Then valu=255
			myPtr [bofs] = valu

			Local surfangle = ATan2 ( y , x )
			x = x + speed * Cos( direction )
			y = y + speed * Sin( direction )

			If (x*x + y*y)>10000
				angle = surfangle - 180
			Else
				If angle = direction
					angle=Rand(0,359)
				EndIf
			EndIf

			angle=(angle + 360) Mod 360
			direction=(direction + 360) Mod 360

			Local angc:Double
			If angle<direction
				angc=360+angle-direction
			Else
				angc=angle-direction
			EndIf

			If angc>180
				direction=direction-1
			ElseIf angc>0
				direction=direction+1
			EndIf
		EndIf
	EndMethod
	'
End Type



Repeat
	Flip 0
	Cls
	Local startime = MilliSecs()

	For Local p:Particle = EachIn particle_list
		p.update
	Next

	For Local yco=0 To maxy
		For Local xco=0 To maxx
			Local myPtr:Byte Ptr = BankBuf(cfb)

			Local rb:Byte = myPtr [xco + yco*240]
			If rb>0
				Local valu=rb*glevel3

				Local x1 = xco-1
				If x1<0 Then x1=x1+maxx

				Local x3 = xco+1
				If x3>maxx Then x3=x3-maxx

				Local y1 = yco-1
				If y1<0 Then y1=y1+maxy

				Local y3 = yco+1
				If y3>maxy Then y3=y3-maxy

				rb=myPtr [x1 + y1 * 240]
				valu=valu+rb*glevel1

				rb=myPtr [xco + y1 * 240]
				valu=valu+rb*glevel2

				rb=myPtr [x3 + y1 * 240]
				valu=valu+rb*glevel1

				rb=myPtr [x1 + yco * 240]
				valu=valu+rb*glevel2

				rb=myPtr [ x3 + yco * 240 ]
				valu=valu+rb*glevel2


				rb=myPtr [x1 + y3 * 240]
				valu=valu+rb*glevel1

				rb=myPtr [xco + y3 * 240]
				valu=valu+rb*glevel2

				rb=myPtr [x3 + y3 * 240]
				valu=valu+rb*glevel1

				valu=valu Shr 4
				
				PokeByte hfb,xco + yco * 240 , valu

			EndIf
		Next
	Next

	For Local yco=0 To maxy
		For Local xco=0 To maxx
			Local bofs=yco*240+xco
			Local valu=PeekByte(hfb,bofs)
			If valu>0
				If valu>4
					valu=valu-4
				Else
					valu=0
				EndIf
				PokeByte hfb,bofs,valu
				WritePixel firepix , xco*2 , yco*2 , gradient[valu]
				WritePixel firepix , xco*2+1 , yco*2 , gradient[valu]
				WritePixel firepix , xco*2+1 , yco*2+1 , gradient[valu]
				WritePixel firepix , xco*2 , yco*2+1 , gradient[valu]
			EndIf
		Next
	Next

	Local temp:TBank = cfb
	cfb = hfb
	hfb = temp
	
	FastDrawPixmap firepix , 160 , 0

	'One beat each 14.4 frames = 12.5 angles a frame

	angl=angl+12.5
	If angl>180 Then angl=angl-180

	Local frametime=MilliSecs()-startime

	If frametime<30
		For Local i = 0 To 9
			New Particle
		Next
	EndIf

	If Particle.pcount>0
		Local part:String="Featuring "+Particle.pcount+" real-time blurred particles."
		DrawText part , 640-TextWidth(part$),0
	EndIf

	If KeyHit(KEY_ESCAPE)
		particle_list.Clear()
		Particle.pcount = 0
		Exit
	EndIf

	While frametime<33
		frametime=MilliSecs()-startime
	Wend

Forever

End

Function SetupGradient()
	Local ofs,grad,i
	While ofs<255
		For i=0 To 63
			Local perc#=i/63.0
			Local x1=col[grad] Shr 16 & $FF
			Local xco=col[grad] Shr 8 & $FF
			Local x3=col[grad] & $FF
			Local y1=col[grad+1] Shr 16 & $FF
			Local yco=col[grad+1] Shr 8 & $FF
			Local y3=col[grad+1] & $FF
			gradient[i+ofs]=$FF000000 + Int(x1*(1-perc)+y1*perc) Shl 16 + Int(xco*(1-perc)+yco*perc) Shl 8 + Int(x3*(1-perc)+y3*perc)
		Next
		ofs=ofs+i;grad=grad+1
	Wend
EndFunction

Function FastDrawPixmap(p:TPixmap,x,y,scalex#=1.0, scaley#=1.0)
	Local blend%=GetBlend()
	glDisable GL_TEXTURE_2D 'DisableTex
	SetBlend SOLIDBLEND
	Local t:TPixmap=p
	If t.format<>PF_RGBA8888 t=ConvertPixmap(p, PF_RGBA8888 )
	glpixelzoom scalex#,-scaley#
	glRasterPos2i 0,0
	glBitmap 0,0,0,0,x,-y,Null
	glPixelStorei GL_UNPACK_ROW_LENGTH, p.pitch Shr 2
	glDrawPixels p.width, p.height, GL_RGBA, GL_UNSIGNED_BYTE, p.pixels
	glEnable GL_TEXTURE_2D
	SetBlend blend
End Function


Like the man says, if you intend on using plot in any significance, you really need to batch process your plots, so you aren't calling glBegin/glEnd all the time. Very wasteful.

WritePixel certainly executes faster, but the time taken to DrawPixmap (or LoadImage/DrawImage) might offset the speed gain some what.

In either case, like tony said, it depends a lot on what you want to do (and probably what hardware you want to do it on).

Thanks Jim, I'll keep that GL-bit in mind for when I feel ready to jump onto the GL-bandawagon... ;)

Forgot to mention the particle demo is using a FastDrawPixmap() routine which, on my Sony craptop, boosts the realtime blured particles from 2770 to 3810!