DrawSubImageRect

Archives Forums/BlitzMax Bug Reports/DrawSubImageRect

_Skully(Posted 2010) [#1]
Has anyone else experienced this? Hopefully shed some light

In TileMax I do the following:
MT:MapTile=new MapTile
MT.Layers[0]=New TMLayer
MT.Layers[0].TileSet=TileSet.LoadTileSet("Media/Graphics/1124.png")
MT.Layers[0].ModeX=Mode_Parallax
MT.Layers[0].ModeY=Mode_Parallax
MT.Layers[0].RatioX=0.4
MT.Layers[0].RatioY=0.4
TMCreateTileMap(30,30,MT)


This creates a 30x30 TileMap using MT as a template MapTile (so we get a 30x30 tile map with a parallax effect) which works great under DX; however, when I switch to the OpenGL driver now the image contained in the TileSet turns solid white and I've confirmed that it changes to all white after the first render.

The renderer does not do any image manipulation what-so-ever but I do make extensive use of the DrawSubImageRect command.

I've debuglogged my code to death just to see if I was crossing image boundaries or anything like that but all the numbers look correct. The numbers never breach the image boundaries including when the image used has to "wrap" which was the only thing I could think of that might be handled differently between DX and OpenGL.

Has anyone experienced something similar? Have any ideas?


GaryV(Posted 2010) [#2]
Is this a desktop app or fullscreen? If it is a desktop app is GLShareContexts of any help?


_Skully(Posted 2010) [#3]
Thanks for the quick reply...

I've tried both Fullscreen and Windowed modes.. no difference.


GaryV(Posted 2010) [#4]
I am not sure of the specifics as I do not use the GL (or DX driver for that matter), but Mark implemented the GLShareContexts command a while back due to issues people were having with BM when using the GL driver. Whether that would help in your case or not, I don't know, but I thought I would suggest trying it.

Hopefully, somebody else will pop in with a solution. Sounds like a nasty problem. ;)


_Skully(Posted 2010) [#5]
Its really frustrating! Been lingering now for several weeks.

I'd carry on forward but DX on my laptop is super slow despite updating graphics drivers and DX itself... OpenGL is orders of magnitude faster... I just switch to DX every now and again to test compatibility.

I have also updated to the latest version again just to make sure I didnt miss a "fix"


_Skully(Posted 2010) [#6]
Must be me if no one else is experiencing similar issues...

Dives back into the code.


_Skully(Posted 2010) [#7]
Ok, here is another oddity...

It works within a MAXGUI Canvas in OpenGL.. WTFrap!!!

more...

Full Screen OpenGL No
Windowed OpenGL No
MAXGUI Canvas OpenGL Yes

Full Screen DX7 Yes
Windowed DX7 Yes
MAXGUI Canvas DX7 Yes
Full Screen DX9 Yes
Windowed DX9 Yes
MAXGUI Canvas DX9 Yes


_Skully(Posted 2010) [#8]
this is what I am getting:

OpenGL:


The square on the right is actually a separately loaded image (same one as background) which is drawn there for comparison... the tileset one is being drawn to the left of that which is why I know the entire image has changed to all white.

DirectX



N(Posted 2010) [#9]
Can I see the code you're using for drawing the image? Are you clamping the sub-image rect to the imagesCan I see the code you're using for drawing the image? Are you clamping the sub-image rect to be within the image's size? If you aren't, you should probably do that.


_Skully(Posted 2010) [#10]
Hey Nilium,
this is the code block responsible for the layer draw operation:

	Method Draw(x:Float,y:Float,TileSizeX:Int,TileSizeY:Int,Mapx:Int,Mapy:Int)
		TMSetDraw(ScaleX,ScaleY,Rotation,Blend,Min(TileMax.Currentlevel.alpha+alpha,1))
		If ModifiedImage
			DrawImage ModifiedImage,x,y
		ElseIf Self.TileSet
			Local ox:Float
			Local oy:Float
			Local dw:Float=TileSizeX		' maximum draw width for this tile
			Local dh:Float=TileSizeY
			
			If ModeX=TileMax.TILELAYERMODE_PARALLAX
				ox=GetParallaxOffset(x,TileMax.FocusX,TileSet.Image.width,RatioX)
				' Limit the draw size so we dont go over the edge of the Parallax image
				If ox+TileSizeX>=TileSet.Image.width
					dw=TileSet.Image.width-1-ox
				End If
			ElseIf ModeX=TileMax.TILELAYERMODE_SCROLLER
				ox=((Abs(TMTick*TMFreqDelta*RatioX) Mod TileSet.Image.width)+Mapx) Mod TileSet.Image.width
				If RatioX<0 Then ox=TileSet.Image.width-ox
				If ox+TileSizeX>=TileSet.Image.width
					dw=TileSet.Image.width-1-ox
				End If
			Else
				ox=ImageX*TileSizeX
			EndIf

			If ModeY=TileMax.TILELAYERMODE_PARALLAX
				oy=GetParallaxOffset(y,TileMax.FocusY,TileSet.Image.height,RatioY)								
				If oy+TileSizeY>=TileSet.Image.height
					dh=TileSet.Image.height-1-oy
				End If

			ElseIf ModeY=TileMax.TILELAYERMODE_SCROLLER
				oy=((Abs(TMTick*TMFreqDelta*RatioY) Mod TileSet.image.height)+MapY) Mod TileSet.image.height
				If RatioY<0 Then oy=TileSet.Image.height-oy
				If oy+TileSizeY>=TileSet.Image.height
					dh=TileSet.Image.height-1-oy
				End If
			Else
				oy=ImageY*TileSizeY
			EndIf
										
			If StepX
				ox=Int(ox/TileSizeX)*TileSizeX
				dw=TileSizeX
			End If

			If StepY
				oy=Int(oy/TileSizeY)*TileSizeY
				dh=TileSizeY
			End If
			
			TMSetDraw(,,,ALPHABLEND,Min(TileMax.Currentlevel.alpha+alpha,1))
			DrawSubImageRect (TileSet.Image,x,y,dw,dh,ox,oy,dw,dh)
			If (dw<TileSizeX) And (dh<TileSizeY)
				' nw quadrant was only drawn... draw the east and south-west quadrants using image start
				DrawSubImageRect (TileSet.Image,x+dw,y,TileSizeX-dw,dh,0,oy,TileSizeX-dw,dh) ' NE
				DrawSubImageRect (TileSet.Image,x+dw,y+dh,TileSizeX-dw,TileSizeY-dh,0,0,TileSizeX-dw,TileSizeY-dh) ' SE
				DrawSubImageRect (TileSet.Image,x,y+dh,dw,TileSizeY-dh,ox,0,dw,TileSizeY-dh) ' SW
'				DebugLog "DrawTile: width="+TileSet.Image.width+" > ox,oy:"+ox+","+oy+" dw,dh:"+dw+","+dh
			ElseIf dw<TileSizeX
				' west half was drawn
				DrawSubImageRect (TileSet.Image,x+dw,y,TileSizeX-dw,dh,0,oy,TileSizeX-dw,dh) ' NE
			ElseIf dh<TileSizeY
				' north half was drawn
				DrawSubImageRect (TileSet.Image,x,y+dh,dw,TileSizeY-dh,ox,0,dw,TileSizeY-dh) ' SW
			End If							
		End If						
	End Method



_Skully(Posted 2010) [#11]
Anything other than the second TMSetDraw call that looks out of order? I'm a little surprised there aren't any ideas from some of the more elite


GaryV(Posted 2010) [#12]
I'm a little surprised there aren't any ideas from some of the more elite
Amazing how that works isn't it?


beanage(Posted 2010) [#13]
I am propably really not of the elite you requested, but did you try loading the background as a separate image/tileset? (To me it looks like for some reason theres an issue with the texture loading or something.. oh well)


Robert Cummings(Posted 2010) [#14]
Hey Nilium,
this is the code block responsible for the layer draw operation:


If you answer his question he might help you in stead of throwing code in his face first :) I wont look at your code till I know if you are clamping (if you aren't, then clamp it).


_Skully(Posted 2010) [#15]
I am propably really not of the elite you requested, but did you try loading the background as a separate image/tileset? (To me it looks like for some reason theres an issue with the texture loading or something.. oh well)


Oh, didn't mean it to come off that way... I just meant that the "elite" tend to want to solve the more advanced problems (and yes Nilium is certainly included).

If you see post 1, I generated a map from scratch using just the one texture. I've tried others as well same result. But I think your question might have broke my tunnel vision... I was going to post the debuglog for that function... so I added one for every Drawsubimagerect... guess what pops up..


DebugLog:GetParallaxOffset 0-512.000000 result:234.879990
DebugLog:GetParallaxOffset 0-512.000000 result:255.200012
DebugLog:>> DrawTile: width/height=512,512 > ox,oy:234.879990,255.200012 dw,dh:32.0000000,32.0000000
DebugLog:GetParallaxOffset 0-512.000000 result:202.879990
DebugLog:GetParallaxOffset 0-512.000000 result:255.200012
DebugLog:>> DrawTile: width/height=512,512 > ox,oy:202.879990,255.200012 dw,dh:32.0000000,32.0000000
DebugLog:>> DrawTile: width/height=256,1536 > ox,oy:64.0000000,1472.00000 dw,dh:32.0000000,32.0000000 <<< WTF is that!


I'm getting an erroneous image width/height being reported!!!


Robert Cummings
He asked for it. Thats the code block that does the clamping.


_Skully(Posted 2010) [#16]
Uh oh, I'm getting it from DX too but perhaps DX has a mod function or something within. More testing....

{edit}
This is really strange...

If I load the vanilla level as posted in #1, the first frame renders properly. The second frame; however, is pooched. BUT, the debug logs I posted above do NOT have that erroneous image width/height problems. Also, when I post the image width/height (direct reference) the numbers are correct while when referenced through a type TMLayer.TileSet.Image the number comes out screwed up, and just for that one Tile. Ugh :P


_Skully(Posted 2010) [#17]
Good:>  DebugLog:TileSet Image W/H 512,512
Good:>  DebugLog:GetParallaxOffset 0-512.000000 result:234.879990
Good:>  DebugLog:GetParallaxOffset 0-512.000000 result:255.200012
Good:>  DebugLog:>> DrawTile: width/height=512,512 > ox,oy:234.879990,255.200012 dw,dh:32.0000000,32.0000000
Good:>  DebugLog:TileSet Image W/H 512,512
Good:>  DebugLog:GetParallaxOffset 0-512.000000 result:202.879990
Good:>  DebugLog:GetParallaxOffset 0-512.000000 result:255.200012
Good:>  DebugLog:>> DrawTile: width/height=512,512 > ox,oy:202.879990,255.200012 dw,dh:32.0000000,32.0000000
WTF :> DebugLog:TileSet Image W/H 256,1536
WTFO:< DebugLog:>> DrawTile: width/height=256,1536 > ox,oy:64.0000000,1472.00000 dw,dh:32.0000000,32.0000000
Good:>  DebugLog:TileSet Image W/H 512,512
Good:>  DebugLog:GetParallaxOffset 0-512.000000 result:170.879990
Good:>  DebugLog:GetParallaxOffset 0-512.000000 result:255.200012
Good:>  DebugLog:>> DrawTile: width/height=512,512 > ox,oy:170.879990,255.200012 dw,dh:32.0000000,32.0000000
WTF :> DebugLog:TileSet Image W/H 256,1536
WTF :> DebugLog:>> DrawTile: width/height=256,1536 > ox,oy:32.0000000,1472.00000 dw,dh:32.0000000,32.0000000
Good:>  DebugLog:GAME: TileSet Image Height 512


Bizarre!


TaskMaster(Posted 2010) [#18]
1536 is 256 x 6, I am guessing it is some sort of bug in your code.


_Skully(Posted 2010) [#19]
This is equivalent to what is happening:

Type TileSet
   Field Image:TImage
   
   Function Load:TileSet(path:string)
      local t:TileSet=new TileSet
      Image=loadimage(path,DYNAMICIMAGE|MASKEDIMAGE)
      return t
   End Function
End Type

local t:tileset=tileset.load("someimage.png")
local img:TImage=t.Image

debuglog "tileset.image.width="+t.image.width+" height="+t.image.height
debuglog "Image.width="+img.width+" height="+img.height


but only produces a messed up number twice in a whole map draw


Floyd(Posted 2010) [#20]
The endless guessing game isn't likely to produce an answer. We need example code we can actually run.


TaskMaster(Posted 2010) [#21]
Exactly Floyd.

Obviously it isn't exactly like what you just posted _Skully, as that doesn't produce the error. Even after I fixed the bug in the code. :)


_Skully(Posted 2010) [#22]
I just mean't in principal...

Ya.. I get that... I'll plug away at it for a while longer and then see about getting someone into the source.


TaskMaster(Posted 2010) [#23]
I know how frustrating it can be. I have run into stuff like this too.

What I always end up doing is backing it up. Then I start tearing the code to pieces, remove something, see if the problem went away, remove more, remove more. When I finally find that it starts working right, I put the final thing that was removed back in, then I have a lot less code to debug.


_Skully(Posted 2010) [#24]
I've done quite a bit of that.. such as disabling the sprite collision code that reads pixels on the images, adding debuglog statements all the way along...

it is very frustrating! LOL Grrr


_Skully(Posted 2010) [#25]
OK... this is going up source included to my alpha team.

If you are an advanced coder and are sitting around thinking about what to do next or need a break, let me know and I'll see about letting you in to have a keen eye. Sometimes distractions can be good inspiration.

Cheers.


Czar Flavius(Posted 2011) [#26]
Did you ever resolve this?