Cubemap offset blur

Hi! I know how to blur a 2D texture using a filter kernel… Something like:

   vec2 off = vec2(1/texWidth,1/texHeight);
   vec2 uv = gl_TexCoord[0];

   vec4 col = texture2D(myTex,uv)*0.25 +
      texture2D(myTex,uv+off)*0.25 + 
      texture2D(myTex,uv+vec2(off.x,0))*0.25 +
      texture2D(myTex,uv+vec2(0,off.y))*0.25

you know the concept…

BUT, how can I do that with a cubemap texture if I only know the normalized vector? I see somebody does this:

   textureCube(myTex,dir+vec3(2.0,1.0,-1))
   textureCube(myTex,dir+vec(-1.0,2.0,1.0))

But I don’t know why… Adding those vectors you will get only weird data… How can I get the offsets to get the neighbor pixels in a cubemap??? Divide by greatest XYZ element and see signs to know the face and then use the texture2D approach? Derivatives? Hooooooooooow? Ofc I don’t want to unwrap the cubemap into a 2D texture like in the ShaderX3 and neither like NVIDIA did with Mike’s demo…

Notice perhaps is very easy to achieve this using “texture-coord wrapping mode”, specifying a (s,t)+(1.0,-1.0) and using special texture clamp mode perhaps could give you the neighbors… I think thats why some people do the textureCube(tex,off+(2,1,-1)). Any ideas?

thx.

My first thought is to use the axis directions in the spec to recreate the texgen in the shader, then just try to simplify it from there. Haven’t really tried it.

Maybe there’s a simpler way?

try the following (u will want a much smaller number than 1 though)
textureCube(myTex,dir+vec3(1,0,0))
textureCube(myTex,dir+vec3(-1,0,0))
textureCube(myTex,dir+vec3(0,1,0))
textureCube(myTex,dir+vec3(0,-1,0))
textureCube(myTex,dir+vec3(0,0,1))
textureCube(myTex,dir+vec3(0,0,-1))
find the average of the resulting values

Originally posted by zed:
try the following (u will want a much smaller number than 1 though)
textureCube(myTex,dir+vec3(1,0,0))
textureCube(myTex,dir+vec3(-1,0,0))
textureCube(myTex,dir+vec3(0,1,0))
textureCube(myTex,dir+vec3(0,-1,0))
textureCube(myTex,dir+vec3(0,0,1))
textureCube(myTex,dir+vec3(0,0,-1))
find the average of the resulting values

Tryed and gave weird results using dir normalized and unormalized. It is logical I think… If I have a direction like (0,0,1) then that code will average this ( sorry for the ugly ASCII )

          h
   *------·N------*
   |      |       |
   |     dir      |
   |      |       |
   |      *       |
   |              |     Z+
   |              |     |
   *--------------*     *-->X+

Dir(normallized in this case) hits in the "h" texel. I want to get the "N" texel. Adding (1,0,0) as suggested then I will get:

          h       h' 
   *------·N------*
   |      |     / |
   |     dir  /   |
   |      | /     |
   |      *------>|
   |        1,0,0 |    Z+
   |              |    |
   *--------------*    *-->X+

I will get "h'" which is far far from the "N" pixel. "h'" is very problematic too because is at an edge!

I could try with 1.0/(cubeTexFaceWidth*0.5), but then I have other problem… You need to know the face signs because adding (1,0,0), (-1,0,0), (0,1,0), (0,-1,0), (0,0,1) and (0,0,-1) to the dir will give you texels in other cube faces that you don’t want to get. Is problematic, indeed.

I really don’t understand why these both omidirectional cube shadowmap examples add (-2,1,-1) to the unormalized vectorToLight to PCF-blur the shadows:

http://www.quakewars.jp/slang/files/demos/flx_ovsm.zip
See the cube_blur.vsh and cube_3x3_blur.fsh
http://www.realityflux.com/abba/C++/Stained%20Shadow%20Maps/StainedShadowMaps.zip
See the Phong.xml

I think they use a trick adding that value to hack the clamp_to_edge mode and get the neightbor texel but not sure…

The Nvidia demo team had a clever trick for blurring cubemaps where there do 3 cylindrical blurs (X, Y and Z) - see page 100 here:
http://download.nvidia.com/developer/presentations/2005/SIGGRAPH/Truth_About_NVIDIA_Demos.pdf

Ya thx simon.

The problem is that technique is more to brutally-blur an environment map and what I want is just to do a kernel to blur a few some edges. I am sure there must be a non-painful technique to do this…

try the following (u will want a much smaller number than 1 though)
what value for 1 did u use?
i’ld try with 1/texsize

Thx zed, I think that will work!

However, why the mentioned demos use the (2,-1,1) thing? any idea?

Anyone have a working implementation of the technique that Simon Green posted? (I’ll give you a star and high praise for it.)