Author Topic: Understanding hardware images  (Read 7173 times)

0 Members and 1 Guest are viewing this topic.

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #15 on: April 17, 2019, 10:40:04 pm »
With "_DISPLAYORDER _SOFTWARE , _GLRENDER , _HARDWARE" it is now behaving like it used to behave for me.  I can now see images and text, with the background colour appearing behind everything.

Any idea why it was behaving differently before (on v1.2)?  I had the same _DISPLAYORDER with _HARDWARE at the bottom of the stack, but CLS, PRINT, and _PUTIMAGE all worked as expected.

FellippeHeitor

  • Guest
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #16 on: April 17, 2019, 10:41:36 pm »
Were the images being converted to hardware before?

Another thing: You don't need _GLRENDER if you're not doing any GL rendering. That would happen in SUB _GL. If you ain't got one, you can remove the switch from _DISPLAYORDER safely.
« Last Edit: April 17, 2019, 10:50:17 pm by FellippeHeitor »

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #17 on: April 17, 2019, 11:07:47 pm »
It's possible I added the 33 switch for hardware loading recently, but I thought I used that before.


This displays nothing but a black screen:
Code: QB64: [Select]
  1.                      _AUTODISPLAY
  2.                      _PUTIMAGE (0, 0), test_handle&, , , _SMOOTH
  3.                      _DELAY 1
  4.                      END
  5.  


This displays the spaceship image for 1 second:
Code: QB64: [Select]
  1.                      _PUTIMAGE (0, 0), test_handle&, , , _SMOOTH
  2.                      _DISPLAY
  3.                      _DELAY 1
  4.                      END
  5.  


Why is _AUTODISPLAY non-functional?

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #18 on: April 17, 2019, 11:12:26 pm »
My original problem that lead me to the CLS/_HARDWARE issue was that I can't use _COPYIMAGE on my loaded image.


This gives me an invalid handle error for the _COPYIMAGE:
Code: QB64: [Select]
  1.                      _PUTIMAGE (0, 0), test_handle&, , , _SMOOTH
  2.                      Fart& = _COPYIMAGE(test_handle&, 33)
  3.  

Same without the 33, invalid handle error.  Why?

FellippeHeitor

  • Guest
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #19 on: April 17, 2019, 11:54:28 pm »
It's possible I added the 33 switch for hardware loading recently

There you have it. That's the change - not one from 1.2 to 1.3.



_COPYIMAGE will fail if you try to COPYIMAGE a hardware image into another. Use it with software images.



Now, about _AUTODISPLAY.

Quote
Why is _AUTODISPLAY non-functional?

Your actual question here is: Why isn't _AUTODISPLAY doing what I thought it would be doing?


This is another case of you misinterpreting what a feature does.

_AUTODISPLAY is the default method for rendering. Draw something, see something immediately. You interrupt that behaviour when you use _DISPLAY.

_DISPLAY not only refreshes the screen, displaying whatever was drawn until the moment it was called, but it also disables _AUTODISPLAY, which means that for whatever you drew after using _DISPLAY to be seen you'll need to call _DISPLAY again. That's the reason we have flicker-free drawing when we use it.

If you use neither, then it's _AUTODISPLAY that's at work, which has everything drawn immediately shown.

Back to your examples, try this:

Code: QB64: [Select]
  1.     _PUTIMAGE (0, 0), test_handle&, , , _SMOOTH
  2.     _LIMIT 30

Your image will be visible as it's being refreshed with enough speed for you to have time to see it. Hardware images are cleared/refreshed at ~60hz.
« Last Edit: April 18, 2019, 12:00:17 am by FellippeHeitor »

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #20 on: April 18, 2019, 12:06:06 am »
I'm asking why _AUTODISPLAY (after using _DISPLAY) followed by a _PUTIMAGE does not display a visible image on the screen?

It should no longer be buffering the output.  How am I not understanding the feature?


"_COPYIMAGE will fail if you try to COPYIMAGE a hardware image"

Why?  How then are you supposed to duplicate a hardware image?

FellippeHeitor

  • Guest
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #21 on: April 18, 2019, 12:22:37 am »
Quote
I'm asking why _AUTODISPLAY (after using _DISPLAY) followed by a _PUTIMAGE does not display a visible image on the screen?
It's a hardware image. If you're not refreshing it on screen it'll show for a fraction of second and go away, that's their nature.

Quote
How then are you supposed to duplicate a hardware image?
You don't.

Hardware images are immutable. You don't draw on them. They are good for displaying, as they're faster and use up less CPU.

The usual practice is to draw on software, convert to hardware, display. Need to update? Redraw on software, convert to hardware, display.

If you really need more than one identical copy of an image in hardware mode, use _COPYIMAGE on the original software version - twice.
« Last Edit: April 18, 2019, 12:24:24 am by FellippeHeitor »

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Why would _PUTIMAGE appear behind the CLS background colour?
« Reply #22 on: April 18, 2019, 01:25:49 am »
I guess I still do not understand the difference between hardware and software images.  The wiki pages have not helped clarify it for me at all.

I also don't understand why QB64 wouldn't support copying a hardware image -- internally it should be just as simple as copying a software image, no?

Why would being immutable affect copying the image, when copying does not alter the original?

What does "refreshing it on screen" mean?

"it'll show for a fraction of second and go away"

Does this mean it will only display for the current screen refresh?

"If you really need more than one identical copy of an image in hardware mode, use _COPYIMAGE on the original software version - twice."

I am loading the images from disk as hardware images, there are no original software images to my knowledge.


My objective is to leave the original image alone, while applying alpha blending for screen display.


This is the code that I was going to be trying, but because of not being able to copy the hardware image I haven't been able to test if it actually works yet:
Code: QB64: [Select]
  1.                      Translucent_Copy = _COPYIMAGE(Objects(Object_ID).Handle)
  2.                      Image_Memory = _MEMIMAGE(Translucent_Copy)
  3.                      Offset_Current = Image_Memory.OFFSET
  4.                      Offset_End = Offset_Start + (Objects(Object_ID).Width_Orig * Objects(Object_ID).Height_Orig * 4)
  5.  
  6.                      IF Offset_Start = Offset_End THEN
  7.                         PRINT "FATAL IMAGE ERROR": ERROR 999: END
  8.                      END IF
  9.  
  10.                      DO
  11.                         Alpha_Original = _MEMGET(Image_Memory, Offset_Current + 3, _UNSIGNED _BYTE)
  12.                         _MEMPUT Image_Memory, Offset_Current + 3, CINT(Alpha_Original * Objects(Object_ID).Opacity) AS _UNSIGNED _BYTE
  13.                         Offset_Current = Offset_Current + 4
  14.                      LOOP UNTIL Offset_Current = Offset_End
  15.  
  16.                      _PUTIMAGE (Objects(Object_ID).X + Offset_X#(Objects(Object_ID).Width, Objects(Object_ID).Orient_X), Objects(Object_ID).Y + Offset_Y#(Objects(Object_ID).Height, Objects(Object_ID).Orient_Y))-(Objects(Object_ID).X + Objects(Object_ID).Width - 1 + Offset_X#(Objects(Object_ID).Width, Objects(Object_ID).Orient_X), Objects(Object_ID).Y + Objects(Object_ID).Height - 1 + Offset_Y#(Objects(Object_ID).Height, Objects(Object_ID).Orient_Y)), Translucent_Copy, , , _SMOOTH
  17.                      _MEMFREE Image_Memory
  18.                      _FREEIMAGE Translucent_Copy
  19.  


Should I be creating a new software image, then reading the hardware image pixel data from memory and writing the alpha blended version onto the software image, or how should I go about this?

Are there any OpenGL functions I can call directly for displaying a hardware image with proper alpha blending (respecting the original image's preexisting alpha values), i.e. display the original hardware image at 0.50 or 0.84 opacity?


Edit:

The wiki references Galleon's OpenGL demo from three pages with the link /gl_package.zip]http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/gl_package.zip, but this link doesn't work.  Any working link for the demo?  I was curious to see what OpenGL functionality there is.

Where can I read up on what library functions are internally available to QB64 cross-platform, for use with DECLARE?
« Last Edit: April 18, 2019, 01:41:11 am by Raven_Singularity »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Understanding hardware images
« Reply #23 on: April 18, 2019, 02:08:53 am »
Think of hardware images like you would printing to a printer.  It goes out, never comes back.  You might LPRINT #1, text$, but you won’t ever see an LINPUT command to read input back from that printer.

In a very similar way, hardware images are sent out to your GPU, with that one-way communication.  You don’t read them back.

They basic way they work is in 3 steps:
1)  create the hardware image and send it to the GPU (_COPYIMAGE ,33 is the easiest way to do this)
2)  display the image with _DISPLAY
3)  purge the image from the GPU after display (done automatically)

Without _DISPLAY, hardware images won’t display; the GPU waits for the call to render them for you.



If you need to blend, or alter, an image, you want to keep it as a software image.  You can’t blend a picture once it’s printed, can you?  By the same token, you can’t blend the hardware image. 

https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Understanding hardware images
« Reply #24 on: April 23, 2019, 10:26:18 am »
So the only way to use hardware images is to keep all the images as software, but also copy them as hardware for fast display?  That would double the RAM usage, I presume.  At least, use as much extra video RAM as the images in RAM.

But why can't the GPU images be read back to being software images?  Video cards are two-way, not one-way like your printing example.  There's no reason why they shouldn't be copyable.


Any clues on my other questions:

1. How can I find out what internal QB64 library functionality is available through DECLARE?

2. Is there OpenGL functionality available which can render hardware images with partial translucency (without changing the original hardware image)?

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Understanding hardware images
« Reply #25 on: April 23, 2019, 01:59:23 pm »
Hi. For better understand OpenGL texturing in QB64 please look to your QB64 instalation folder to Programs/samples/open_gl/simple_example.bas   This program use texturing but not so directly as C, but with Galleon's functions writed in OpenGL / QB64. Specially look to SUB GLH_Select_Texture and FUNCTION DONT_USE_GLH_New_Texture_Handle.

Hardware images are images loaded into OpenGL in the same way, but then are in memory area reserved with OpenGL and not with QB64.

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Understanding hardware images
« Reply #26 on: April 27, 2019, 07:05:06 pm »
Why does the function name start with "DONT_USE_"?

Doesn't seem encouraging, lol.

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Understanding hardware images
« Reply #27 on: April 28, 2019, 10:00:43 am »

1. How can I find out what internal QB64 library functionality is available through DECLARE?

2. Is there OpenGL functionality available which can render hardware images with partial translucency (without changing the original hardware image)?
for first question,  functions which are available in libqb.cpp, glut, glu, glew are available. You can check them inside internal/c/.... folder.

for second one, you can use the following example to render software images using OpenGL in realtime. The advantage will be that you can also modify image whenever needed.

Code: QB64: [Select]
  1. _TITLE "Using OpenGL to Render partial translucent images"
  2. SCREEN _NEWIMAGE(600, 600, 32)
  3.  
  4. img& = _LOADIMAGE("rainbow.png")
  5.  
  6. glAllow = -1
  7.     mouseX = _MOUSEX: mouseY = _MOUSEY
  8.     _LIMIT 30
  9.  
  10. SUB _GL ()
  11.     SHARED glAllow, img&, mouseX, mouseY
  12.     STATIC glInit
  13.  
  14.     IF glAllow = 0 THEN EXIT SUB
  15.  
  16.     _glMatrixMode _GL_MODELVIEW
  17.  
  18.     putimageGL mouseX - 100, mouseY - 100, mouseX + 100, mouseY + 100, img&
  19.  
  20.  
  21. SUB putimageGL (x1, y1, x2, y2, img_handle&)
  22.     IF img_handle& < -1 THEN
  23.         DIM m AS _MEM
  24.         DIM glTex&
  25.         m = _MEMIMAGE(img_handle&)
  26.         _glGenTextures 1, _OFFSET(glTex&)
  27.         _glBindTexture _GL_TEXTURE_2D, glTex&
  28.  
  29.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_S, _GL_CLAMP
  30.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_T, _GL_CLAMP
  31.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR
  32.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_NEAREST
  33.  
  34.         _glTexImage2D _GL_TEXTURE_2D, 0, _GL_RGBA, _WIDTH(img_handle&), _HEIGHT(img_handle&), 0, _GL_BGRA_EXT, _GL_UNSIGNED_BYTE, m.OFFSET
  35.  
  36.         _MEMFREE m
  37.         'converting 2D coordinates into OpenGL 2D coordinates
  38.         px1 = map(x1, -_WIDTH * 0.5, 1.5 * _WIDTH, -2, 2)
  39.         px2 = map(x2, -_WIDTH * 0.5, 1.5 * _WIDTH, -2, 2)
  40.         py1 = map(y1, -_WIDTH * 0.5, 1.5 * _WIDTH, 2, -2)
  41.         py2 = map(y2, -_WIDTH * 0.5, 1.5 * _WIDTH, 2, -2)
  42.  
  43.         _glEnable _GL_TEXTURE_2D
  44.         _glEnable _GL_BLEND
  45.  
  46.         _glBindTexture _GL_TEXTURE_2D, glTex&
  47.  
  48.         _glBegin _GL_QUADS
  49.         _glTexCoord2f 0, 0
  50.         _glVertex2f px1, py1
  51.         _glTexCoord2f 1, 0
  52.         _glVertex2f px2, py1
  53.         _glTexCoord2f 1, 1
  54.         _glVertex2f px2, py2
  55.         _glTexCoord2f 0, 1
  56.         _glVertex2f px1, py2
  57.         _glEnd
  58.  
  59.         _glDeleteTextures 1, _OFFSET(glTex&)
  60.  
  61.     END IF
  62.  
  63. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  64.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  65.  
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: Understanding hardware images
« Reply #28 on: April 29, 2019, 02:54:30 pm »
Thank you, Ashish.  I will investigate how this works later.  After converting my app to software images my code using _MEM for partial translucency is working.  It's fairly fast, but OpenGL accelleration should improve the speed, I imagine.

One question:

In your code example it appears to just be drawing the image as-is.  Is there a way to apply an opacity level when drawing the image to the screen?  Such as opacity = 0.500.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Understanding hardware images
« Reply #29 on: April 30, 2019, 03:46:51 pm »
Hi. Is this what you're looking for? Change the transparency by pressing + or - on the numeric keypad.

Code: QB64: [Select]
  1.  
  2. _TITLE "Using OpenGL to Render partial translucent images"
  3. SCREEN _NEWIMAGE(600, 600, 32)
  4.  
  5. img& = _LOADIMAGE("rainbow.png")
  6. glAllow = -1
  7. na = 127
  8.  
  9.     mouseX = _MOUSEX: mouseY = _MOUSEY
  10.     _LIMIT 30
  11.     k& = _KEYHIT
  12.     IF k& = 43 THEN na = na + 1 'numerical +
  13.     IF k& = 45 THEN na = na - 1 'numerical -
  14.     IF na > 255 THEN na = 255
  15.     IF na < 0 THEN na = 0
  16.     IF oldNA <> na THEN
  17.         _SETALPHA na, _RGBA32(0, 0, 0, 0) TO _RGBA32(255, 255, 255, 255), img&
  18.        oldNA = na    
  19. LOOP UNTIL k& = 27
  20.  
  21. SUB _GL ()
  22.     SHARED glAllow, img&, mouseX, mouseY
  23.     STATIC glInit
  24.  
  25.     IF glAllow = 0 THEN EXIT SUB
  26.  
  27.     _glMatrixMode _GL_MODELVIEW
  28.  
  29.     putimageGL mouseX - 100, mouseY - 100, mouseX + 100, mouseY + 100, img&
  30.  
  31.  
  32. SUB putimageGL (x1, y1, x2, y2, img_handle&)
  33.     IF img_handle& < -1 THEN
  34.         DIM m AS _MEM
  35.         DIM glTex&
  36.         m = _MEMIMAGE(img_handle&)
  37.         _glGenTextures 1, _OFFSET(glTex&)
  38.         _glBindTexture _GL_TEXTURE_2D, glTex&
  39.  
  40.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_S, _GL_CLAMP
  41.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_WRAP_T, _GL_CLAMP
  42.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR
  43.         _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_NEAREST
  44.  
  45.         _glTexImage2D _GL_TEXTURE_2D, 0, _GL_RGBA, _WIDTH(img_handle&), _HEIGHT(img_handle&), 0, _GL_BGRA_EXT, _GL_UNSIGNED_BYTE, m.OFFSET
  46.  
  47.         _MEMFREE m
  48.         'converting 2D coordinates into OpenGL 2D coordinates
  49.         px1 = map(x1, -_WIDTH * 0.5, 1.5 * _WIDTH, -2, 2)
  50.         px2 = map(x2, -_WIDTH * 0.5, 1.5 * _WIDTH, -2, 2)
  51.         py1 = map(y1, -_WIDTH * 0.5, 1.5 * _WIDTH, 2, -2)
  52.         py2 = map(y2, -_WIDTH * 0.5, 1.5 * _WIDTH, 2, -2)
  53.  
  54.         _glEnable _GL_TEXTURE_2D
  55.         _glEnable _GL_BLEND
  56.  
  57.         _glBindTexture _GL_TEXTURE_2D, glTex&
  58.  
  59.         _glBegin _GL_QUADS
  60.         _glTexCoord2f 0, 0
  61.         _glVertex2f px1, py1
  62.         _glTexCoord2f 1, 0
  63.         _glVertex2f px2, py1
  64.         _glTexCoord2f 1, 1
  65.         _glVertex2f px2, py2
  66.         _glTexCoord2f 0, 1
  67.         _glVertex2f px1, py2
  68.         _glEnd
  69.  
  70.         _glDeleteTextures 1, _OFFSET(glTex&)
  71.  
  72.     END IF
  73.  
  74. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  75.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  76.  
  77.  
  78.  

Ashish wrote this program absolutely brilliantly, because as it did, you can using textured movies.
« Last Edit: April 30, 2019, 04:27:48 pm by Petr »