Texture 'banding' (or ghost lines)

Blitz3D Forums/Blitz3D Programming/Texture 'banding' (or ghost lines)

Rhyolite(Posted 2004) [#1]
Hi,

I have found this topic (or similiar) mentioned on the forums but without any solutions. Hopefully someone can give me an answer or direct me to an answer - thanks :)

I have a textures surface consisting of quads (two polys) running parrallel to each other. When viewed at a distance, faint white lines can be seen along the parallel polys which gets worse the further away they are viewed and when at an angle.

I have tried with/without mipmapping, adjusting camera near/far range and a dozen other things I can't remember now. Have also tried using a solid colour texture but still same problem (although perhaps slightly less).

The only way I have removed the 'ghost' lines is to use vertex colours instead of a texture, but this is not what I require. But it obviously (??) shows its a texture problem.

I am beginning to wonder if this is just a limitation of Blitz3D/DirectX, but thought I would pick the brains of everyone before giving up ;) Sigh, just when I was starting to feel I was getting to grips with 3D!! Hehe ;)

Thanks in advance,
Rhy


Warren(Posted 2004) [#2]
Screen shots?


Rhyolite(Posted 2004) [#3]
Here goes, not sure if size will be ok.

Both shots are from a distant camera, the first head on and the second at an angle.





Rhy


Shane(Posted 2004) [#4]
To show your pics use square brackets, ditch the src= and the "'s.

i.e. [img http: //..etc ] (but without the spaces in the url


Rhyolite(Posted 2004) [#5]
Thanks Shane, you should see my coding!! ;o)

Rhy Out!


Rhyolite(Posted 2004) [#6]
To clarify, both piccys are using a solid green texture (rather than the actual texture, but problem is the same) and the white 'lines' are running along the edges where two parallel triangle edges meet (I have tried moving the edges apart a little rather than sharing the same 3d space, but no difference).

If this is a Blitz3D/DirectX limitation can someone please say so and I can then stop worrying about it and get some sleep again ;) The problem is only occuring at the far extreme of my visible camera range, so I can always reduce my range slightly (but would rather solve the problem if possible).

Cheers,
Rhy


big10p(Posted 2004) [#7]
Those screenies aren't too clear. Is that a single quad (2 tris) or a load of connected quads, being rendered?


Rhyolite(Posted 2004) [#8]
The screenies are showing multiple quads. There is a quad inbetween each of the faintish white lines, and the white lines are occuring at the edge of those quads. The quads are NOT welded together in anyway (so there are two vertices occupying the same 3d space at each corner).

Hope that helps? Should have posted a wire mesh piccy really, but do not have access to upload right now.

Rhy


big10p(Posted 2004) [#9]
Hmmm, you often get gaps appearing when rendering quads like that, but I've never seen those white lines before.

Any chance of some example code?


Rob Farley(Posted 2004) [#10]
Definately a need to example code... either that or you've got tippex on your screen. ;)


SoggyP(Posted 2004) [#11]
Hi Folks,

We can hope it's tippex! Eww, green plane fetish alert.

Later,

Jes


Rhyolite(Posted 2004) [#12]
Hehe, I wish it was tippex!

There is nothing special about the code, just calculating vertex coords and UVs at runtime and forming a single FLAT surface of 'joined' quads. I have tried not overlapping AND overlapping the quads but no difference so dont think its an 'alignment' issue. The UV's map about a 12 pixel high (V) portion of a 256x256 texture onto the quad of varying lengths (U).

The code is kinda jumbled in with lots of other stuff thats being calculated at the same time, but really is just:

Start loop:

;top left vertex
vx = blah_left : vy = blah_top : vz = same_every_time
u = blah_leftU : v = blah_topV
v1 = addvertex(surf,vx,vy,vz,u,v)

;bottom left vertex
vx = blah_left : vy = blah_bottom : vz = same_every_time
u = blah_leftU : v = blah_bottomV
v2 = addvertex(surf,vx,vy,vz,u,v)

;top right vertex
vx = blah_right : vy = blah_top : vz = same_every_time
u = blah_rightU : v = blah_topV
v3 = addvertex(surf,vx,vy,vz,u,v)

;bottom right vertex
vx = blah_right : vy = blah_bottom : vz = same_every_time
u = blah_rightU : v = blah_bottomV
v4 = addvertex(surf,vx,vy,vz,u,v)

;add triangles (clockwise)
t1 = addtriangle(surf,v1,v3,v2)
t2 = addtriangle(surf,v3,v4,v2)

end loop:

UpdateNormals(meshofsurf)

brush = loadbrush("tex.png",4+8)
paintsurface(surf,brush)

I am pretty convinced its something to do with the closeness of the 'percieved' quads as you get further away when a texture is applied (vertex colours are ok). This is because the effect is only seen at distance, but if viewed at an acute angle the effect is seen closer to the camera (because quads are percieved as more closely packed at an angle).

Thanks for the input so far,
Rhy


big10p(Posted 2004) [#13]
Couple of thoughts:

- Remove UpdateNormals() and set the normals youself. Easy enough as they should all be: nx=0 ny=0 nz=-1
As your using simple quads, every vertex normal should be perpedicular to the quad (like a surface normal) but UpdateNormals() is probably trying to smoothe them.

- Try turning off mip-mapping for the texture to see if that makes a difference. As the effect only happens at a certain distance, maybe one of the mip-maps is corrupt (long shot :)?


DJWoodgate(Posted 2004) [#14]
You need to post some code and texture which demonstrates the problem. Then at least we can determine if maybe it is something which only effects certain cards/drivers and perhaps how they filter textures or whether something else is to blame.


Rhyolite(Posted 2004) [#15]
@ DJW: Ok, I may try and knock up some working code which demonstrates the problem. Trouble is I am going away for a few days and I unless I get it done before I go this post will be dead. Spose I can ressurect it!

@big10p: About the normals, I am 'actualy' using sswifts 'Calculate_Normals' routine rather than the native Blitz command. I know i used the blitz command in the code, but I wanted to keep it simple and the 'effect/bug' occurs regardless of which method is used. However, your suggesting setting them manualy has made me think that I could try setting them myself. Its an indication of my 3D learning curve that when I started this code I had no idea what a 'normal' was, yet now I feel confident to have a bash myself :o) Oh, and much of that confidence is down to the blitz community, either help directly or just reading previous posts and tutorials etc - thanks all :)

Oh, mipmapping (and back on topic!) - already tried that and every other comination of flags/FX etc I could think off ;) Thanks for suggestion though :)

Rhy Out!


big10p(Posted 2004) [#16]
Don't leave us in suspenders! Please try setting the normals manually. I'm betting the prob at least has something to do with knackered normals, and have got 50 quid riding on it!

...well, not really, but you get the point. :P


Rhyolite(Posted 2004) [#17]
Ok, busted my guts and got you some example code - but you owe me 50 big ones big10p, hehe!

Ok, I think I explained everything with comments in code. If I have done something completly stupid, please be gentle ;o)


;Texture 'banding' example by Rhyolite
;'Problem' occured on Pentium 4 with Radeon 9800 Pro, Blitz3D 1.87

;Occurs (for me) when splitting a single texture into very small parts
;by using fractional UV coordinates.
;Although the example uses 16x16 and 64x64 pixel textures this merely
;simulates a larger (256x256) texture being sub-divided into smaller parts.

;Both textured surfaces display correctly closer to the camera
;but as the distance increases they both begin to show white lines
;with the 'smaller' textured surface being worse.

;I 'believe' this is due to a loss of accuracy in the UV coordinates
;as distance increases?? Really not sure about this as I can not see
;why this should be the case - but can not think of anything else!!

;You can also tilt the camera to straight down then zoom out (move up)
;and get the same effect at higher distances.
;I believe this is due to the 'perceived' narrowing of the quads when
;viewed at an angle (maybe??).



;This is the offset of the UV's from edge of texture
;Two differnet green textures are created with different sized white borders
;but the same 'percentage' UV offset is applied to both
;However, in both cases the offset is always 'greater' than the white border
;and therefore the white border should never be visible.

factor = 8 ;you can also try other values eg. 4 and 16
offset# = 1.0 / factor

;A factor of 8 will give 1/8 = 0.125 UV offset from edge of texture
;Or another way of looking at it is 1/8*100 = 12.5% offset in either dimension


;Places please..
Graphics3D 800,600,16,0

;Light...
light = CreateLight(1)

;Camera..
cam = CreateCamera()
CameraRange(cam,0.8,350)
camx = 110 : camy = 115 : camz = 60
tilt = 1 : wire = 0


;Create two different sized textures
;Both are solid green with a one pixel white band at top and bottom
;Therefore the white band makes up a smaller percentage of the larger texture


;The small texture border is 1/16 or 6.25% of either dimension

texsml = CreateTexture(16,16)
SetBuffer TextureBuffer(texsml)
Color(0,128,0)
Rect(0,0,16,16,1) ;solid green
Color(255,255,255)
Rect(0,0,16,1,1) ;one white pixel along top
Rect(0,16,16,1,1) ;one white pixel along bottom
brushsml = CreateBrush()
BrushTexture(brushsml,texsml)


;The large texture border is 1/64 or 1.56% of either dimension

texlrg = CreateTexture(64,64)
SetBuffer TextureBuffer(texlrg)
Color(0,128,0)
Rect(0,0,64,64,1) ;solid green
Color(255,255,255)
Rect(0,0,64,1,1) ;one white pixel along top
Rect(0,64,64,1,1) ;one white pixel along bottom
brushlrg = CreateBrush()
BrushTexture(brushlrg,texlrg)


;Reset stuff
Color(255,255,255)
SetBuffer BackBuffer()


;Create two identical surfaces side by side
;but paint with different sized textures

meshsml = Create_Surface(offset)
PaintMesh(meshsml,brushsml)
PositionMesh(meshsml,0,0,0)

meshlrg = Create_Surface(offset)
PaintMesh(meshlrg,brushlrg)
PositionMesh(meshlrg,120,0,0)


;Action..!
While Not KeyHit(1)

PositionEntity(cam,camx,camy,camz)
RotateEntity(cam,180 - (tilt * 45),0,0)

WireFrame(wire)
RenderWorld()

Text 10,10,"Space = Wireframe"
Text 10,30,"Enter = Tilt"
Text 10,50,"Arrow keys scroll"
Text 10,70,"A/Z for up/down"

Text 10,100,"X: " + camx
Text 10,120,"Y: " + camy
Text 10,140,"Z: " + camz

Flip

If KeyHit(57) Then wire = Not wire
If KeyHit(28) Then tilt = Not tilt

If KeyDown(200) Then camy = camy - 1
If KeyDown(208) Then camy = camy + 1
If KeyDown(203) Then camx = camx - 1
If KeyDown(205) Then camx = camx + 1

If KeyDown(30) Then camz = camz + 1
If KeyDown(44) Then camz = camz - 1

Wend

End



Function Create_Surface(offset#)

mesh = CreateMesh()
surf = CreateSurface(mesh)

texstart# = offset
texend# = 1.0 - offset

For x = 0 To 100
For y = 0 To 100

v1 = AddVertex(surf, x, y, 0, texstart, texstart ) ;top left
v2 = AddVertex(surf, x, y+1, 0, texstart, texend ) ;bot left
v3 = AddVertex(surf, x+1, y, 0, texend, texstart ) ;top right
v4 = AddVertex(surf, x+1, y+1, 0, texend, texend ) ;bot right

VertexNormal(surf,v1,0,0,-1)
VertexNormal(surf,v2,0,0,-1)
VertexNormal(surf,v3,0,0,-1)
VertexNormal(surf,v4,0,0,-1)

t1 = AddTriangle(surf,v1,v3,v2)
t2 = AddTriangle(surf,v2,v3,v4)

Next
Next

;UpdateNormals(mesh)

Return mesh

End Function


podperson(Posted 2004) [#18]
One possibility is that the program you've saved the textures from has "helpfully" antialiased the edges of your texture map to some other (e.g. background) color. Photoshop has an annoying tendency to do this in some situations.

Take a close look at the edges of your textures to confirm this possibility OR try insetting your texture coordinates slightly and see if the problem goes away (e.g. use 0.05 and 0.95 instead of 0.0 and 1.0 for texture coordinates).


DJWoodgate(Posted 2004) [#19]

To clarify, both piccys are using a solid green texture


or not...

Well I suppose you had to keep the white bands you are drawing on your texture a secret to the last. Here's the rub. I do not see white lines on the textures at all in the example above, unless I enable mipmapping on the textures. Mipmapping is not enabled on created textures by default. (Yeah a little blitz quirk). With mipmapping enabled they are all too obvious. This is due to bilinear filtering on my card. As the texture size is mapped down the white bands get blended across a proportionally larger area. Your radeon will have filtering modes galor. Now if you still get the problem with mipmapping disabled it might be because your Radeon is optimised for performance rather than quality. You can probably modify a lot of these settings in the driver. Don't ask me which ones you need to change to fix this though.


Rhyolite(Posted 2004) [#20]
OMG !!!

@DJW: Yes, its down to the mipmapping on my gfx card! Geez, I suddenly have a whole lot of new stuff to learn about!!

Sorry about not mentioning the 'white bands'. I had originaly ruled out mipmapping/texture alignment as the effect still occured (on my gfx card with optimum quality settings) even after 'cleartexturefilters' and loading texture without mipmapping (I use loaded textures in my game, not created ones). Seems my Radeon9800pro must force mipmapping even when disabled in blitz?? However, when putting together the example code it became apparent I needed the 'white bands'. Apolgies again and thanks for being patient ;o)

Even when I have forced disabling of mipmapping on my gfx card, although my example code does not display banding on its default settings, if I increase the 'factor' to 16 (i.e. less offset from edge of texture) I once again get banding on the smaller (16x16) texture. This 'factor 16' also more closely represents the situation in my game code where I still have the 'banding' even after disabling mipmapping on gfx card! Grrrrr!!

Ok, off for a short break with the kids soon - but I have plenty to think about when I get back!! If anyone can post a few pointers to help me out they will be very much appreciated. I am currently confused about (but tbh not really spent any time looking into it yet) how I would go about 'forcing' disabling mipmapping on gfx card from within blitz or if there is some special tricks I can do when creating my textures. It seems obvious I am going to have to cram less textures into the same space and allow more 'blank' space (currently use 2 pixels either side of each texture, so thats a 4 pixel total seperation on a 256x256 png) between them though - but just how much space I dont know, especialy when some gfx cards are still going to force mipmapping.... Too many questions and no time to think about them....

Rhy Out!

PS - BIG THANKS to EVERYONE for helping me out on this :o)


big10p(Posted 2004) [#21]

Ok, busted my guts and got you some example code - but you owe me 50 big ones big10p, hehe!



Damn, wrong again! You're cheque's in the post. :)

...mind you, I did mention a possible mip-mapping problem in an earlier post. Can I have my money back? please? :P

[extremely fast, quiet voiceover]
Any mention of payment by the poster (big10p) is entirely fictional and does not represent a legally binding contract between the two parties concerned. By reading this copyrighted post you implicitly agree to pay the copyright holder (big10p) the sum of £50 per month for life. You're property may be at risk if you fail to keep up payments.
[extremely fast, quiet voiceover]