In a previous post I detailed how I work with GLSL files, specifically loading them into the app itself in an convenient way.
One notable missing feature was automatically validating the shaders before they are used the browser.
This post will detail how you can do this directly from your editor, to help you spot stupid mistakes while editing, rather than only alerts when testing in the browser.
For me, it was a huge frustration to make a change in a GLSL file, reload my app in the browser and then after waiting for it to load to be told (by a pretty obscure message) that I’d missed a semicolon in my code.
Originally, I was using the GLSL Compiler, which alerted me when I made silly mistakes, such as missing a semicolon. However, it could not spot all types of errors. In particular I was forever doing things like this:
float r = 10;
Only to be greeted by the following message in the browser (usually obscured by a dump of my entire shader):
cannot convert from 'const mediump int' to 'float'
For a while, I thought that I would have to live with this, as Googling around didn’t seem to yield anything. The breakthrough came when I found a plugin for Sublime Text, GL-Shader-Validator. While I don’t use Sublime, the guts of this plugin were interesting, namely ANGLE was used to actually compile the code and detect any errors.
What the ANGLE executables let you do is pass in a fragment or vertex shader file, and it will try to compile it for you, reporting back any errors. E.g.
Never have I been so happy to see a list of errors!
The output format wasn’t quite what I wanted so I have wrapped this in a python script, which gives me an easier to parse output:
Now the above works great for self-contained shaders, however I’m working with THREE.js, which passes in helpful variables into the shaders for me, like the
modelViewMatrix. The trouble is, ANGLE doesn’t know anything about these variables and hence whenever I use them, they are reported as errors. Not great.
To solve this I’ve included prefix files that the
glsl-validate.py script will automatically prepend to any shader it passes to the ANGLE compiler. This basically mocks out the things that we expect to have passed in.
This approach could easily be extended to support other libraries, if you feel like doing so, please submit a pull request!
Extending the library integration idea, I’ve been working on adding a rudimentary form of
#include to my shaders, so I can effectively share code between them. The implementation is pretty simple, basically whenever the validator encounters a statment like
#include shader.glsl, it replaces the include statement with the contents of the included file.
I use vim for editing and set it up so that whenever a file is saved,
glsl-validate.py is run over the file, reporting any errors. In the future I’ll probably wrap this up into a Syntastic plugin, so that the error messages appear directly in vim.
So far, I’ve been very pleased with the accuracy of detected errors, I’ve yet to hit an occassion where my shaders wouldn’t compile in the browser if they passed through the validator.
The project is up on Github, hopefully others will find it useful.