Posted: 18th May 2022 18:38
Not sure if this is a bug as I am using AppGameKit Classic and broadcasting to my iPad, so I do not think Vulcan should be involved, but I receive an error message stating "Error: Vulcan does not support rendering to loaded images; only images created with CreateRenderImage can be used with setRenderToImage in main.agc at line 63." The sample code is below with the needed attachment and shows that the image used is a loaded image "gray.png", not an image created with CreateRenderImage. I have also tested this with GetImage to create an image and the problem is the same. Code works fine on Windows and broadcasting to Android. Does anyone know if there a way around this?

Thanks.

+ Code Snippet
// Project: revealnoshader 
// Created: 2022-04-13

#constant KEY_ESCAPE 27
#constant SCREEN_WIDTH 1024
#constant SCREEN_HEIGHT 768
#constant SCREEN_DEPTH 32

SetErrorMode(2)
// set window properties
SetWindowTitle( "revealnoshaderv2" )
SetWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT, 0)
SetWindowAllowResize(0)
SetOrientationAllowed(1, 0, 0, 0)
 
SetVirtualResolution(SCREEN_WIDTH, SCREEN_HEIGHT)
SetSyncRate(0, 0)
SetScissor(0,0,0,0)
UseNewDefaultFonts(1)

SetRawMouseVisible(0) //hide mouse cursor
 
Global TSprite as Integer
Global CircleImageID as Integer
Global x2# as Float
Global y2# as Float
Global rechide as Integer //sprite number for hidden rectangle

Global rechImageID as Integer //image number for hidden sprite

DrawEllipse(12, 12, 12, 12, MakeColor(200, 200, 200), MakeColor(200, 200, 200), 1)
CircleImageID=GetImage(0,0,48,48)


TSpriteID=CreateSprite(CircleImageID) //pointer sprite
SetSpritePosition(TSpriteID, 700, 700)
SetSpriteDepth(TSpriteID, 4)
SetSpriteOffSet(TSpriteID, 12, 12)
ClearScreen()

DrawBox(0, 0, 512, 384, MakeColor(10,10,255), MakeColor(10,10,255), MakeColor(10,10,255), MakeColor(10,10,255), 1)  //blue image for covered sprite
rechImageID=GetImage(0, 0, 512, 384)
ClearScreen()

rechide = CreateSprite(rechImageID)  //create covered blue sprite
//SetSpritePosition(rechide, 0, 0)
SetSpritePosition(rechide, 250, 200)
SetSpriteDepth(rechide, 9)

 
// overlay image
imgRender = LoadImage("gray.png")

sprRender = CreateSprite(imgRender)
SetSpritePosition(sprRender, 250, 200)
SetSpriteTransparency(sprRender, 1)
SetSpriteDepth(sprRender, 8)

do
  
  ClearScreen()
  SetRenderToImage(imgRender, 0)
  
  x2# = GetPointerX()
  y2# = GetPointerY()
   
  if (GetPointerState() = 1)
	    
      SetSpritePositionByOffset(TSpriteID, x2#, y2#)
      
      //set ellipse to same color as transparency color and convert x2# and y2# coordinates for ellipse to render image coordinates of 0,0 to 1023,767 using hidden image's left and top positions--could use scratch off image position as well
      DrawEllipse((x2# - GetSpriteX(rechide)) * (SCREEN_WIDTH/GetSpriteWidth(rechide)) , (y2# - GetSpriteY(rechide)) * (SCREEN_HEIGHT/GetSpriteHeight(rechide)), 24, 24, MakeColor(255, 100, 100), MakeColor(255, 100, 100), 1)
  endif
  
  SetRenderToScreen()
  
  SetImageTransparentColor(imgRender, 255, 100, 100)

  SetSpritePositionByOffset(TSpriteID, x2#, y2#) 
  
  SetSpriteImage(sprRender, imgRender)  //Change the sprite's image to new image that has part scratched off

  if (GetRawKeyState(KEY_ESCAPE) = 1)
    end
  endif
  
   Print( ScreenFPS() )

 Sync()
 
loop
Posted: 19th May 2022 0:28
regardless of the vulkan reference, use CreateRenderImage().
Posted: 19th May 2022 17:59
@Virtual Nomad,

Thanks for the reply. If I use CreateRenderImage(), how would I get an image from a file, or an image grabbed from the screen into that blank created render image? I have tried using a sprite with the image I want by using RenderToImage() to the created render image when rendering the sprite to the screen. The resulting image size is wrong (much smaller than the CreateRenderImage size), so I must reset the sprite size that uses that rendered to image. The sprite size also shows and acts differently on different devices. Is there a better way to update that created render image to either a file or screen image?

Thanks,

Joe
Posted: 19th May 2022 18:29
Not at a computer/dont have code handy but, IIRC, its best to have the render image created @ the same aspect ratio as the device.

Then DrawSprite() to the render image.

Same dimensions would be ideal, as well but there are occasions where u'd want different dimensions. Ie, if ur render image was scaled @ 50% of the screen, u'd scale the sprite(s), DrawSprite() @ scaled coords. Then u would scale the RenderImage sprite @ 200%.

Meanwhile, i was able to find some code i had offered on discord that might be usefull. See attached

I can't remember if that was a 'final version' but i'll look for it when i get home/can test.

Meanwhile, the code was meant to depict the accumulation of shell casings spit out by turret guns without creating sprite after sprite in anticipation of reaching "thousands" of them soon enough:
Posted: 19th May 2022 20:24
That's clever. In my example, I set the created render image to the max screen size and then created a sprite with a loaded image. I then sized the sprite the same as the screen size to use it to render to the created render image. Finally, I created a sprite using this image. The sprite does resize properly. While the code works okay in Windows and Android, there are some issues with Apple iOS. Also, this is much more system intensive then doing it with the original example code, maybe 1/4 to 1/10 the FPS. I also receive an error message when broadcasting to my iPad with the line SetImageTransparentColor(imgRender1, 255, 100, 100): Cannot update image data on an image that has been used with SetRenderToImage, only modifications by the GPU are allowed. If I REM that line out, the code will broadcast, but does not do what it should to remove some of the image to revel the hidden image.

I did notice in your example there are y locations (0 to some number around 50) where the shell casings do not show. I am not able to determine why that occurs.
Posted: 20th May 2022 13:04
JosephB,

have you tried exporting? does it do the same?

either way, you could report it on the repository: https://github.com/TheGameCreators/AGK-Studio/issues.
Posted: 20th May 2022 14:13
Virtual Nomad,

I have not tried to export. I have not reported it yet either but will try to work around it for a while before I do as this is likely an error somewhere on my part. I was hoping that someone could point me in the right direction or explain what is wrong with the code and why. Basically, trying to keep learning. I did discover something about your code and the issue I noticed with the casings not showing at some y coordinate locations. If I rem-out line 69--Render()--the casings show at all locations. I have no idea why that is though.
Posted: 22nd May 2022 2:38
It isn't a bug, but the correct behaviour.
Apple on iOS have their own Graphics Driver and API called Metal., which effectively is their own version of OpenGL (Metal v1) and Vulkan (Metal v2).
The other thing to note here is that the AppGameKit Player is Universal to AppGameKit Classic and Studio... but keep in mind it uses the Studio Renderer.

Now something to note is that the AppGameKit Player DOES NOT Support changing Rendering Mode.
On Android, it will start and always be in OpenGL (Basic) Mode.
On iOS, if you're using Metal v1 it will be OpenGL (Basic) where-as if you're on Metal v2 it will be Vulkan (Advanced).
And again... you can't change this.

It doesn't mean that when you output the Runtime Package, it will run in that mode. "Native" Code as it were, CAN change the Rendering Mode; and AppGameKit Classic Apps will use the AppGameKit Classic Renderer.
While AppGameKit Studio, you can select which you want it to start in.

It would be nice if we could have a setting for the AppGameKit Player to select which mode you start in (Basic or Advanced) on Compatible Platforms.
Certainly make it easier to test Vulkan-Based Android Apps without having to create an APK every dang time.

In any case you'll need to write support for how AppGameKit Studio (Vulkan) works for Metal v2 Devices., assuming you want to test via AppGameKit Player.
Posted: 23rd May 2022 21:51
Virtual Nomad/Raven,

Thank you. I finally got it working and it looks nice on Windows and Android, but the iOS is not pretty (probably an Apple thing that I have no idea how to make work properly yet). I had to finally write some short VS and PS code that took care of the performance issues. For those interested I included the AppGameKit code and the shader codes. The color in this instance used to make parts of the covering sprite become transparent must be color (RGB) 12, 12, 12 or less. I used 0, 0, 0 as the color to render onto the image.

AGK:
+ Code Snippet
// Project: revealwshaderv1 
// Created: 2022-05-23

#constant KEY_ESCAPE 27
#constant SCREEN_WIDTH 1024 
#constant SCREEN_HEIGHT 768 

SetErrorMode(2)
// set window properties
SetWindowTitle( "revealwshaderv1" )
SetWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT, 0)
SetWindowAllowResize(0)
SetOrientationAllowed(0, 0, 1, 1)
 
SetVirtualResolution(SCREEN_WIDTH, SCREEN_HEIGHT)
SetSyncRate(0, 0)
SetScissor(0,0,0,0)
UseNewDefaultFonts(1)

//SetRawMouseVisible(0) //hide mouse cursor
Global dw as Integer
Global dh as Integer
Global TSprite as Integer
Global CircleImageID as Integer
Global x2 as Float
Global y2 as Float
Global rechide as Integer //sprite number for hidden rectangle
Global imgRender as Integer //gray area image
Global imgRender1 as Integer //gray area image
Global rechImageID as Integer //image number for hidden sprite
Global shaderid as Integer //shader number
Global tops as Integer //top of screen
Global lefts as Integer //left side of screen
Global rights as Integer //right bounds
Global bottoms as integer //bottom bounds

dw = GetDeviceWidth()
dh = GetDeviceHeight()
tops = GetScreenBoundsTop()
lefts = GetScreenBoundsLeft()
rights = GetScreenBoundsRight()
bottoms = GetScreenBoundsBottom()

imgRender1 = CreateRenderImage(SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0)
SetRenderToImage(imgRender1, 0)
ClearScreen()
DrawBox(lefts, tops, 512 * (dw/512), 384 * (dh/384), MakeColor(20,20,20), MakeColor(20,20,20), MakeColor(20,20,20), MakeColor(20,20,20), 1)  //dark gray image for covering sprite
 
SetRenderToScreen()
ClearScreen()

//pointer
DrawEllipse(12, 12, 12, 12, MakeColor(255, 0, 0), MakeColor(255, 0, 0), 1)
CircleImageID=GetImage(0,0,48,48)

TSpriteID=CreateSprite(CircleImageID) //pointer sprite
SetSpritePosition(TSpriteID, 700, 700)
SetSpriteDepth(TSpriteID, 4)
SetSpriteOffSet(TSpriteID, 12, 12)
ClearScreen()

//hidden image
DrawBox(0, 0, 512, 384, MakeColor(10,10,255), MakeColor(10,10,255), MakeColor(10,10,255), MakeColor(10,10,255), 1)  //blue image for covered sprite
rechImageID=GetImage(0, 0, 512, 384)
ClearScreen()

rechide = CreateSprite(rechImageID)  //create covered blue sprite
SetSpritePosition(rechide, 100, 100)
SetSpriteSize(rechide, 512, 384)
SetSpriteDepth(rechide, 9)

// overlay image that will be rubbed away with pointer
shaderid = LoadShader("alphaoff.vs", "alphaoff.ps")
sprRender = CreateSprite(imgRender1)
SetSpritePosition(sprRender, 100, 100)
SetSpriteSize(sprRender, 512, 384)
SetSpriteTransparency(sprRender, 1)
SetSpriteDepth(sprRender, 8)

SetSpriteShader(sprRender, shaderid)

do

  x2 = GetPointerX()
  y2 = GetPointerY()
   
  If (GetPointerState() = 1)
	   SetRenderToImage(imgRender1, 0)

      //set ellipse to same color as transparency color and convert x2# and y2# coordinates for ellipse to render image coordinates of tops ,lefts to 1023,767 (screen resolution) using hidden image's left and top positions--could use scratch off image position as well
      DrawEllipse((x2 - GetSpriteX(rechide)) * ((rights +  ABS(lefts))/GetSpriteWidth(rechide)) + Lefts, (y2 - GetSpriteY(rechide)) * ((bottoms + ABS(tops))/GetSpriteHeight(rechide)), 24, 24, MakeColor(0, 0, 0), MakeColor(0, 0, 0), 1)
	  //SetShaderConstantByName(shaderid,"AlphaOff",1.0, 0.0, 0.0, 0.0)  
   EndIf

  SetRenderToScreen()
  ClearScreen()
  SetSpritePositionByOffset(TSpriteID, x2, y2) 

  If (GetRawKeyState(KEY_ESCAPE) = 1)
    End
  EndIf
  
   Print( ScreenFPS() )
 
 Sync()
 
loop


VS:
+ Code Snippet
attribute highp vec4 position;
attribute mediump vec4 color;
attribute mediump vec2 uv;
varying mediump vec2 uvVarying;
varying mediump vec4 colorVarying;
uniform highp mat4 agk_Ortho;

void main()
{ 
	gl_Position = agk_Ortho * position;
	uvVarying = uv;
	colorVarying = color;
}


PS:
+ Code Snippet
uniform sampler2D texture0;
varying mediump vec2 uvVarying;
varying mediump vec4 colorVarying;

uniform lowp vec4 AlphaOff;

void main()
{
	vec4 tcol = texture2D(texture0, uvVarying);
    
    if (tcol.r <= 0.05 && tcol.g <= 0.05 && tcol.b <= 0.05)  //alpha any black drawing that is around RGB 12, 12, 12 or less
    {
       gl_FragColor = AlphaOff; 
    }
	else
	{
		gl_FragColor = tcol; 
	}
}
Posted: 24th May 2022 1:54
iOS is not pretty

might help if you add #renderer "basic" to your code?
Posted: 24th May 2022 15:20
I already tried the #renderer "Basic", but AppGameKit classic seems to ignore that command as I can say #renderer "hello" and no errors. I did try this in AppGameKit Studio and while #renderer"Basic" or the other possibilities seem to do something, the problem still persists. It just looks blocky. I attached a screenshot.