UNPKG

8.84 kBMarkdownView Raw
1gl-shader
2=========
3A wrapper for WebGL shaders. Part of [stack.gl](http://stack.gl)
4
5# Example
6
7Try it out now in your browser: [http://stackgl.github.io/gl-shader/](http://stackgl.github.io/gl-shader/)
8
9```javascript
10var shell = require('gl-now')()
11var createShader = require('gl-shader')
12var shader, buffer
13
14shell.on('gl-init', function() {
15 var gl = shell.gl
16
17 //Create shader
18 shader = createShader(gl,
19 'attribute vec3 position;\
20 varying vec2 uv;\
21 void main() {\
22 gl_Position = vec4(position, 1.0);\
23 uv = position.xy;\
24 }',
25 'precision highp float;\
26 uniform float t;\
27 varying vec2 uv;\
28 void main() {\
29 gl_FragColor = vec4(0.5*(uv+1.0), 0.5*(cos(t)+1.0), 1.0);\
30 }')
31
32 //Create vertex buffer
33 buffer = gl.createBuffer()
34 gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
35 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
36 -1, 0, 0,
37 0, -1, 0,
38 1, 1, 0
39 ]), gl.STATIC_DRAW)
40})
41
42shell.on('gl-render', function(t) {
43 var gl = shell.gl
44
45 //Bind shader
46 shader.bind()
47
48 //Set attributes
49 gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
50 shader.attributes.position.pointer()
51
52 //Set uniforms
53 shader.uniforms.t += 0.01
54
55 //Draw
56 gl.drawArrays(gl.TRIANGLES, 0, 3)
57})
58```
59
60Here is the result:
61
62<img src="https://raw.github.com/stackgl/gl-shader/master/screenshot.png">
63
64# Install
65
66 npm install gl-shader
67
68# API
69
70```javascript
71var createShader = require('gl-shader')
72```
73
74
75### Constructor
76
77There are two main usages for the constructor. First,
78
79#### `var shader = createShader(vertexSource, fragmentSource[, uniforms, attributes])`
80
81Constructs a wrapped shader object with shims for all of the uniforms and attributes in the program.
82
83* `gl` is the webgl context in which the program will be created
84* `vertexSource` is the source code for the vertex shader
85* `fragmentSource` is the source code for the fragment shader
86* `uniforms` is an (optional) list of all uniforms exported by the shader program
87* `attributes` is an (optional) list of all attributes exported by the shader program
88
89The optional `uniforms` and `attributes` arrays have the following format. This will be extracted at run-time from the shader, so you can typically omit the `uniforms` and `attributes` arguments.
90
91```js
92{
93 uniforms: [
94 { type: 'mat4', name: 'projection' },
95 { type: 'sampler2D', name: 'texture0' }
96 ],
97 attribuets: [
98 { type: 'vec3', name: 'position' }
99 ]
100}
101```
102
103You can specify a default `location` number for each attribute, otherwise WebGL will bind it automatically.
104
105**Returns** A compiled shader object.
106
107#### `var shader = createShader(gl, opt)`
108
109The same as above, but takes an object instead of a parameter list.
110
111* `gl` is a WebGL context
112* `opt.vertex` a vertex shader source
113* `opt.fragment` a fragment shader source
114* `opt.uniforms` (optional) a list of uniforms
115* `opt.attributes` (optional) a list of attributes
116
117**Returns** A wrapped shader object
118
119### Methods
120
121#### `shader.bind()`
122Binds the shader for rendering
123
124#### `shader.update(vertSource,fragSource[,uniforms,attributes])`
125Rebuilds the shader object with new vertex and fragment shaders (same behavior as constructor)
126
127#### `shader.update(opt)`
128Rebuilds the shader object with new vertex and fragment shaders (same behavior as constructor)
129
130#### `shader.dispose()`
131Deletes the shader program and associated resources.
132
133### Properties
134
135#### `gl`
136The WebGL context associated to the shader
137
138#### `program`
139A reference to the underlying program object in the WebGL context
140
141#### `vertShader`
142A reference to the underlying vertex shader object
143
144#### `fragShader`
145A reference to the underlying fragment shader object
146
147### Uniforms
148The uniforms for the shader program are packaged up as properties in the `shader.uniforms` object. The shader must be bound before the uniforms are assigned. For example, to update a scalar uniform you can just assign to it:
149
150```javascript
151shader.bind()
152shader.uniforms.scalar = 1.0
153```
154
155While you can update vector uniforms by writing an array to them:
156
157```javascript
158shader.uniforms.vector = [1,0,1,0]
159```
160
161Matrix uniforms must have their arrays flattened first:
162
163```javascript
164shader.uniforms.matrix = [ 1, 0, 1, 0,
165 0, 1, 0, 0,
166 0, 0, 1, 1,
167 0, 0, 0, 1 ]
168```
169
170You can read the value of uniform too if the underlying shader is currently bound. For example,
171
172```javascript
173shader.bind()
174console.log(shader.uniforms.scalar)
175console.log(shader.uniforms.vector)
176console.log(shader.uniforms.matrix)
177```
178
179Struct uniforms can also be accessed using the normal dot property syntax:
180
181```javascript
182shader.uniforms.light[0].color = [1, 0, 0, 1]
183```
184
185It is also possible to initialize uniforms in bulk by assigning an object:
186
187```javascript
188shader.uniforms = {
189 model: [1, 0, 0, 0,
190 0, 1, 0, 0,
191 0, 0, 1, 0,
192 0, 0, 0, 1],
193 color: [1, 0, 1, 1]
194}
195```
196
197The contents of uniform values are lost when a shader is unbound.
198
199### Attributes
200
201The basic idea behind the attribute interface is similar to that for uniforms, however because attributes can be either a constant value or get values from a vertex array they have a slightly more complicated interface. All of the attributes are stored in the `shader.attributes` property.
202
203#### `attrib = constant`
204For non-array attributes you can set the constant value to be broadcast across all vertices. For example, to set the vertex color of a shader to a constant you could do:
205
206```javascript
207shader.attributes.color = [1, 0, 0, 1]
208```
209
210This internally uses [`gl.vertexAttribnf`](http://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttrib.xml). Setting the attribute will also call `gl.disableVertexAttribArray` on the attribute's location.
211
212#### `attrib.location`
213This property accesses the location of the attribute. You can assign/read from it to modify the location of the attribute. For example, you can update the location by doing:
214
215```javascript
216attrib.location = 0
217```
218
219Or you can read the currently bound location back by just accessing it:
220
221```javascript
222console.log(attrib.location)
223```
224
225**WARNING** Changing the attribute location requires recompiling the program. This recompilation is deferred until the next call to `.bind()`
226
227#### `attrib.pointer([type, normalized, stride, offset])`
228A shortcut for `gl.vertexAttribPointer`/`gl.enableVertexAttribArray`. See the [OpenGL man page for details on how this works](http://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttribPointer.xml). The main difference here is that the WebGL context, size and index are known and so these parameters are bound.
229
230* `type` is the type of the pointer (default `gl.FLOAT`)
231* `normalized` specifies whether fixed-point data values should be normalized (`true`) or converted directly as fixed-point values (`false`) when they are accessed. (Default `false`)
232* `stride` the byte offset between consecutive generic vertex attributes. (Default: `0`)
233* `offset` offset of the first element of the array in bytes. (Default `0`)
234
235#### Matrix attributes
236
237Matrix attributes are also supported, however there are a few subtle difference. Due to WebGL limitations, d-dimensional matrix attributes require d separate attribute locations. If `matrix` is a matrix attribute, then the rows of the matrix can be accessed independently using:
238
239```javascript
240//First row of matrix
241shader.attributes.matrix[0]
242
243//Second row
244shader.attributes.matrix[1]
245
246// ... etc.
247```
248
249The interface for these attributes is identical to the above interfaces for vector attributes (support constant setters, `.pointer()`, and `.location`).
250
251There is also a bulk interface which simplifies working with the matrix as a whole unit. For example, it is possible to update the location of each row of the matrix simultaneously by assigning it a vector value:
252
253```javascript
254shader.attributes.matrix.location = [1, 2, 3, 4]
255```
256
257Similarly, if the matrix attribute is stored as a contiguous range in memory, the pointer for each row can be set using `.pointer()`. For example, if `matrix` is a 4x4 matrix attribute then,
258
259```javascript
260shader.attributes.matrix.pointer(gl.FLOAT, false, 16, 0)
261```
262
263is equivalent to,
264
265```javascript
266shader.attributes.matrix[0].pointer(gl.FLOAT, false, 16, 0)
267shader.attributes.matrix[0].pointer(gl.FLOAT, false, 16, 4)
268shader.attributes.matrix[0].pointer(gl.FLOAT, false, 16, 8)
269shader.attributes.matrix[0].pointer(gl.FLOAT, false, 16, 12)
270```
271
272### Reflection
273
274Finally, the library supports some reflection capabilities. The set of all uniforms and data types are stored in the "type" property of the shader object,
275
276```javascript
277console.log(shader.types)
278```
279
280This reflects the uniform and attribute parameters that were passed to the shader constructor.
281
282## Acknowledgements
283
284(c) 2013-2015 Mikola Lysenko. MIT License