【问题标题】:Generate gradient image texture on iOS在 iOS 上生成渐变图像纹理
【发布时间】:2019-06-16 08:51:04
【问题描述】:

我需要在 iOS 上生成一个 256x1 的纹理。我有 4 种颜色红色、绿色、黄色、蓝色,一端是红色,另一端是蓝色,黄色和绿色分别位于 3/4 和 1/4 位置。中间的颜色需要线性插值。我需要在 Metal 中使用此纹理在着色器代码中查找。在代码中生成此纹理的最简单方法是什么?

【问题讨论】:

  • 颜色或位置有变化吗?如果没有,为什么不直接创建一个图像并将其作为资产添加到您的应用程序包中呢?如果颜色确实发生了变化,最简单的方法(如果您不需要像 HSV 空间这样的自定义插值)可能是在其中创建 CGBitmapContext 和 draw a gradient,然后将生成的字节复制到 MTLTexture 中。
  • 好的,我创建了图像并生成了 256x1 纹理。问题是 Metal 默认将其视为 texture2d。如何在生成时指定一维纹理?当然,我可以通过在 y 坐标中指定 0 来将其用作 texture2d,但仍然可以。

标签: ios opengl-es uiimage metal texture-mapping


【解决方案1】:

由于MTKTextureLoader 目前不支持创建 1D 纹理(至少从 2016 年开始,这是一项功能请求),因此您需要手动创建纹理。

假设您已经加载了图像,您可以向它索取CGImage,然后使用此方法提取像素数据并将其加载到纹理中:

func texture1DForImage(_ cgImage: CGImage, device: MTLDevice) -> MTLTexture? {
    let width = cgImage.width
    let height = 0
    let bytesPerRow = width * 4 // RGBA, 8 bits per component

    let bitmapInfo: UInt32 = /* default byte order | */ CGImageAlphaInfo.premultipliedLast.rawValue
    let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)!
    let context = CGContext(data: nil,
                            width: width,
                            height: height,
                            bitsPerComponent: 8,
                            bytesPerRow: bytesPerRow,
                            space: colorSpace,
                            bitmapInfo: bitmapInfo)!

    let bounds = CGRect(x: 0, y: 0, width: width, height: height)
    context.draw(cgImage, in: bounds)

    guard let data = context.data?.bindMemory(to: UInt8.self, capacity: bytesPerRow) else { return nil }

    let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm,
                                                                     width: width,
                                                                     height: height,
                                                                     mipmapped: false)
    textureDescriptor.textureType = .type1D
    textureDescriptor.usage = [ .shaderRead ]

    let texture = device.makeTexture(descriptor: textureDescriptor)!
    texture.replace(region: MTLRegionMake1D(0, width), mipmapLevel: 0, withBytes: data, bytesPerRow: bytesPerRow)

    return texture
}

【讨论】:

    猜你喜欢
    • 2017-05-13
    • 2018-08-06
    • 1970-01-01
    • 2014-05-13
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2017-03-28
    相关资源
    最近更新 更多