   Bilinear sampling of cube map using CPU.
  Hi,I'm currently trying to speed up a piece of code, basically it's an expensive function that returns a value based on a direction vector (in 3D).Since the function is more or less static and rather smooth I was thinking of  storing pre-computed values in a cube map.So my first question is how to efficiently sample a cube map using a bilinear filter that avoids the seems at face borders?Secondly, since this is all running on a CPU I'm not bound to using cube maps but rather any data structure would do.I was thinking about spherical harmonics since they seems very suitable for this.However, I have some concerns since I need a lot more detail than the typical usage of SH (diffuse lighting etc).Initial tests seems to indicate that I need to have a cube map size of around 128 pixels in order to capture enough details of the function.What's the performance for evaluating higher order SH's?Are there any precision problems (floats, doubles) when evaluating higher order SH's?Another idea I had was to calculate the value of N points uniformly spread over the sphere surface.Store them in a KD-tree or similar for fast lookup, is there a way to get a smooth function from k-nearest neighbour points?Any other ideas?Cheers,Eq   
Quote:So my first question is how to efficiently sample a cube map using a bilinear filter that avoids the seems at face borders?If your six square textures all share edge pixels with adjacent ones, and if you identify these rows/columns of pixels as actually corresponding to the same point on the cube edge, you should entirely avoid seems.  You'd just have to be careful about some +1 and -1s in your indexing code at the edges...Quote:Another idea I had was to calculate the value of N points uniformly spread over the sphere surface.Store them in a KD-tree or similar for fast lookup, is there a way to get a smooth function from k-nearest neighbour points?Sure... radial basis functions, for one.  I don't think I'd actually use this approach though.   ;  Thanks for the reply, you don't happen do have an idea on how to implement the look up in a clean/fast/robust way?In my mind I see a lot of conditionals and logic which isn't to fast.Reading my question again I realize that using SH or any other representation isn't really what I need, they are all about COMPRESSING data on the sphere surface, but I'm more interested in REPRESENTING data.I wonder if I could tessellate an icosahedron and storing the data at the vertices, that would solve edges but maybe it's too expensive.First finding which triangle a vector belongs too, then subdivide, normalize and recheck.. and so on?;Quote:Original post by eqI was thinking about spherical harmonics since they seems very suitable for this.However, I have some concerns since I need a lot more detail than the typical usage of SH (diffuse lighting etc).What's the performance for evaluating higher order SH's?You could in theory get as much detail as you want to using enough coefficients. However as you go up each 'level of detail' the number of coefficients increases exponentially (2*l+1 coefficients at each level).Even with a lot of coeficients, this could potentially still be quite fast compared to the cube map -- the data set is still quite small compared to a cube map, every sample uses the same data instead of fetching different parts and there's no branching.Quote:Original post by eqThanks for the reply, you don't happen do have an idea on how to implement the look up in a clean/fast/robust way?In my mind I see a lot of conditionals and logic which isn't to fast.A few ideas for avoiding seams without excessive branching:* Add a 1px border to each face, fill with the edge pixels of the adjacent faces. One group of conditionals to select the right face, then just math to fetch/lerp the nearest 4 texels.* Don't branch. Add a 2px border to each face and with alpha of zero in the border region and alpha of 1 in the non-border region. Fetch 4 samples from all faces (clamping to the border region) and generate their weights as usual. Multiply each sample's weight with it's alpha to reject the 20 invalid samples from the total 24 samples.   ;  if your cubemap is some static one, you could transform it once into a 360 degree panorama and sample from that. That gave me the best result, although there was some stretching and the texture needed to be higher res, it was still faster when bilinear filtering was enabled (to have it correct I had to use this complex if-else-if-else.. lookup for cubemaps, 4times per pixel and that killed the performance).   ;Quote:Original post by HodgmanYou could in theory get as much detail as you want to using enough coefficients. However as you go up each 'level of detail' the number of coefficients increases exponentially (2*l+1 coefficients at each level).Why would you need any more SPH coefficients than cube map samples?I know it's not quite as straightforward as the FFT, which takes N numbers, returns N numbers, and is invertible.  But I get the feeling that it should have the same general character...  Here's what I mean:Bilinear-interpolated cube maps are also sums of basis functions on the sphere.  The basis functions in this case are translations of the bilinear interpolation influence function, composed with the inverse of the cube-map coordinate chart.  They're also linearly independent, so their span is an N-dimensional subspace of L^2.The SPH basis functions are all orthogonal and square integrable, so their span is also an N-dimensional subspace of L^2.Hence in either case we have an N-dimensional subspace of L^2.There's even a nice bijection between the two, that you get by identifying points on the two subspaces V1 and V2 with their projections onto the subspace (1/2)(V1+V2) -- sort of a "best bijective approximation."So, though I haven't put my finger precisely on why, I get the feeling that you'd never need more SPH coefficients.On the other hand, I appreciate that many smooth functions can probably be approximated with sparser expansions with an SPH basis than with a bilinear-cubemap basis (the latter is only sparse for functions that are zero most places!).Quote:Original post by Hodgman* Add a 1px border to each face, fill with the edge pixels of the adjacent faces. One group of conditionals to select the right face, then just math to fetch/lerp the nearest 4 texels.Yeah, that's what I was going for with my post.  It sounds like this also would have solved your branching performance issue, Krypt0n?   ;Quote:Add a 1px border to each face, fill with the edge pixels of the adjacent faces. One group of conditionals to select the right face, then just math to fetch/lerp the nearest 4 texels.I think I'll go for this approach, I was planning on using a swizzled (tiled) memory layout to increase cache-coherence since I'm pretty sure I'll benefit from that. Quote:Why would you need any more SPH coefficients than cube map samples?I'm sure that you don't need that, the problem as I see it that you need to read (access in memory) every coefficients for every look up...sounds slow to me,  correct me if I'm wrong?