I need to be able to output individual bits from a fragment shader.
I need a lot of bits per fragment too, otherwise I will face a tremendous performance drag.
Let's say that we have a whole bunch of single-direction lights, let's say 128 of them.
Let's also say that we have already rendered their depth buffers and have a huge FBO
Well, from the player-camera's perspective, All we really need to know from the depth buffer is whether or not an individual screen pixel is in a shadow or not.
I want to do a mid-level pass in my algorithm (Trust me- I have a reason) for testing whether or not a screen pixel is in the shadow of a particular light
As in, all the pixels have boolean values for each light stored in them
The thing is, I don't want Numlights of these buffers.
I would like to pack as many lights into one of these "Boolean Buffers" as I call them as possible. I want to be memory efficient.
(NOTE: I've devised a way to mix this with the shadow map generation too, i'm really trying to reduce the amount of gpu memory my algorithm uses)
Booleans are either 1 or 0. Conveniently, computers store data as ones and zeros.
This includes the output of a fragment, which is four GLfloats.
I'm wondering if it would be possible to manipulate individual bits of a GLfloat, to the maximum bitdepth of a float.
This would allow me to run through all my depth buffers (32 buffers at a time, even) and calculate the cansee/cannotsee of all my lights, 32 at a time (OpenGL allows for 32 texture units at once)
My depth buffers are stored as textures.
My algorithm theoretically works, however ANY evaluation of the floats' values when they are being read from or written to GPU memory will cause my algorithm to fail (Although it wouldn't crash...).
E.g. if Not-a-Number floats get evaluated as all zeros in bits (rather than directly copying the bits regardless of evaluation) then my boolean buffer will fail!
My algorithm also fails if there is any sort of clamping or estimation applied to the floats.
My questions are then as such:
- Are there any float values (in bits) that will be evaluated and copied incorrectly to/from GPU memory when a fragment is rendered or the texture2d call in glsl reads it?
- Is there any clamping or evaluation or estimation done on the output floats of a fragment shader? What are they?
- Is there a better way of outputting as many bits as possible from a fragment shader, that wouldn't have any weirdnesses? (E.g. changing the rendering mode to doubles or ints or something)
but... I would also like to tell you...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In case you're curious what I'm using it for... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'm developing a brand-new low-memory-footprint and relatively computationally efficient light and shadow rendering technique for rendering thousands of lights (my current plan is 128 per middle-pass FBO, as the bitdepth of a GLfloat is 32 and there are 4 floats output by the fragment shader... RGBA) which uses shadow mapping but I need to use middle-pass buffers filled with boolean data for whether or not a shadow can "see" a light. Using this along with of course all the light locations in the scene I can generate the lighting buffer (Stores the net color change of fragments due to lighting) using relatively few passes (For unidirectional lights, the number of passes to generate the lighting color buffer would be equivalent to 1 + Numlights(1 per light)(NumShadowmaps) + Numlights/128/32 (rounded up, next highest int)(Number of Middlepass BooleanBuffers) + Numlights/128/32/31 (rounded up, next highest int)(Number of Cumulative light color change buffer passes, 31 b/c we need to pass in the old cumulative buffer alongside all those boolean buffers)
if I was able to find someway to store more than 128 bits per fragment, say 256, then I could store even more lights! 1+Numlights + Numlights/256/32 + Numlights/256/32/31! SO MANY LIGHTS, SO FEW PASSES, SO LITTLE MEMORY! :D
The pass to generate the lighting color buffer of course gets a couple vector operations more complicated with every new light, but since the shader for my lighting color buffer automatically checks all its uniform variables to see if they are valid and only calculates what it needs to, and since I seperated out the shadowmapping process, it is not a huge impact. An additional shadowmap is usually the only additional complexity, with only shadowmaps that increase the number of middlepasses (multiples of 32) or cumulative color change passes (multiples of 128 times 31). Cumulative color change passes are additive, so there is no recursive effect or anything. We're not getting an infinite series of 1+1/32+1/(128*31)+...
if I ever manage to make it a reality, i'll see what I can do about uploading an open-source demo. I've been studying shadow algorithms for a couple weeks and very few algorithms seem to solve this apparent light-number-limit and computational complexity problem as efficiently as I do.
My solution becomes even more efficient with more unit textures allowed.
If I bothered to write much larger textures made up of a lot of smaller textures (I've heard this called "texels" but I hate the name), it could be even more efficient but I'm somewhat new to OpenGL and I don't feel like coding a huge complicated texel mess right now. it would actually decrease performance for a small number of lights too, and make the overhead for rendering the final pass larger.