我目前正在尝试在场景套件中设置一个旋转球.我创造了球,并为它应用了纹理.
ballMaterial.diffuse.contents = UIImage(named: ballTexture) ballMaterial.doubleSided = true ballGeometry.materials = [ballMaterial]
目前的ballTexture是一个半透明的纹理,因为我希望看到背面滚动.
然而,我得到一些奇怪的剔除,即使doubleSided属性设置为true,也只显示一半背面多边形.
任何帮助将不胜感激,谢谢.
发生这种情况是因为透明度的影响取决于绘制顺序.SceneKit不知道在面向正面之前绘制球体的背面多边形.(实际上,如果没有为每个帧重新组织GPU上的顶点缓冲区,它就无法真正做到这一点,这将对渲染性能产生巨大的影响.)
它的顶点布局SCNSphere
使其像地球上的纬度/长度网格一样设置:三角形沿着从0°到360°的子午线顺序渲染,因此取决于球体相对于相机的方向,一些球体远端的面将在较近的面之前呈现.
要解决此问题,您需要直接或通过深度缓冲区强制渲染顺序.这是一种方法,使用内部表面的单独材料来说明差异.
// add two balls, one a child of the other let node = SCNNode(geometry: SCNSphere(radius: 1)) let node2 = SCNNode(geometry: SCNSphere(radius: 1)) scene.rootNode.addChildNode(node) node.addChildNode(node2) // cull back-facing polygons on the first ball // so we only see the outside let mat1 = node.geometry!.firstMaterial! mat1.cullMode = .Back mat1.transparent.contents = bwCheckers // my "bwCheckers" uses black for transparent, white for opaque mat1.transparencyMode = .RGBZero // cull front-facing polygons on the second ball // so we only see the inside let mat2 = node2.geometry!.firstMaterial! mat2.cullMode = .Front mat2.diffuse.contents = rgCheckers // sphere normals face outward, so to make the inside respond // to lighting, we need to invert them let shader = "_geometry.normal *= -1.0;" mat2.shaderModifiers = [SCNShaderModifierEntryPointGeometry: shader]
(最后的着色器修改器位不是必需的 - 它只是使内部材质得到漫反射着色.您也可以使用不涉及法线或光照的材质属性,例如emission
,取决于您想要的外观. )
您也可以通过禁用使用带有双面材质的单个节点来执行此操作writesToDepthBuffer
,但这也可能导致与场景内容的其他部分进行不良交互 - renderingOrder
在这种情况下您可能还需要处理.