Real world example where 24-bits isn't enough for graphics.

bloodbob

Trollipop
Veteran
Well not really doing any shader stuff till today ( was fiddling with the shaders in humus' latest demo ) I really didn't expect to hit the 24-bit limit so soon.

Where I hit the 24-bit limit for reference was converting a texture into HSV modifing the hue value and converting back to RGB. There is conditional code based on the hue value but with the lack of precision certain textures ( such as enivorment maps in humus' demo ) end up following the incorrect branching.

Can anyone else give me some real world examples where 24-bits just isn't enough.
 
The shader 23 (water colour like rendering) in ShaderMark v2.0 is a real simple shader(summed area tables), but if you run it at high resolutions (1600x1200) you will see some wrong coloured pixel on the r3xx. With the refrast. they are gone, I think because of the 32 bit prec. per component.

Thomas
 
HSV to RGB and back should work just fine with 24bit. Heck, I implemented that using 3D texture lookups in 8bit/channel when I was at ATI, and the results were virtually identical to those using full math. The full math example is included in the latest RenderMonkey if you want to take a look at it.
 
My water.shd try it out and notice the pink stuff. Then remove the line of code as mentioned in the comments. I have you a nicer way for me to wrap the range please feel free to tell me.

By the way normal its a range 0-360 but for obvious reasons I've worked with 0-6.

Code:
[Vertex shader]

float4x4 view_proj_matrix;
float3 camPos;

struct VS_OUTPUT {
   float4 Pos: POSITION;
   float2 texCoord: TEXCOORD0;
   float3 viewVec:  TEXCOORD1;
};

VS_OUTPUT main(float4 pos: POSITION, float2 texCoord: TEXCOORD0){
   VS_OUTPUT Out;

   Out.Pos = mul(view_proj_matrix, pos);
   Out.texCoord = texCoord;
   Out.viewVec = pos - camPos;

   return Out;
}


[Fragment shader]

sampler Tex: register(s0);
sampler Env: register(s1);
float off;


float4 main(float2 texCoord: TEXCOORD0, float3 viewVec: TEXCOORD1) : COLOR {
float4 texy = texCUBE(Env, float3( texCoord , 0.5 ));

   

   float min = min( min (texy.x, texy.y), texy.z );
   float maxy = max( max(texy.x, texy.y), texy.z );
   float delta = maxy-min;
   float s = delta / maxy;
   float h= ( texy.y - texy.z ) / delta;
  if( texy.x == maxy )
   {

   }
   else if( texy.y == maxy )
   {
   h = 2 + ( texy.z - texy.x ) / delta;
   }
else
   {
   h = 4 + ( texy.x - texy.y ) / delta;
   }


if( h < 0.0 ) h+=6.0;
h=clamp(h, 0, 6.0);//(h,6.0);

h=frac(h/6.0)*6.0; /// THE PROBLEM LIES HERE WHEN I DO MODIFICATION HERE
// AND THEN USE FRAC TO WRAP THE VALUES TO THE RANGE [0,6] I LOOSE TO MUCH PRECESSION
// NO MODIFICATION IS BEING DONE IN THIS CODE REMOVE THIS LINE AND NOTICE THE ARTIFACTS ARE GONE

int i = floor (h);
float r,g,b;
   float f = h - i;       
   float p = maxy * ( 1 - s );
   float q = maxy * ( 1 - s * f );
   float t = maxy * ( 1 - s * ( 1 - f ) );

if( i == 0 )
   {
   r = maxy;
   g = t;
   b = p;
   }
else if( i == 1 )
   {
   r = q;
   g = maxy;
   b = p;
   }
else if( i == 2 )
   {
  r = p;
         g = maxy;
        b = t;
        
   }else if( i == 3 )
   {
  r = p;
         g = q;
         b = maxy;
   }else if( i == 4 )
   {
   r = t;
         g = p;
         b = maxy;
   }
else{
r = maxy;
         g = p;
         b = q;
}

   return float4( r,g,b,0);


}
 
Well, the == operator is always sensitive to precision. Especially since DX9 HLSL implements floor(x) as x - frac(x). So you should be using < instead. Like this:

Code:
if( h < 1 ) 
{ 
   r = maxy; 
   g = t; 
   b = p; 
} 
else if( h < 2 ) 
{ 
   r = q; 
   g = maxy; 
   b = p; 
} 

...
 
Spanks humus very nice still I guess this is where we need true integer support I assumed incorrectly that it would return the closest float representation of the integer.
 
Back
Top