QUOTE(crunch @ May 1 2008, 11:05 AM)

The texture() function uses the surface derivatives to sample an area of the texture map.
My guess is that what you're experiencing is most likely due to the fact that you're using a modulo function, or some other function which has discontinuities.
Hey crunch,
I just read your post, and everything you say makes perfect sense, but I think that what rdg is seeing is a different issue (related perhaps, but different). I made some tests and would love to hear your take on this.
In the "classical" bombing scenario, you set up a virtual grid of cells over the bound texture uv's. Each cell is a 1X1 domain where each bomb is placed. Each bomb's extent is restricted to a maximum size of 1X1 and allowed to be placed at a random location within the cell (which implies the need for a unique ID or random seed for each cell). The shader then loops over a 3X3 cell neighborhood (to allow for overlaps) placing a bomb in each cell. This is different from a pulse train where a modulo would be involved (and be subject to the issues you mentioned).
Here's a simple version of that classical setup:
CODE
surface bomb2(
string map = "";
float bfreq_u = 10;
float bfreq_v = 10;
vector uv = 0;
)
{
// incoming uv's
float u=s,v=t;
if(isbound("uv")) { u=uv.x; v=uv.y; }
// underlying bombing uv's
vector buv = set(u*bfreq_u, v*bfreq_v, 0);
// central cell coords in the virtual grid
vector cell = floor(buv);
vector C = 0; // final bomb color
// loop over the 9-cell neighborhood centered at 'cell'
float i,j;
for(i=-1;i<=1;i+=1) {
for(j=-1;j<=1;j+=1) {
// c = the test cell
vector c = cell+set(i,j,0);
// p = the bomb pos within the test cell
vector p = c + random©*{1,1,0};
// texture coords relative to bomb position
vector tp = (buv-p)+{.5,.5,0};
float du = abs(Du(tp.x))*.5;
float dv = abs(Dv(tp.y))*.5;
if(tp.x>=-du && tp.x<=1+du && tp.y>=-dv && tp.y<=1+dv) {
if(map!="") {
vector4 Ctx = texture(map,tp.x,tp.y,"mode","black");
C = lerp(C,(vector)Ctx,Ctx.w);
} else {
float a = (filterstep(0,tp.x)-filterstep(1,tp.x)) *
(filterstep(0,tp.y)-filterstep(1,tp.y));
C = lerp(C,set(tp.x,tp.y,0)*a,a);
}
}
}
}
Cf = C;
}
If you don't give it a texture map it displays each bomb's uv space -- easier to see the problems this way, and there's not texture() call involved. So, at default, that shader produces this result:
Click to view attachmentThe artifacts are aligned to the cell boundaries, and the way I read it is that they're caused by the floor() and random() functions having infinite frequency at those boundaries -- i.e: the assignment to 'cell' will jitter wildly when crossing these regions and so will the entire 3X3 neighborhood as a result.
The problem is... I can't think of any way to avoid this (at least not within the structure of this classic algorithm). As given, it
depends on a unique ID/seed per cell, but by definition, all the tools we can use to generate such an ID will be unstable at the cell boundaries.
And that's my question: can you think of a way to avoid this problem while keeping the overall cell-based approach?
The only way I could come up with involves completely changing the algorithm: Erasing the boundary/cell dependency by generating all points at all times... not as expensive as it may sound, but a different approach altogether:
CODE
surface bomb3(
string map = "";
float bfreq_u = 10;
float bfreq_v = 10;
vector uv = 0;
)
{
// incoming uv's
float u=s,v=t;
if(isbound("uv")) { u=uv.x; v=uv.y; }
vector buv = set(u*bfreq_u, v*bfreq_v, 0);
vector C = 0; // final bomb color
// loop over all bomb positions
float i,j;
for(i=-1;i<=bfreq_u;i+=1) {
for(j=-1;j<=bfreq_v;j+=1) {
// bomb pos
vector p = random(set(i,j,0))*{1,1,0}+set(i,j,0);
// texture coords relative to bomb position
vector tp = (buv-p)+{.5,.5,0};
float du = abs(Du(tp.x))*.5;
float dv = abs(Dv(tp.y))*.5;
if(tp.x>=-du && tp.x<=1+du && tp.y>=-dv && tp.y<=1+dv) {
if(map!="") {
vector4 Ctx = texture(map,tp.x,tp.y,"mode","black");
C = lerp(C,(vector)Ctx,Ctx.w);
} else {
float a = (filterstep(0,tp.x)-filterstep(1,tp.x)) *
(filterstep(0,tp.y)-filterstep(1,tp.y));
C = lerp(C,set(tp.x,tp.y,0)*a,a);
}
}
}
}
Cf = C;
}
Click to view attachmentThis "fixes" the problem (doesn't really, just walks around it trying to ignore it

), but it has some drawbacks: The concept of "frequency" goes out the window (I just kept the parameter names for convenience), and the bombing domain is fixed (could be parameterized though).
Anyhoo... I'd love it if someone could come up with a *real* fix to the first version. So far, I got nothin'