I read somewhere that three.js uses an 8-bit depth buffer by default, but I can't find any information on increasing this precision. I'm using a linear depth buffer and my camera's near and far planes are reasonable for my scene. However, my scene appears like shown (with lines between many triangles or objects that are adjacent to one another). In regular WebGL, I would fix this by increasing the depth buffer precision. I'm using a far plane of 8000.
If there's a different way to fix this that I'm overlooking, please say so.
#How do I use a higher precision depth buffer?
154 messages · Page 1 of 1 (latest)
Are you using any post-processing or EffectComposer?
This might be an option:
https://www.reddit.com/r/threejs/comments/mm7u2g/zfighting_lines_on_a_plane/gtqhp62/
That didn't seem to do much. I'm not drawing lines or anything.
That doesn't look like a depth buffer precision issue to me.
Also I've never heard of an 8 bit depth buffer...
depth buffer is usually 32 bits by default, sometimes 16 bit on mobile..
The crack shown in your picture looks like the vertices/edges not being lined up exactly.
iirc threejs doesn't "chose" a depth buffer format at all.. it uses what the hardware/driver/chrome feels is appropriate for your platform.
You can create your own rendertarget and depth buffer manually, but then you'll have to transfer it to the screen when you're done rendering to it.
I'm absolutely certain they're aligned because, when constructing the mesh, I construct the 8 points and reuse them in the position attribute.
Okay, apologies. I'm probably I'm wrong about how that works, although I could have sworn you have gl.DEPTH_ATTATCHMENT16, gl.DEPTH_ATTATCHMENT24, etc. Maybe that doesn't work how I thought it did.
are your points on integer boundaries?
I'm not sure. Are you asking if they're round numbers?
I'm using Float32BufferAttribute for the attribute if that means something
yeah.. if they are on integer boundaries, then I would expect them to be aligned.. if you're computing the position in code.. then I wouldn't be so sure that they are exactly identical..
Also.. what is shown in your picture is what's called a "T-junction" in that the line in question shares 2 axes that are the same on the edge, but on one block, the edge extends higher.... so the intersection forms a T shape.. instead of cross shape like you would get with minecraft cubes...
t-junctions can cause cracks to appear...
but.. even then, with an orthographic camera like you appear to be using, i'd still expect correct rendering
can you verify that the vertices really are identical in the X/Z plane or whatever ground axes you're using ?
if there was an issue with depth buffer precision.. it probably wouldn't manifest as a hole between pixels.. it would show as things flickering in front of/behind.
but i could be wrong 🙂
t-junctions generally can be problematic tho.
(but also.. it doesn't look like a T junction crack issue to me in your thing, because they usually look .. crappier? more uneven.. like skinny at the bottom and wideer in the middle of the crack..
these columns are all in the same BufferGeometry yeah?
Sorry for taking a little while to respond. I printed the vertecies and there are definitely duplicated numbers; the only unique items are 0, 128, and 256 (the cubes are twice as tall as they are wide, so it makes sense).
Yes, you're right about me using an orthographic camera.
To clarify: this happens on every face pointing a certain direction.
are the cubes separate meshes?
i see lots of cracks between tiles in that screenshot
if the columns are in separate meshes.. they each get transformed by a different matrix, and that can cause imprecision during transformation..
Yeah, they are different meshes in an instanced mesh (with one instanced mesh for each tile type). That still doesn't explain the gaps between triangles, though, right?
it doesn't explain the black gaps on an individual tile, but could eplain the cracks between neighboring tiles..
Makes sense, although I had this exact same thing set up in WebGL previously and it worked fine (I'm sure three.js handles things differently, of course, but I know that this setup works.)
I had the same issue in WebGL until I started rendering depth into a gl.DEPTH_COMPONENT24 texture
Which is where my original assumption came from
Yeah
to test your theory you could create a new rendertarget and set up the depth buffer how you want...
but then you'd have to copy the offscreen rendertarget to the current target.
also.. do you have antialias: true on your renderer constructor?
Yeah, antialias is set to true
ok
so yeah.. you could test your theory.. but I'd be pretty surprised if that was the issue
I can try. I'm not sure how to do this in three.js, though; is there a simple way to configure the attachments manually?
Yeah, it doesn't really make as much sense after thinking through it a lot now.
from chatgpt:
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBAFormat,
depthBuffer: true
};
var renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, options);
renderTarget.depthTexture = new THREE.DepthTexture();
but.. that all said..
I have gone through this same stuff many times before..
Basically if you have 2 meshes.. transformed by 2 different matrices.. and there are any non-integer fractional components in the matrices.. you'lll get alignment/precision issues
but.. the fact that it "works" in webGL is.. odd..
I saw THREE.DepthTexture but I didn't find a way to specify the precision. I don't really know how all that works, though, t be honest.
ya. its a bit hairy. that's why i asked chatGPT.. it's pretty rare to have to create a depth target in everyday use
for depth texture:
That makes sense. Is it possible the transformations could break the vertex positions too?
I mean... they shouldn't since the inputs are identical
less so.. because 2 identical vertices transformed by the Same matrix will result in the same output
But I don't really know what else could be happening
yup.. which is why i hilighted the "vertex issue" in that screenshot
presumably those planes are in the same mesh, but we;re still seeing black cracks betw. them.. so the "shared" verts are not identical.
You can solve that part by changing the math you use to generate those chunks.. OR using an index instead and sharing the corner vertices via the index.
im guessing rn you're using non-indexed geometry?
and writing one triangle at a time?
(which might be a requirement if you're texturing each side differently)
I didn't think I could use indices with texture uvs because the uvs aren't shared per vertex. I tried at first but didn't think it would work.
Yeah
yup that's correct.
but you can still make sure the vertices are identical xyz
another question.. are the colors coming from texture? maybe the seam is some kind of texel leak?
like.. u have the UV right on the edge of a pixel in your texture.. and you're getting bleeding from the next texel over
Ohh, that's a good point. I'm using NearestFilter on the minFilter and magFilter on my texture but that's possible too.
yeah.. curious if the cracks go away if you use a solid gray texture on everything
that would indicate that hte UVs are involved
That was a great idea! It looks like the UVs must be the problem.
nice! and the light fringe on the shadow. that's prolly just a separate shadow issue
The shadows seem weird, although that's probably actually matrix issues.
Oh lol
Yeah
shadows have their own set of problems 🙂
adjusting the bias on the shadow lights can fix that
Higher or lower?
it depends.. but you want to experiment with values between...
-.0001 and + .0001 to start
the smaller the better.. too big. and shadows start to float above the ground..
too small, and you get shadow acne
Yeah, I tried both of those and it didn't seem to fix it
three uses 24 bit depth or even 32 by default
also.. check to make sure the shadow.camera.near and .far are not super small or gigantic
if you want absolute highest depth buffer precision, use a render target with a floattype depth texture attached
I think we identified that it's a UV issue...
i was just answering the og question
-0.0002 seems to have done the trick but now there's a large gap between the objects and shadows. I assume I can't have both?
Ya its a classical tradeoff with shadow mapping..
but.. so heres one other thing...
i suspect that your cubes are occupying a large numerical space in the scene...
Yeah, I made sure it just barely covers the scene
you might want to tweak scale
wait, how are you texturing your cubes?
I'm using UVs and a texture. The last few pictures were without textures so I could see the shadows better.
he discussed earlier in the thread.. it does look like the OG artifact was possibly a uv mapping issue.
it could be an abrupt uv seam
Or a mipmap error
Okay. Just curious: how come things change at a larger scale?
because you're moving the bulk of the numeric precision higher in the float range.. I don't 100% understand it...
It doesn't look like a mipmap error; I get the same results when texture.generateMipmaps is false.
but like.. a 256.00 wide cube might have problems that a 1.0 wide cube doesn't
Okay. So do you suggest I just reduce every number in my project or is there an easier way to go about it?
scene.scale.set(.01,.01,.01) might yield insight
makes sense
but.. i feel like.. we're narrowing down that it is a UV issue
Would a large scale break any UV things? I can't imagine it would.
try subdividing your cubes maybe
it shouldn't.
i don't think u need to subdivide your cubes.
minecraft doesnt 🙂
unless they are like SUPER tall or something in a way were not seeing
I made a custom loader that loads OptiFine's JPM files to a BufferGeometry. Is there an easy way to add a subdivided cube to a bufferGeometry?
No, they are pretty much what you see; the height is twice the width.
yeah. that should be fine
but.. a good rule of thumb is like 1 unit = 1 meter...
so.. the "natural" size for a cube could reasonably be 1
Okay... Right now I'm at the scale of about 100 units = 1 meter so my scale is definitely way too high. It won't be too bad to scale everything down.
yaaaa
but.. only if you need to!
bc .. we've kinda narrowed into this being caused by UVs
Nope it shouldn't.
Okay
BUT it will affect how many cubes you can render off in the distance.. how big your camera frustum has to be.. how much yuou have to adjust your lights to cast light the proper distance etc.
its good to ground things in something close to real world units
Yeah, that makes sense. I'll make that change once I figure out the UVs.
how big your shadow light frustum needs to be.. thus affecting how the depth precision is used etc.
for uv's you can try pulling them inwards by half a texel width...
also.. there are variations on GPU and driver setup.. some drivers/gpus have a slight different default sampling centerpoint for texels
Is using THREE.NearestFilter an issue? In WebGL (sorry to relate everything to WebGL but that's the only thing I have experience in) I would just set a texture's min and mag to gl.NEAREST so I assume it's identical.
no that's good.
without that you will Definitely get more bleeding on edge texels
if you want filtering.. you have to add a skirt to all your tiles in the texture so the filtering has a proper color to filter too.. and the higher the filtering you have set, the bigger that skirt has to be
see the with/without padding gif there
but if you have nearestFilter it shouldnt be unsolvable without padding
you might have to adjust your UVs by a half texel width inward
Makes sense. I like the style without blending either way so I think I'm good.
so instead of 0 to 1.. it would be ( (1/ texturewidth)/2) and 1-(( (1/ texturewidth)/2) )
Hmm, I'm pretty sure I did it correctly and it's causing some weird artifacts.
It works on some faces but not others?
WEIRD
My UV code is a mess so it might just be wrong in some other way
All my UV stuff is probably wrong, lol. I'll rewrite it and hopefully it works.
Is there a good template for creating a cube's uvs and positions from given face texcoords? I've been messing with the numbers for far too long now...