Open ianmackenzie opened 7 years ago
I just came to try use this extension in one of my shaders and found that I couldn't. Currently I am just exploring WebGL. The particular thing I was trying to do was calculate the face normals in the fragment shader for flat shading. I am using glslify to write modular glsl and use other libs from npm. In this particular case I wanted to use glsl-face-normal to calculate the normals from a position. Unfortunately this requires this extension and therefore is currently incompatible with elm.
If memory serves correctly VSM shadows (low cost, soft, dynamic shadows) require standard derivatives as well.
It should be possible to support this feature when we replace the glsl parser in the Elm compiler.
This won't make it into Elm 0.19, but will be considered later.
These 'standard derivative' functions are very useful for a variety of techniques such as edge detection and blurring without requiring a second rendering pass. They seem to have very good support across most browsers:
I believe this change should be safe even on browsers that don't support the extension (not sure how to test this!), since
getExtension()
simply returns null if the extension is not available. Additionally, individual fragment shaders must still explicitly enable the extension by addingas the first line, so there is a strong hint to the shader writer that using these functions may not work on all browsers.
Unfortunately Elm's GLSL parser doesn't seem to recognize
#extension
as valid syntax; ideally that would be fixed in the upstream Haskell package, but in the meantime the workaround is to useunsafeShader
.Update: I've added
standardDerivatives
as anOption
that must be explicitly enabled, since there's at least one report of extension-loading having measurable performance impact.As mentioned in the documentation I added for
WebGL.standardDerivatives
, it's possible to detect the presence or absence of the extension using#ifdef GL_OES_standard_derivatives
in the fragment shader to conditionally compile different fragment shader code (example).As far as I can tell, calling
getExtension()
to attempt to enable a non-available extension (or enabling one that is then not used) has no effect other than the time taken to callgetExtension()
. Shaders will only fail to compile (potential runtime error) ifdFdx
etc. is used outside of an#ifdef GL_OES_standard_derivatives
block, on a browser where standard derivatives are not supported.What to do about
[glsl|...|]
parsing?Right now, as mentioned above, Elm's GLSL parser doesn't recognize
#extension
lines (or even#ifdef
, actually) so any shader using them has to be created withunsafeShader
, which is messy. Additionally, if uniforms, attributes or varyings were added within#ifdef
blocks then the inferred Elm type of the shader would change depending on the presence of the extension! Some potential solutions:#extension
and#ifdef
, and disallow declaration of uniforms, attributes or varyings inside an#ifdef
. Most flexible, but requires the most work. (This is the 'perfect world' that the currentWebGL.standardDerivatives
documentation text assumes...)StandardDerivatives
option has been enabled. This way the shader writer doesn't have to remember to add the#extension
line to their shaders (just callWebGL.toHtmlWith
withWebGL.standardDerivatives
as one of the options, then go ahead and start usingdFdx
etc.). Since the GLSL parser also doesn't seem to support#ifdef
, I think in this case the approach would be "if you want to usedFdx
and friends, just realize that it may not work cross-browser". (It seems to me, though, that for practical purposes it's pretty safe to assume that the extension is available anywhere that WebGL is.) If people really want to support both cases, then there's alwaysunsafeShader
...