Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Shader code is extremely performance sensitive, and poorly written or complex shaders can absolutely destroy framerate.

Conditionals, loops, and even function calls on bad drivers are all things that need to be avoided, when possible, and it's very rare you can get ship a game without having to spend time optimizing your shaders.



Right, and using a well used library improves your chances of avoiding such issues. Optimizing compilers should be the one to decide when to inline function calls and the like. Source code is for people.


Tell that to end users who leave bad reviews for your game, complaining that it doesn't make 60fps.

Not to mention the fact that the landscape of GLSL compilers is fairly broad and you have absolutely no control over whether or not you have one worth anything (frequently on mobile, you don't).

Unfortunately, the fact that shader code is hard to write, and has a huge number of performance pitfalls mean that you're going to have to inspect the source of any non-trivial library you use, and in most cases you'll probably need to write it yourself, if you care.

Here, I took the time to look at a few from NPM.

- https://github.com/Jam3/glsl-hsl2rgb/blob/master/index.glsl This is awful. Data dependant branching absolutely destroys performance on the GPU. A vectorized, zero branch solution to this exists and is fairly well known, the author just doesn't know it or doesn't care. - https://github.com/hughsk/glsl-dither/blob/master/2x2.glsl A neat effect, but the statement above is still true. The other dimensions (4x4 and 8x8) are even worse.

There are others as well. The point seems to be that many of them that are doing something other more complicated than a couple lines, are not well written for code that runs on the GPU and are going to perform very poorly in practice.


It's true; a public npm module will probably not be as optimized as your hand-tuned and application-specific shader effects.

But for most use cases, especially quick prototyping, a fraction of a millisecond isn't going to make a difference when your game is already at 60 FPS, or when your bottlenecks don't lie in the shader.

In rare cases where it makes a difference, you can just require a local file that has been optimized for your use case, or a module that you control (for semantic versioning and better reusability).

    #pragma glslify: optimizedHSL2RGB = require('./hsl2rgb')
P.S. If you link to the branchless HSL to RGB, I can update the module.


This seems (http://www.chilliant.com/rgb2hsv.html) to have a few implementations of color space conversions (in HLSL but that shouldn't be a difficult translation). They're not perfect but they're a good starting point.

With some inlining and algebraic simplification (the kind that, unfortunately, can't safely be done by a compiler most of the time) you can get even simpler than the ones linked. For example, I've used something similar to the following for hsl to rgb before.

l + (1.0 - abs(2.0 * l - 1.0)) * s * (clamp(abs(mod(h + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0) - 0.5)



Just tried it on the two examples I provided. It doesn't remove conditionals, which was basically my whole point

FWIW, I don't think it can without assuming the input lies in a certain range.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: