Proper usage of OpenGL method glTexImage2D()? - opengl

The specification for the OpenGL method glTexImage2D() gives a large table of accepted internalFormat parameters. I'm wondering though, if it really matters what I set this parameter as, since the doc says
If an application wants to store the texture at a certain
resolution or in a certain format, it can request the resolution
and format with internalFormat. The GL will choose an internal
representation that closely approximates that requested by internalFormat, but
it may not match exactly.
which makes it seem as though OpenGL is just going to pick what it wants anyways. Should I bother getting an images bit depth and setting the internalFormat to something like GL_RGBA8 or GL_RGBA16? All the code examples I've seen just use GL_RGBA...

which makes it seem as though OpenGL is just going to pick what it wants anyways.
This is very misleading.
There are a number of formats that implementations are required to support more or less exactly as described. Implementations are indeed permitted to store them in larger storage. But they're not permitted to lose precision compared to them. And there are advantages to using them (besides the obvious knowledge of exactly what you're getting).
First, it allows you to use specialized formats like GL_RGB10_A2, which is handy in certain situations (storing linear color values for deferred rendering, etc). Second, FBOs are required to support any combination of image formats, but only if all of those image formats come from the list of required color formats for textures/renderbuffers (but not the texture-only). If you're using any other internal formats, FBOs can throw GL_FRAMEBUFFER_UNSUPPORTED at you.
Third, immutable texture storage functions require the use of sized internal formats. And you should use those whenever they're available.
In general, you should always use sized internal formats. There's no reason to use the generic ones.

Using a generic internal format OpenGL will choose whatever it "likes" best, and tell it that you don't care. With an explicit internal format, you're telling OpenGL, that you actually care about the internal representation (most likely because you need the precision). While an implementation is free to up- or downgrade if an exact match can not be made, the usual fallback is to upgrade to the next higher format precision that can satisfy the requested demands.
Should I bother getting an images bit depth and setting the internalFormat
If you absolutely require the precision, then yes. If your concerns are more about performance, then no, as the usual default of the OpenGL implementations being around, is to choose the internal format for best performance if no specific format has been requested.

Related

Should I prefer glMapBufferRange over glMapBuffer?

The documentation for glMapBuffer says it can only use the enum access specifiers of GL_READ_ONLY, GL_WRITE_ONLY, or GL_READ_WRITE.
The documentation for glMapBufferRange says it uses bitflag access specifiers instead, which include a way to persistently map the buffer with GL_MAP_PERSISTENT_BIT.
I want to map the buffer persistently, so should I just always use glMapBufferRange even though I want to map the entire buffer? I haven't seen anyone point out this rather important distinction between the two functions, so I was wondering if glMapBufferRange is a total and complete replacement for glMapBuffer, or if I should be prepared to use both in certain situations?
(I guess I'm just confused because, given the naming, I would think only the sub-range would be the difference between the two calls.)
glMapBufferRange was first introduced in OpenGL 3. OpenGL has evolved to provide more control to developers while keeping backwards compatibility as much as possible. So glMapBuffer remained unchanged, and glMapBufferRange introduced the explicitness that developers wanted (not only the subrange part, but also other bits).
glMapBufferRange reminds me of the options that are available nowadays in Vulkan (i.e cache invalidation and explicit synchronization). For some use cases, you might get better performance using the right flags with the new function. If you don't use any of the optional flags, the behaviour should be equivalent to the old function (except for the subrange part).
I think I would always use glMapBufferRange as it can do everything that the other does. Plus you can tweak for performance later on. Just my humble opinion :)

Different OpenGL behaviour on different hardware

I have an application that uses OpenGL to draw output images. For testing purposes I'm trying to create reference images and then use precision hash to compare them to program output. While it works flawlessly within a context of a single computer I've encountered strange problems when using the same approach with computers running different GPUs. While the images generated on different GPUs appear absolutely identical to human eye they cannot pass prescision hash test when compared to one another and per-pixel comparison reveals that there are several pixels that are "off". I've been trying to find problems in my code for several days to no avail and this behaviour manifests itself on all the shaders that I use. Could this possibly be due to differences in OpenGL implementation from different hardware manufacturers? Is it a valid approach to compare images generated on different GPUs with phash for testing purposes?
Could this possibly be due to differences in OpenGL implementation
from different hardware manufacturers? Is it a valid approach to
compare images generated on different GPUs with phash for testing
purposes?
No, it is not. Quoting the OpenGL 4.6 core profile specification, Appendix A "Invariance" (emphaisis mine):
The OpenGL specification is not pixel exact. It therefore does not
guarantee an exact match between images produced by different GL
implementations. However, the specification does specify exact
matches, in some cases, for images produced by the same
implementation. The purpose of this appendix is to identify and
provide justification for those cases that require exact matches.
The guarantees for exact matches are made only within the same implementation, under very strict limits, and these are usueful for example for multi-pass approaches where you need to get exactly the same fragments in different passes.
Note that the other 3D rendering API are not pixel-exact either. The actual hardware implementations do vary between individual GPUs, and the specifications typically only specify broader rules that every implementation must fulfill, and you can rely on.

"GL_HALF_FLOAT" with OpenGL Rendering and GLSL

I am programming an OpenGL renderer in C++. I want it to be as efficient as possible and each vertex/normal/UV tex coord/tangents/etc to take up as little memory as possible. I am using indexes, line strips, and fans. I was thinking that 32bit floating points are not necessary and 16 bit Floating points should be fine, at least for some of these like normals and UVs. I can't seem to find any examples of this anywhere. I can find talk of "GL_HALF_FLOAT", but no real examples. Am I on the right track? Or is this not worth looking in to? If anyone knows of an example of this could they send a link of source code?
In full OpenGL (unlike in OpenGL ES), shader code always operates with 32-bit floats. Starting with OpenGL 3.0, specifying vertex data as half-floats is supported, though. If the precision is sufficient for your needs, this can reduce memory usage for your vertex data, and reduce the bandwidth needed for vertex fetching.
Keep in mind that the precision of a half-float is only about 3-4 decimal digits. So the accuracy really is seriously limited.
As for how to use them, it's quite straightforward. If you have a pointer to half-float values, you store them in a VBO using glBufferData() or glBufferSubData(), just like you would for any other type. The glVertexAttribPointer() call will then look like this, using an attribute with 3 components as an example:
glVertexAttribPointer(loc, 3, GL_HALF_FLOAT, GL_FALSE, 0);
The format of the data itself is defined in the ARB_texture_float extension. While it's not officially named, it looks at least very similar to the IEEE 754-2008 format. I wrote conversion code based on that Wikipedia format description before, and it worked fine for OpenGL usage.
Most languages don't have built-in types for half-floats. So you either will have to write a few lines of code to do the conversion from float to half-float, or use code that somebody else wrote.
The following resources about half-float conversion are from a quick search. I have no personal experience with any of them, and you should do your own search to find the one most suitable for your needs:
Interesting article from Intel, explaining possible performance benefits: https://software.intel.com/en-us/articles/performance-benefits-of-half-precision-floats. This also mentions that Intel processors have instructions for the conversion (e.g. there's a _mm256_cvtps_ph intrinsic to convert from float to half-float).
Open source library for half-float operations and conversions: http://half.sourceforge.net/.
gcc documentation saying that it supports a half-float type (__fp16) for ARM targets.

OpenGL: Is aliasing a predictable and consistent phenomena?

This may be a weird question, but I need to know if the way OpenGL aliases the edges of drawn geometry (polygons, lines, etc) is "consistant", meaning it looks the same across different platforms/hardware.
Aliasing in this case is the sharp edges that "anti-aliasing" aims to remove. I want aliasing however, and would like to use it for animation techniques that need the aliasing effect to be pixel perfect (it's for sprite-type effects). Is this feasible, or is it impossible to predict how it'll alias across different computers?
No it is not. To quote the spec (any version, Appendix A: Invariance):
The OpenGL specification is not pixel exact. It therefore does not guarantee an exact match between images produced by different GL implementations. However, the specification does specify exact matches, in some cases, for images produced by the same implementation.
So there might variation. Also consider that some graphics drivers allow the user to force antialiasing, overriding the application's settings.

OpenGL pixel precise rasterizing on different archs

for an application I'm developing I need to be able to
draw lines of different widths and colours
draw solid color filled triangles
draw textured (no alpha) quads
Very easy...but...
All coordinates are integer in pixel space and, very important: glReading all the pixels from the framebuffer
on two different machines, with two different graphic cards, running two different OS (Linux and freebsd),
must result in exactly the same sequence of bits (given an appropriate constant format conversion).
I think this is impossible to safely be achieved using opengl and hardware acceleration, since I bet different graphic
cards (from different vendors) may implement different algorithms for rasterization.
(OpenGl specs are clear about this, since they propose an algorithm but they also state that implementations may differ
under certain circumstances).
Also I don't really need hardware acceleration since I will be rendering very low speed and simple graphics.
Do you think I can achieve this by just disabling hardware acceleration? What happens in that case under linux, will I default on
MESA software rasterizer? And in that case, can I be sure it will always work or I am missing something?
That you're reading back in rendered pixels and strongly depend on their mathematical exactness/reproducability sounds like a design flaw. What's the purpose of this action? If you, for example, need to extract some information from the image, why don't you try to extract this information from the abstract, vectorized information prior to rendering?
Anyhow, if you depend on external rendering code and there's no way to make your reading code more robust to small errors, you're signing up for lots of pain and maintenance work. Other people could break your code with every tiny patch, because that kind of pixel exactness to the bit-level is usually a non-issue when they're doing their unit tests etc. Let alone the infinite permutations of hard- and software layers that are possible, and all might have influence on the exact pixel bits.
If you only need those two operatios: lines (with different widths and colors) and quads (with/without texture), I recommend writing your own rendering/rasterizer code which operates on a 8 bit uint array representing the image pixels (R8G8B8). The operations you're proposing aren't too nasty, so if performance is unimportant, this might actually be the better way to go on the long run.