kovasb / gamma

glsl shaders made simple
Eclipse Public License 1.0
306 stars 20 forks source link

Tips for readable Gamma output #13

Open sgrove opened 9 years ago

sgrove commented 9 years ago

It looks like it'll be a long road to get human-readable output from gamma. For example, at a glance, can you tell if these two shaders are equivalent?

    precision mediump float;

    varying vec2 vTextureCoord;
    varying vec3 vTransformedNormal;
    varying vec4 vPosition;

    uniform bool uUseColorMap;
    uniform bool uUseSpecularMap;
    uniform bool uUseLighting;

    uniform vec3 uAmbientColor;

    uniform vec3 uPointLightingLocation;
    uniform vec3 uPointLightingSpecularColor;
    uniform vec3 uPointLightingDiffuseColor;

    uniform sampler2D uColorMapSampler;
    uniform sampler2D uSpecularMapSampler;

    void main(void) {
        vec3 lightWeighting;
        if (!uUseLighting) {
            lightWeighting = vec3(1.0, 1.0, 1.0);
        } else {
            vec3 lightDirection = normalize(uPointLightingLocation - vPosition.xyz);
            vec3 normal = normalize(vTransformedNormal);

            float specularLightWeighting = 0.0;
            float shininess = 32.0;
            if (uUseSpecularMap) {
                shininess = texture2D(uSpecularMapSampler, vec2(vTextureCoord.s, vTextureCoord.t)).r * 255.0;
            }
            if (shininess < 255.0) {
                vec3 eyeDirection = normalize(-vPosition.xyz);
                vec3 reflectionDirection = reflect(-lightDirection, normal);

                specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), shininess);
            }

            float diffuseLightWeighting = max(dot(normal, lightDirection), 0.0);
            lightWeighting = uAmbientColor
                + uPointLightingSpecularColor * specularLightWeighting
                + uPointLightingDiffuseColor * diffuseLightWeighting;
        }

        vec4 fragmentColor;
        if (uUseColorMap) {
            fragmentColor = texture2D(uColorMapSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        } else {
            fragmentColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
        gl_FragColor = vec4(fragmentColor.rgb * lightWeighting, fragmentColor.a);
    }
precision mediump float;
uniform vec3 uPointLightingSpecularColor;
uniform vec3 uPointLightingLocation;
varying mediump vec3 vTransformedNormal;
varying highp vec4 vPosition;
uniform sampler2D uColorMapSampler;
uniform vec3 uAmbientColor;
varying mediump vec2 vTextureCoord;
uniform sampler2D uSpecularMapSampler;
void main(void){
vec3 v1848;
vec3 v1850;
vec3 v1849;
vec2 v1839;
(v1839 = vec2(vTextureCoord.st));
(v1848 = vPosition.xyz);
(v1849 = normalize(vTransformedNormal));
(v1850 = normalize((uPointLightingLocation - v1848)));
(gl_FragColor = vec4(
  (texture2D(uColorMapSampler, v1839).rgb * (uAmbientColor + ((uPointLightingSpecularColor * pow(
    max(dot(reflect((-1.0 * v1850), v1849), normalize((-1.0 * v1848))), 0.0),
    (texture2D(uSpecularMapSampler, v1839).r * 255.0))) + (uPointLightingSpecularColor * max(
    dot(v1849, v1850),
    0.0))))),
  1.0));
}

Ultimately the gamma-source shader isn't so bad, but as people are learning (and learning to trust) gamma, it's likely they'll want to compare some hand-written glsl with the output, to get a sense of things. Could certainly be a big issue with onboarding new developers.

There will probably be lots of ways to "pretty-print" the shaders, but here are a two I've thought of:

  1. Group the inputs into uniforms, attributes, and varying with one empty line between each group
  2. For each group, either arrange them 1.) alphabetically, or 2.) (possibly more useful) by the order they appear in the body of the shader.
  3. Being able to give locals names so they show up when pretty-printing the source of a gamma shader, with the understanding that this is only a debugging tool e.g.:
(let [st (g/local :st (g/vec2 (g/swizzle v-texture-coord :st)))
       diffuse-light-weighting (g/local :diffuseLightWeighting (.....))]
  ....)

This would probably be enough for me to quickly piece together whether the above shaders were equivalent, which would probably tell me why my current example is not working.

brandonbloom commented 9 years ago

Could also consider https://en.wikipedia.org/wiki/A-normal_form to make it super explicit, so you can verify one expression at a time.