SceneKit在相同的几何体上使用具有不同纹理坐标的2种材质

时间:2019-04-16 14:52:53

标签: swift scenekit texture-mapping

我尝试在相同的几何图形上应用两种不同的材料。 一种用于平铺的材料,另一种用于环境光遮盖和其他效果的材料。 example

我以 DAE 格式导出具有2个 UVSet (可以)的模型。当我尝试应用第二种材料时,它永远不会出现。在第二种材料上,我尝试应用blendMode,transparentMode,png文件等。没有任何效果:(( 如果我在第一种材料上更改了mappingChannel,则映射就可以了!

let mat1 = SCNMaterial()
mat1.name = "Mat1"
mat1.diffuse.mappingChannel = 0
mat1.diffuse.contents = UIImage(named: "somePNGFile.png")


let mat2 = SCNMaterial()
mat2.name = "Mat2"
mat2.diffuse.mappingChannel = 1
mat2.diffuse.contents = UIImage(named: "otherPNGFile.png")

cube.geometry!.materials = [mat1, mat2]

这是我的 SCN文件https://drive.google.com/open?id=1ddbE815hlS0VbKPsbwcJoS9cL8hOf6Mt

我的代码有什么问题?也许是3D文件... 如果您有想法,建议或解决方案,那就太好了。

谢谢

1 个答案:

答案 0 :(得分:0)

最后,我找到了带有 shaderModifiers 的解决方案。

可以在不同的插槽(环境,漫反射,镜面反射等)上分配不同的 mappingChannel 。 苹果公司的参考文档:https://developer.apple.com/documentation/scenekit/scnshadermodifierentrypointsurface?language=objc

这是我的代码:

    var mat:SCNMaterial!
    var model:SCNReferenceNode!

    override init() {
        super.init()

        // INIT
        initModel()
        initShader()
        assignTextures()
    }

    func initModel() {
        let url = Bundle.main.url(forResource: "Test_MixMaterials", withExtension: "scn", subdirectory: "Test.scnassets")!
        model = SCNReferenceNode(url: url)!
        model.load()
        self.addChildNode(model)

        if let cube = model.childNode(withName: "pCube1", recursively: true) {
            mat = SCNMaterial()
            // Define mapping Channel 0 on diffuse slot
            mat.diffuse.mappingChannel = 0
            // Define mapping Channel 1 on ambient slot
            mat.ambient.mappingChannel = 1
            // Assign material
            cube.geometry!.firstMaterial = mat
        }
    }

    func initShader() {
        let shader = """

        // Samplers 2D.
        uniform sampler2D texture_UV1;
        uniform sampler2D texture_UV2;

        // Directives
        #pragma transparent
        #pragma body

        // Source Diffuse  ------------------------------------------------------------------------------------------------------------
        vec4 source = texture2D(texture_UV1, _surface.diffuseTexcoord);

        // Destination Diffuse --------------------------------------------------------------------------------------------------------
        vec4 dest = texture2D(texture_UV2, _surface.ambientTexcoord);

        // MULTIPLY Diffuses ---------------------------------------------------------------------------------------------------------------
        _surface.diffuse = source * dest;
        """

        mat.shaderModifiers = [
            .surface:shader
        ]
    }

    func assignTextures() {
        let setTexture_1 = SCNMaterialProperty(contents: UIImage(named: "someImage.png")!)
        let setTexture_2 = SCNMaterialProperty(contents: UIImage(named: "otherImage.png")!)

        mat.setValue(setTexture_1, forKey: "texture_UV1")
        mat.setValue(setTexture_2, forKey: "texture_UV2")
    }

那行得通...

如果要测试,这是我使用的模型https://drive.google.com/open?id=1ddbE815hlS0VbKPsbwcJoS9cL8hOf6Mt