0

I'm porting some OpenGL code from a technical paper to use with Metal. In it, they use a render target with only one channel - a 16-bit float buffer. But then they set blending operations on it like this:

glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

With only one channel, does that mean that with OpenGL, the target defaults to being an alpha channel?

Does anyone know if it is the same with Metal? I am not seeing the results I expect and I am wondering if Metal differs, or if there is a setting that controls how single-channel targets are treated with regards to blending.

genpfault
  • 51,148
  • 11
  • 85
  • 139
bsabiston
  • 721
  • 6
  • 22
  • 1
    Not 100% sure, but having a single channel framebuffer doesn't mean that the shader can't output an alpha value in addition. You won't have a destination alpha stored but there can still be a source alpha which can be used in the blending calculation. – BDL Nov 08 '17 at 17:54

1 Answers1

2

In OpenGL, image format channels are labeled explicitly with their channels. There is only one one-channel color format: GL_R* (obviously with different bitdepths and other info). That is, red-only. And while texture swizzling can make the red channel appear in other channels from a texture fetch, that doesn't work for framebuffer writes.

Furthermore, that blend function doesn't actually use the destination alpha. It only uses the source alpha, which has the value the FS gave it. So the fact that the framebuffer doesn't store an alpha is essentially irrelevant.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks -- I am still a little confused though. In this example, the destination multiplier is 1 - srcAlpha. What is srcAlpha in this case? Normally I would think it is the alpha value returned by the fragment shader, is that not correct? But there is no alpha value for a shader whose target is a single channel. Do you see my confusion? – bsabiston Nov 08 '17 at 20:23
  • @bsabiston: "*But there is no alpha value for a shader whose target is a single channel.*" Says who? The source alpha is the *output* from the fragment shader. That output doesn't care what the framebuffer does or does not contain. Only the *destination* values care about that. – Nicol Bolas Nov 08 '17 at 20:24
  • My fragment shader outputs a single float, since it targets a single-channel buffer. And from what I can tell, Metal seems to think that is a color value, not an alpha value. – bsabiston Nov 08 '17 at 20:27
  • If the fragment shader output has fewer than 4 components, the missing components are assumed to be those from `4(0, 0, 0, 1)`. So, the source alpha is 1. Given the blend func you're supposedly using (source factor 0, dest factor 1 - source alpha == 0), that would imply that only zeroes are written to the destination. – Ken Thomases Nov 08 '17 at 21:12
  • @KenThomases: Can you cite a location in the specification that specifies this? For example, 10.3.5 is what defines this to be true for vertex shader attributes. Where is the corresponding location for fragment shaders? – Nicol Bolas Nov 08 '17 at 21:40
  • @KenThomases that lines up with what I am seeing - nothing! :) I think this is where Metal and OpenGL differ -- the OpenGL shader is able to return a regular float4 with the value it wants to be in the alpha buffer. But I have to return a single value in Metal to match the bound buffer -- which means I think I need to use srcColor instead of srcAlpha in the blend functions. – bsabiston Nov 08 '17 at 22:07
  • 2
    Why do you believe you have to return a single float? Your fragment shader should be able to return a `float4`. – Ken Thomases Nov 08 '17 at 22:09
  • @NicolBolas, you appear to be referring to the OpenGL spec, I think. I'm talking about Metal. Unfortunately, I still can't point to definitive documentation. The Metal spec is decidedly non-comprehensive. – Ken Thomases Nov 08 '17 at 22:22
  • @KenThomases Ah I see you are right. I was under the mistaken impression that I got errors if the return type didn't match the bound buffer, but I didn't realize I could specify a return type buffer in the shader that does not match the actual bound buffer, and not get errors. Thanks! – bsabiston Nov 09 '17 at 18:09
  • 1
    A "return type buffer"? The shader return type (or the `[[color]]` field of a struct return type) must match the render target texture in general type (`float` vs. `int` vs. `uint`) but not necessarily in number of components. – Ken Thomases Nov 09 '17 at 20:31