Posts Tagged ‘rm’

Input / Output with GPUs

It has been a while since my last blog post. Anyway, talking with Junskyman about the Translucent Shadow Map technique, a problem aroused: how do the GPU handles data within textures?

Before dealing with this, it might be better starting with the basics: let’s then talk about Input / Output with GPUs.

When you define a texture, you also specify it’s Format, Internal Format and expecially it’s type:

glTexImage2D( target, level, iFormat, w, h, border, format, type, *data );

with the InternalFormat you basically define how many channels are being used in that texture, while format specifies the format of the input data defined in *data.

Type, however, tells the OpenGL pipeline how the data associated with the texture is to be treated.

From now on one could decide to work exclusively on GPU thanks to shaders, or instead allowing the CPU to handle some of the operations.

As for the CPU/GPU approach, usually getting data from GPU is done by glReadPixels(). It copies the texture data located in the VRam into an array. Pay attention that if the array’s type differs from texture’s type, will result in artifacts and wrong data being read. Usually, with floating point textures, there are no restrictions in the output values (they can be both positive or negative).

Integer texture type, instead, forces data to be converted from floating point (if that’s the case with original data stored in VRam) to Unsigned Integer. Negative or greater than 8bit values are simply clamped in 0 … 2^8 range.

The same thing applies with data processed using the shaders-only approach, but in this case are also normalized in -1.0 … 1.0 range. But, let’s say we want to transfer negative data using integer textures. In this case, we simply have to map the original values according to the following equation:

vec4 convData = origData * 0.5 + 0.5;

A weird thing happened while using RenderMonkey, however. In RM, even if you set texture type to GL_RGBA32F, assigning negative data results in clamping. Therefore, compacting data in 0.0 … 1.0 range and then scale it back to -1.0 … 1.0 range is mandatory.

In my past tutorial I made some changes to the source code, removing this conversion since it should not be needed in a real world application.

At the end, my advice is simple though: always pay attention to the range of values your data have at any time, and use fewer conversions as possible, since it always introduces errors.

Categories: OpenGL Tags: , , , ,