1# Introduction 2 3There are many situations in which it's useful for WebGL applications to 4transform shaders in various ways. ANGLE's shader translator can be used for 5this purpose: compiling it with [Emscripten](http://emscripten.org/) allows it 6to be invoked from a web page. This wiki page provides some preliminary details 7about how to do this. 8 9# Details 10 11Pull top of tree ANGLE. 12 13Install the Emscripten toolchain per the [instructions](http://emscripten.org/). 14 15Symlink (preferred) or copy the ANGLE directory into ...emsdk/emscripten/master. 16 17Put a shader to compile into a file (named with .vert or .frag suffix) in the 18same directory. For example, put the following shader from the [WebGL Aquarium] 19(http://webglsamples.org/aquarium/aquarium.html) into `aq-fish-nm.frag`: 20 21``` 22precision mediump float; 23uniform vec4 lightColor; 24varying vec4 v_position; 25varying vec2 v_texCoord; 26varying vec3 v_tangent; // #normalMap 27varying vec3 v_binormal; // #normalMap 28varying vec3 v_normal; 29varying vec3 v_surfaceToLight; 30varying vec3 v_surfaceToView; 31 32uniform vec4 ambient; 33uniform sampler2D diffuse; 34uniform vec4 specular; 35uniform sampler2D normalMap; // #normalMap 36uniform float shininess; 37uniform float specularFactor; 38// #fogUniforms 39 40vec4 lit(float l ,float h, float m) { 41 return vec4(1.0, 42 max(l, 0.0), 43 (l > 0.0) ? pow(max(0.0, h), m) : 0.0, 44 1.0); 45} 46void main() { 47 vec4 diffuseColor = texture2D(diffuse, v_texCoord); 48 mat3 tangentToWorld = mat3(v_tangent, // #normalMap 49 v_binormal, // #normalMap 50 v_normal); // #normalMap 51 vec4 normalSpec = texture2D(normalMap, v_texCoord.xy); // #normalMap 52 vec3 tangentNormal = normalSpec.xyz - vec3(0.5, 0.5, 0.5); // #normalMap 53 tangentNormal = normalize(tangentNormal + vec3(0, 0, 2)); // #normalMap 54 vec3 normal = (tangentToWorld * tangentNormal); // #normalMap 55 normal = normalize(normal); // #normalMap 56 vec3 surfaceToLight = normalize(v_surfaceToLight); 57 vec3 surfaceToView = normalize(v_surfaceToView); 58 vec3 halfVector = normalize(surfaceToLight + surfaceToView); 59 vec4 litR = lit(dot(normal, surfaceToLight), 60 dot(normal, halfVector), shininess); 61 vec4 outColor = vec4( 62 (lightColor * (diffuseColor * litR.y + diffuseColor * ambient + 63 specular * litR.z * specularFactor * normalSpec.a)).rgb, 64 diffuseColor.a); 65 // #fogCode 66 gl_FragColor = outColor; 67} 68``` 69 70Compile the shader translator, the translator sample, and the shader all 71together: 72 73``` 74./emcc -Iangle/include -Iangle/src angle/samples/translator/translator.cpp angle/src/compiler/preprocessor/*.cpp angle/src/compiler/translator/*.cpp angle/src/compiler/translator/timing/*.cpp angle/src/compiler/translator/depgraph/*.cpp angle/src/third_party/compiler/*.cpp angle/src/common/*.cpp -o translator.html --preload-file aq-fish-nm.frag -s NO_EXIT_RUNTIME=1 75``` 76 77Serve up the resulting translator.html via `python -m SimpleHTTPServer`. 78Navigate the browser to localhost:8000. 79 80The translator sample will run, displaying its output into the text area on the 81page. Since it isn't receiving any input, it simply outputs a help message and 82exits. 83 84To invoke the translator again, processing the shader we included along with the 85source code, open the JavaScript console and type: 86 87``` 88Module['callMain'](['-s=w', '-u', 'aq-fish-nm.frag']) 89``` 90 91The active uniforms and their types will be printed to the text area after the 92translator sample processes the shader. 93 94# Issues and Next Steps 95 96It's clearly not useful to have to compile the shader in to the 97Emscripten-translated executable. It would be helpful to define a simple wrapper 98function which can easily be called from JavaScript and which defines enough 99parameters to pass in a shader as a string, transform it somehow or compile it 100to another language target, and return the compiled result (or other 101information). A simple JavaScript library that wraps all of the interactions 102with the Emscripten binary would be useful. 103 104It's not feasible to interact with the translator's data structures, nor 105traverse the AST from JavaScript. The code that operates upon the shader must be 106written in C++ and compiled in to the shader translator. 107 108emcc should be integrated better with ANGLE's build system. 109