gpt4 book ai didi

ios - 使用 3D 类型初始化 Metal 纹理

转载 作者:搜寻专家 更新时间:2023-10-31 08:30:48 24 4
gpt4 key购买 nike

最近在玩SceneKit,发现了colorGrading这个属性。医生说

The contents value for this material property must be a 3D color lookup table, or a 2D texture image that represents such a table arranged in a horizontal strip.

并且 3D 颜色查找表可以从 Metal 纹理中读取。

You can provide data in this cubic format as a Metal texture with the type3D texture type.

那么如何设置 scnCamera.colorGrading.contents 属性。

最佳答案

创建 3D 纹理与创建 2D 纹理非常相似,前提是您有一个包含适当布局的图像数据的缓冲区。我假设你已经有了。以下是如何创建纹理本身,将数据复制到其中,并将其设置为颜色分级纹理:

var dim = 16

var values: UnsafeMutablePointer<Float> = ... // alloc and populate 3D array of pixels

let textureDescriptor = MTLTextureDescriptor()
textureDescriptor.textureType = .type3D
textureDescriptor.pixelFormat = .rgba32Float
textureDescriptor.width = dim
textureDescriptor.height = dim
textureDescriptor.depth = dim
textureDescriptor.usage = .shaderRead

let texture = device.makeTexture(descriptor: textureDescriptor)

texture.replace(region: MTLRegionMake3D(0, 0, 0, dim, dim, dim),
mipmapLevel:0,
slice:0,
withBytes:values,
bytesPerRow:dim * MemoryLayout<Float>.size * 4,
bytesPerImage:dim * dim * MemoryLayout<Float>.size * 4)

camera.colorGrading.contents = texture

编辑

这是一个完整的解析器,可以将 .cube 文件转换为适合与此属性一起使用的 MTLTexture:

import Metal

class AdobeLUTParser {

static func texture(withContentsOf url: URL, device: MTLDevice) -> MTLTexture? {

let lutString = try! NSString(contentsOf: url, encoding: String.Encoding.utf8.rawValue)

let lines = lutString.components(separatedBy: "\r\n") as [NSString]

var dim = 2

var values: UnsafeMutablePointer<Float>? = nil
var index = 0

for line in lines {

if line.length == 0 { continue; } // skip blanks

let firstChar = line.character(at: 0)

if firstChar < 58 /*':'*/ {
if values == nil {
print("Error: Got data before size in LUT")
break;
}

let numbers = line.components(separatedBy: " ") as [NSString]
if numbers.count == 3 {
let r = numbers[0].floatValue
let g = numbers[1].floatValue
let b = numbers[2].floatValue
let a = Float(1)

values![index * 4 + 0] = r
values![index * 4 + 1] = g
values![index * 4 + 2] = b
values![index * 4 + 3] = a

index += 1
}
} else {
if line.hasPrefix("LUT_3D_SIZE") {
let sizeString = line.components(separatedBy: " ")[1] as NSString
dim = Int(sizeString.intValue)
if dim < 2 || dim > 512 {
print("Error: insane LUT size: \(dim)")
}
let rawPointer = malloc(dim * dim * dim * 4 * MemoryLayout<Float>.size)
values = rawPointer!.bindMemory(to: Float.self, capacity: dim * dim * dim * 4)
} else if line.hasPrefix("LUT_1D_SIZE") {
print("Error: 1D LUTs not supported")
break
}
}
}

if values == nil {
print("Did not parse LUT successfully")
return nil
}

let textureDescriptor = MTLTextureDescriptor()
textureDescriptor.textureType = .type3D
textureDescriptor.pixelFormat = .rgba32Float
textureDescriptor.width = dim
textureDescriptor.height = dim
textureDescriptor.depth = dim
textureDescriptor.usage = .shaderRead

let texture = device.makeTexture(descriptor: textureDescriptor)

texture.replace(region: MTLRegionMake3D(0, 0, 0, dim, dim, dim),
mipmapLevel:0,
slice:0,
withBytes:values!,
bytesPerRow:dim * MemoryLayout<Float>.size * 4,
bytesPerImage:dim * dim * MemoryLayout<Float>.size * 4)

return texture
}
}

用法:

let mtlDevice = MTLCreateSystemDefaultDevice()

let lutURL = Bundle.main.url(forResource: "MyGradingTexture", withExtension: "cube")

let lutTexture = AdobeLUTParser.texture(withContentsOf: lutURL!, device: mtlDevice!)

camera.colorGrading.contents = lutTexture

关于ios - 使用 3D 类型初始化 Metal 纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42327664/

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