Why I Love this forum

Started by 3DzForMe, December 28, 2018, 07:37:32

Previous topic - Next topic

RemiD

#15
after a quick look at your code, i have noticed a possible cause of the problem :

setbuffer(backbuffer()) must be used before any rendering (2D or 3D) (if you then want to flip it on the frontbuffer), the exception is when you use renderworld(), because apparently setbuffer(backbuffer()) is automaticlaly called, but in your code, since you only render 2D stuff, you have to put setbuffer(backbuffer()) before drawing anything on this buffer. (else you are still on the frontbuffer !!! (to be precise, half of the time))

I really don't understand how you can, after so many years of using blitzbasic, don't grasp simple concepts like this (be reassured, you are not alone, the old codes archives is full of such mistakes...)

3DzForMe

I simply massaged some existing code.... Too tired to rectify now, just in from a 300 miles road trip, after my first go at a skate park with my daughter on quads, my left hip sure knows about it!
BLitz3D, IDEal, AGK Studio, BMax, Java Code, Cerberus
Recent Hardware: Dell Laptop
Oldest Hardware: Commodore Amiga 1200 with 1084S Monitor & Blitz Basic 2.1

MagosDomina

#17
RemiD is correct a discrete graphics card while superior is not a requirement for Blitz. But I would expect much lower performance on integrated Intel chipsets.

That sounds like an awesome trip, how well did the quad handle inside the skate park?  ;D

3DzForMe

I gave my son my £100 graphics card a while back and tried reverting to an old lesser specced graphics card, Blitz3D failed to play, although it was probably some PC config nuance.

As for the quads, they performed great, as for me, my first time in a skate park at 47 ,if I fell once, I fell 10 times, did get some good jumps in though! Then after getting home at 3 am this morning, was up cobbling together pre amp and amp stuff for my sons bands last practice before their first gig of 2019,in Nottingham, shameless plug in an attached images.

Bought a new set of knee pads, Which cracked within the first two hours, so some heavy falls!

So, they're my excuses for my syntactical XP diminishing in Blitz3D diminishing, use it or lose it folks. Happy Coding  8)
BLitz3D, IDEal, AGK Studio, BMax, Java Code, Cerberus
Recent Hardware: Dell Laptop
Oldest Hardware: Commodore Amiga 1200 with 1084S Monitor & Blitz Basic 2.1

RemiD

Of course, if the graphics card is very old, maybe damaged or maybe with drivers which are not compatible with recent OS, it may cause problems... But personally i have tested Blitz3d 2d / 3d functions on many different hardwares / OS and it always worked (except cubemapping and stencil shadows)

But a black screen (without any crash) may be caused by a wrong use of the setbuffer(xbuffer) and of flip(), that's what i have tried to explain to you...

3DzForMe

Ah, I understand now, apologies for being a bit slow. Will try to update the code inline with your recommendations, Happy New Year RemiD and all.
BLitz3D, IDEal, AGK Studio, BMax, Java Code, Cerberus
Recent Hardware: Dell Laptop
Oldest Hardware: Commodore Amiga 1200 with 1084S Monitor & Blitz Basic 2.1

3DzForMe

#21
Modified code with SetBuffer(Backbuffer)) called, may stop crashes:

@RemiD, realise why I wasn't calling SetBuffer - I usually always have Renderworld() in my code.



; Original author Credit:
; https://www.syntaxbomb.com/index.php/topic,2714.msg3703.html#msg3703

; Version 0.3
; Setbuffer added

; Version 0.2
; Adding mouse cursor info to allow for capture of additional datapoints:
; Completed 28 Dec 18, by 3DZforMe, aka Blitzplotter

; Set the screensize
Graphics 800,600,32,2
SetBuffer BackBuffer()

MaxNumberOfPoints=200
Global CurrentPlotCount=4
Global NextPlotCount=5

; Dimension the pointarray and set startvalues
Dim DataPoint(MaxNumberOfPoints,1)
DataPoint(0,0) = 100 : DataPoint(0,1) = 090
DataPoint(1,0) = 200 : DataPoint(1,1) = 160
DataPoint(2,0) = 300 : DataPoint(2,1) = 300
DataPoint(3,0) = 400 : DataPoint(3,1) = 210
DataPoint(4,0) = 500 : DataPoint(4,1) = 100

    ; Set the clearcolor to red, and select point 0
ClsColor 255,255,255 : Global Selected = 0

SetBuffer(BackBuffer())   ; Required if Renderworld not being used

    ; Mainloop
While Not KeyDown(1)
Cls ; Clear screen

       ; Userinput (Use [Q] and [W] to select a point,
       ; and Arrowkeys to position the selected point)
If KeyHit(16) And Selected > 0 Then Selected = Selected - 1
If KeyHit(17) And Selected < CurrentPlotCount Then Selected = Selected + 1
If KeyDown(203) Then DataPoint(Selected,0) = DataPoint(Selected,0) - 1
If KeyDown(205) Then DataPoint(Selected,0) = DataPoint(Selected,0) + 1
If KeyDown(200) Then DataPoint(Selected,1) = DataPoint(Selected,1) - 1
If KeyDown(208) Then DataPoint(Selected,1) = DataPoint(Selected,1) + 1

DrawLine(CurrentPlotCount) ; Draw the interpolated line between point 0 and 4

xP=MouseX()
yP=MouseY()

Color 0,0,250

Text 40,1,"Userinput: (Use [Q] and [W] to select a point, and Arrowkeys to Move the selected point"

Color 100,180,0

Text 40,26,"Left Mouse Click to add a point, Right Mouse Click to remove a point, then press a key"

Text 12,60,"x: "+xP+" y: "+yP+" Points to Draw:"+CurrentPlotCount

;If left click add extra position to current list of points

button$="No"
If MouseDown(1) Then button$="Left"
If MouseDown(2) Then button$="Right"
If MouseDown(3) Then button$="Middle"

Text 400,300, button$ + " mouse button pressed!"

If button$="Left"

DataPoint(NextPlotCount,0) = xP : DataPoint(NextPlotCount,1) = yP
CurrentPlotCount=CurrentPlotCount+1
NextPlotCount=NextPlotCount+1

;Implement a pause to stop NUMEROUS extra points being added in quick succesion

SetBuffer(BackBuffer())   ; Required if Renderworld not being used

Text 300,60,"Press any key to continue to add your next point"

Flip

WaitKey()

EndIf

If button$="Right"

DataPoint(NextPlotCount,0) = xP : DataPoint(NextPlotCount,1) = yP

If CurrentPlotCount>1

CurrentPlotCount=CurrentPlotCount-1
NextPlotCount=NextPlotCount-1

SetBuffer(BackBuffer())   ; Required if Renderworld not being used

Text 140,260,"Press any key to continue....."

Flip

WaitKey()

Else

SetBuffer(BackBuffer())   ; Required if Renderworld not being used

Text 340,60,"Add some more points first please....."

;Implement a pause to stop NUMEROUS extra points being added in quick succesion

Text 140,280,"Press any key to continue....."

Flip

WaitKey()


EndIf


EndIf

If button$="Middle"

SetBuffer(BackBuffer())   ; Required if Renderworld not being used

Text 200,50,"Congratutaions on 3 buttons...."


Flip

WaitKey()

EndIf


Flip ; Flip backbuffer to frontbuffer
Wend

End ; End of programm

Function DrawLine(CurrentPlotCount)
       ; Startpoint for the first Line
X = DataPoint(0,0) : Y = DataPoint(0,1) : Color 0,0,0

       ; Draw the interpolyted Line between point 0 and 1
MX = (DataPoint(0,0) - DataPoint(1,0)) * (-1)
For MU# = 0 To 1.0 Step 0.08
OX = X : OY = Y
Y = CosineInterpolate(DataPoint(0,1),DataPoint(1,1),MU#)
X = MX * MU# + DataPoint(0,0)
Line OX,OY,X,Y
Next

       ; Draw the interpolated line between point 1 and 4
For I = 2 To CurrentPlotCount
MX = (DataPoint(I - 1,0) - DataPoint(I,0)) * (-1)
For MU# = 0 To 1.0 Step 0.08
OX = X : OY = Y
Y = CosineInterpolate(DataPoint(I - 1,1),DataPoint(I,1),MU#) 
X = MX * MU# + DataPoint(I - 1,0)
Line OX,OY,X,Y
Next
Next

       ; Dra the anchor points
Color 255,0,0
For I = 0 To CurrentPlotCount
If Selected = I Then
Color 0,0,255
Else
Color 255,0,0
EndIf
Oval DataPoint(I,0) - 2,DataPoint(I,1) - 2,5,5,1
Next
End Function

    ; Function for cosineinterpolated line
Function CosineInterpolate(Y1#,Y2#,MU#)
Local MU2#
MU2# = (1.0 - Cos(MU# * 180.0))/2.0
Return (Y1# * (1.0 - MU2#) + Y2# * MU2#)
End Function

    ; Function for normal line
Function LinearInterpolate(Y1#,Y2#,MU#)
Return Y1# * (1 - MU#) + Y2# * MU#
End Function

BLitz3D, IDEal, AGK Studio, BMax, Java Code, Cerberus
Recent Hardware: Dell Laptop
Oldest Hardware: Commodore Amiga 1200 with 1084S Monitor & Blitz Basic 2.1

RemiD

#22
either you have not read my post carefully, or my english is bad ?! :-[

Quote
setbuffer(backbuffer()) must be used before any rendering (2D or 3D)
you have to put setbuffer(backbuffer()) before drawing anything on this buffer. (else you are still on the frontbuffer !!! (to be precise, half of the time))

this means :

;go on the buffer on which you want to draw (backbuffer in this case)
setbuffer(backbuffer())
;draw 3d
renderworld()
;draw 2d / text
color(R,G,B) : Rect() : Plot() : Text()
;flip the backbuffer to the frontbuffer, Flip is then used to make the BackBuffer become the FrontBuffer, at the same time the FrontBuffer becomes the BackBuffer, allowing you to draw the next screen update on the BackBuffer before Flipping again. (from the documentation)
Flip()

i have rewritten your code (removed the useless things, and added the setbuffer(backbuffer()) at the right places, with comments, maybe it will be more clear :


; Original author Credit:
; https://www.syntaxbomb.com/index.php/topic,2714.msg3703.html#msg3703

; Version 0.3
; Setbuffer added

; Version 0.2
; Adding mouse cursor info to allow for capture of additional datapoints:
; Completed 28 Dec 18, by 3DZforMe, aka Blitzplotter

; Set the screensize
Graphics 800,600,32,2
;on which buffer are we ? i don't know, i don't care !!!

MaxNumberOfPoints=200
Global CurrentPlotCount=4
Global NextPlotCount=5

; Dimension the pointarray and set startvalues
Dim DataPoint(MaxNumberOfPoints,1)
DataPoint(0,0) = 100 : DataPoint(0,1) = 090
DataPoint(1,0) = 200 : DataPoint(1,1) = 160
DataPoint(2,0) = 300 : DataPoint(2,1) = 300
DataPoint(3,0) = 400 : DataPoint(3,1) = 210
DataPoint(4,0) = 500 : DataPoint(4,1) = 100

;select point 0
Global Selected = 0

    ; Mainloop
While Not KeyDown(1)
   
       ; Userinput (Use [Q] and [W] to select a point,
       ; and Arrowkeys to position the selected point)
If KeyHit(16) And Selected > 0 Then Selected = Selected - 1
If KeyHit(17) And Selected < CurrentPlotCount Then Selected = Selected + 1
If KeyDown(203) Then DataPoint(Selected,0) = DataPoint(Selected,0) - 1
If KeyDown(205) Then DataPoint(Selected,0) = DataPoint(Selected,0) + 1
If KeyDown(200) Then DataPoint(Selected,1) = DataPoint(Selected,1) - 1
If KeyDown(208) Then DataPoint(Selected,1) = DataPoint(Selected,1) + 1

;here you want to draw, so we must go on the backbuffer !
SetBuffer(BackBuffer())

ClsColor(255,255,255) : Cls() ;-> to clear the active buffer

       ;here you are still on the backbuffer, you can draw, no problem

DrawLine(CurrentPlotCount) ; Draw the interpolated line between point 0 and 4

xP=MouseX()
yP=MouseY()

Color 0,0,250

Text 40,1,"Userinput: (Use [Q] and [W] to select a point, and Arrowkeys to Move the selected point"

Color 100,180,0

Text 40,26,"Left Mouse Click to add a point, Right Mouse Click to remove a point, then press a key"

Text 12,60,"x: "+xP+" y: "+yP+" Points to Draw:"+CurrentPlotCount

;If left click add extra position to current list of points

button$="No"
If MouseHit(1) Then button$="Left"
If MouseHit(2) Then button$="Right"
If MouseHit(3) Then button$="Middle"

SStr$ = button$+" mouse button pressed!" : Color(012,012,012) : Text(GraphicsWidth()/2-StringWidth(SStr)/2,GraphicsHeight()-StringHeight(SStr),SStr)

If button$="Left"

;here you are still on the backbuffer, you can draw, no problem

DataPoint(NextPlotCount,0) = xP : DataPoint(NextPlotCount,1) = yP
CurrentPlotCount=CurrentPlotCount+1
NextPlotCount=NextPlotCount+1

;Implement a pause to stop NUMEROUS extra points being added in quick succesion

SStr$ = "press any key to continue" : Color(012,012,012) : Text(xP-StringWidth(SStr)/2,yP-StringHeight(SStr)/2,SStr)

;here the backbuffer is fliped to the frontbuffer and then you are on the frontbuffer ( that's why, at the beginning of the next frame, you need to go back to the backbuffer before drawing anything else ! )
Flip()

FlushKeys()
WaitKey()

Else If button$="Right"

;here you are still on the backbuffer, you can draw, no problem

DataPoint(NextPlotCount,0) = xP : DataPoint(NextPlotCount,1) = yP

If CurrentPlotCount>1

CurrentPlotCount=CurrentPlotCount-1
NextPlotCount=NextPlotCount-1

SStr$ = "press any key to continue" : Color(012,012,012) : Text(xP-StringWidth(SStr)/2,yP-StringHeight(SStr)/2,SStr)

;here the backbuffer is fliped to the frontbuffer and then you are on the frontbuffer ( that's why, at the beginning of the next frame, you need to go back to the backbuffer before drawing anything else ! )
Flip()

FlushKeys()
WaitKey()

Else

;here you are still on the backbuffer, you can draw, no problem

Color(125,125,125) : Text 340,60,"Add some more points first please....."

;Implement a pause to stop NUMEROUS extra points being added in quick succesion

SStr$ = "press any key to continue" : Color(012,012,012) : Text(xP-StringWidth(SStr)/2,yP-StringHeight(SStr)/2,SStr)

;here the backbuffer is fliped to the frontbuffer and then you are on the frontbuffer ( that's why, at the beginning of the next frame, you need to go back to the backbuffer before drawing anything else ! )
Flip()

FlushKeys()
WaitKey()


EndIf


Else If button$="Middle"

;here you are still on the backbuffer, you can draw, no problem

SStr$ = "congratulations on 3 buttons... wtf?!" : Color(012,012,012) : Text(xP-StringWidth(SStr)/2,yP-StringHeight(SStr)/2,SStr)

;here the backbuffer is fliped to the frontbuffer and then you are on the frontbuffer ( that's why, at the beginning of the next frame, you need to go back to the backbuffer before drawing anything else ! )
Flip()

FlushKeys()
WaitKey()

Else

;here the backbuffer is fliped to the frontbuffer and then you are on the frontbuffer ( that's why, at the beginning of the next frame, you need to go back to the backbuffer before drawing anything else ! )    
Flip()

EndIf

Wend

End ; End of programm

Function DrawLine(CurrentPlotCount)
       ; Startpoint for the first Line
X = DataPoint(0,0) : Y = DataPoint(0,1) : Color 0,0,0

       ; Draw the interpolyted Line between point 0 and 1
MX = (DataPoint(0,0) - DataPoint(1,0)) * (-1)
For MU# = 0 To 1.0 Step 0.08
OX = X : OY = Y
Y = CosineInterpolate(DataPoint(0,1),DataPoint(1,1),MU#)
X = MX * MU# + DataPoint(0,0)
Line OX,OY,X,Y
Next

       ; Draw the interpolated line between point 1 and 4
For I = 2 To CurrentPlotCount
MX = (DataPoint(I - 1,0) - DataPoint(I,0)) * (-1)
For MU# = 0 To 1.0 Step 0.08
OX = X : OY = Y
Y = CosineInterpolate(DataPoint(I - 1,1),DataPoint(I,1),MU#) 
X = MX * MU# + DataPoint(I - 1,0)
Line OX,OY,X,Y
Next
Next

       ; Dra the anchor points
Color 255,0,0
For I = 0 To CurrentPlotCount
If Selected = I Then
Color 0,0,255
Else
Color 255,0,0
EndIf
Oval DataPoint(I,0) - 2,DataPoint(I,1) - 2,5,5,1
Next
End Function

    ; Function for cosineinterpolated line
Function CosineInterpolate(Y1#,Y2#,MU#)
Local MU2#
MU2# = (1.0 - Cos(MU# * 180.0))/2.0
Return (Y1# * (1.0 - MU2#) + Y2# * MU2#)
End Function

    ; Function for normal line
Function LinearInterpolate(Y1#,Y2#,MU#)
Return Y1# * (1 - MU#) + Y2# * MU#
End Function


i hope that you will understand why it must be done this way (to reassure you, from what i have seen in the code archives, most coders don't, they just hope it will go well and with the fast fliping between the frontbuffer and the backbuffer, at 60fps, it is not noticeable for humans, even if it is incorrect !)

Holzchopf

Errm sorry RemiD, but that's not correct. You've been mislead by the docs there. To be fair, they are a bit misleading: It's not the buffers that are swapped, it's their contents. Of course, internally it's only a pointer that's swapped, but from BBs view it's like their contents were swapped. After Flip(), the drawing operations are "taking place" on the buffer that's now the back buffer.

You only need to set the backbuffer once (or after rendering to an image, but that's not used here). Here's a simple demonstration:

Graphics 800,600,0,2
; get the identities of the two available buffers, for later use
Local bufb% = BackBuffer()
Local buff% = FrontBuffer()
; initially set the back buffer
SetBuffer bufb
; needed for "debuggin" info
Local ty% = 0
Local buf0%, buf1%

While Not KeyDown(1)
; False statement: After the First Flip() we're on the front buffer
; (so this should be rendered immediately visible)
ClsColor 255,0,0
Cls
; we can actually check on which buffer we're currently are
buf0 = GraphicsBuffer()
; this is to make sure windows would find the time to
; draw, if there was anything to draw ;-)
Delay 500
; False statement: only now we're going to the back buffer
; (try commenting/uncommenting this line and see for yourself)
SetBuffer BackBuffer()
ClsColor 0,255,0
Cls
;... wait, in which buffer were we again?
buf1 = GraphicsBuffer()
; additional "debug" info. Moving, so you see the program
; is still running ;-)
Text 10,ty, "BackBuffer id: "+bufb
Text 10,ty+15, "FrontBuffer id: "+buff
Text 10,ty+30, "After Flip(), we were drawing on buffer: "+buf0
Text 10,ty+45, "After SetBuffer BackBuffer(), we were drawing on buffer: "+buf1
ty = ty + 5
If ty > 540 Then ty = 0
; swap buffer contents and let them be for a while
Flip()
Delay 500
Wend



RemiD

#24
the documentation says that after having used Flip() the backbuffer becomes the frontbuffer and so, at the start of the mainloop, in theory you are still on the frontbuffer, or maybe you are still on the backbuffer and the frontbuffer has been copied to the frontbuffer, but in this case, the documentation is indeed confusing.

in any case, there must have been a reason (that i don't remember, it was a few years ago) why is started to write code this way, so i am going to code something to really see what is on the backbuffer / frontbuffer ( before and after using flip() )...


Graphics3D(640,480,32,2)

DebugLog(GraphicsBuffer())

BackB% = BackBuffer()
DebugLog("BackBuffer ref = "+BackB)

FrontB% = FrontBuffer()
DebugLog("FrontBuffer ref = "+FrontB)

;SetBuffer(BackB)

DebugLog(GraphicsBuffer())

Repeat

DebugLog("start of mainloop")

DebugLog(GraphicsBuffer())

;SetBuffer(BackB)

;Renderworld()

Flip()

DebugLog("end of mainloop")

FlushKeys()
WaitKey()

Until( KeyDown(1)=1 )

End()

Holzchopf is correct, i was mistaken...

in fact, you don't even need to use setbuffer(backbuffer()) at all (if you don't draw on others image buffers / texture buffers), apparently, by default, the back buffer is automatically set for you to draw, see the example above...

i remmember why i started to write setbuffer(backbuffer()) before dawing anything (3D or 2D) -> to be safe, because i often play with images and textures, so just to be sure that i draw on the backbuffer, i always go on it before drawing 3d or 2d.

Flanker

#25
Quote from: RemiD on January 06, 2019, 11:55:34
in fact, you don't even need to use setbuffer(backbuffer()) at all (if you don't draw on others image buffers / texture buffers), apparently, by default, the back buffer is automatically set for you to draw, see the example above...

I remember having issues if not setting the backbuffer, especially in 2D examples, I'll try to replicate it, but there was a reason why people start to always set it once on top of the program.

Just try that, with and without setting the backbuffer, and check the FPS you get :
Graphics 800,600,32,2
SetBuffer BackBuffer()

While Not KeyHit(1)

Cls

Text 200,200,Rnd(1000)

Flip

Wend

End
Everyone knew it was impossible, until someone who didn't know made it.

RemiD

Quote
but there was a reason why people start to always set it once on top of the program
run the code example that i have posted, you will see that you are by default on the backbuffer... so no need to go where you already are ?

there is also a reason why i took the habit to always write setbuffer(backbuffer()) before drawing 3d or 2d, but if you never play with images / textures, it seems that there is no need to write it at all...

even with 3d + 2d :

Graphics3D(640,480,32,2)

DebugLog(GraphicsBuffer())

BackB% = BackBuffer()
DebugLog("BackBuffer ref = "+BackB)

FrontB% = FrontBuffer()
DebugLog("FrontBuffer ref = "+FrontB)

Camera = CreateCamera()
CameraClsColor(Camera,015,015,015)
CameraRange(Camera,0.15,150)
PositionEntity(Camera,0,1.65,-3)

Shape = CreateCube()
ScaleMesh(Shape,1.0/2,1.0/2,1.0/2)
EntityColor(Shape,125,125,125)
PositionEntity(Shape,0,0,0)

;SetBuffer(BackB)

DebugLog(GraphicsBuffer())

Repeat

millistart% = MilliSecs()

;DebugLog("start of mainloop")

If( KeyHit(57)=1 )
  DebugLog(GraphicsBuffer())
EndIf

TurnEntity(Shape,0,+3,0)

;SetBuffer(BackB)

;ClsColor(010,010,010) : Cls()

CameraClsColor(Camera,010,010,010)
RenderWorld()

Color(125,125,125) : Rect(GraphicsWidth()/2-1,GraphicsHeight()/2-1,2,2,True)

Color(255,255,255) : XStr$ = FPS : Text(GraphicsWidth()/2-StringWidth(XStr)/2,0,XStr)

Flip(True)

;DebugLog("end of mainloop")

millitime% = MilliSecs() - millistart

FPS% = 1000.0/millitime

;FlushKeys()
;WaitKey()

Until( KeyDown(1)=1 )

End()

i don't notice an abnormal FPS hit ?

Flanker

Quote from: RemiD on January 06, 2019, 16:55:00
run the code example that i have posted, you will see that you are by default on the backbuffer... so no need to go where you already are ?

Yes this doesn't seem to happen whith Graphics3D(), but test my example with Graphics() and you'll see the FPS drop.
Everyone knew it was impossible, until someone who didn't know made it.

RemiD

#28
recently i have encountered the same weird behavior (bug?) that i have encountered some years ago, and that made me write setbuffer(backbuffer()) before renderworld()

the scenario was that :
i create a texture
i go on the texture buffer to draw on the texture
then when renderworld() happens, the render is on the texture buffer instead of the back buffer, and i had to write setbuffer(backbuffer()) before renderworld() to render the scene on the back buffer.

however i can't reproduce it lol

STEVIE G

Quote from: RemiD on October 06, 2019, 07:47:43
recently i have encountered the same weird behavior (bug?) that i have encountered some years ago, and that made me write setbuffer(backbuffer()) before renderworld()

the scenario was that :
i create a texture
i go on the texture buffer to draw on the texture
then when renderworld() happens, the render is on the texture buffer instead of the back buffer, and i had to write setbuffer(backbuffer()) before renderworld() to render the scene on the back buffer.

however i can't reproduce it lol

This isn't a bug.  It's normal practice to use 'setbuffer backbuffer()' once you are done writing to an image/texture buffer.