Scenekit some textures have a red hue
Asked Answered
A

3

8

I have a scene that has many objects, that all have different textures. For some reason 2 objects have a red hue to them, even though their textures have no red. You can still see the pattern in the texture, it just has different shades on red. (On the simulator the 2 objects have black and white textures and on device shades of red) Does anyone have any idea why this is happening? Other objects are working fine.

Alfilaria answered 15/10, 2016 at 11:18 Comment(0)
K
11

For material properties such as metalness and roughness SceneKit has support for 1 channel (grayscale) images. In order to save memory these images are kept as grayscale textures, they are not converted to RGB textures that have the same data in each channel.

When you use such an image for a "coloured" material property (such as diffuse), SceneKit will ask for the red, green and blue components of the sample but green and blue will always be 0 and the image will appear red.

One unfortunate solution consists in reworking your texture in an image editing app so that it's saved as RBG instead of grayscale.

You can also try shader modifiers to convert from grayscale to RGB:

_surface.diffuse.rgb = _surface.diffuse.rrr;

Edit

Starting iOS 11 you can use the textureComponents property when using single channel textures:

material.diffuse.textureComponents = .red
Kazmirci answered 15/10, 2016 at 11:49 Comment(5)
I don't think i understood. My texture is already RGB. And i just dragged the texture into the model just like i did to every object.Alfilaria
And with saying that my texture is RGB, i mean that it has colors.Alfilaria
I might have misunderstood what you meant by "On the simulator the 2 objects have black and white textures and on device shades of red)". Can you post pictures of the image and how they look once in the scene?Kazmirci
What i meant is that for example i have 1 dae 3d model in the scene. I also have a .png texture that has a blue and green pattern. In xcode i drag the .png texture to the object, and for some reason when i take a look at what it looks like in the simulator, the texture is black and white, even though it was green and blue. When i play it on the device (iphone) the texture has the pattern, but the colors are shades of red.Alfilaria
Hi @mnuages! Would you be able to help with a Scenekit/ARKit related problem?Dwelt
S
3

I've had the same problem with loading (grey) .png images as texture for a SCNMaterial.

On the simulator it rendered fine. But on the device all images with only black, white or grey, renders with a red base color.

let texture = SCNMaterial()
texture.diffuse.contents = UIImage(named: "rgb image with only gray")

I solved this problem by creating a new UIImage from the given UIImage:

let texture = SCNMaterial()
var newImage: UIImage?
if let textureImage = UIImage(named: "rgb image with only gray") {
    UIGraphicsBeginImageContext(textureImage.size)
    let width = textureImage.size.width
    let height = textureImage.size.height
    textureImage.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
    newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}
texture.diffuse.contents = newImage

HTH

Seve answered 28/12, 2017 at 20:53 Comment(1)
This works! I had the problem on some devices (iPhone X, where my pure white+alpha texture showed in red) and not on others (iPad Pro, where it looks correct) and this workaround fixed it. Clearly something is going on with the original image asset or its loading by UIImage, perhaps converting to a one-channel image instead of RGB somewhere and causing it to be interpreted as red only on some devices.Jilli
A
0

I had the same problem with an indexed-color png texture.
What I did for solving the problem was to convert the indexed-color png into the truecolor png.

It might be an NSImage bug. When I used CGImage to load the png file, it didn't cause any problem.

let url = URL(fileURLWithPath: pngFileName, relativeTo: directoryPath)

// let reddishImage = NSImage(contentsOf: url)

let cgDataProvider = CGDataProvider(url: url as CFURL)!
let cgImage = CGImage(pngDataProviderSource: cgDataProvider, decode: nil, shouldInterpolate: false, intent: CGColorRenderingIntent.defaultIntent)!
let imageSize = CGSize(width: cgImage.width, height: cgImage.height)
let correctImage = NSImage(cgImage: cgImage, size: imageSize)
Adnah answered 22/8, 2017 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.