View Full Version : Blurring a cube map?
starstutter
02-13-2008, 11:09 AM
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.
Vilem Otte
02-13-2008, 01: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!!!).
Reedbeta
02-13-2008, 01: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.
Vilem Otte
02-13-2008, 02: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?)
starstutter
02-13-2008, 05:06 PM
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.
CheshireCat
02-13-2008, 11:05 PM
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.
Vilem Otte
02-14-2008, 05:31 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.
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 ;).
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)
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.
starstutter
02-14-2008, 10:25 AM
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"
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 :)
vBulletin, Copyright ©2000-2010, Jelsoft Enterprises Ltd.