因此,我正在尝试渲染具有 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 对象的每个像素的颜色?不只是边缘?也许是,但不显示?
最佳答案
不,3D 纹理不会让你那样。
没有 3D 对象,只有三角形(您提供)。这些是 2D 对象,尽管它们位于 3D 空间内。 Metal 不会试图通过从您告诉它绘制的三角形进行推断来弄清楚您要绘制的实体对象。没有通用的 3D 绘图 API 可以做到这一点。一般是不可能的。除其他事项外,请记住,您甚至不必将所有三角形一起交给 Metal;它们可以在绘图调用中拆分。
就 Metal 所知,任何对象都没有“内部”,只有点、线和三角形。如果你想渲染一个对象的内部,你必须对其进行建模。对于立方体的一部分,您必须计算“暴露在内部”的新表面并将三角形传递给 Metal 以绘制它。
3D 纹理只是可以使用 3D 坐标采样的纹理。请注意,关于要绘制哪些片段的决定已经在您的片段着色器被调用之前做出,并且 Metal 在做出这些决定时甚至不知道您将使用 3D 纹理。
关于iOS Metal API 在体积内绘制 3d 纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49321669/