Как настроить физический рендеринг в SceneKit из кода? - PullRequest
0 голосов
/ 01 июня 2018

Я хочу представить какую-нибудь сцену с PBR.Я создал текстуры по металлу и шероховатости и хочу применить их к сетке.Когда я пытаюсь сделать это в Xcode - все нормально.Я могу добавить эту модель на сцену, а затем добавить эти текстуры к модели.in 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 содержит всю информацию о шероховатости и металличности, а материал - нет.Что не так?

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Назначьте это через материал в слотах Геометрии:

// Swift
let material = sphereNode.geometry?.firstMaterial
material?.roughness.contents = NSNumber(value: 0.72)
material?.metalness.contents = NSNumber(value: 0.33)
material?.lightingModelName = SCNLightingModelPhysicallyBased

// Obj-C
sphereNode.geometry.firstMaterial.roughness.contents = @0.72;
sphereNode.geometry.firstMaterial.metalness.contents = @0.33;
sphereNode.geometry.firstMaterial.lightingModelName = SCNLightingModelPhysicallyBased;
0 голосов
/ 01 июня 2018

Удалось сделать это только через SCNGeometry.

SCNNode *node = [SCNNode nodeWithGeometry:geometry];
node.geometry.firstMaterial.diffuse.contents = plyItem.textureFileURL;
node.geometry.firstMaterial.metalness.contents = [[[NSBundle mainBundle] URLForResource:@"metalness" withExtension:@"jpg"] path];
node.geometry.firstMaterial.roughness.contents = [[[NSBundle mainBundle] URLForResource:@"roughness" withExtension:@"jpg"] path];
node.geometry.firstMaterial.lightingModelName = SCNLightingModelPhysicallyBased;
...