- Home /
Cg and "for" statements, what's the deal?
I have this code:
float cnoise(float3 p)
{
float noise = 0;
float freq = _Frequency;
float amp = _Amplitude;
for (int i = 0; i < 2; i++)
{
noise += inoise(p * freq) * amp;
freq *= 2;
amp *= _Persistence;
}
return clamp(abs(noise), 0, 1);
}
Which works, don't get me wrong, though where you see the integer 2, in the expression i < 2; you should see _Octaves, or i < _Octaves.
It seems that if I add that variables, I get problems where the "for" statement is unsupported, and can not be unrolled.
Well, that's weird indeed.. Any insight on this problem, and how I might fix it? =]
good question. this works:
// fractal sum, range -1.0 - 1.0
float fBm(float3 p, int octaves)
{
float freq = _Frequency, amp = 0.5;
float sum = 0;
for(int i = 0; i < octaves; i++)
{
sum += inoise(p * freq) * amp;
freq *= _Lacunarity;
amp *= _Gain;
}
return sum;
}
Answer by Murcho · May 28, 2010 at 12:43 AM
Without seeing the entire shader I can't be certain, but I have a feeling it may have something to do with Instruction limits. Here is a list of the different shader models under Direct X and the limits within a shader.
Basically, if you're adding a variable to the for loop limit, the for loop could cause the shader to go over the available amount of instructions if set to a high value, however when set to 2 it knows how many instructions will be executed. You may be able to get around the compilation error by placing a clamp on the variable or something like that.
Interesting. I've never worked with shaders, didn't realize they had limitations like that. Guess it makes sense, given they run on every pixel.
Answer by reefwirrax · Sep 30, 2013 at 05:29 PM
Proper looping in shaders (dynamic branching) is only possible with Shader Model 4.0 (OpenGL 3 or DirectX 10). In previous shader models, things like for loops are "unrolled": that is, the compiler looks at the loop, sees how many times it will run, and actually copies out - or unrolls - the whole loop so it's as if you wrote them down one at a time. As for passing in an arbitrary number of textures... I think you'd at least have to define a maximum number, and then just use as many as you need. But yeah, you need a SM4-capable card to even get off the ground with dynamic branching. curses his 7300gt
You need to declare octaves as a static int for this to work. When unrolling a loop, the iteration count has to be a compile-time constant; without the static on there, the compiler has to assume you might change the value of the parameter at runtime.