Skip to content
Patricio Gonzalez Vivo edited this page Sep 21, 2019 · 17 revisions

Beside the defines you can pass as an argument using -D[define] you can relay on the following native defines automatically generated for you.

  • GLSLVIEWER <GLSLVIEWER_VERSION_WOUT_DOTS>: you can use it to tell your shader it's being render in GlslViewer.

Depending on the platform

  • PLATFORM_OSX: added only on MacOS/OSX platforms.

  • PLATFORM_RPI: added only only on RaspberryPi devices.

  • PLATFORM_LINUX: added only in i86 and 64bit Linux platforms.

The following defines fork and reuse the same shader program in different passes

  • BACKGROUND: added a background subshader when rendering a 3D geometry.

  • FLOOR: add a floor geometry and fork the behavior of the shader to render the floor using it

  • BUFFER_[NUMBER]: added extra buffer passes trough branching subshader. Each one renders to uniform sampler2D u_buffer[NUMBER];. (Read more about it in the next section)

  • POSTPROCESSING: added a post-processing pass where the main scene have been render to uniform sampler2D u_scene;.

Depending on the geometry:

  • MODEL_NAME_<NAME>: only OBJ file import a name. Default is MODEL_NAME_MESH

  • MODEL_VERTEX_COLOR: if the model have a vertex color attribute will be follow by the name of the attribute (Default: a_color)

  • MODEL_VERTEX_NORMAL: if the model have a vertex normal attribute will be follow by the name of the attribute (Default: a_normal`)

  • MODEL_VERTEX_TEXCOORD: if the model have a vertex normal attribute will be follow by the name of the attribute (Default: a_texcoord)

  • MODEL_VERTEX_TANGENT: if the model have a vertex normal attribute will be follow by the name of the attribute (Default: a_tangent)

Depending on the material (only OBJ import materials):

  • MATERIAL_NAME_[NAME]: only OBJ file import a name. Default is MATERIAL_NAME_DEFAULT

  • MATERIAL_ILLUM: integer between 0 to 10. Specs from here

    0 Color on and Ambient off
    1 Color on and Ambient on
    2 Highlight on
    3 Reflection on and Ray trace on
    4 Transparency: Glass on

    Reflection: Ray trace on
    5 Reflection: Fresnel on and Ray trace on
    6 Transparency: Refraction on

    Reflection: Fresnel off and Ray trace on
    7 Transparency: Refraction on

    Reflection: Fresnel on and Ray trace on
    8 Reflection on and Ray trace off
    9 Transparency: Glass on

    Reflection: Ray trace off
    10 Casts shadows onto invisible surfaces
  • MATERIAL_AMBIENT: the color as vec3

  • MATERIAL_AMBIENTMAP: the name of a samplerd2D

  • MATERIAL_BASECOLOR: a color as vec3

  • MATERIAL_BASECOLORMAP: the name of a samplerd2D

  • MATERIAL_SPECULAR: a color as vec3

  • MATERIAL_SPECULARMAP: the name of a samplerd2D

  • MATERIAL_ROUGHNESS: a normalize float value

  • MATERIAL_ROUGHNESSMAP: the name of a samplerd2D

  • MATERIAL_METALLIC: a normalize float value

  • MATERIAL_METALLICMAP: the name of a samplerd2D

  • MATERIAL_SHININESS: a scallar factor for speculars

  • MATERIAL_SHEEN: a normalize float value

  • MATERIAL_SHEENMAP: the name of a samplerd2D

  • MATERIAL_SPECULAR_HIGHLIGHTMAP: the name of a samplerd2D

  • MATERIAL_REFLECTIONMAP: the name of a samplerd2D

  • MATERIAL_CLEARCOAT_THICKNESS: a normalize float value

  • MATERIAL_CLEARCOAT_ROUGHNESS: a normalize float value

  • MATERIAL_ANISOTROPY: a normalize float value

  • MATERIAL_ANISOTROPY_ROTATION: float value

  • MATERIAL_EMISSIVE: a color as vec3

  • MATERIAL_EMISSIVEMAP: the name of a samplerd2D

  • MATERIAL_NORMALMAP: the name of a samplerd2D

  • MATERIAL_BUMPMAP: the name of a samplerd2D

  • MATERIAL_DISPLACEMENTMAP: the name of a samplerd2D

  • MATERIAL_ALPHAMAP: the name of a samplerd2D

  • MATERIAL_TRANSMITTANCE: a color as vec3

  • MATERIAL_DISSOLVE: a normalize float value

  • MATERIAL_IOR: a normalize float value

Using the defines flags to use multiple buffer passes

You can use multiple buffers by forking the code using #ifdef BUFFER_[number], #if defined (BUFFER_[number]) and/or #elif defined (BUFFER_[number]). Then you can fetch the content of those buffers by using the uniform sampler2D u_buffer[number] texture. Ex.:

    uniform sampler2D   u_buffer0;
    uniform sampler2D   u_buffer1;

    varying vec2        v_texcoord;

    void main() {
        vec3 color = vec3(0.0);
        vec2 st = v_texcoord;

    #ifdef BUFFER_0
        color.g = abs(sin(u_time));

    #elif defined( BUFFER_1 )
        color.r = abs(sin(u_time));

    #else
        color.b = abs(sin(u_time));

        color = mix(color,
                    mix(texture2D(u_buffer0, st).rgb,
                        texture2D(u_buffer1, st).rgb,
                        step(0.5, st.x) ),
                    step(0.5, st.y));
    #endif

        gl_FragColor = vec4(color, 1.0);
    }

There is an extended example on examples/test_multibuffer.frag and examples/grayscott.frag.

Using the defines flags to draw the background

If you load a 3D model or set a shader without opacity you will notice the background is black by default (actually transparent in RaspberryPi).

It's possible to set a background by adding a #ifdef BACKGROUND check and adding your code there. Check the example examples/model_background.frag

uniform vec2 u_resolution;
uniform float u_time;

varying vec4 v_color;
varying vec3 v_normal;

float stroke(float x, float size, float w) {
    float d = step(size, x+w*.5) - step(size, x-w*.5);
    return clamp(d, 0., 1.);
}

vec2 ratio(in vec2 st, in vec2 s) {
    return mix( vec2((st.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,st.y),
                vec2(st.x,st.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),
                step(s.x,s.y));
}

float rectSDF(vec2 st, vec2 s) {
    st = st*2.-1.;
    return max( abs(st.x/s.x),
                abs(st.y/s.y) );
}

void main(void) {
   vec4 color = vec4(1.0);
   vec2 st = gl_FragCoord.xy/u_resolution.xy;
   vec2 pixel = 1./u_resolution.xy;

#ifdef BACKGROUND
    st = ratio(st, u_resolution);

    color.rgb *= vec3(0.75, 0.0, 0.0) * step(0.5, fract((st.x - st.y - u_time * 0.1) * 20.));

    float sdf = rectSDF(st, vec2(1.0));
    color.rgb *= step(sdf, 0.7);
    color.rgb += vec3(1.0, 0.0, 0.0) * stroke(sdf, 0.75, 0.01);
#else
    color.rgb = v_color.rgb;
    float shade = dot(v_normal, normalize(vec3(0.0, 0.75, 0.75)));
    color.rgb *= smoothstep(-1.0, 1.0, shade);
#endif

    gl_FragColor = color;
}

Using the defines flags to draw the a postprocessing layer

Also when loading 3D models it's possible to add a postprocessing layer adding a #ifdef POSTPROCESSING to branch the logic of the shader. To apply a postprocessing layer you need to read the scene as a texture, this is saved on the uniform sampler2D u_scene; texture together with a depth render pass of the scene located in uniform sampler2D u_scene_depth;. Here is an example of a cheap DoF at examples/model_postprocessing.frag

uniform sampler2D u_scene;          // Scene RGB
uniform sampler2D u_scene_depth;    // Scene Depth

uniform vec2 u_resolution;
uniform float u_time;

varying vec4 v_position;
varying vec4 v_color;
varying vec3 v_normal;
varying vec2 v_texcoord;

float stroke(float x, float size, float w) {
    float d = step(size, x+w*.5) - step(size, x-w*.5);
    return clamp(d, 0., 1.);
}

vec2 ratio(in vec2 st, in vec2 s) {
    return mix( vec2((st.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,st.y),
                vec2(st.x,st.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),
                step(s.x,s.y));
}

float rectSDF(vec2 st, vec2 s) {
    st = st*2.-1.;
    return max( abs(st.x/s.x),
                abs(st.y/s.y) );
}

float LinearizeDepth(float zoverw) {
	float n = 1.0; //
	float f = 20000.0;
	return (2.0 * n) / (f + n - zoverw * (f - n));	
}

void main(void) {
   vec4 color = vec4(1.0);
   vec2 st = gl_FragCoord.xy/u_resolution.xy;
   vec2 pixel = 1./u_resolution.xy;

#ifdef BACKGROUND
    // Background pattern
    st = ratio(st, u_resolution);

    color.rgb *= vec3(0.75, 0.0, 0.0) * step(0.5, fract((st.x - st.y - u_time * 0.1) * 20.));

    float sdf = rectSDF(st, vec2(1.0));
    color.rgb *= step(sdf, 0.7);
    color.rgb += vec3(1.0, 0.0, 0.0) * stroke(sdf, 0.75, 0.01);

#elif defined(POSTPROCESSING)

    // Get depth
    float depth = texture2D(u_scene_depth, st).r;
    depth = LinearizeDepth(depth) * 200.0;

    // Define focal point
    float focalDistance = 100.0;
    float focalRange = 50.0;
    depth = min( abs(depth  - focalDistance) / focalRange, 1.0);
    
    // Cheap box blur
    pixel *= 4.;
    color.rgb = texture2D(u_scene, st + vec2(pixel.x, 0.0)).rgb;
    color.rgb += texture2D(u_scene, st + vec2(0.0, pixel.y)).rgb;
    color.rgb += texture2D(u_scene, st + vec2(-pixel.x, 0.0)).rgb;
    color.rgb += texture2D(u_scene, st + vec2(0.0, -pixel.y)).rgb;
    color.rgb *= 0.25;

    // Mix blur and crisp scene images based on depth
    color.rgb = mix(color.rgb, texture2D(u_scene, st).rgb, 1.0 - depth);

    // Debug Depth
    // color.rgb = vec3(1.) * depth;
#else

    // Material of model
    color.rgb = v_color.rgb;
    float shade = dot(v_normal, normalize(vec3(0.0, 0.75, 0.75)));
    color.rgb *= smoothstep(-1.0, 1.0, shade);
#endif

    gl_FragColor = color;
}

Clone this wiki locally