- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的问题分为两个部分:
第一节
我有一个要求,我必须传递一个结构,其中包含 3 个颜色 (RGB) 值,范围从 0 到 1,但结果是当我测试代码对值进行硬编码时,我收到的任何值都是不同的。
这是我的片段着色器方法
struct RGBColors {
half red;
half green;
half blue;
};
fragment float4
samplingShader(RasterizerData in [[stage_in]],
texture2d<half> colorTexture [[ texture(0) ]],
const device struct RGBColors *color [[ buffer(0) ]]
)
{
constexpr sampler textureSampler (mag_filter::linear,
min_filter::linear,
s_address::repeat,
t_address::repeat,
r_address::repeat);
const half4 colorSample = colorTexture.sample (textureSampler, in.textureCoordinate);
float4 outputColor = float4(0,0,0,0);
half red = color->red;
half blue = color->blue;
half green = color->green;
outputColor = float4(colorSample.r * red, colorSample.g * green, colorSample.b * blue, 0);
return outputColor;
}
我的 swift 结构是这样的,
struct RGBColors {
var r: Float
var g: Float
var b: Float
func floatBuffers() -> [Float] {
return [r,g,b]
}
}
我像这样将缓冲区传递给片段,
let colors = color.floatBuffers()
let colorBuffer = device.makeBuffer(bytes: colors, length: 16, options: [])
renderEncoder.setFragmentBuffer(colorBuffer, offset: 0, at: 0)
但是如果我将 const device struct RGBColors *color [[ buffer(0) ]]
中的参数 color 更改为 float3,就像这样 constant float3 *color [[ buffer(0) ] ]
并通过 rgb
值访问它正常工作。
第二节
正如您在我的代码中看到的那样 let colorBuffer = device.makeBuffer(bytes: colors, length: 16, options: [])
长度是 16 但如果我把它改成
`MemoryLayout.size(ofValue: colors[0]) * colors.count`
它正在崩溃并说
`failed assertion `(length - offset)(12) must be >= 16 at buffer binding at index 0 for color[0].'`
我无法弄清楚发生了什么。有人可以建议我吗。
谢谢。
最佳答案
Swift Float
类型与 Metal half
类型不对应。据我所知,half
在 Swift(或者,就此而言,C 或 Objective-C)中没有很好的表示。您正在为需要 3 个 16 位值的对象提供 3 个 32 位值。您提供的值与接收代码访问它们的方式不一致,因此它访问的是值的子部分。
因此,我建议在着色器中从使用 half
切换到使用 float
,这在 Swift 中更容易表示。
接下来,您的 RGBColors
结构基本上只是内置类型 half3
的冗余,或者,如果您采纳了我的上述建议,float3
.所以,我建议您只使用 float3
。如果您 import simd
,该类型甚至可以在 Swift 中使用。在 Metal(和 C)中,您可以使用 .r
、.g
、.b
或 访问其成员>.x
, .y
, .z
,不过Swift好像只支持后者。两种语言都支持使用数组下标语法访问成员。
如 MemoryLayout
overview 中所述,在计算缓冲区大小时或偏移量时,您应该不使用size
属性或size(ofValue:)
方法。你应该使用stride
/stride(ofValue:)
。此外,您不应使用复合类型的一个元素的步长乘以元素数。您需要使用整个复合类型的步幅。这是因为编译器可以向复合类型添加填充以保持对齐要求,而前一种技术没有考虑到这一点。
最后一点:在您的着色器中,color
变量仅用于访问单一颜色。也就是说,它不是一组颜色。因此,您应该将其声明为引用类型而不是指针类型。这让编译器知道,因此它可以生成更好的代码。
const device float3 &color [[ buffer(0) ]]
当然,那么您需要将color->
更改为color.
。
关于swift - 无法在 Metal 的片段着色器中正确访问结构对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46002564/
在 Metal 中,在着色器内部(进出)使用什么坐标系?当我们渲染到纹理时是一样的吗?也有z缓冲区?有没有不一致的地方?最后 Metal ,opengl和directX有什么区别? 最佳答案 Meta
我正在尝试在 Mac 上的 Apple metal 中开发我自己的迷你游戏引擎,但我被困在我想在 GPU 上渲染文本的地方。我没有太多的图形编程经验,因此我不知道该怎么做。我偶然发现了 Warren
我找不到答案的简单问题,在 openGL 上有一个 glDeleteTextures(1, &t) 显然模型有很大的不同,但我想知道 Metal 是否有相同的需要或要求。 MTLTexture 是通过
我是 Metal 新手。我想使用 Metal 计算来做一些数学运算,所以我创建了一个内核函数(着色器?),比方说 kernel void foo(device float *data1,
我假设除了 Metal 之外的其他 API 中存在颜色附件(我肯定知道 OpenGL),但我是图形编程的新手,我想知道颜色附件在概念上到底是什么。我所做的所有绘图都涉及在颜色附件数组中的第一个设置属性
在计算着色器中,我可以看到双三次是一个选项,但前提是定义了 __HAVE_BICUBIC_FILTERING__。当我将 bicubic 设置为过滤选项时,出现语法错误。 Linear 或Neares
这是一个绝对的初学者问题。 背景:我并不是真正的游戏开发者,但我正在努力学习底层 3D 编程的基础知识,因为这是一个有趣且有趣的话题。我选择了 Apple 的 Metal 作为图形框架。我知道 Sce
在 GLSL 中,我只需使用 out vec3 array[10]; 将数组从顶点着色器传递到片段着色器。然而,在 Metal 中,我想这样做: struct FragmentIn { flo
我看到 Apple GPU 硬件和 iOS/MacOS 版本的组合决定了一个功能集。我可以使用下面的快速代码片段查询我的 MTLDevice 支持哪些功能集。 device.supportsFeatu
我想将深度缓冲区保存到 Metal 纹理中,但我尝试过的任何方法似乎都不起作用。 _renderPassDesc.colorAttachments[1].clearColor = MTLClearCo
我想在我的 Metal 应用程序中实现一个 A-Buffer 算法来实现与订单无关的透明度。该技术的描述提到使用原子计数器。我从未使用过其中之一,甚至没有听说过。我刚刚阅读了 Metal Shadin
假设我有一个 N channel MPSImage 或基于 MTLTexture 的纹理数组。 我如何从中裁剪一个区域,复制所有 N 个 channel ,但改变“像素大小”? 最佳答案 我将只讨论裁
TL;DR:Metal 似乎没有检测到我的顶点着色器返回的内容 我有这两个用 MSL 编写的函数: vertex float4 base_image_rect(constant float4 *pos
如何在目标设置为 iOS 模拟器的情况下在 Xcode 6 中编译 iOS «Metal» 游戏? error: can't exec 'metal' (No such file or directo
将一些基本的 OpenGL ES 2.0 着色器移植到 Metal 着色器时,我不知道如何将 glsl 中的 in/inout/out 限定符转换为 Metal 着色器语言 (MSL)。例如, //O
我不想使用texture1d_array。我可以简单地传递一个 float 组吗?我将把它写入我的内核函数中。 最佳答案 为了写入内核函数内的 float 组,您需要向内核提供一个缓冲区参数。该参数应
我不想使用texture1d_array。我可以简单地传递一个 float 组吗?我将把它写入我的内核函数中。 最佳答案 为了写入内核函数内的 float 组,您需要向内核提供一个缓冲区参数。该参数应
我有一组 Metal 纹理作为纹理集存储在 Xcode Assets 目录中。我正在使用 MTKTextureLoader.newTexture(name:scaleFactor:bundle:opt
Apple 系统中似乎至少有六个矩阵库。其中之一是 simd 库,其类型在 CPU 和 GPU 代码中的工作方式相同。 import simd let mat = float3x3(...) let
有谁知道 Apple 的旧版本 Metal Feature Set Table 的可用性?文件? 当前的 Metal 3.0 文档仅引用 beta MTLGPUFamily 和 MTLSoftware
我是一名优秀的程序员,十分优秀!