StdLibShader top-level constant

String const StdLibShader

Implementation

const String StdLibShader = """
// ============================================================
// MISC
// ============================================================

vec3 ColorFromPosition(vec3 pos) {
    return vec3( sin(pos.x) / 2.0 + 0.5,
                 cos(pos.y) / 2.0 + 0.5,
                 sin(pos.z) / 2.0 + 0.5);
}

vec3 RangeToGray(float f, float a, float b) {
    if (f > a) return vec3(1.0);
    if (f < b) return vec3(0.0);
    return vec3 ((f - b) / (a-b));
}

float useValueButReturnZero(float x) {
    return (x + 1.0) * (x + 1.0) - x * x - 2.0 * x - 1.0;
}

// ============================================================
// LIGHT
// ============================================================

float GetDiffuse(vec3 lightDir, vec3 normal) {
    return max(dot(normal, lightDir), 0.0);
}

float GetSpecular(vec3 lightDir, vec3 viewDir, vec3 normal, float glossiness) {
    vec3 angleW = normalize(viewDir + lightDir);
    float specComp = max(0., dot(normal, angleW));
    return pow(specComp, max(1.0, glossiness));
}

struct ColorComponents {
   vec3 diffuse;
   vec3 specular;
};

// ============================================================
// Spot Light
// ============================================================

struct SpotLightInfo {
    vec3 pos;      // for spot and point
    vec3 dir;      // for spot and dir light
    vec3 diffuseColor;
    vec3 specularColor;
    float range;        // for spot and point
    float spotCutoff;   // for spot
    float spotFocus;    // for spot
    // float glossiness;   // Oddball: this comes from the material
};

SpotLightInfo UnpackSpotLightInfo(mat4 m) {
    SpotLightInfo info;
    info.pos = m[0].xyz;
    info.dir = normalize(m[1].xyz);
    info.diffuseColor = m[2].xyz;
    info.specularColor = m[3].xyz;
    // info.glossiness = m[0].a;
    info.range = m[1].a;
    info.spotCutoff = m[2].a;
    info.spotFocus = m[3].a;
    return info;
}

ColorComponents SpotLightGetDiffuseAndSpecular(SpotLightInfo light,
                                               vec3 vertexPos,
                                               vec3 vertexNormal,
                                               vec3 eyePos,
                                               float uShininess) {
    vec3 toSpot = light.pos - vertexPos;
    vec3 spotDir = normalize(toSpot);
    vec3 lightDirNorm = -normalize(light.dir);
    float cosAngle = max(0., dot(lightDirNorm, spotDir));
	  if (cosAngle < light.spotCutoff) {
        return ColorComponents(vec3(0.0), vec3(0.0));
    }

    cosAngle = max(0.0, pow(cosAngle, light.spotFocus));
	  float attenuation = max(0.0, 1.0 - length(toSpot) / light.range) * cosAngle;
	  vec3 viewDirNorm = normalize(eyePos - vertexPos);
	  return ColorComponents(
	           attenuation *
             GetDiffuse(lightDirNorm, vertexNormal) *
             light.diffuseColor,
             attenuation *
             GetSpecular(lightDirNorm, viewDirNorm, vertexNormal, uShininess) *
             light.specularColor);
}

// ============================================================
// Point Light
// ============================================================

struct PointLightInfo {
    vec3 pos;
    vec3 diffuseColor;
    vec3 specularColor;
    float range;
    // float glossiness;
};

PointLightInfo UnpackPointLightInfo(mat4 m) {
    PointLightInfo info;
    info.pos = m[0].xyz;
    info.diffuseColor = m[2].xyz;
    info.specularColor = m[3].xyz;
    info.range = m[1].a;
    // info.glossiness = m[0].a;
    return info;
}

ColorComponents PointLightGetDiffuseAndSpecular(PointLightInfo info,
                                     vec3 vertexPos,
                                     vec3 vertexNormal,
                                     vec3 eyePos,
                                     float uShininess) {
    vec3 lightDir = info.pos - vertexPos;
    float attenuation = max(0.0, 1.0 - length(lightDir) / info.range);
    vec3 lightDirNorm = normalize(lightDir);
    vec3 viewDirNorm = normalize(eyePos - vertexPos);
    return ColorComponents(
              attenuation *
              GetDiffuse(lightDirNorm, vertexNormal) *
              info.diffuseColor,
               attenuation *
               GetSpecular(lightDirNorm, viewDirNorm, vertexNormal, uShininess) *
               info.specularColor);
}

// ============================================================
// Directional Light
// ============================================================

struct DirectionalLightInfo {
    vec3 dir;      // for spot and dir light
    vec3 diffuseColor;
    vec3 specularColor;
    // float glossiness;   // Oddball: this comes from the material
};

DirectionalLightInfo UnpackDirectionalLightInfo(mat4 m) {
    DirectionalLightInfo info;
    info.dir = normalize(m[1].xyz);
    info.diffuseColor = m[2].xyz;
    info.specularColor = m[3].xyz;
    // info.glossiness = m[0].a;
    return info;
}

ColorComponents DirectionalLightGetDiffuseAndSpecular(DirectionalLightInfo info,
                                                      vec3 vertexPos,
                                                      vec3 vertexNormal,
                                                      vec3 eyePos,
                                                      float uShininess) {
    vec3 viewDirNorm = normalize(eyePos - vertexPos);
    return ColorComponents(
              GetDiffuse(-info.dir, vertexNormal) *
              info.diffuseColor,
              GetSpecular(-info.dir, viewDirNorm, vertexNormal, uShininess) *
              info.specularColor);
}


ColorComponents CombinedLightSpot(
    vec3 vVertexPosition, vec3 vNormal, vec3 uEyePosition, mat4 lightDesc,
    float shininess) {
    SpotLightInfo info = UnpackSpotLightInfo(lightDesc);
    return SpotLightGetDiffuseAndSpecular(
        info, vVertexPosition, vNormal, uEyePosition, shininess);
}

ColorComponents CombinedLightPoint(
    vec3 vVertexPosition, vec3 vNormal, vec3 uEyePosition, mat4 lightDesc,
    float shininess) {
    PointLightInfo info = UnpackPointLightInfo(lightDesc);
    return PointLightGetDiffuseAndSpecular(
        info, vVertexPosition, vNormal, uEyePosition, shininess);
}

ColorComponents CombinedLightDirectional(
    vec3 vVertexPosition, vec3 vNormal, vec3 uEyePosition, mat4 lightDesc,
    float shininess) {
    DirectionalLightInfo info = UnpackDirectionalLightInfo(lightDesc);
    return DirectionalLightGetDiffuseAndSpecular(
        info, vVertexPosition, vNormal, uEyePosition, shininess);
}

// ============================================================
// Combined Light
// ============================================================
ColorComponents CombinedLight(vec3 vVertexPosition,
                   vec3 vNormal,
                   vec3 uEyePosition,
                   const mat4 uLightDescs[${kMaxLights}],
                   const float uLightTypes[${kMaxLights}],
                   float uShininess) {
    ColorComponents acc = ColorComponents(vec3(0.0), vec3(0.0));

    for (int i = 0; i < ${kMaxLights}; ++i) {
        ColorComponents curr;
        float type = ${uLightTypes}[i];
        if (type == ${lightTypeSpotFloat}) {
            curr = CombinedLightSpot(
                       vVertexPosition, vNormal, uEyePosition, uLightDescs[i],
                       uShininess);
        } else if (type == ${lightTypePointFloat}) {
            curr = CombinedLightPoint(
                       vVertexPosition, vNormal, uEyePosition, uLightDescs[i],
                       uShininess);
        } else if (type == ${lightTypeDirectionalFloat}) {
            curr = CombinedLightDirectional(
                       vVertexPosition, vNormal, uEyePosition, uLightDescs[i],
                       uShininess);
        } else {
            continue;
        }
        acc.diffuse = acc.diffuse + curr.diffuse;
        acc.specular = acc.specular + curr.specular;
    }
    return acc;
}
""";