Using Vulkan + OpenXR, getting strange transparency results on quest (not present in PCVR)

311 views Asked by At

The long story short is that alpha values are behaving very strangely: transitioning reasonably between 1.0 to 0.5, but from 0.5 to 0.0 transitioning from half-opacity-{color} to opaque-black.

enter image description here

^ this is my font renderer (captured from quest beamed to iphone) with the shader replaced. Rather than display a font, it should be displaying red quads fading in and out of transparency according to the sin of the fragment x coordinate. I have no idea where the "black" is coming from. Here is the shader:

#version 450
#extension GL_KHR_vulkan_glsl : enable
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_multiview : enable
layout(set = 0, binding = 2) uniform sampler2D colorSampler;
layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor;
void main()
{
  float x = (sin(gl_FragCoord.x/20.0)+1.0)/2.0;
  outColor = vec4(1.0,0.0,0.0,x)
}

and my pipeline blend config is:

VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
  //alpha blend
  colorBlendAttachment.colorWriteMask =
    VK_COLOR_COMPONENT_R_BIT |
    VK_COLOR_COMPONENT_G_BIT |
    VK_COLOR_COMPONENT_B_BIT |
    VK_COLOR_COMPONENT_A_BIT |
    0;
  colorBlendAttachment.blendEnable = VK_TRUE;
  colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
  colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
  colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
  colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
  colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;

VkPipelineColorBlendStateCreateInfo colorBlendInfo = {};

  colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  colorBlendInfo.logicOpEnable = VK_FALSE;
  colorBlendInfo.logicOp = VK_LOGIC_OP_COPY;
  colorBlendInfo.attachmentCount = 1;
  colorBlendInfo.pAttachments = &colorBlendAttachment;
  colorBlendInfo.blendConstants[0] = 0.0f;
  colorBlendInfo.blendConstants[1] = 0.0f;
  colorBlendInfo.blendConstants[2] = 0.0f;
  colorBlendInfo.blendConstants[3] = 0.0f;

The wackiest bit is that this works perfectly (as expected) when run from pcvr (with no major differences in code paths between the two: same spirv, same pipeline generation, etc...)

1

There are 1 answers

0
Triang3l On BEST ANSWER

You have alpha writing enabled in your colorWriteMask, and (1 * source + 0 * destination) blending equation for alpha, so you're overwriting the framebuffer's alpha with text opacity. With compositeAlpha of the swap chain being VK_COMPOSITE_ALPHA_PRE/POST_MULTIPLIED_BIT_KHR, the compositor blends your swapchain images with what's behind the surface — and since you write alpha below 1 to the image where the text is supposed to be, the compositor considers those areas translucent. You should disable writing the alpha channel when drawing to the swapchain images by removing the alpha bit from the colorWriteMask in the blending parameters, or via (0 * source + 1 * destination) alpha blending equation, or use VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR swapchain compositeAlpha if VkSurfaceCapabilitiesKHR of the target surface declare its availability (which is also recommended for potentially faster composition).