• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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