我使用blender创建了一个3D对象,并将其导出为OBJ文件,然后我按照这个http://metalbyexample.com/modern-metal-1教程所示尝试使用Metal来渲染它。但我的一些3D部件丢失了,它们没有被正确地渲染出来。
以下是我的blender 3D对象:
以下是我在Metal中渲染的对象:
以下是我的blender文件:
https://gofile.io/?c=XfQYLK
我应该如何解决这个问题?
我已经成功地渲染了一些其他形状,比如矩形、圆形和星形。但是这个形状有问题。我没有改变创建形状的方式,也没有改变从blender导出的方式。即使我以同样的方式进行了所有操作,问题仍然存在。
以下是我加载OBJ文件的方法:
以下是我的blender 3D对象:
![enter image description here](https://istack.dev59.com/b5OMW.webp)
![enter image description here](https://istack.dev59.com/n0Wht.webp)
我已经成功地渲染了一些其他形状,比如矩形、圆形和星形。但是这个形状有问题。我没有改变创建形状的方式,也没有改变从blender导出的方式。即使我以同样的方式进行了所有操作,问题仍然存在。
以下是我加载OBJ文件的方法:
private var vertexDescriptor: MTLVertexDescriptor!
private var meshes: [MTKMesh] = []
private func loadResource() {
let modelUrl = Bundle.main.url(forResource: self.meshName, withExtension: "obj")
let vertexDescriptor = MDLVertexDescriptor()
vertexDescriptor.attributes[0] = MDLVertexAttribute(name: MDLVertexAttributePosition, format: .float3, offset: 0, bufferIndex: 0)
vertexDescriptor.attributes[1] = MDLVertexAttribute(name: MDLVertexAttributeNormal, format: .float3, offset: MemoryLayout<Float>.size * 3, bufferIndex: 0)
vertexDescriptor.attributes[2] = MDLVertexAttribute(name: MDLVertexAttributeTextureCoordinate, format: .float2, offset: MemoryLayout<Float>.size * 6, bufferIndex: 0)
vertexDescriptor.layouts[0] = MDLVertexBufferLayout(stride: MemoryLayout<Float>.size * 8)
self.vertexDescriptor = MTKMetalVertexDescriptorFromModelIO(vertexDescriptor)
let bufferAllocator = MTKMeshBufferAllocator(device: self.device)
let asset = MDLAsset(url: modelUrl, vertexDescriptor: vertexDescriptor, bufferAllocator: bufferAllocator)
(_, meshes) = try! MTKMesh.newMeshes(asset: asset, device: device)
}
这是我的顶点和片段着色器代码:
struct VertexOut {
float4 position [[position]];
float4 eyeNormal;
float4 eyePosition;
float2 texCoords;
};
vertex VertexOut vertex_3d(VertexIn vertexIn [[stage_in]])
{
VertexOut vertexOut;
vertexOut.position = float4(vertexIn.position, 1);
vertexOut.eyeNormal = float4(vertexIn.normal, 1);
vertexOut.eyePosition = float4(vertexIn.position, 1);
vertexOut.texCoords = vertexIn.texCoords;
return vertexOut;
}
fragment float4 fragment_3d(VertexOut fragmentIn [[stage_in]]) {
return float4(0.33, 0.53, 0.25, 0.5);
}
这是我的 CommandEncoder:
func render(commandEncoder: MTLRenderCommandEncoder) {
commandEncoder.setRenderPipelineState(self.renderPipelineState)
let mesh = meshes[0]
let vertexBuffer = mesh.vertexBuffers.first!
commandEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, index: 0)
let indexBuffer = mesh.submeshes[0].indexBuffer
commandEncoder.drawIndexedPrimitives(type: mesh.submeshes[0].primitiveType,
indexCount: mesh.submeshes[0].indexCount,
indexType: mesh.submeshes[0].indexType,
indexBuffer: indexBuffer.buffer,
indexBufferOffset: indexBuffer.offset)
commandEncoder.endEncoding()
}
在可绘制对象上进行呈现处理是在不同的位置处理的。
我应该如何使用Metal正确渲染我的3D对象?
setCullMode(.none)
?如果是这样,那么您的模型导出器正在导出具有不一致面向的三角形。您可以通过在建模软件中选择有问题的三角形并将其“翻转”来修复它。 - warrenmsetCullMode(.none)
,但它没有起作用。因为当我从blender导出OBJ文件时,我没有对所有面进行三角剖分。Metal处理了三角剖分。所以这就引起了问题。在我启用从blender导出时的三角剖分后,它就正常工作了。在我的情况下,还有另一个问题,因为三角剖分会改变3D对象的顶点顺序。但是它显示得很好。所以你的建议很好。你能否将“启用三角剖分导出”添加到你的评论中,并将其发布为答案。这样我就可以标记它了。谢谢。 - Nilupul Sandeepa