objective-c - 如何从代码在 SceneKit 中设置基于物理的渲染?
问题描述
我想用 PBR 呈现一些场景。我创建了金属度和粗糙度纹理,并希望将其应用于网格。当我尝试在 Xcode 中执行此操作时 - 一切都很好。我可以将此模型添加到场景中,然后将此纹理添加到模型中。
但我想以编程方式进行。这是我的代码:
NSData *vertices = [[NSData alloc] initWithBytes:modelPly->vertices length:modelPly->vertexCount * 3 * sizeof(float)];
SCNGeometrySource *vertexSource = [SCNGeometrySource geometrySourceWithData:vertices
semantic:SCNGeometrySourceSemanticVertex
vectorCount:modelPly->vertexCount
floatComponents:YES
componentsPerVector:3
bytesPerComponent:sizeof(float)
dataOffset:0
dataStride:sizeof(float) * 3];
// Normal source
NSData *normals = [[NSData alloc] initWithBytes:modelPly->normals length:modelPly->vertexCount * 3 * sizeof(float)];
SCNGeometrySource *normalSource = [SCNGeometrySource geometrySourceWithData:normals
semantic:SCNGeometrySourceSemanticNormal
vectorCount:modelPly->vertexCount
floatComponents:YES
componentsPerVector:3
bytesPerComponent:sizeof(float)
dataOffset:0
dataStride:sizeof(float) * 3];
// Texture coordinates source
NSData *facesTextures = [[NSData alloc] initWithBytes:modelPly->texCoord length:modelPly->vertexCount * 2 * sizeof(float)];
SCNGeometrySource *texcoordSource = [SCNGeometrySource geometrySourceWithData:facesTextures
semantic:SCNGeometrySourceSemanticTexcoord
vectorCount:modelPly->vertexCount
floatComponents:YES
componentsPerVector:2
bytesPerComponent:sizeof(float)
dataOffset:0
dataStride:sizeof(float) * 2];
NSData *indicesData = [NSData dataWithBytes:modelPly->indices length:modelPly->indexCount * sizeof(uint) * 3];
SCNGeometryElement *elements = [SCNGeometryElement geometryElementWithData:indicesData
primitiveType:SCNGeometryPrimitiveTypeTriangles
primitiveCount:modelPly->indexCount
bytesPerIndex:sizeof(uint)];
SCNGeometry *geometry = [SCNGeometry geometryWithSources:@[vertexSource, normalSource, texcoordSource] elements:@[elements]];
MDLMesh *mesh = [MDLMesh meshWithSCNGeometry:geometry];
然后我正在尝试创建材料:
MDLPhysicallyPlausibleScatteringFunction *scatFunction = [MDLPhysicallyPlausibleScatteringFunction new];
MDLMaterial *mdlMaterial = [[MDLMaterial alloc] initWithName:@"material" scatteringFunction:scatFunction];
[mdlMaterial removeAllProperties];
MDLMaterialProperty *bcProperty = [[MDLMaterialProperty alloc] initWithName:@"BaseColor" semantic:MDLMaterialSemanticBaseColor URL:plyItem.textureFileURL];
MDLMaterialProperty *metalnessProperty = [[MDLMaterialProperty alloc] initWithName:@"metallic" semantic:MDLMaterialSemanticMetallic URL:[[NSBundle mainBundle] URLForResource:@"metalness" withExtension:@"jpg"]];
MDLMaterialProperty *roughnessProperty = [[MDLMaterialProperty alloc] initWithName:@"roughness" semantic:MDLMaterialSemanticRoughness URL:[[NSBundle mainBundle] URLForResource:@"roughness" withExtension:@"jpg"]];
[mdlMaterial setProperty:bcProperty];
[mdlMaterial setProperty:metalnessProperty];
[mdlMaterial setProperty:roughnessProperty];
并将其应用于我的几何图形:
SCNNode *node = [SCNNode nodeWithMDLObject:mesh];
SCNMaterial *material = [SCNMaterial materialWithMDLMaterial:mdlMaterial];
material.lightingModelName = SCNLightingModelPhysicallyBased;
node.geometry.firstMaterial = material;
如果我检查调试器mdlMaterial包含有关粗糙度和金属度的所有信息,但材料没有。怎么了?
解决方案
通过几何槽中的材质分配它:
// Swift 5.3
let sphereNode = SCNNode(geometry: SCNSphere(radius: 1))
let material = sphereNode.geometry?.firstMaterial
material?.roughness.contents = 0.72
material?.metalness.contents = 0.33
material?.lightingModel = .physicallyBased
// Objective-C
sphereNode.geometry.firstMaterial.roughness.contents = @0.72;
sphereNode.geometry.firstMaterial.metalness.contents = @0.33;
sphereNode.geometry.firstMaterial.lightingModelName = SCNLightingModelPhysicallyBased;
推荐阅读
- hadoop - 如何从配置单元中的日期中提取月份并按月份分组
- java - java.lang.NoClassDefFoundError:解析失败
- qt - 如何用新窗口显示每个 qDebug?
- mod-security2 - Modsec ruleRemoveTargetById 没有删除规则
- reactjs - 如何在 REACT 项目中使用 Scrollmagic 和 GSAP
- netlink - 来自内核 vport 的 upcall 和用户空间 upcall 线程之间的映射
- ms-access - Is Not Null 有效 - Is Null 无效
- r - 如何在句子中添加删除的空格?
- python - Pyserial 可以在命令行中从 arduino 读取数据,但 python 文件不能
- java - 求地图到地图转换的优化建议