使用 GoogleVR 和 SceneKit 时纹理显示不正确
Textures not displaying correctly when using GoogleVR and SceneKit
我正在试验 Google-VR iOS SDK。我有一个非常简单的 SceneKit 场景,其中包含一个纹理对象。这是使用 SCNRenderer 在 GVRCardboardViewDelegate drawEye 方法中呈现的。当 GVRCardboardView 上的 vrModeEnabled 设置为 false 时,对象会正确渲染,但当设置为 true 时,纹理不会正确应用。见下图。
经过更多调查,我发现从 SceneKit .scn 文件加载包含纹理对象的场景效果很好。使用 ModelIO 将 OBJ 文件(以及它的 .mtl 文件和 jpg 纹理)加载到 SCNNode 时会出现问题,如下所示:
let stageURL = NSBundle.mainBundle().URLForResource("newStage", withExtension: "obj", subdirectory: "Art.scnassets")
let stageAsset = MDLAsset(URL: stageURL)
let stageObject = asset.objectAtIndex(0)
let stage = SCNNode(MDLObject: stageObject)
scene.addChildNode(stage)
这似乎是 OpenGL 状态问题(也可能是 ModelIO 中的错误),但我一直无法找到解决方案或解决方法。有什么建议吗?
Example of texture appearance. Top vrModeEnabled = false, bottom vrModeEnabled = true
更新:实际的解决方案很简单。由于某些未知原因,纹理变换被搞乱了。在问题中的代码中添加以下行,使纹理按预期显示。
var transformForTexture = SCNMatrix4MakeScale(1, -1, 1);
transformForTexture = SCNMatrix4Translate(transformForTexture, 0, 1, 0)
stage.geometry?.firstMaterial?.diffuse.contentsTransform = transformForTexture
原始解决方法:
使用 ModelIO 加载 OBJ 文件将隐式使用关联的 material 描述文件(与 OBJ 文件具有相同的文件名,但扩展名为 .mtl)来提供纹理和 material几何的属性。删除 material 文件并加载纹理明确地解决了这个问题。
let stageURL = NSBundle.mainBundle().URLForResource("newStage", withExtension: "obj", subdirectory: "Art.scnassets")
let stageAsset = MDLAsset(URL: stageURL)
let stageObject = asset.objectAtIndex(0)
let stage = SCNNode(MDLObject: stageObject)
let texture = SCNMaterial()
texture.diffuse.contents = UIImage(named: "Art.scnassets/stage.jpg")
stage.geometry?.firstMaterial = texture
scene.addChildNode(stage)
这不是一个理想的解决方案,但在我有时间调试确切原因之前,这是一个足够的解决方法。
请注意,在得出此解决方案之前,我尝试更新节点漫反射 material 上 SCNMaterialProperty 中的纹理属性,但这没有任何效果。
我正在试验 Google-VR iOS SDK。我有一个非常简单的 SceneKit 场景,其中包含一个纹理对象。这是使用 SCNRenderer 在 GVRCardboardViewDelegate drawEye 方法中呈现的。当 GVRCardboardView 上的 vrModeEnabled 设置为 false 时,对象会正确渲染,但当设置为 true 时,纹理不会正确应用。见下图。
经过更多调查,我发现从 SceneKit .scn 文件加载包含纹理对象的场景效果很好。使用 ModelIO 将 OBJ 文件(以及它的 .mtl 文件和 jpg 纹理)加载到 SCNNode 时会出现问题,如下所示:
let stageURL = NSBundle.mainBundle().URLForResource("newStage", withExtension: "obj", subdirectory: "Art.scnassets")
let stageAsset = MDLAsset(URL: stageURL)
let stageObject = asset.objectAtIndex(0)
let stage = SCNNode(MDLObject: stageObject)
scene.addChildNode(stage)
这似乎是 OpenGL 状态问题(也可能是 ModelIO 中的错误),但我一直无法找到解决方案或解决方法。有什么建议吗?
Example of texture appearance. Top vrModeEnabled = false, bottom vrModeEnabled = true
更新:实际的解决方案很简单。由于某些未知原因,纹理变换被搞乱了。在问题中的代码中添加以下行,使纹理按预期显示。
var transformForTexture = SCNMatrix4MakeScale(1, -1, 1);
transformForTexture = SCNMatrix4Translate(transformForTexture, 0, 1, 0)
stage.geometry?.firstMaterial?.diffuse.contentsTransform = transformForTexture
原始解决方法:
使用 ModelIO 加载 OBJ 文件将隐式使用关联的 material 描述文件(与 OBJ 文件具有相同的文件名,但扩展名为 .mtl)来提供纹理和 material几何的属性。删除 material 文件并加载纹理明确地解决了这个问题。
let stageURL = NSBundle.mainBundle().URLForResource("newStage", withExtension: "obj", subdirectory: "Art.scnassets")
let stageAsset = MDLAsset(URL: stageURL)
let stageObject = asset.objectAtIndex(0)
let stage = SCNNode(MDLObject: stageObject)
let texture = SCNMaterial()
texture.diffuse.contents = UIImage(named: "Art.scnassets/stage.jpg")
stage.geometry?.firstMaterial = texture
scene.addChildNode(stage)
这不是一个理想的解决方案,但在我有时间调试确切原因之前,这是一个足够的解决方法。
请注意,在得出此解决方案之前,我尝试更新节点漫反射 material 上 SCNMaterialProperty 中的纹理属性,但这没有任何效果。