Jump to content


Blurring a cube map?


7 replies to this topic

#1 starstutter

    Senior Member

  • Members
  • PipPipPipPip
  • 1039 posts

Posted 13 February 2008 - 06:09 PM

So I'm trying to take a few pointers from Valve's "ambient cube" that they use for their lighting scheme. I have not tried to blur a cubemap yet, but in my mind, it wouldn't really work out if I did. I would think that near the edges of the cube, the blur would be kind of cut off and distorted.

So, my question is, how do I go about blurring a cube map (in all directions, not just one). Also, if anyone has any idea of how to generate a sphere-map (like renering the surrounding environment) in runtime, that would be great too.

#2 Vilem Otte

    Valued Member

  • Members
  • PipPipPip
  • 215 posts

Posted 13 February 2008 - 08:45 PM

Blurring a cubemap - the best way to compute that, is to precompute that - but I presume you need to compute it dynamically, so you could use 3 dimensional kernel blur (and no clamping on texture):
BTW. I presume you've got mapSize for all three dimensions of cubemap the same

for(i = -kernel; i < kernel + 1; i++)

{

          for(j = -kernel; j < kernel + 1; j++)

          {

                    for(k = -kernel; k < kernel + 1; k++)

                    {

                              blurredCube = textureCube(Cubemap, 

                                        reflectionCoord.xyz + vec3(i * 1.0/mapSize, 

                                        j * 1.0 / mapSize, k * 1.0/mapSize)

                    }

          }

}

blurredCube /= 6 * kernel + 3;

Anyway this is HUGE PERFORMANCE HIT, I'd use lower cubemap size (scaling can be achieved gluScaleImage() function) and linear texture filters (much more better than using kernel to blur big cubemap, cause kernel is slow!!!).

#3 Reedbeta

    DevMaster Staff

  • Administrators
  • 4979 posts
  • LocationBellevue, WA

Posted 13 February 2008 - 08:56 PM

To blur a cube map, basically you need to think of blurring over directions rather than over texels. For each texel in the output, you need to find which direction that texel corresponds to and then average the input over a cone of directions surrounding that. So you can think of intersecting the cone with the cube and figuring out which cube texels are in the cone, and then averaging them, but weighting each cube texel according to how much solid angle it subtends (for narrow cones, this is approximately the same as its area when projected onto a plane perpendicular to the cone axis). You might also weight the texels by some function of the angle from the cone axis (e.g. a triangle function, Gaussian, cosine raised to a power, etc. depending on what the cubemap is used for).

The algorithm as I described it above is probably fairly slow. I'm not sure however if there's any clever way to speed it up like by using separability or something like you can for a flat image.
reedbeta.com - developer blog, OpenGL demos, and other projects

#4 Vilem Otte

    Valued Member

  • Members
  • PipPipPip
  • 215 posts

Posted 13 February 2008 - 09:29 PM

#Reedbeta - well, it'd take lot of time to computation. Anyway that texel-based kernel too (maybe even more computation time), so the best would be to use smaller cubemap (F.e. 32*32 pixels for each of 6 faces) and use linear filter - solution would look like blurred cube map and It'd be damn fast (I tested that today using OpenGL - 7x7x7 kernel on cubemap with few dozens of fps or smaller linearly filtered cubemap with several hunderts of fps -> that's quite a difference don't you think?)

#5 starstutter

    Senior Member

  • Members
  • PipPipPipPip
  • 1039 posts

Posted 14 February 2008 - 12:06 AM

Vilem Otte said:

Blurring a cubemap - the best way to compute that, is to precompute that - but I presume you need to compute it dynamically.

actually no, this is to be pre-computed. Although I do plan to implement a dynamic version in the future. This is a little strange lighting idea I'm messing with that involves pre-computing the patterns of unpredictable dynamic light. However, it will only be good for lower frequency and indirect light, I think the reasons for that are fairly obvious. Unfortunatley I don't think the simple downscaling will work because the level of blur I need would make the image practically unrecognizable, but at the same time, I need to preserve very bright (small) spots in the image.

Also, is that code for a shader or the application? I'm not familiar with openGL in any way, shape or form. I'll just assume it's shader code for now, just not used to seeing it like that.


Anyway, thank you both for your input, and Vilem I can't quite imagine mathmaticly how your method would work (but then again I'm bad at math :P ), but it seems logical to me. I just didn't figure it would be that simple.

#6 CheshireCat

    New Member

  • Members
  • PipPip
  • 19 posts

Posted 14 February 2008 - 06:05 AM

Bear in mind that you get no filtering across cubemap faces which may be a problem with low-resolution cubemaps causing discontinuities in the lighting.

#7 Vilem Otte

    Valued Member

  • Members
  • PipPipPip
  • 215 posts

Posted 14 February 2008 - 12:31 PM

Quote

Bear in mind that you get no filtering across cubemap faces which may be a problem with low-resolution cubemaps causing discontinuities in the lighting.

Yeah, that's true - you must find good balance value -> middle resolution + small kernel (and that'd create nice blurred cubemap). If you'd use so small cubemap, there'd be issues with edges of cubemap of course ;).

Quote

Also, is that code for a shader or the application? I'm not familiar with openGL in any way, shape or form. I'll just assume it's shader code for now, just not used to seeing it like that.

That code is for shader. (btw. it's pseudo-code not actually the code)

Quote

Anyway, thank you both for your input, and Vilem I can't quite imagine mathmaticly how your method would work (but then again I'm bad at math :P ), but it seems logical to me. I just didn't figure it would be that simple.

Well, that method is quite simple. Kernel will help you with this, but it'd be slow on GPUs with small fillrate and computational power.
Precomputing is good as far as you're NOT using moving lights or lights that can be turned off (well, you could precompute that data, but that'd be plenty of megabytes for that purposes), this can solve dynamic ambient cube mapping with some kind of tree (when to render which cube - most affected first, less affected after).
Back to that kernel blur - what is blur? Blur is sum of sorrounding area of the pixel - so it can be calculated like (3 * 3 kernel blur of 2D texture, on pixel[x][y]):
blur3x3 = (pixel[x-1][y-1] + pixel[x][y-1] + pixel[x+1][y-1] +
pixel[x-1][y] + pixel[x][y] + pixel[x+1][y] + 
pixel[x-1][y+1] + pixel[x][y+1] + pixel[x+1][y+1]) / 9;
So it's standart sum (adding sorrounding pixels divided by their number). To the code for cubemap - cubemap coordinates are stored in X, Y and Z not X and Y axis - so it have to be summed over three directions. I'm beginning at minus kernel, cause i want to blur sorrounding area in every positive and negative direction (not only positive). And I'm ending at kernel + 1, cause tag < is much faster than <= in GLSL (and i think even CG or HLSL) languague. I sum all colors into one vec3 (also can be vec4, or float [3], etc.), and at last I need to divide that by number of kernel steps (thats for positive axes 3 * kernel, for negative axes 3 * kernel and + 3 cause we're not counting points x=0 y=0 z=0!!!)

I hope that this math explanation is understandable (I was born in Czech Rep. and I live there, so my english isn't the best).

I appologize for long posts.

#8 starstutter

    Senior Member

  • Members
  • PipPipPipPip
  • 1039 posts

Posted 14 February 2008 - 05:25 PM

Vilem Otte said:

I hope that this math explanation is understandable (I was born in Czech Rep. and I live there, so my english isn't the best).
Besides the occasional missed fill word it's perfectly clear. Your english is better than some Americans I know. :lol: . "ya no, cuz tokin like diz is kool"

Vilem Otte said:

I appologize for long posts.
Why would you do that? Most posts suffer from being too short. That's one reason I left GameDev so early, half the responses people get are either "see the SDK" or "google it retard". Anyway, it's good to be informative rather than assuming :)





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users