Skip to content

Instantly share code, notes, and snippets.

@akfish
Created May 13, 2014 08:58
Show Gist options
  • Save akfish/a2d7e011b7546d0dd369 to your computer and use it in GitHub Desktop.
Save akfish/a2d7e011b7546d0dd369 to your computer and use it in GitHub Desktop.
Shader.Js Concept

Shader.Js

Goal

  • Write WebGL shaders in JavaScript (shader classes)
  • Compile shader classes to GLSL at runtime or compile time
  • Assemble and run glProgram (material) seamlessly in JavaScript syntax

Review of Native WebGL Shading Workflow

1. Write shaders in GLSL

Cons:

  • It's a different language
  • No #include
  • Not easy to interface with JavaScript

2. Link glProgram

3. Set all kinds of parameters

  • attributes for each vertex
  • uniforms for each render call
  • varyings to brige vertex shader and fragment shader

Cons:

  • Can be complex
  • Too differenct from JavaScript Syntax

Concept

Example

Vertex Shader

    uniform mat4 u_modelViewProjMatrix;
    uniform mat4 u_normalMatrix;
    uniform vec3 lightDir;
 
    attribute vec3 vNormal;
    attribute vec4 vTexCoord;
    attribute vec4 vPosition;
 
    varying float v_Dot;
    varying vec2 v_texCoord;
 
    void main()
    {
        gl_Position = u_modelViewProjMatrix * vPosition;
        v_texCoord = vTexCoord.st;
        vec4 transNormal = u_normalMatrix * vec4(vNormal, 1);
        v_Dot = max(dot(transNormal.xyz, lightDir), 0.0);
    }

Fragment Shader:

    precision mediump float;
 
    uniform sampler2D sampler2d;
 
    varying float v_Dot;
    varying vec2 v_texCoord;
 
    void main()
    {
        vec2 texCoord = vec2(v_texCoord.s, 1.0 - v_texCoord.t);
        vec4 color = texture2D(sampler2d, texCoord);
        color += vec4(0.1, 0.1, 0.1, 1);
        gl_FragColor = vec4(color.xyz * v_Dot, color.a);
    }

Compile and link:

var vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
var fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
var program = createProgram(gl, [vertexShader, fragmentShader]);
gl.useProgram(program);

Set uniforms:

// TODO

Set attributes:

// TODO:

Shader.Js Implementation

Vertex Shader Class

class SimpleVertex extends ShaderBase.Vertex
    # Init arguments are like uniforms
    init: (mvp_mat, normal_mat, light_dir) ->
    
    # Process arguments are like attributes
    process: (normal, uv, pos) ->
        # position is gl_Position
        @position = @mvp_mat * pos
        
        trans_normal = normal_mat * new Vec4(normal, 1)
        
        # Return array contains varying
        return [uv.st, max dot(trans_normal.xyz, @light_dir), 0.0]

Fragment Shader Class

class SimpleFragment extends ShaderBase.Fragment
    init: (sampler2d) ->
    
    # Varyings are passed as process arguments
    process: (uv, dot) ->
        uv_coord = new Vec2 uv.s, 1.0 - uv.t
        color = new Texture2D @sampler2d, uv_coord
        color += new Vec4 0.1, 0.1, 0.1, 1
        # Color is gl_FragColor
        @Color = new Vec4 color.xyz * dot, color.a

Make Material

# Pass named shaders to intialize a material
mat = new Material 
    vertex: new SimpleVertex
    frag: new SimpleFragment
    
# Set uniforms with init
mat.vertex.init mvp, normal_mat, light_dir
mat.frag.init simpler2d

# Pass atrributes with render
mat.render normal, uv, pos
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment