1

I'm trying to achieve with SceneKit the drawing of a simple set of 4 boxes which are next to each other with textures applied on each of them (Minecraft style) :

enter image description here

The texture are like this (png files) :

enter image description here

I would like to avoid the small blue lines between the boxes (which are not in the textures) but whatever setup I try, these artefacts stay.

Any idea how to avoid them ?

Below the setup of the material in the scenekit editor (exactly the same for each box, except the diffuse part which is refering to the right texture file)

enter image description here

enter image description here

The issue in the scenekit editor is also appearing in the app running on the device.

What is strange is that if I just do a full black (or whatever color) texture (with or without anything inside), these artefacts do not appear, example below :

enter image description here

Jonah Begood
  • 317
  • 2
  • 14
  • 1
    It looks like the texture coordinates on those edges are going slightly under 0.0 or over 1.0, which invokes whatever sampling behavior is configured via the `wrapS` and `wrapT` properties of the material properties. You could try setting the wrap modes for each axis of each material property of each material of each face of each cube to `.clamp`, but since that's the default, it may not have an effect, nor does it actually fix the lack of precision in the texture coordinates. I don't know how to configure these properties with the SceneKit editor in Xcode, but it may be possible to do so. – warrenm Nov 02 '18 at 18:01
  • Having reproduced this myself, I can confirm that the wrapping behavior of the texture sampler is the culprit here. It seems that materials loaded from an .scn file actually have a default wrap mode of `.repeat` rather than `.clamp`. Programmatically setting them to `.clamp` fixed the issue in my test. – warrenm Nov 02 '18 at 18:27

2 Answers2

1

It seems you need to programmatically set the wrap modes of each material property in order to avoid this "wrap-around" behavior. Configure each material property to which you've assigned a texture such that its wrapS and wrapT properties are .clamp, rather than .repeat, which appears to be the default when loading materials from an .scn file.

let nodes = scene.rootNode.childNodes // get a list of relevant nodes
for node in nodes {
    guard let materials = node.geometry?.materials else { continue }
    for material in materials {
        material.diffuse.wrapS = .clamp
        material.diffuse.wrapT = .clamp
        // ...confgure other material properties as necessary...
    }
}
warrenm
  • 31,094
  • 6
  • 92
  • 116
  • 1
    It is indeed the right solution. You have also access to these properties in the xcode editor when you extend the diffuse property (or any other when a texture file has been selected instead of a color). Thanks ! – Jonah Begood Nov 03 '18 at 09:51
  • 1
    Note that this can also be done in the SceneKit scene editor if you prefer to have everything configured in the scene file. In your screenshot click on the disclosure triangle on the left of the "Diffuse" material property. There you'll be able ton configure wrapping, mipmapping, UV transforms etc. – mnuages Nov 03 '18 at 13:30
  • Nice, I didn't realize the options behind the disclosure triangle on material properties change based on the contents type, but that makes sense. – warrenm Nov 04 '18 at 17:07
1

When I zoom in on your texture png files, it actually looks like there is a thin blue border on all sides: enter image description here

Have you verified that these lines aren't there on your actual texture files, even a couple pixels wide?

If you're sure your original textures are perfect, it is likely a problem with your texture wrap settings, as warrenm commented. i.e. the SCNWrapMode assigned to material.diffuse.wrapS and material.diffuse.wrapT is set to SCNWrapMode.repeat. I would set your wrap mode to either SCNWrapMode.clamp. I'm not sure how to edit this in the Xcode editor, but programmatically it would look something like this, if your texture is in the Assets.xcassets folder:

...
material.diffuse.contents = UIImage(named: "your_texture")!
material.diffuse.wrapS = SCNWrapMode.clamp
material.diffuse.wrapT = SCNWrapMode.clamp
...

Or alternatively, you could use SCNWrapMode.clampToBorder and set the material's borderColor property to black.

But I would really look at your original png files to make sure that blue border doesn't exist in the texture itself. Good luck!

Michael
  • 291
  • 2
  • 6