gpt4 book ai didi

ios - 如何使用 Metal IOS 正确渲染 3d 模型?

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:58:10 24 4
gpt4 key购买 nike

我使用 blender 创建了一个 3D 对象并将其导出为 OBJ 文件,然后我尝试按照此 http://metalbyexample.com/modern-metal-1 使用 Metal 渲染它教程。但是我的一些 3D 对象部分丢失了。它们未正确呈现。

这是我在 blender 中的 3D 对象:- enter image description here

这是我在 Metal 中渲染的对象:- enter image description here

这是我的 blender 文件:- https://gofile.io/?c=XfQYLK

我应该如何解决这个问题?

我已经成功渲染了一些其他形状,例如矩形、圆形、星形。但问题在于这种形状。我没有改变我创建形状的方式,也没有改变它从 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 对象?

最佳答案

我制作了这个公开 repo :https://github.com/danielrosero/ios-touchingMetal ,我认为这是使用 Metal 进行 3d 渲染的一个很好的起点,具有纹理和计算功能。

你应该只更改里面的模型,检查 Renderer.swift init(view: MTKView) 方法。

//       Create the MTLTextureLoader options that we need according to each model case. Some of them are flipped, and so on.


let textureLoaderOptionsWithFlip: [MTKTextureLoader.Option : Any] = [.generateMipmaps : true, .SRGB : true, .origin : MTKTextureLoader.Origin.bottomLeft]

let textureLoaderOptionsWithoutFlip: [MTKTextureLoader.Option : Any] = [.generateMipmaps : true, .SRGB : true]



// ****




// Initializing the models, set their position, scale and do a rotation transformation

// Cat model

cat = Model(name: "cat",vertexDescriptor: vertexDescriptor,textureFile: "cat.tga", textureLoaderOptions: textureLoaderOptionsWithFlip)
cat.transform.position = [-1, -0.5, 1.5]
cat.transform.scale = 0.08

cat.transform.rotation = vector_float3(0,radians(fromDegrees: 180),0)


// ****


// Dog model

dog = Model(name: "dog",vertexDescriptor: vertexDescriptor,textureFile: "dog.tga", textureLoaderOptions: textureLoaderOptionsWithFlip)
dog.transform.position = [1, -0.5, 1.5]
dog.transform.scale = 0.018

dog.transform.rotation = vector_float3(0,radians(fromDegrees: 180),0)


// ****

这是我在实现中导入模型的方式,检查 Model.swift

//
// Model.swift
// touchingMetal
//
// Created by Daniel Rosero on 1/8/20.
// Copyright © 2020 Daniel Rosero. All rights reserved.
//
import Foundation
import MetalKit

//This extension allows to create a MTLTexture attribute inside this Model class
//in order to be identified and used in the Renderer. This is to ease the loading in case of multiple models in the scene
extension Model : Texturable{

}

class Model {

let mdlMeshes: [MDLMesh]
let mtkMeshes: [MTKMesh]
var texture: MTLTexture?
var transform = Transform()
let name: String

//In order to create a model, you need to pass a name to use it as an identifier,
// a reference to the vertexDescriptor, the imagename with the extension of the texture,
//the dictionary of MTKTextureLoader.Options

init(name: String, vertexDescriptor: MDLVertexDescriptor, textureFile: String, textureLoaderOptions: [MTKTextureLoader.Option : Any]) {
let assetUrl = Bundle.main.url(forResource: name, withExtension: "obj")
let allocator = MTKMeshBufferAllocator(device: Renderer.device)

let asset = MDLAsset(url: assetUrl, vertexDescriptor: vertexDescriptor, bufferAllocator: allocator)

let (mdlMeshes, mtkMeshes) = try! MTKMesh.newMeshes(asset: asset, device: Renderer.device)
self.mdlMeshes = mdlMeshes
self.mtkMeshes = mtkMeshes
self.name = name
texture = setTexture(device: Renderer.device, imageName: textureFile, textureLoaderOptions: textureLoaderOptions)

}



}

关于ios - 如何使用 Metal IOS 正确渲染 3d 模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57608378/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com