iOS Metal API在卷内绘制3d纹理

时间:2018-03-16 13:12:59

标签: ios swift textures metal 3d-texture

所以,我试图用3d纹理渲染一个立方体。纹理包含3片3种不同的颜色,红色绿色和蓝色。每个切片由4个具有相同颜色的像素组成。工作良好。 https://imgur.com/a/a5oXi

private func makeTexture() {
    let width = 2
    let height = 2
    let depth = 3
    let byteSize = 4
    let bytesPerRow = byteSize * width
    let bytesPerImage = bytesPerRow * height
    let blue: UInt32 = 0x000000FF
    let green: UInt32 = 0xFF00FF00
    let red: UInt32 = 0x00FF0000

    let textureDescriptor = MTLTextureDescriptor()
    textureDescriptor.pixelFormat = .bgra8Unorm
    textureDescriptor.width = width
    textureDescriptor.height = height
    textureDescriptor.depth = depth
    textureDescriptor.textureType = .type3D

    let image = UnsafeMutableRawPointer.allocate(bytes: width*height*depth*byteSize, alignedTo: 1)
    image.storeBytes(of: red, toByteOffset: 0, as: UInt32.self) 
    image.storeBytes(of: red, toByteOffset: 4, as: UInt32.self)
    image.storeBytes(of: red, toByteOffset: 8, as: UInt32.self)
    image.storeBytes(of: red, toByteOffset: 12, as: UInt32.self)

    image.storeBytes(of: green, toByteOffset: 16, as: UInt32.self)
    image.storeBytes(of: green, toByteOffset: 20, as: UInt32.self)
    image.storeBytes(of: green, toByteOffset: 24, as: UInt32.self)
    image.storeBytes(of: green, toByteOffset: 28, as: UInt32.self)

    image.storeBytes(of: blue, toByteOffset: 32, as: UInt32.self)
    image.storeBytes(of: blue, toByteOffset: 36, as: UInt32.self)
    image.storeBytes(of: blue, toByteOffset: 40, as: UInt32.self)
    image.storeBytes(of: blue, toByteOffset: 44, as: UInt32.self)

    texture = device?.makeTexture(descriptor: textureDescriptor)

    let region = MTLRegionMake3D(0, 0, 0, width, height, depth)
    texture?.replace(region: region,
                     mipmapLevel: 0,
                     slice: 0,
                     withBytes: image,
                     bytesPerRow: bytesPerRow,
                     bytesPerImage: bytesPerImage)
}

片段着色器代码:

struct VertexOut{
float4 position [[position]];
float3 textureCoordinate;
};

fragment half4 basic_fragment(VertexOut in [[stage_in]],
                          texture3d<half> colorTexture [[ texture(0) ]]) {

    constexpr sampler textureSampler (mag_filter::nearest,
                                  min_filter::nearest);

    // Sample the texture to obtain a color
    const half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);

    // We return the color of the texture
     return colorSample;
}

然后我想让红色和蓝色切片透明,所以我将alphas等于0

 let blue: UInt32 = 0x000000FF
 let green: UInt32 = 0xFF00FF00
 let red: UInt32 = 0x00FF0000

片段着色器现在包含

const half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);
if (colorSample.a <= 0)
   discard_fragment();

并期望看到绿色的剪裁,但我只看到绿色边https://imgur.com/a/yGQdQ

立方体内部没有任何东西,我甚至看不到后边缘,因为cullMode设置为.front。

我可以绘制并查看对象内的纹理,以便可以看到它的内部吗?到目前为止,我还没找到方法。当我将纹理类型设置为3d时,它应该计算3D对象的每个像素的颜色吗?不只是边缘?也许它确实如此,但没有显示出来?

1 个答案:

答案 0 :(得分:0)

不,3D纹理不会让你这么做。

没有3D对象,只有三角形(您提供)。这些是2D对象,尽管它们位于3D空间内。金属不会试图通过从你告诉它绘制的三角形中推断出你试图绘制的实体对象。没有常见的3D绘图API。通常不可能。除其他事项外,请记住,您甚至不必将所有三角形都放在一起;它们可以分为绘制调用。

没有&#34;内部&#34;对于任何物体,就金属而言,只是点,线和三角形。如果要渲染对象的内部,则必须对其进行建模。对于切片的立方体,您必须计算&#34;暴露在内部的新表面&#34;并将三角形传递给Metal以绘制它。

3D纹理只是一个可以使用3D坐标进行采样的纹理。请注意,在调用片段着色器之前,已经确定了要绘制哪些片段的决定并且Metal甚至不知道您在制作它时会使用3D纹理那些决定。