gpt4 book ai didi

swift - 这个 MVP Metal main.swift 显示为空白

转载 作者:行者123 更新时间:2023-11-28 13:47:40 30 4
gpt4 key购买 nike

因此,在项目的 main.swift 文件中,您可以像这样创建一个窗口(并从那里开始):

let nsapp = NSApplication.shared
let window = NSWindow(
contentRect: NSMakeRect(0, 0, 200, 200),
styleMask: .fullSizeContentView,
backing: NSWindow.BackingStoreType.buffered,
defer: false
)
window.cascadeTopLeft(from:NSMakePoint(20,20))
nsapp.run()

我想知道如何使用 Metal 三角形做同样的事情。我一直在浏览 github.com/topics/metalkit但到目前为止我发现的最接近的东西不在那里,而是在 gist 中.

import Cocoa
import MetalKit

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, MTKViewDelegate {
weak var window: NSWindow!
weak var metalView: MTKView!
let device = MTLCreateSystemDefaultDevice()!
var commandQueue: MTLCommandQueue!
var pipelineState: MTLRenderPipelineState!

func applicationDidFinishLaunching(_ aNotification: Notification) {
metalView = MTKView(frame: NSRect(origin: CGPoint.zero, size: window.frame.size), device: device)
metalView.delegate = self
window.contentView = metalView
commandQueue = device.makeCommandQueue()
let shaders = """
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
packed_float3 position;
packed_float3 color;
};
struct VertexOut {
float4 position [[position]];
float4 color;
};
vertex VertexOut vertex_main(device const VertexIn *vertices [[buffer(0)]],
uint vertexId [[vertex_id]]) {
VertexOut out;
out.position = float4(vertices[vertexId].position, 1);
out.color = float4(vertices[vertexId].color, 1);
return out;
}
fragment float4 fragment_main(VertexOut in [[stage_in]]) {
return in.color;
}
"""
do {
let library = try device.makeLibrary(source: shaders, options: nil)
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
pipelineDescriptor.vertexFunction = library.makeFunction(name: "vertex_main")
pipelineDescriptor.fragmentFunction = library.makeFunction(name: "fragment_main")
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
} catch {}
}

func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}

func draw(in view: MTKView) {
guard let commandBuffer = commandQueue.makeCommandBuffer() else { return }
guard let passDescriptor = view.currentRenderPassDescriptor else { return }
guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDescriptor) else { return }
let vertexData: [Float] = [ -0.5, -0.5, 0, 1, 0, 0,
0.5, -0.5, 0, 0, 1, 0,
0, 0.5, 0, 0, 0, 1 ]
encoder.setVertexBytes(vertexData, length: vertexData.count * MemoryLayout<Float>.stride, index: 0)
encoder.setRenderPipelineState(pipelineState)
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3)
encoder.endEncoding()
commandBuffer.present(view.currentDrawable!)
commandBuffer.commit()
}
}

它至少从头开始构建一个 MTKView。但是我还不确定要让一个 Metal 的东西在没有任何 Controller 、委托(delegate)、应用程序的情况下工作的最低可行产品是什么,我将开始只是通过反复试验来让它工作,但是这可能需要几天的时间,如果有人已经弄明白了,它可能会对其他人有所帮助。

我已将两者结合起来,但据我所知,它没有呈现任何内容。

import AVFoundation
import AudioToolbox
import Foundation
import QuartzCore
import Security
import WebKit
import Cocoa
import Metal
import MetalKit
import Swift

let device = MTLCreateSystemDefaultDevice()!
// Our clear color, can be set to any color
let clearColor = MTLClearColor(red: 0.1, green: 0.57, blue: 0.25, alpha: 1)
let nsapp = NSApplication.shared
let appName = ProcessInfo.processInfo.processName
let window = NSWindow(
contentRect: NSMakeRect(0, 0, 1000, 1000),
styleMask: .fullSizeContentView,
backing: NSWindow.BackingStoreType.buffered,
defer: false
)
window.cascadeTopLeft(from:NSMakePoint(20,20))
window.title = appName;
window.makeKeyAndOrderFront(nil)

struct Vertex {
var position: float3
var color: float4
}

let view = MTKView(frame: NSRect(origin: CGPoint.zero, size: window.frame.size), device: device)
window.contentView = view
view.device = device
view.colorPixelFormat = .bgra8Unorm
view.clearColor = clearColor

let queue = device.makeCommandQueue()!
var vertexBuffer: MTLBuffer!
var vertices: [Vertex] = [
Vertex(position: float3(0,1,0), color: float4(1,0,0,1)),
Vertex(position: float3(-1,-1,0), color: float4(0,1,0,1)),
Vertex(position: float3(1,-1,0), color: float4(0,0,1,1))
]

let shaders = """
#include <metal_stdlib>
using namespace metal;

// Basic Struct to match our Swift type
// This is what is passed into the Vertex Shader
struct VertexIn {
float3 position;
float4 color;
};
// What is returned by the Vertex Shader
// This is what is passed into the Fragment Shader
struct VertexOut {
float4 position [[ position ]];
float4 color;
};
vertex VertexOut basic_vertex_function(const device VertexIn *vertices [[ buffer(0) ]],
uint vertexID [[ vertex_id ]]) {
VertexOut vOut;
vOut.position = float4(vertices[vertexID].position,1);
vOut.color = vertices[vertexID].color;
return vOut;
}
fragment float4 basic_fragment_function(VertexOut vIn [[ stage_in ]]) {
return vIn.color;
}
"""
let library = try device.makeLibrary(source: shaders, options: nil)
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
pipelineDescriptor.vertexFunction = library.makeFunction(name: "basic_vertex_function")
pipelineDescriptor.fragmentFunction = library.makeFunction(name: "basic_fragment_function")
let pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)

vertexBuffer = device.makeBuffer(
bytes: vertices,
length: MemoryLayout<Vertex>.stride * vertices.count,
options: []
)

enum MetalErrors: Error {
case commandBuffer
case passDescriptor
case encoder
}

guard let drawable = view.currentDrawable else { throw MetalErrors.commandBuffer }
guard let commandBuffer = queue.makeCommandBuffer() else { throw MetalErrors.commandBuffer }
guard let passDescriptor = view.currentRenderPassDescriptor else { throw MetalErrors.passDescriptor }
guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDescriptor) else { throw MetalErrors.encoder }

nsapp.run()

// let vertexData: [Float] = [ -0.5, -0.5, 0, 1, 0, 0,
// 0.5, -0.5, 0, 0, 1, 0,
// 0, 0.5, 0, 0, 0, 1 ]
encoder.setRenderPipelineState(pipelineState)
// encoder.setVertexBytes(vertexData, length: vertexData.count * MemoryLayout<Float>.stride, index: 0)
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: vertices.count)
encoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()

它对我来说是空白的。我尝试关注 this

This越来越近了。

最佳答案

这里的主要问题是 NSApplicationrun 方法在应用程序终止之前不会返回,因此您的渲染命令编码永远不会发生。您可以子类化 MTKView 并覆盖其 draw 方法来代替您的绘图:

import Cocoa
import MetalKit

let device = MTLCreateSystemDefaultDevice()!
// Our clear color, can be set to any color
let clearColor = MTLClearColor(red: 0.1, green: 0.57, blue: 0.25, alpha: 1)

let shaders = """
#include <metal_stdlib>
using namespace metal;

// Basic Struct to match our Swift type
// This is what is passed into the Vertex Shader
struct VertexIn {
float3 position;
float4 color;
};
// What is returned by the Vertex Shader
// This is what is passed into the Fragment Shader
struct VertexOut {
float4 position [[ position ]];
float4 color;
};
vertex VertexOut basic_vertex_function(const device VertexIn *vertices [[ buffer(0) ]],
uint vertexID [[ vertex_id ]]) {
VertexOut vOut;
vOut.position = float4(vertices[vertexID].position,1);
vOut.color = vertices[vertexID].color;
return vOut;
}
fragment float4 basic_fragment_function(VertexOut vIn [[ stage_in ]]) {
return vIn.color;
}
"""
let library = try device.makeLibrary(source: shaders, options: nil)
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm
pipelineDescriptor.vertexFunction = library.makeFunction(name: "basic_vertex_function")
pipelineDescriptor.fragmentFunction = library.makeFunction(name: "basic_fragment_function")
let pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)

struct Vertex {
var position: float3
var color: float4
}

let queue = device.makeCommandQueue()!
var vertexBuffer: MTLBuffer!
var vertices: [Vertex] = [
Vertex(position: float3(0,1,0), color: float4(1,0,0,1)),
Vertex(position: float3(-1,-1,0), color: float4(0,1,0,1)),
Vertex(position: float3(1,-1,0), color: float4(0,0,1,1))
]

vertexBuffer = device.makeBuffer(
bytes: vertices,
length: MemoryLayout<Vertex>.stride * vertices.count,
options: []
)

enum MetalErrors: Error {
case commandBuffer
case passDescriptor
case encoder
}

class MyMTKView : MTKView {
override func draw() {
guard let drawable = currentDrawable else { return }
guard let passDescriptor = currentRenderPassDescriptor else { return }
guard let commandBuffer = queue.makeCommandBuffer() else { return }
guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDescriptor) else { return }
encoder.setRenderPipelineState(pipelineState)
encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0 )
encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: vertices.count)
encoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()
}
}

let nsapp = NSApplication.shared
let appName = ProcessInfo.processInfo.processName
let window = NSWindow(
contentRect: NSMakeRect(0, 0, 1000, 1000),
styleMask: [.titled, .closable, .resizable],
backing: NSWindow.BackingStoreType.buffered,
defer: false
)
window.cascadeTopLeft(from:NSMakePoint(20,20))
window.title = appName;

let view = MyMTKView(frame: NSRect(origin: CGPoint.zero, size: window.frame.size), device: device)
window.contentView = view
view.device = device
view.colorPixelFormat = .bgra8Unorm
view.clearColor = clearColor

window.makeKeyAndOrderFront(nil)

nsapp.run()

关于swift - 这个 MVP Metal main.swift 显示为空白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55204725/

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