SceneKit 在同一几何体上使用两种具有不同纹理坐标的材质
SceneKit using 2 materials with different Texture Coordinates on same geometry
我尝试在同一几何体上应用两个不同的 material。
一个 material 用于 tiling,第二个用于 Ambient Occlusion 和其他效果。
我以 DAE 格式导出带有 2 UVSet(没关系)的模型。当我尝试应用第二个 material 时,它从未出现。在第二个 material 上,我尝试应用 blendMode、transparencyMode、png 文件等。没有任何效果:((
如果我在第一个 material 上更改 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 文件...
如果您有想法、建议、解决方案,那就太好了。
谢谢
最后,我找到了 shaderModifiers 的解决方案。
可以在不同的 slots(环境光、漫反射、镜面反射等)上分配不同的 mappingChannel。
来自 Apple 的参考文档: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
我尝试在同一几何体上应用两个不同的 material。
一个 material 用于 tiling,第二个用于 Ambient Occlusion 和其他效果。
我以 DAE 格式导出带有 2 UVSet(没关系)的模型。当我尝试应用第二个 material 时,它从未出现。在第二个 material 上,我尝试应用 blendMode、transparencyMode、png 文件等。没有任何效果:(( 如果我在第一个 material 上更改 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 文件... 如果您有想法、建议、解决方案,那就太好了。
谢谢
最后,我找到了 shaderModifiers 的解决方案。
可以在不同的 slots(环境光、漫反射、镜面反射等)上分配不同的 mappingChannel。 来自 Apple 的参考文档: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