read and write integer 1-channel texture opengl

折月煮酒 提交于 2019-12-04 15:24:15

The interal format GL_R8I is actually the correct format for your use case, and the spec explicitely lists that format as color-renderable.

layout(location = 2) out float value;

Why are you using a float output type if you intend to store integers? The OpenGL 3.3 core profile specification explicitely states the following:

Color values written by a fragment shader may be floating-point, signed integer, or unsigned integer. If the color buffer has an signed or unsigned normalized fixed-point format, color values are assumed to be floating-point and are converted to fixed-point as described in equations 2.6 or 2.4, respectively; otherwise no type conversion is applied.

However, as you put it:

Now what I'd ideally like is to be able to write an integer and sample that integer.

You can do that, assuming you use the correct integer sampler type in the shader. What you can't do is use blending with integers. To quote the spec:

Blending applies only if the color buffer has a fixed-point or floating-point format. If the color buffer has an integer format, proceed to the next operation.

So if you need the blending, the best option is to work with GL_R8 normalized integer format, and with floating point outputs in the shader.

With more modern GL, you could simply emulate the additive blending by directly sampling the previous value in the shader which is updating the texture. Such feedback loops where a shader reads exactly the texel location it is later going to write to are well-defined and allowed in recent GL versions, but unfortunately not in GL3.x.

UPDATE

I found that if I write 0.5, then this work:

if (texture2D(Tshadow, v_sampler_coo).r == 0.4980392307){discard;}

Well, 0.5 is not representable by normalized integer formats (and actually, the bit depth does not even matter, it will never work). In the 8 bit case, the GL will convert 0.5 to 0.5*255 = 127.5. Now it will be implementation specific if it will round to 127 or 128, so you will end up with either 127.0/255.0 (which you got), or 128.0/255.0.

Note on the rounding rules: In the GL 3.3 spec, it is stated that the value after the multiplication

is then cast to an unsigned binary integer value with exactly b bits

With no rounding at all, so that 127 should always be the result. However, in the latest version, GL 4.5, it is stated as

returns one of the two unsigned binary integer values with exactly b bits which are closest to the floating-point value r (where rounding to nearest is preferred).

so actually, any rounding behavior is allowed...

As a final note: you should never compare floats for equality.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!