OpenGL ES 2.0 solid colour & colour value precision issue

后端 未结 1 1654
情深已故
情深已故 2021-01-23 08:13

Issue partially resolved, leaving previous post & code here for reference, new issue (stated in title) after the strong text at the bottom

I am tryi

1条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-23 08:50

    There are at least two aspects that can come in your way of getting exactly the expected color:

    Dithering

    Dithering for color output is enabled by default. Based on what I've seen, it doesn't typically seem to come into play (or at least not in a measurable way) if you're rendering to targets with 8 bits per component. But it's definitely very noticeable when you're rendering to a lower color depth, like RGB565.

    The details of what exactly happens as the result of dithering appears to be very vendor dependent.

    Dithering is enabled by default. For typical use, that's probably a good thing, because you only care about the visual appearance. And the whole idea of dithering is obviously to enhance the visual quality. But if you rely on getting controllable and predictable values for your output colors, like it's necessary in your picking case, you should always disable dithering:

    glDisable(GL_DITHER);
    

    Precision

    As you're already aware based on your code, precision is a big concern here. You obviously can't expect to get exactly the same floating point value back as the one you originally specified for the color.

    The primary loss of precision comes from the conversion of the color value to a normalized value in the color buffer. With 8 bits/component color depth, the precision of that value is 1.0/255.0. Which means that you should be fine with generating and comparing values with a precision of 0.01.

    Another source of precision loss is the shader processing. Since you specify mediump for the precision in the shader code, which gives you at least about 10 bits of precision, that also looks like it should not be harmful.

    One possibility is that you didn't actually get a configuration with 8-bit color components. This would also be consistent with the visual dithering effect. Say if you got a RGB565 surface, your observed precision starts to make sense.

    For example, with RGB565, if you pass in 0.77 for the green component, the value is multiplied with 63 (2^6 - 1) during fixed point conversion, which gives 48.51. Now, the spec says:

    Values are converted (by rounding to nearest) to a fixed-point value with m bits, where m is the number of bits allocated to the corresponding R, G, B, A, or depth buffer component.

    The nearest value for 48.51 is 49. But if you lose any kind of precision somewhere on the way, it could very easily become 48.

    Now, when these values are converted back to float while you read them back, they are divided by 63.0. If the value in the framebuffer was 48, the result is 0.762, which you would round to in your code 0.76. If it was 49, the result is 0.777, which rounds to 0.78.

    So in short:

    • Be very careful about what kind of precision you can expect.
    • I think you might have an RGB565 framebuffer.

    Also, using multiples of 0.01 for the values does not look like an ideal strategy because it does not line up with the representation in the framebuffer. I would use multiples of 2^b - 1, where b is the number of bits in the color components. Use those values when specifying colors, and apply the matching quantization when you compare the values you read back with the expected value.

    0 讨论(0)
提交回复
热议问题