Copy BackBuffer to Texture?

Started by Midimaster, December 02, 2021, 09:05:52

Previous topic - Next topic

Midimaster

After sucessfull installation of the OpenB3D I now try to re-activate my old 3D-code-snipplets to new BlitzMax-NG+OpenB3D.

Now I'm a a function, where a rendered world needs to be copied to a texture. The texture is part of a wall mirror and shows (think of a car mirror), what is behind the player.

It looks like there is no BackBuffer() access like in old Blitz3D, but I  found the command BackBufferToTex(), which is not as flexible like old 
CopyRect 700+i,100,1,256,256-i,0,BackBuffer(),TextureBuffer(MirrorTexture)


With the old code I could swap left side to right side...
Code (BlitzMax) Select
...
         UpdateWorld
         RenderWorld
         'seitenverkehrt
         For Local i%=1 To 256
            CopyRect 700+i,100,1,256,256-i,0,BackBuffer(),TextureBuffer(MirrorTexture)
         Next
...


The new CopyRect looks like working different. It needs TPixMaps to work with.
QuoteFunction CopyRect( srcX:Int,srcY:Int,srcW:Int,srcH:Int,dstW:Int,dstH:Int,src:Byte Ptr,dst:Byte Ptr,bPP:Int=4,invert:Int=0 )
Description Copy rectangle of source pixmap pixels to destination, not exactly like B3D.
Information srcW/H is src size, srcX/srcY top-left position, dstW/H is dst size, bytes per pixel defaults to 4.



But how to connect the 3D-RenderResult with PixMap or how to connect PixMap with a TTexture?
...back from Egypt

angros47

There is no BackBuffer() access, but there is the command CameraToTex, that was not present in the old Blitz3D

QuoteCameraToTex (Texture* tex , Camera* cam , int frame )
Renders the output of a camera on a texture. Shadows are rendered as well, other informations
related to stencils, or to postprocessing are ignored. The camera viewport is ignored, as well. The
texture must be created with CreateTexture. The argument tex is the texture handle, the argument
cam is the camera handle. Argument frame is currently unused.

Original Blitz3D documentation (https://kippykip.com/b3ddocs/commands/3d_commands/TextureBuffer.htm) stated:
QuoteYou cannot render 3D to a texture buffer; 3D can only be rendered to the back buffer. To display 3D graphics on a texture, use CopyRect to copy the contents of the back buffer to a texture buffer.

The same operation, instead, is perfectly allowed on OpenB3D: so, there is no need to try to use the tricks of Blitz3D: at the time, they were a workaround that is no longer needed.

markcwm

Yes, Openb3d doesn't support CopyRect or the buffer commands, here's a workaround for you to try while I work on a real CopyRect. The CopyRect you found is really CopyPixels and just uses memcopy on pixel buffers.

RenderWorld

         For Local i%=1 To 256
            'CopyRect 700+i,100,1,256,256-i,0,BackBuffer(),TextureBuffer(MirrorTexture)
            Local pix:TPixmap=GrabPixmap(700+i,100,1,256)
            If PixmapFormat(pix)<>PF_RGBA8888 Then pix=ConvertPixmap(pix,PF_RGBA8888)
            BufferToTex(MirrorTexture,PixmapPixelPtr(pix,256-i,0))
         Next

Midimaster

Thank you.. with your help I was able to reactivate my old "Wall Mirror"-demo, which shows that the mirroring in a real mirror cannot be done with Shaders, because the "image", that is visible on the mirror is related to the position of the main (player) camera. So the camera needs a own camera, which needs to be updated each FLIP

Because of your help the rendering of the "mirror camera" I needed not more than this:
...
      ' copy rear view to mirror texture
         UpdateWorld
         RenderWorld
         'reversed view
Spiegel:TPixmap=XFlipPixmap(GrabPixmap(700,100,256,256))
BufferToTex MirrorTexture, Spiegel.PixelPtr(0,0)
...


who is interested in the complete code, here is a executable example. Dont worry... 90% of the code are only because of creating a room "by code". The mirror stuff fits in 30 code lines... see function RenderMirror()

Wall Mirror Demo updated to OpenB3D and BlitzMax NG

Code (BlitzMax) Select
SuperStrict
Import openb3d.b3dglgraphics


' Definitionin des Spiegels
Global Mirror:TEntity
Global MirrorCamera:TCamera
Global MirrorTexture:TTexture
Global MirrorPlan:TEntity

Global Spiegel:TPixmap




' dieser teil dient nur zum Erstellen des beliebigen Raums

   Graphics3D 1024,768,32,2
   
   AntiAlias True
   
   ' Licht
      AmbientLight 111,111,111
      Global Licht:TLight= CreateLight(1)
      MoveEntity licht, -5,10,10
      RotateEntity licht, 45,45,0
      LightColor Licht, 255,222,222
      Global Licht2:TLight= CreateLight(1)
      MoveEntity licht2, 5,10,10
      RotateEntity licht2, 45,-45,0
      LightColor Licht2, 222,222,252
   
   'Camera
      Global Camera:TCamera=CreateCamera()
      Global kommode:TEntity=CreatePivot()
      SeedRnd MilliSecs()
      Global MaterialBreite#=0.02
      MoveEntity kommode, 0,0,0
      PositionEntity Camera, -2,1,-5
      RotateEntity Camera, 0,0,0
      CameraViewport Camera,20,20,620,620
     
   
   
   ' Der Raum
      Global Raum:TMesh=CreateCube()
      FlipMesh raum
      EntityColor Raum,115,82,42
      MoveEntity raum, 1,2.82,-4.47
      ScaleEntity raum,6,4,5
   
   
   ' Die Kommode
      Global Wand:TEntity[99]
      Global Fuss:TEntity[99]
      Global Schub:TEntity[99]
     
      Local TexName$="holz.png"
      Local Holz:TTexture=LoadTexture(TexName)
      If holz=Null Then
         Holz=CreateTexture(256,256,0)
         
      EndIf
      RotateTexture Holz, 90
     
      ScaleTexture  Holz,1,0.3
      ' linke wand
      Wand[0]=CreateCube (Kommode)
      ScaleEntity wand[0],MaterialBreite,1,0.5
      MoveEntity wand[0], -1.5,0,0
      EntityColor Wand[0],211,211,211
      EntityTexture Wand[0],Holz
     
      ' rechte wand
      Wand[1]=CreateCube (Kommode)
      ScaleEntity wand[1],MaterialBreite,1,0.5
      MoveEntity wand[1], 1.5,0,0
      EntityColor Wand[1],191,191,191
      EntityTexture Wand[1],Holz
     
      ' oben
      Wand[2]=CreateCube (Kommode)
      ScaleEntity wand[2],1.6,2*MaterialBreite,0.55
      MoveEntity wand[2], 0,1,-0.05
      EntityTexture Wand[2],Holz
     
     
      ' unten
      Wand[3]=CreateCube (Kommode)
      ScaleEntity wand[3],1.55,MaterialBreite,0.51
      MoveEntity wand[3], 0,-1,0
      EntityColor Wand[3],111,111,111
      EntityTexture Wand[3],Holz
     
     
      ' hinten
      Wand[4]=CreateCube (Kommode)
      ScaleEntity wand[4],1.50,0.97,MaterialBreite
      MoveEntity wand[4], 0,0,0.5
      EntityColor Wand[4],11,11,11
     
     
     
      ' fuss
      fuss[0]=CreateSphere (8,Kommode)
      ScaleEntity fuss[0],0.1,0.1,0.1
      MoveEntity fuss[0], -1.4,-1.1,-0.4
      EntityColor fuss[0],48,33,24
      Fuss[1]=CopyEntity(Fuss[0],Kommode)
      MoveEntity fuss[1], +2.8,0,0
      Fuss[2]=CopyEntity(Fuss[0],Kommode)
      MoveEntity fuss[2], 0,0,0.8
      Fuss[3]=CopyEntity(Fuss[0],Kommode)
      MoveEntity fuss[3], +2.8,0,0.8
     
      ' Schublade
      'holz=LoadTexture(TexName)
      ScaleTexture  holz,1,0.4
      RotateTexture holz, 90
      Schub[0]=CreatePivot(Kommode)
      MoveEntity Schub[0],-0.76,0.625,-0.55
      '
      Global SchubZier:TEntity =CreateCube(Schub[0])
      ScaleEntity SchubZier,0.75,0.3,MaterialBreite
      MoveEntity SchubZier, 0,0,0
      EntityTexture SchubZier,holz
      'EntityColor SchubZier,Rand(100,255),Rand(100,255),Rand(100,255)
      '
      Global SchubKnopf:TEntity =CreateCylinder(16,True,Schub[0])
      ScaleEntity SchubKnopf, 0.1,0.03,0.02
      MoveEntity SchubKnopf,0,0,-0.1
      TurnEntity SchubKnopf,90,0,0
      EntityColor SchubKnopf,155,155,155
      EntityColor SchubKnopf,48,33,24
      EntityShininess SchubKnopf,1
      '
      Global SchubWangeL:TEntity =CreateCube(Schub[0])
      ScaleEntity SchubWangeL,MaterialBreite,0.25,0.5
      MoveEntity SchubWangeL, -0.65,0,0.5
      EntityColor SchubWangeL,211,211,211
      EntityTexture SchubWangeL,holz
     
      '
      'HideEntity SchubWangel
      Global SchubWangeR:TEntity =CopyEntity (Schubwangel,Schub[0])
      MoveEntity SchubWangeR, 1.3,0,0
      EntityColor SchubWangeR,169,169,188
      '
      Global SchubBoden:TEntity =CreateCube(Schub[0])
      ScaleEntity SchubBoden,0.65,MaterialBreite,0.5
      MoveEntity SchubBoden, 0,-0.25,0.5
      EntityColor SchubBoden,151,151,151
      EntityTexture SchubBoden,holz
     
      '
      Global SchubRueck:TEntity =CreateCube(Schub[0])
      ScaleEntity SchubRueck,0.65,0.25,MaterialBreite
      MoveEntity SchubRueck, 0,0,1
      EntityColor SchubRueck,111,111,91
      EntityTexture SchubRueck,holz
     
     
      For Local I%=1 To 6
         Schub[i]=CopyEntity (Schub[0],Kommode)
      Next
      MoveEntity Schub[1],1.52,0,0
      MoveEntity Schub[2],0,-0.63,0
      MoveEntity Schub[3],1.52,-0.63,0
      MoveEntity Schub[4],0,-1.26,0
      MoveEntity Schub[5],1.52,-1.26,0
     
   
   ' restliches Mobiliar
      Global Wuerfel:TEntity =CreateCube()
      ScaleEntity wuerfel,0.5,1,0.5
      MoveEntity wuerfel, 0,-1,-4
      EntityColor wuerfel, 0,0,55
     
      Global Lampe:TEntity =CreateSphere(8)
      'ScaleEntity Lampe, 0.5,0.5,0.5
      MoveEntity Lampe, 0,4,-2
      EntityColor lampe,55,213,222
     
      Global Saeule:TEntity =CreateCylinder(8,0)
      ScaleEntity Saeule,0.5,5,0.5
      EntityColor Saeule, 111,111,111
      MoveEntity Saeule, -4,2,0
      EntityShininess Saeule,1
     
     
      Global Teppich:TEntity =CreateCube()
      ScaleEntity Teppich, 8,0.001,8
      MoveEntity teppich, 3,-1.15,-6
      EntityColor teppich, 55,0,0
      Global r#=1
      Global X#=100
     
      Global  Regal:TEntity[9]
      Regal[0]=CreateCube()
      ScaleEntity regal[0] ,0.5,0.05,2
      EntityColor Regal[0], 111,211,111
      MoveEntity Regal[0],6.6,0,-4
      EntityShininess Regal[0],1
      For Local i%= 1 To 4
         Regal[i]=CopyEntity(Regal[0])
         MoveEntity regal[i],0,i*0.5,0
      Next


' Spiegel Init !!!!!!!!!!!!!!!!

      InitMirror

' Hauptschleife
Repeat
       PointEntity camera, mirror
     ScaleEntity Kommode, 1,1,1

      RenderMirror Camera, MirrorCamera
      UpdateWorld
      RenderWorld

BeginMax2D()

      SetColor 202,161,114
   
      DrawText "W A L L   M I R R O R    D E M O ",700,400
     
      DrawText "<E> and <R> to rotate Mirror",700,460
      DrawText "<NUM+> and <NUM-> to up/down camera pivot",700,490
      DrawText "<curosr keys>  to move camera pivot",700,520
      DrawText "<ESC>  to Quit",700,550
      DrawText "(C)   M I D I M A S T E R   M U S I C   E D U C A T I O N   S O F T W A R E   www.midimaster.de ",700,580
'  DrawImage LoadImage(Spiegel),0,0
      Flip 0
      ' Schublade auf/zu
         If EntityZ(Schub[3]) < -1.45
            r=0.002
         ElseIf EntityZ(Schub[3]) > -0.56
            r=-0.002
' PositionEntity(Schub[3], EntityX(Schub[3]), EntityY(Schub[3]), -0.55)
         EndIf
         x=x+r
         MoveEntity schub[3],0,0,r
         'DebugLog x + " " + r


      'Steuerung
            If KeyDown(KEY_LEFT) Then
               MoveEntity camera,0.03,0,0
            EndIf
            If KeyDown(KEY_RIGHT) Then
               MoveEntity camera,-0.03,0,0
            EndIf
            If KeyDown(KEY_UP) Then
               MoveEntity camera,0,0,0.03
            EndIf
            If KeyDown(KEY_DOWN) Then
               MoveEntity camera,0,0,-0.03
            EndIf
            If KeyDown(KEY_NUMSUBTRACT) Then
               MoveEntity camera,0,+0.003,0
            EndIf
            If KeyDown(KEY_NUMADD) Then
               MoveEntity camera,0,-0.003,0
            EndIf
            If KeyDown(KEY_NUM8) Then
              ' TurnEntity camera,0,0.3,0
            EndIf
            If KeyDown(KEY_NUM2) Then
              ' TurnEntity camera,0,-0.3,0
            EndIf
            If KeyDown(KEY_R) Then
               TurnEntity mirror,0,-0.3,0
            EndIf
            If KeyDown(KEY_E) Then
               TurnEntity mirror,0,0.3,0
            EndIf
           
            If KeyDown(KEY_ESCAPE) Then
               End
            EndIf
EndMax2D
Forever







' Spiegel-Funktionen



Function InitMirror()

      mirror = CreatePivot()
      MirrorCamera = CreateCamera()
      '   ScaleEntity MirrorCamera, 0.02,0.02,0.02
      CameraViewport MirrorCamera,700,100,256,256

      PositionEntity mirror, 3,1,-1
      RotateEntity mirror,0,90,0

      ' die Scheibe:
      MirrorPlan=CreateCube(mirror)
      ScaleEntity mirrorPlan,1,1,0.0003
      MirrorTexture = CreateTexture(256,256,256)
      ScaleTexture MirrorTexture,1,1
      EntityFX mirrorPlan,9
      EntityTexture mirrorPlan,MirrorTexture     
     
      ' nur schöner Rahmen:
      Local SpiegelRahmen:TEntity =CreateCube(mirror)
      ScaleEntity Spiegelrahmen,1.05,0.05,0.05
      MoveEntity SpiegelRahmen,0,1,0
      EntityColor SpiegelRahmen, 65,25,0
     
      Local SpiegelRahmen2:TEntity =CopyEntity(SpiegelRahmen,mirror)
      MoveEntity SpiegelRahmen2,0,-2,0

      Local SpiegelRahmen3:TEntity =CreateCube(mirror)
      ScaleEntity Spiegelrahmen3,0.05,2.0,0.05
      MoveEntity SpiegelRahmen3,1,-0.5,0
      EntityColor SpiegelRahmen3, 65,25,0
     
      Local SpiegelRahmen4:TEntity =CopyEntity(SpiegelRahmen3,mirror)
      MoveEntity SpiegelRahmen4,-2,0,0

End Function




Function RenderMirror(Camera:TCamera,MirrorCamera:TCamera)
        'Kamera umschalten
         CameraProjMode Camera,0
         CameraProjMode MirrorCamera,1
         
      ' Spiegel-Kamera an den Spiegel
         PositionEntity MirrorCamera, EntityX(Mirror),EntityY(Mirror),EntityZ(Mirror)
         CameraZoom MirrorCamera,1.5
          HideEntity Mirror
      ' Winkel zwischen Original-Kamera und Spiegel feststellen
         ' alte Werte merken
         Local Winkel_Y#=EntityYaw(Camera)
         Local Winkel_X#=EntityPitch(Camera)
         PointEntity Camera,MirrorCamera

      ' D I E  F O R M E L :
      RotateEntity MirrorCamera, 360-2*EntityPitch(Mirror)+EntityPitch(Camera),180+2*EntityYaw(Mirror)-EntityYaw(Camera),0
     
      ' Foto davon auf MirrorPlan
         UpdateWorld
         RenderWorld
         'seitenverkehrt
Spiegel:TPixmap=XFlipPixmap(GrabPixmap(700,100,256,256))

BufferToTex MirrorTexture, Spiegel.PixelPtr(0,0)
      ' Original Kamera wieder zurückrichten
          ShowEntity Mirror
         RotateEntity Camera,Winkel_X,winkel_Y,0
         CameraProjMode Camera,1
         CameraProjMode MirrorCamera,0
End Function


to run it you need the Holz.png- file form the attachment here:
...back from Egypt

angros47

Have you tried scaling the camera to 1,1,-1 or something like that? OpenB3D allows that

Midimaster

Quote from: angros47 on December 03, 2021, 15:35:02
Have you tried scaling the camera to 1,1,-1 or something like that? ...

This gives strange screenshots.... but not all objects are rendered by such a camera.

I tested all combinations of "-1" and "1" and I can tell you:

ScaleEntity MirrorCamera, 1, 1, -1  ' = objects are visible, but not the walls, camera look to wrong direction

ScaleEntity MirrorCamera, -1, 1, 1  ' = objects are visible, but not the walls, left-right-swap is correct

ScaleEntity MirrorCamera, x, -1, x ' = objects are visible, but top-down reversed

ScaleEntity MirrorCamera, -1, 1, -1 ' = objects are visible, also the walls, camera looks to wrong direction
...back from Egypt

markcwm

Hey Midimaster,

that's a nice little demo, I was thinking of writing a real mirror demo for the Openb3d.docs, real as in being able to reflect from any angle, so thank you, that will save me some time! I'll credit you for it.

col

Quotewhich shows that the mirroring in a real mirror cannot be done with Shaders
You shouldn't say things when you're not well versed with them.

This is done purely with shaders and has plenty of mirrors:
https://www.shadertoy.com/view/4sS3zc

Perhaps you mean OpenB3D is too restricting to do this with shaders? Even then I find that hard to believe but I accept that I've not used OpenB3D so that well may be the case.
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

Midimaster

#8
Ok... when I watch the video, it could be that the miror effect maybe correct. But it is difficult to prove, because the mirrors are spheric and there are a lot of side effects. I would like to see  the same on a plane mirror with clear to understand objects in the room behind the camera.

What language is this? It looks like a real time simulation. But I do not know how to place a plane mirror and some harmless cubes to understand what happens.

Some coders still believe that a mirror shows a fixed impression only depending on its position. But the truth is, that a mirror shows impressions depending on the observers position. Means two people looking at the same mirror see two different images on its plane.

...back from Egypt

col

QuoteBut it is difficult to prove, because the mirrors are spheric and there are a lot of side effects.
The code is using ray tracing. You don't really get much more accurate than that.
There are flat planes at the sides and back - hexagonal shaped.

QuoteWhat language is this? It looks like a real time simulation.
It's GLSL, the shader language used with OpenGL. It is real time yes.

QuoteBut I do not know how to place a plane mirror and some harmless cubes to understand what happens.
The whole scene is made of parametric shapes generated within the shader code itself. Isn't math great  ;D

QuoteBut the truth is, that a mirror shows impressions depending on the observers position. Means two people looking at the same mirror see two different images on its plane.
Yes a mirror is a reflection of the scene seen from the viewer position.
You would do well to search and follow some tutorials to understand the math behind it all. YouTube can be a respectable source nowadays for searching for a lot of tutorials relating to graphics work.
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

_PJ_

Sorry to 'necro' this old topic, but I found that when I run this, the "mirror" rendering seems to be extremely "flickering"
I changed the
Flip 0
to
Flip 1
and it's better - Still flickering rapidly, but without 'tearing' [[ Apparently Graphics3D includes some auto frame limiting, but not sure what it's doing under-the hood to achieve this) ]]
Same results in either DebugMode or 'Release'

I am just wondering if this is due to my graphics card (  Radeon RX580 ) or something else specific to me, or if this happens to others ?

It's reasonable that this could just be an artifact of the dual rendering calls, but I wanted to be sure it wasn't something specific to my setup