Facepunch / garrysmod-issues

Garry's Mod issue tracker
141 stars 56 forks source link

Bad UV tiling in surface.DrawTexturedRectUV #3173

Open Klizmotron opened 7 years ago

Klizmotron commented 7 years ago

Details

For some reason the UV coordinates in this function do not do what they should. For example, when you set some 8x8 texture as a material to draw and want to draw a 64x64 rectangle with it using surface.DrawTexturedRectUV, where the texture tiles (it should tile 8 times for x and y), you would expect the correct UVs to be 0, 0, 8, 8, but in reality it leads to some uneven and crappy results, but when you add some randomly discovered offset, which is equal to tiling/texture_resolution to the end UV coordinate it fixes the thing. This is very strange behavior and I wonder if it can be fixed. Here are some illustrations of my words:

The code:

-- Just rendering a few background colored rectangles to show where is what
surface.SetMaterial( White )
surface.SetDrawColor( 255, 0, 0, 128 )
surface.DrawRect( 0, 0, 256, 256 )
surface.DrawRect( 256, 0, 256, 256 )
surface.SetDrawColor( 0, 255, 0, 128 )
surface.DrawRect( 0, 256, 256, 256 )
surface.DrawRect( 256, 256, 256, 256 )
surface.SetMaterial( Icon )
surface.SetDrawColor( 255, 255, 255, 255 )

-- (THE THINGS THAT ARE ON THE RED BACKGROUND)
-- The meant UVs, seems to tile those incorrectly

-- Should draw a 8x8 grid of icons, in reality cuts it to 7.5x7.5 or something
surface.DrawTexturedRectUV( 0, 0, 256, 256, 0, 0, 8, 8 ) 
-- Should draw a 16x16 grid of icons, in reality cuts it to 15x15 or something
surface.DrawTexturedRectUV( 256, 0, 256, 256, 0, 0, 16, 16 ) 

-- (THE THINGS THAT ARE ON THE GREEN BACKGROUND)
-- For some reason when you add a [tile_amount/texture_resolution] to the end UV 
-- coordinate, it tiles seamlessly and keeps on the pixel grid as it should

-- Draws exactly 8x8 grid
surface.DrawTexturedRectUV( 0, 256, 256, 256, 0, 0, 8 + 8 / 16, 8 + 8 / 16 ) 
-- Draws exactly 16x16 grid
surface.DrawTexturedRectUV( 256, 256, 256, 256, 0, 0, 16 + 16 / 16, 16 + 16 / 16 ) 

In-game results

In-game results

I hope it can be fixed soon, this is not the way it should work

thegrb93 commented 7 years ago

Yeah I can confirm. I think there was a hack put in the surface functions to help prevent artifacts on textured rects not bordered correctly. Without the hack, some of the texture on one side of the rect appears wrapped to the other side due to AA.

robotboy655 commented 7 years ago

DrawTexturedRectUV is a direct binding with no extra code to DrawTexturedSubRect

thegrb93 commented 7 years ago

Then it's valve's doing.

Klizmotron commented 7 years ago

Well, seems like we'll have to keep on using this arbitrary adjustment to make it all look good

robotboy655 commented 3 years ago

https://github.com/VSES/SourceEngine2007/blob/master/src_main/vguimatsurface/TextureDictionary.cpp#L535-L546

This is the cause. Apparently to do with DX to GL abstraction layer the engine uses according to internal comments.

"Fixing" this (provided a nice way of doing so is found) not only will break all existing code that has been adjusted, it will also break all code that has not been adjusted. Interestingly some parts of the spawnmenu are not affected by this, like silk icons and the derma skin.

thegrb93 commented 3 years ago

I imagine the unaffected materials are already the correct size for the border correction. Most addons use render.drawQuad instead to avoid this bug. You might as well fix it.

WilliamVenner commented 3 years ago

Weirdly, this doesn't affect macOS. No idea about Linux