Sign in to follow this  
mlt

Dot product in Cg?

Recommended Posts

mlt    138
I have the following test in a fragment shader:
float2 test1 = (1,1);
float2 test2 = (1,15);
float res    = dot(test1, test2);
	
if (res == 16) {
  color = (0.0,0.0,0.0,0.0);
} else {
  color = (1.0,1.0,1.0,1.0);	
	
}	

But it outputs black instead of white, why!?

Share this post


Link to post
Share on other sites
mlt    138
Sorry I of course mean that it prints WHITE, which it still does.
I have also tried:

float res = test1.x*test2.x+test1.y*test2.y;

but it still prints white.

Share this post


Link to post
Share on other sites
Daivuk    413
This is weird indeed, and it is not the first time I get problems with if statements in CG.

I would say, always try to avoid if statements in a shader. Do it mathematically if possible.

EDIT: Or it might be because of a shader imprecision. Try something like:
if (res > 15.9 && res < 16.1)

Share this post


Link to post
Share on other sites
mlt    138
The problem is that I have written a function that at some point does the dot product and that function currently does not give the correct result.

I have written the same function in matlab and it gives the correct result, but for some reason it does not work in Cg:


float sineWave(float4 wave_spec, float2 pos, float2 direction, float time, float k){

// Currently testing with hardcoded values.
float amplitude = 1.0;
float freq = 1.0;
float speed = 10.0;

float frac = (sin(dot(direction,pos)*freq+time*speed)+1)/2;
float res = 2*amplitude*pow(frac,k);
return res;
}






I have a feeling that its the dot product that gives the problem (since a very simple use of this as previously described does not give the correct result), but I have no idea on how to debug/see the returned value.



EDIT: I have now tried:



float2 test1 = (1,1);
float2 test2 = (1,15);
float res = dot(test1, test2);

if (res > 25 && res < 35) {
// Black
color = (0.0,0.0,0.0,0.0);
} else {

// White
color = (1.0,1.0,1.0,1.0);
}




and now it prints black, so the dotproduct of test1 and test2 is somewhere in-between ]25;35[ which of course still makes no sense what so ever.

Share this post


Link to post
Share on other sites
Ximmer    314
I couldn't get it to work until I changed the code to:


vec2 test1 = vec2(1.0,1.0);
vec2 test2 = vec2(1.0,15.0);
float res = dot(test1, test2);

if(res == 16.0)
{
gl_FragColor = vec4 (0,1,0,1);
}else{
gl_FragColor = vec4 (1,0,0,1);
}





was getting all kinds of warnings trying to compile the original version of that

Share this post


Link to post
Share on other sites
V-man    813
You code is invalid. It should be


if (res == 16.0)
{
color = vec4(0.0,0.0,0.0,0.0);
}
else {
color = vec4(1.0,1.0,1.0,1.0);

}


notice I added vec4 in
color = (0.0,0.0,0.0,0.0);

Share this post


Link to post
Share on other sites
mlt    138
You are right, though its before the if statement that the problem occurs and its float2/float4 in Cg and not vec2/vec4. Here is how it worked out:



float2 test1 = float2(1,1); //Notice the use of float2 on RHS
float2 test2 = float2(1,15); //Notice the use of float2 on RHS

float res = dot(test1, test2);
if (res == 16) {
// Black
color = float4(0.0,0.0,0.0,0.0);
} else {
// White
color = float4(1.0,1.0,1.0,1.0);

}

Share this post


Link to post
Share on other sites
phresnel    953
I am not sure if Cg takes the precision of floating point numbers automatically into account, but I bet it doesn't. Surely, google won't be silent. But as a general device:


  • Never use the equality operator ('==') on floating point numbers (that includes floats, double, long double, in C/C++)

  • Floating point numbers *are* imprecise, as compared to integers (which is the reason why often business software works entirely on integer numbers, using floats there could decide about the next million € loss)

  • E.g. 'float x = (1/y) * y' will generally not yield the same as 'float x = y;', and a serious compiler won't make that optimisation, because it would violate IEEE floating point laws (unless you explicitly set a flag to do it anyway)



Wikipedia explains the reasons for this, especially here.

There exist different workarounds to this, but the canonical beginners' workaround is something like:

const float epsilon = 0.00001;
...
float x = ...;
float y = ...;
if (x > y-epsilon && x < y+epsilon) {
...
}





Actually, a proper definition of epsilon is not very easy to beginners, so something like the above is a good start. Make it smaller or higher on purpose.

In Ray Tracing, this can be really annoying, as there is often no difference between "Hitpoint on surface" or "Hitpoint directly above it", so there more complicated solutions then the above, because the epsilon sometimes should depend on the actual size of the floats, but I don't want to go into too much detail for now.

Later, you might consult "What every Scientist should now about Floating-Point Arithmetic", which is a gem and should be standard lecture for every graphics programmer (though I myself haven't read it completely yet).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this