October 2005


info and techno20 Oct 2005 07:37 am

Well, it’s been awhile since I meandered on over to Tom Nyuden’s Delphi3D OpenGL tutorial page. A few months ago a demo was posted that carried Tom’s usual statement that the application would likely only work with NV 68xx + graphics accelerators.

The ARB made a decision to choose GLSL over Cg as the supported high level shading language, beginning with the introduction of ARB_vertex_shader and ARB_fragment_shader OpenGL API extensions.

When NVIDIA released a compiler, it did so with a quite interesting set of
release notes
. This was done August 30th, 2004. Well over a year ago, NVIDIA admitted that they did not supply a conformant compiler and they’ve yet to do so. Thankfully, NVIDIA’s compiler does consume valid GLSL code, it is simply relaxed (consuming much of the Cg grammar as well). 3Dlabs came out with an open source tool called GLSL Validate that enables developers to ensure their code is portable. It simply is a specification conformant compiler front end that can run on any computer, even one without an OpenGL enabled graphics card!

For reasons unbenownst to myself and much of the OpenGL community, the tutorials found on Delphi3D have contained non-portable, non-compliant, syntactically incorrect OpenGL Shading Language shaders. They will only run on NVIDIA hardware because only the NVIDIA compiler accepts malformed code such as that contained within the demos.

My first attempt to correct this with the developer at Delphi3D resulted in him shutting down the thread I posted in and not responding to any of my emails or forum postings. One thing I will say with certainty is that the demos on Delphi3D are awesome! It is a shame that they are being promoted as GLSL demos and are ill formed! This posting will go over one of the shaders in his most recent demo, HDR rendering. (High Dynamic Range)

The shader that fails to compile on conformant hardware is the f_blur.glsl fragment shader. The OpenGL Shading Language Specification states in section 4.1.9 There is no mechanism for initializing arrays at declaration time from within a shader. Taking a look at line 6 of the shader, we see the following:

. . .
const float weights[] = {
1.0000,
0.9394,
0.7788,
0.5697,
0.3678,
0.2096,
0.1053,
0.0467,
0.0183,
};
. . .

Clearly, this array is being initialized. Since according to the specification there is no mechanism to do this, the parser should not consume this code. A compile time error should be generated. If the desire is for these to be const floats, this should be written as follows:

. . .
const float weight0 = 1.000;
const float weight1 = 0.9394;
const float weight2 = 0.7788;
. . .

In the shader’s main loop an array can be declared and the values inserted into the array.

. . .
float weights[9];
weights[0] = weight0;
weights[1] = weight1;
. . .

Next, there is a texture lookup that indexes into a two dimensional texture, using a vec4 to index into the two dimensional texture, whereas the spec requires a vec2.

//as written
. . .
vec4 color = texture2D(t_hdrimage, gl_TexCoord[0]) * weights[0];
. . .


//corrected
. . .
vec4 color = texture2D(t_hdrimage, gl_TexCoord[0].xy) * weights[0];
. . .

Next, the shader attempts to autopromote an integer to a float. This also is explicitly disallowed in the language specification.

//as written
. . .
for (int i = 1; i < = samples; i++)
{
offset = blur_offset * i;
. . .


//corrected
. . .
for (int i = 1; i< =samples; i++)
{
offset = blur_offset * float(i);
. . .

Last but not least, two more texture lookups are attempted using a 4 dimensional vector to index into a 2 dimensional texture.

//as written
vec4 tc;
vec4 offset;
. . .
tc = gl_TexCoord[0] + offset;
color += texture2D(t_hdrimage, tc) * weights[i];
. . .
tc = gl_TexCoord[0] - offset;
color += texture2D(t_hdrimage, tc) * weights[i];
. . .


//corrected
vec4 tc;
vec4 offset;
. . .
tc = gl_TexCoord[0] + offset;
color += texture2D(t_hdrimage, tc.st) * weights[i];
. . .
tc = gl_TexCoord[0] - offset;
color += texture2D(t_hdrimage, tc.st) * weights[i];
. . .

As you can see from the infolog below, we’ve started with a shader that would not compile and managed to quickly fix it up into a portable GLSL shader!

Parsing fragment shader ‘f_blur.glsl’….
Failure.

ERROR: 0:33: ‘texture2D’ : no matching overloaded function found
ERROR: 0:33: ‘=’ : cannot convert from ‘float’ to ‘4-component vector of float’
ERROR: 0:42: ‘*’ : wrong operand types no operation ‘*’ exists that takes a left-hand operand of type ‘uniform 4-component vector of float’ and a right operand of type ‘int’ (or there is no acceptable conversion)
ERROR: 0:46: ‘texture2D’ : no matching overloaded function found
ERROR: 0:50: ‘texture2D’ : no matching overloaded function found
ERROR: 5 compilation errors. No code generated.

Parsing fragment shader ‘f_blur.glsl’….
Failure.

ERROR: 0:42: ‘*’ : wrong operand types no operation ‘*’ exists that takes a left-hand operand of type ‘uniform 4-component vector of float’ and a right operand of type ‘int’ (or there is no acceptable conversion)
ERROR: 0:46: ‘texture2D’ : no matching overloaded function found
ERROR: 0:50: ‘texture2D’ : no matching overloaded function found
ERROR: 3 compilation errors. No code generated.

Parsing fragment shader ‘f_blur.glsl’….
Failure.

ERROR: 0:46: ‘texture2D’ : no matching overloaded function found
ERROR: 0:50: ‘texture2D’ : no matching overloaded function found
ERROR: 2 compilation errors. No code generated.

Parsing fragment shader ‘f_blur.glsl’….
Success.

In closing, I am extremely appreciative of the contributions Tom has made to the OpenGL community with his site, Delphi3D. I hope that he continues to release demos, and that given this post is able to appreciate the importance and simplicity of providing aspiring developers of programmable graphics well formed portable code to learn from.

I must also say that this posting - along with all other posts done on this site, are done on my own time and are of my own opinion.

techno19 Oct 2005 10:40 pm

I hope you once have to stand in front of a class and talk about byte quantities. Have fun with disgruntled students because you make a big mess once implying base 10 and once base 2, always using the same prefix.

No problem at all. Byte quantities are measured in powers of 2 - KB = 1024, MB = 1024^2, and so on. The only reason for confusion is that disk manufacturers play fast and loose with the facts, using powers of 10 and gaining 5% on paper. Creating a new term . . .

I just find these arguments hilarious. It gets even better when you intermingle video/pixel speak. Like what’s a pixel? If it’s 8 X 8 would that not imply binary quantization? Shouldn’t a megapixel be base 2 - implying a 1024X1024 display would be 1 megapixel? Or would it be 1.1 megapixel? It depends if you’re in engineering or marketing . . .

techno19 Oct 2005 10:30 pm

Plus, just to make geeks happy, I made sure that gigabyte was 2^30 and not 10^9. Better to get it right.

/. is just brilliant . . .

info and techno12 Oct 2005 10:40 am

It’s sites like morgueFile that really show the power of the internet. Here is a site that provides high quality, raw photography from professional photographers. These photos are provided absolutely free of charge - you don’t even have to register to download them. I like to email the photographer if he or she has left contact information and let him or her know where I used the photo.

The header banner on this very site was created using this photo. Thanx Clarita!

I also created a logo using the following photograph . . .
photo of a circuit board

After a little photoshop work . . .
finished logo

In summary, I’d like to thank the founders of morgueFile, Michael and Kevin Connors for their generous contribution to the online community!

emo11 Oct 2005 02:19 am

Why does my ex-wife keep sending me emails and cards that are religious? It’s annoying, if you’re not going to follow the teachings of the church at all (i.e. cheating on your spouse, etc.) then why bother going? Does it make you feel better to write that check every week? Don’t get me wrong, I certainly believe in a higher power . . . but organized religion just doesn’t fit me like it used to. It really seems like a guise for the guilty to hide behind.

I only needed the church once in my life and they weren’t there.

So, if you don’t mind - keep the cards, keep the emails, keep it all.

If you want to send me a card, skip the “God Loves You” shi*, and just stick to the “Happy Birthday” or “Happy Halloween”. I’ll appreciate it and so will He.

anim10 Oct 2005 08:19 pm

It should be coming today, for the first time this season. Powder, soft and fluffy, falling from the sky. The ski season is nearly upon us, I can’t wait. It’s been raining for two days but today it’ll turn to snow. I love the snow!

emo09 Oct 2005 10:04 am

It is everywhere. Motivation does not exist without it, yet one continually seeks it. Perhaps it is a state of being, that isn’t meant to be overcome. What is left upon content? Death? The End?

I suppose I should be satisfied with the journey . . . life is a rollercoaster right? That doesn’t make sense, though. A rollercoaster is controlled by the operator . . . and surely one can’t consider “God” a simple ride attendant at the local amusement park ;-)

Perhaps it’s the difference between discontent and yearning. I never want to be satisfied, I always want to improve, to build, to influence. The things I yearn for are those which I cannot control. I yearn for that which only others can give. I give to others what I yearn, if only they could make the connection.