├── .editorconfig
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── __tests__
└── browser
│ ├── animation
│ ├── fs.glsl
│ ├── index.html
│ └── vs.glsl
│ ├── basic
│ ├── fs.glsl
│ ├── index.html
│ └── vs.glsl
│ ├── feedback
│ ├── fs.glsl
│ ├── index.html
│ └── vs.glsl
│ ├── particle
│ ├── index.html
│ ├── particle_renderer_fs.glsl
│ ├── particle_renderer_vs.glsl
│ ├── particle_updater_fs.glsl
│ └── particle_updater_vs.glsl
│ ├── texture
│ ├── fs.glsl
│ ├── index.html
│ ├── texture-300x300.png
│ └── vs.glsl
│ └── uniformbufferobject
│ ├── fs.glsl
│ ├── index.html
│ └── vs.glsl
├── build
└── xenogl.min.js
├── docs
├── .nojekyll
├── assets
│ ├── css
│ │ ├── main.css
│ │ └── main.css.map
│ ├── images
│ │ ├── icons.png
│ │ ├── icons@2x.png
│ │ ├── widgets.png
│ │ └── widgets@2x.png
│ └── js
│ │ ├── main.js
│ │ └── search.js
├── classes
│ ├── _buffer_.arraybuffer.html
│ ├── _buffer_.bufferbase.html
│ ├── _buffer_.elementarraybuffer.html
│ ├── _buffer_.uniformbuffer.html
│ ├── _shader_program_.fragmentshader.html
│ ├── _shader_program_.program.html
│ ├── _shader_program_.shaderbase.html
│ ├── _shader_program_.vertexshader.html
│ ├── _texture_.texture2d.html
│ ├── _texture_.texturebase.html
│ ├── _transform_feedback_.transformfeedback.html
│ ├── _uniform_buffer_object_.uniformbufferobject.html
│ ├── _variable_.attribute.html
│ ├── _variable_.uniform.html
│ ├── _vertex_array_object_.vertexarrayobject.html
│ └── _webgl2_.webgl2.html
├── globals.html
├── index.html
├── interfaces
│ ├── _buffer_.buffer.html
│ └── _texture_.texture.html
└── modules
│ ├── _buffer_.html
│ ├── _constants_.html
│ ├── _index_.html
│ ├── _shader_program_.html
│ ├── _texture_.html
│ ├── _transform_feedback_.html
│ ├── _uniform_buffer_object_.html
│ ├── _utils_.html
│ ├── _variable_.html
│ ├── _vertex_array_object_.html
│ └── _webgl2_.html
├── jest.config.js
├── lib
├── buffer.d.ts
├── buffer.js
├── constants.d.ts
├── constants.js
├── index.d.ts
├── index.js
├── shader_program.d.ts
├── shader_program.js
├── texture.d.ts
├── texture.js
├── transform_feedback.d.ts
├── transform_feedback.js
├── transformfeedback.d.ts
├── transformfeedback.js
├── uniform_buffer_object.d.ts
├── uniform_buffer_object.js
├── utils.d.ts
├── utils.js
├── variable.d.ts
├── variable.js
├── vertex_array_object.d.ts
├── vertex_array_object.js
├── webgl2.d.ts
└── webgl2.js
├── package-lock.json
├── package.json
├── src
├── buffer.ts
├── constants.ts
├── index.ts
├── shader_program.ts
├── texture.ts
├── transform_feedback.ts
├── uniform_buffer_object.ts
├── utils.ts
├── variable.ts
├── vertex_array_object.ts
└── webgl2.ts
├── tsconfig.json
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 |
6 | charset = utf-8
7 |
8 | indent_style = space
9 | indent_size = 2
10 |
11 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | .idea
3 | *.iml
4 | out
5 | gen
6 | *~
7 | .fuse_hidden*
8 | .directory
9 | .Trash-*
10 | .nfs*
11 | .DS_Store
12 | .AppleDouble
13 | .LSOverride
14 | Icon
15 | ._*
16 | .DocumentRevisions-V100
17 | .fseventsd
18 | .Spotlight-V100
19 | .TemporaryItems
20 | .Trashes
21 | .VolumeIcon.icns
22 | .com.apple.timemachine.donotpresent
23 | .AppleDB
24 | .AppleDesktop
25 | Network Trash Folder
26 | Temporary Items
27 | .apdisk
28 | logs
29 | *.log
30 | npm-debug.log*
31 | yarn-debug.log*
32 | yarn-error.log*
33 | pids
34 | *.pid
35 | *.seed
36 | *.pid.lock
37 | lib-cov
38 | coverage
39 | .nyc_output
40 | .grunt
41 | bower_components
42 | .lock-wscript
43 | build/Release
44 | node_modules/
45 | jspm_packages/
46 | typings/
47 | .npm
48 | .eslintcache
49 | .node_repl_history
50 | *.tgz
51 | .yarn-integrity
52 | .env
53 | .next
54 | Thumbs.db
55 | ehthumbs.db
56 | ehthumbs_vista.db
57 | *.stackdump
58 | [Dd]esktop.ini
59 | $RECYCLE.BIN/
60 | *.cab
61 | *.msi
62 | *.msm
63 | *.msp
64 | *.lnk
65 | .idea
66 | *.iml
67 | out
68 | gen
69 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 0.1.0
4 |
5 | * \[Breaking Change\] Buffers treat dataOrLength as length rather than byte length when its value is number.
6 |
7 | * \[Breaking Change\] TransformFeedback.feedback() receives an array of targetBuffers rather than single buffer.
8 |
9 | * Support textures.
10 |
11 | ## 0.0.1
12 |
13 | * Initial release with basic functions.
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Koto Furumiya
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XenoGL
2 |
3 | XenoGL is a lightweight and Object-Oriented wrapper for WebGL2.
4 |
5 | ## Unstable
6 |
7 | XenoGL is under unstable yet. APIs may be going to change, which breaks your code. **Do not use XenoGL for production softwares**.
8 |
9 | ## Install without Node.js
10 |
11 | Download the zip file from [Release page on GitHub](https://github.com/kotofurumiya/xenogl/releases) and unzip the file.
12 |
13 | Copy **build/xenogl.min.js** to your directory and append below code to your HTML file:
14 |
15 | ```html
16 |
17 |
20 | ```
21 |
22 | ## Install with Node.js
23 |
24 | Run the install command.
25 |
26 | ```
27 | $ npm install xenogl --save
28 | ```
29 |
30 | Then import xenogl in JavaScript file.
31 |
32 | ```javascript
33 | const XenoGL = require('xenogl');
34 | ```
35 |
36 | ## Basic usage
37 |
38 | First, create a WebGL2 context from a canvas.
39 |
40 | ```javascript
41 | // create a canvas.
42 | const canvas = document.body.createElement('canvas');
43 | canvas.width = 500;
44 | canvas.height = 500;
45 | document.body.appendChild(canvas);
46 |
47 | // create a context.
48 | const xgl = new XenoGL.WebGL2(canvas);
49 | ```
50 |
51 | Next, create two shaders and a program. And add the program to the context.
52 |
53 | ```javascript
54 | // load source as you like.
55 | const vertexShaderSource = await fetch('vertex_shader.glsl').then((res) => res.text());
56 | const fragmentShaderSource = await fetch('fragment_shader.glsl').then((res) => res.text());
57 |
58 | // create shaders.
59 | const vertexShader = new XenoGL.VertexShader(vertexShaderSource);
60 | const fragmentShader = new XenoGL.FragmentShader(fragmentShaderSource);
61 |
62 | // create a program.
63 | const program = new XenoGL.Program({
64 | vertexShader: vertexShader,
65 | fragmentShader: fragmentShader
66 | });
67 |
68 | // add the program to the context.
69 | xgl.addProgram(program);
70 | ```
71 |
72 | You need data to draw. For example, vertex positions and colors.
73 |
74 | ```javascript
75 | const vertices = new Float32Array([
76 | -0.5, 0.5, 0.0,
77 | -0.5, -0.5, 0.0,
78 | 0.5, 0.5, 0.0,
79 | -0.5, -0.5, 0.0,
80 | 0.5, -0.5, 0.0,
81 | 0.5, 0.5, 0.0
82 | ]);
83 |
84 | const colors = new Float32Array([
85 | 1.0, 0.0, 0.0, 1.0,
86 | 0.0, 1.0, 0.0, 1.0,
87 | 0.0, 0.0, 1.0, 1.0,
88 | 0.0, 1.0, 0.0, 1.0,
89 | 0.0, 0.0, 0.0, 1.0,
90 | 0.0, 0.0, 1.0, 1.0
91 | ]);
92 | ```
93 |
94 | Then, create a buffer from data.
95 |
96 | ```javascript
97 | // create attributes which is defined in shaders.
98 | const positionAttribute = new XenoGL.Attribute('vertexPosition', 3);
99 | const colorAttribute = new XenoGL.Attribute('color', 4);
100 |
101 | // create buffers with data and attributes.
102 | const positionBuffer = new XenoGL.ArrayBuffer({
103 | dataOrLength: vertices,
104 | attributes: [positionAttribute],
105 | dataType: XenoGL.FLOAT
106 | });
107 |
108 | const colorBuffer = new XenoGL.ArrayBuffer({
109 | dataOrLength: colors,
110 | attributes: [colorAttribute],
111 | dataType: XenoGL.FLOAT
112 | });
113 |
114 | // add buffers to the program.
115 | program.addBuffer(positionBuffer);
116 | program.addBuffer(colorBuffer);
117 | ```
118 |
119 | Finally, draw it!
120 |
121 | ```javascript
122 | xgl.draw(XenoGL.TRIANGLES);
123 | ```
124 |
125 | That's all.
126 |
127 | ## Program
128 |
129 | You can use multiple programs.
130 |
131 | To switch programs, use `activateProgram`.
132 |
133 | ```javascript
134 | xgl.addProgram(updaterProgram);
135 | xgl.addProgram(rendererProgram);
136 |
137 | xgl.activateProgram(rendererProgram);
138 | ```
139 |
140 | `activateProgram` is a very heavy operation. If you switch programs every frames, it causes performance issues. Because it toggles every attributes on buffers.
141 |
142 | If you want just change the program without toggling attributes, use `useProgram` instead.
143 |
144 | But if you don't have knowledge about OpenGL/WebGL, you should use `activateProgram`.
145 |
146 | ## Buffer
147 |
148 | You can send data to buffers.
149 |
150 | ```javascript
151 | const positionBuffer = new XenoGL.ArrayBuffer({
152 | attributes: [positionAttribute],
153 | dataType: XenoGL.FLOAT
154 | });
155 |
156 | program.addBuffer(positionBuffer);
157 |
158 | positionBuffer.bufferData(new Float32Array([1.0, 1.0, 1.0]));
159 | ```
160 |
161 | ## Interleaved buffer
162 |
163 | To make a buffer interleaved, pass an array of attributes to constructor of ArrayBuffer.
164 |
165 | ```javascript
166 | const vertices = new Float32Array([
167 | -30.0, 30.0, 0.0, // position
168 | 0.0, 1.0, 0.0, 1.0, // color
169 | -30.0, -30.0, 0.0,
170 | 1.0, 0.0, 0.0, 1.0,
171 | 30.0, 30.0, 0.0,
172 | 1.0, 0.0, 0.0, 1.0,
173 | 30.0, -30.0, 0.0,
174 | 0.0, 0.0, 1.0, 1.0
175 | ]);
176 |
177 | const positionAttribute = new XenoGL.Attribute('vertexPosition', 3);
178 | const colorAttribute = new XenoGL.Attribute('color', 4);
179 |
180 | const buffer = new XenoGL.ArrayBuffer({
181 | dataOrLength: vertices,
182 | attributes: [positionAttribute, colorAttribute],
183 | dataType: XenoGL.FLOAT,
184 | usage: XenoGL.DYNAMIC_DRAW
185 | });
186 | ```
187 |
188 | XenoGL detect stride and offset automatically and make the buffer interleaved.
189 |
190 | ## Index buffer
191 |
192 | You can create a index buffer by using `XenoGL.ElementArrayBuffer` object.
193 |
194 | ```javascript
195 | const indices = new Uint16Array([0, 1, 2, 1, 3, 2]);
196 |
197 | const indexBuffer = new XenoGL.ElementArrayBuffer({
198 | dataOrLength: indices,
199 | dataType: XenoGL.UNSIGNED_SHORT,
200 | usage: XenoGL.DYNAMIC_DRAW
201 | });
202 |
203 | program.addBuffer(indexBuffer);
204 | ```
205 |
206 | An ElementArrayBuffer object is treated as an index buffer when it is added to the program.
207 |
208 | When you add multiple ElementArrayBuffer to the program, latest one is used as an index buffer.
209 |
210 | If you need to choose an index buffer manually, use `program.activateElemntArrayBuffer()`.
211 |
212 | ```javascript
213 | program.activateElementArrayBuffer(firstBuffer);
214 | ```
215 |
216 | ## Other buffers
217 |
218 | Not supported yet. Stay tuned.
219 |
220 | ## Uniform variables
221 |
222 | To create uniform variables, use `XenoGL.Uniform` and add it to the program.
223 |
224 | ```javascript
225 | const modelUniform = new XenoGL.Uniform('model');
226 | const viewUniform = new XenoGL.Uniform('view');
227 | const projectionUniform = new XenoGL.Uniform('projection');
228 |
229 | modelUniform.setMatrix(model);
230 | projectionUniform.setMatrix(projection);
231 |
232 | program.addUniform(modelUniform);
233 | program.addUniform(viewUniform);
234 | program.addUniform(projectionUniform);
235 | ```
236 |
237 | `XenoGL.Uniform` object has `setValue(value, type)`, `setVector(vector, type)` and `setMatrix(matrix)` to apply a value. `type` can be XenoGL.FLOAT, XenoGL.UNSIGNED_SHORT and other data types.
238 |
239 | Don't forget to add an uniform to the program.
240 |
241 | ## Vertex Array Objects
242 |
243 | XenoGL supports Vertex Array Object(VAO).
244 |
245 | ```javascript
246 | const buffer = new XenoGL.ArrayBuffer({
247 | dataOrLength: particleInitialDataF32,
248 | attributes: [positionAttr, velocityAttr, ageAttr, lifeAttr],
249 | dataType: XenoGL.FLOAT,
250 | usage: XenoGL.DYNAMIC_COPY
251 | });
252 |
253 | // 2nd arg is optional.
254 | const vao = new XenoGL.VertexArrayObject(buffer, {
255 | dataOrLength: particleInitialDataF32, // initial data
256 | attributes: [positionAttr, velocityAttr] // attributes to enable
257 | });
258 |
259 | // add it to the program.
260 | program.addVertexArrayObject(vao);
261 | ```
262 |
263 | If you activate another VAO, use `program.activateVertexArrayObject`.
264 |
265 | ```javascript
266 | program.activateVertexArrayObject(vao);
267 | ```
268 |
269 | ## Uniform Buffer Object
270 |
271 | Uniform Buffer Objects(UBO) make you able to share values between programs.
272 |
273 | ```javascript
274 | // create a buffer.
275 | const sharedUniformBuffer = new XenoGL.UniformBuffer({
276 | dataOrLength: new Float32Array([1.0, 0.0, 0.0, 1.0]),
277 | dataType: XenoGL.FLOAT
278 | });
279 |
280 | // create ubos.
281 | const ubo1 = new XenoGL.UniformBufferObject('param', sharedUniformBuffer);
282 | const ubo2 = new XenoGL.UniformBufferObject('param', sharedUniformBuffer);
283 |
284 | // add to programs.
285 | program1.addUniformBufferObject(ubo1);
286 | program2.addUniformBufferObject(ubo2);
287 | ```
288 |
289 | ## Transform Feedback
290 |
291 | To use transform feedbacks, first, create a program with additional options.
292 |
293 | ```javascript
294 | const program = new XenoGL.Program({
295 | vertexShader: vs,
296 | fragmentShader: fs,
297 | feedbackVaryings: ['vertexPosition', 'vertexVelocity', 'vertexAge', 'vertexLife'], // variables to feedback.
298 | feedbackBufferMode: XenoGL.INTERLEAVED_ATTRIBS // XenoGL.SEPARATE_ATTRIB or XenoGL.INTERLEAVED_ATTRIBS
299 | });
300 | ```
301 |
302 | Then, create a `TransformFeedback` object and add it to the context(**not to the program**).
303 |
304 | ```javascript
305 | const tf = new XenoGL.TransformFeedback();
306 | xgl.addTransformFeedback(tf);
307 | ```
308 |
309 | `feedback` method executes a calc and feedback.
310 |
311 | ```javascript
312 | tf.feedback({
313 | mode: XenoGL.POINTS,
314 | targetBuffers: [buffer], // buffers to feedback.
315 | count: 100 // how many calc.
316 | });
317 | ```
318 |
319 | ## Textures
320 |
321 | Using textures, create a `Texture2D` object and add it to the context.
322 |
323 | ```javascript
324 | const textureSource = await fetch('texture-300x300.png').then((res) => res.blob())
325 | .then((blob) => createImageBitmap(blob));
326 | const texture = new XenoGL.Texture2D(textureSource);
327 | xgl.addTexture(texture);
328 | ```
329 |
330 | Source of texture can be img, canvas, video, ImageBitmap, ImageData or ArrayBufferView.
331 |
332 | You can crete textures with options.
333 |
334 | ```javascript
335 | const texture = new XenoGL.Texture2D(textureSource, {
336 | target: XenoGL.TEXTURE_2D,
337 | mipmapLevel: 0,
338 | internalFormat: XenoGL.RGBA,
339 | format: XenoGL.RGBA,
340 | dataType: XenoGL.UNSIGNED_BYTE,
341 | width: 500,
342 | height: 500
343 | });
344 | ```
345 |
346 | To use another texture, use `xgl.activateTexture(texture)`.
347 |
348 | ```javascript
349 | xgl.activateTexture(texture2);
350 | ```
351 |
352 |
353 | ## Misc.
354 |
355 | ```javascript
356 | xgl.clearColor(0.0, 0.0, 0.0, 1.0);
357 | xgl.clear(XenoGL.COLOR_BUFFER_BIT | XenoGL.DEPTH_BUFFER_BIT);
358 | xgl.enable(XenoGL.RASTERIZER_DISCARD);
359 | xgl.disable(XenoGL.RASTERIZER_DISCARD);
360 | ```
361 |
362 | ## API Document
363 |
364 | For more information, see [API Document](https://kotofurumiya.github.io/xenogl/).
--------------------------------------------------------------------------------
/__tests__/browser/animation/fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 | precision highp float;
3 |
4 | in vec4 vColor;
5 | out vec4 fragmentColor;
6 |
7 | void main() {
8 | fragmentColor = vColor;
9 | }
10 |
--------------------------------------------------------------------------------
/__tests__/browser/animation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | XenoGL Test - Animation
6 |
7 |
8 |
9 |
10 |
11 |
108 |
109 |
--------------------------------------------------------------------------------
/__tests__/browser/animation/vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec3 vertexPosition;
4 | in vec4 color;
5 |
6 | uniform mat4 model;
7 | uniform mat4 view;
8 | uniform mat4 projection;
9 |
10 | out vec4 vColor;
11 |
12 | void main() {
13 | vColor = color;
14 | gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
15 | }
--------------------------------------------------------------------------------
/__tests__/browser/basic/fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 | precision highp float;
3 |
4 | in vec4 vColor;
5 | out vec4 fragmentColor;
6 |
7 | void main() {
8 | fragmentColor = vColor;
9 | }
10 |
--------------------------------------------------------------------------------
/__tests__/browser/basic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | XenoGL Test - Basic
6 |
7 |
8 |
9 |
10 |
73 |
74 |
--------------------------------------------------------------------------------
/__tests__/browser/basic/vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec3 vertexPosition;
4 | in vec4 color;
5 |
6 | out vec4 vColor;
7 |
8 | void main() {
9 | vColor = color;
10 | gl_Position = vec4(vertexPosition, 1.0);
11 | }
--------------------------------------------------------------------------------
/__tests__/browser/feedback/fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision highp float;
4 |
5 | out vec4 fragmentColor;
6 |
7 | void main() {
8 | fragmentColor = vec4(1.0);
9 | }
--------------------------------------------------------------------------------
/__tests__/browser/feedback/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | XenoGL Test - Feedback
6 |
7 |
8 |
9 |
10 |
83 |
84 |
--------------------------------------------------------------------------------
/__tests__/browser/feedback/vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec4 vecA;
4 | in vec4 vecB;
5 |
6 | out vec4 result1;
7 | out vec4 result2;
8 |
9 | void main() {
10 | result1 = vecA + vecB;
11 | result2 = vecA - vecB;
12 | }
13 |
--------------------------------------------------------------------------------
/__tests__/browser/particle/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | XenoGL Test - Particle
6 |
7 |
8 |
9 |
10 |
157 |
158 |
--------------------------------------------------------------------------------
/__tests__/browser/particle/particle_renderer_fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision highp float;
4 |
5 | out vec4 fragColor;
6 |
7 | void main() {
8 | fragColor = vec4(1.0);
9 | }
--------------------------------------------------------------------------------
/__tests__/browser/particle/particle_renderer_vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec2 particlePosition;
4 |
5 | void main() {
6 | gl_PointSize = 2.0;
7 | gl_Position = vec4(particlePosition, 0.0, 1.0);
8 | }
--------------------------------------------------------------------------------
/__tests__/browser/particle/particle_updater_fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision highp float;
4 |
5 | void main() {
6 | discard;
7 | }
--------------------------------------------------------------------------------
/__tests__/browser/particle/particle_updater_vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | uniform vec2 origin;
4 | uniform float elapsedTimeDelta;
5 |
6 | in vec2 particlePosition;
7 | in vec2 particleVelocity;
8 | in float particleAge;
9 | in float particleLife;
10 |
11 | out vec2 vertexPosition;
12 | out vec2 vertexVelocity;
13 | out float vertexAge;
14 | out float vertexLife;
15 |
16 | void main() {
17 | if(particleAge > particleLife) {
18 | vertexPosition = origin;
19 | vertexVelocity = particleVelocity;
20 | vertexAge = 0.0;
21 | vertexLife = particleLife;
22 | } else {
23 | vertexPosition = particlePosition + (particleVelocity * elapsedTimeDelta);
24 | vertexVelocity = particleVelocity;
25 | vertexAge = particleAge + elapsedTimeDelta;
26 | vertexLife = particleLife;
27 | }
28 | }
--------------------------------------------------------------------------------
/__tests__/browser/texture/fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 | precision highp float;
3 |
4 | uniform sampler2D tex;
5 | in vec2 textureCoord;
6 | out vec4 fragmentColor;
7 |
8 | void main() {
9 | fragmentColor = texture(tex, textureCoord);
10 | }
--------------------------------------------------------------------------------
/__tests__/browser/texture/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | XenoGL Test - Texture
6 |
7 |
8 |
9 |
72 |
73 |
--------------------------------------------------------------------------------
/__tests__/browser/texture/texture-300x300.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/xenogl/8ab6a66fdb585c2d6a3c207d4433e7097e80982c/__tests__/browser/texture/texture-300x300.png
--------------------------------------------------------------------------------
/__tests__/browser/texture/vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec3 vertexPosition;
4 | in vec2 texCoord;
5 |
6 | out vec2 textureCoord;
7 |
8 | void main() {
9 | textureCoord = texCoord;
10 | gl_Position = vec4(vertexPosition, 1.0);
11 | }
12 |
--------------------------------------------------------------------------------
/__tests__/browser/uniformbufferobject/fs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | precision highp float;
4 |
5 | in vec4 vColor;
6 | out vec4 fragmentColor;
7 |
8 | void main() {
9 | fragmentColor = vColor;
10 | }
11 |
--------------------------------------------------------------------------------
/__tests__/browser/uniformbufferobject/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | XenoGL Test - UBO
6 |
7 |
8 |
9 | It's ok if you see a red square.
10 |
90 |
91 |
--------------------------------------------------------------------------------
/__tests__/browser/uniformbufferobject/vs.glsl:
--------------------------------------------------------------------------------
1 | #version 300 es
2 |
3 | in vec3 vertexPosition;
4 |
5 | layout (std140) uniform param {
6 | vec4 color;
7 | };
8 |
9 | out vec4 vColor;
10 |
11 | void main() {
12 | vColor = color;
13 | gl_Position = vec4(vertexPosition, 1.0);
14 | }
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/xenogl/8ab6a66fdb585c2d6a3c207d4433e7097e80982c/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/assets/images/icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/xenogl/8ab6a66fdb585c2d6a3c207d4433e7097e80982c/docs/assets/images/icons.png
--------------------------------------------------------------------------------
/docs/assets/images/icons@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/xenogl/8ab6a66fdb585c2d6a3c207d4433e7097e80982c/docs/assets/images/icons@2x.png
--------------------------------------------------------------------------------
/docs/assets/images/widgets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/xenogl/8ab6a66fdb585c2d6a3c207d4433e7097e80982c/docs/assets/images/widgets.png
--------------------------------------------------------------------------------
/docs/assets/images/widgets@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kotofurumiya/xenogl/8ab6a66fdb585c2d6a3c207d4433e7097e80982c/docs/assets/images/widgets@2x.png
--------------------------------------------------------------------------------
/docs/globals.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
62 |
63 |
64 |
65 |
66 |
67 | Index
68 |
69 |
70 |
71 | External modules
72 |
85 |
86 |
87 |
88 |
89 |
90 |
136 |
137 |
138 |
197 |
198 |
Generated using TypeDoc
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/docs/modules/_buffer_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "buffer" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "buffer"
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Index
71 |
72 |
73 |
82 |
83 | Interfaces
84 |
87 |
88 |
89 |
90 |
91 |
92 |
153 |
154 |
155 |
214 |
215 |
Generated using TypeDoc
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/docs/modules/_index_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "index" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "index"
63 |
64 |
65 |
66 |
118 |
177 |
178 |
Generated using TypeDoc
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/docs/modules/_shader_program_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "shader_program" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "shader_program"
63 |
64 |
65 |
66 |
146 |
205 |
206 |
Generated using TypeDoc
207 |
208 |
209 |
210 |
211 |
212 |
--------------------------------------------------------------------------------
/docs/modules/_transform_feedback_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "transform_feedback" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "transform_feedback"
63 |
64 |
65 |
66 |
134 |
193 |
194 |
Generated using TypeDoc
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/docs/modules/_uniform_buffer_object_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "uniform_buffer_object" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "uniform_buffer_object"
63 |
64 |
65 |
66 |
134 |
193 |
194 |
Generated using TypeDoc
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/docs/modules/_utils_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "utils" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "utils"
63 |
64 |
65 |
66 |
67 |
68 |
69 |
82 |
83 | Functions
84 |
85 |
86 | getBytesPerElementByGlType
87 |
88 | - getBytesPerElementByGlType(type: number): number | null
89 |
90 |
91 | -
92 |
97 |
Parameters
98 |
99 | -
100 |
type: number
101 |
102 |
103 | Returns number
104 | |
105 | null
106 |
107 |
108 |
109 |
110 |
111 |
112 |
161 |
162 |
163 |
222 |
223 |
Generated using TypeDoc
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/docs/modules/_vertex_array_object_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "vertex_array_object" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "vertex_array_object"
63 |
64 |
65 |
66 |
134 |
193 |
194 |
Generated using TypeDoc
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/docs/modules/_webgl2_.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | "webgl2" | xenogl
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | - Preparing search index...
23 | - The search index is not available
24 |
25 |
xenogl
26 |
27 |
49 |
50 |
51 |
52 |
53 |
54 |
62 |
External module "webgl2"
63 |
64 |
65 |
66 |
134 |
193 |
194 |
Generated using TypeDoc
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "transform": {
3 | "^.+\\.tsx?$": "ts-jest"
4 | },
5 | "testMatch": ['**/__tests__/**/*.test.(ts|js)?(x)'],
6 | "moduleFileExtensions": [
7 | "ts",
8 | "tsx",
9 | "js",
10 | "jsx",
11 | "json",
12 | "node"
13 | ]
14 | };
--------------------------------------------------------------------------------
/lib/buffer.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Attribute, TypedArrayLike } from './variable';
3 | export interface Buffer {
4 | readonly data: TypedArrayLike | null;
5 | readonly dataType: number;
6 | readonly usage: number;
7 | readonly bufferType: number;
8 | readonly totalAttributesSize: number;
9 | readonly dataCount: number;
10 | readonly glBuffer: WebGLBuffer | null;
11 | readonly isInitialized: boolean;
12 | bufferData(data: TypedArrayLike | number): void;
13 | activate(): void;
14 | deactivate(): void;
15 | _init(context: WebGL2RenderingContext, program?: WebGLProgram | null, attributes?: Attribute[] | null): void;
16 | _initOnce(context: WebGL2RenderingContext, program?: WebGLProgram | null, attributes?: Attribute[] | null): void;
17 | _createWebGLVertexArrayObject(context: WebGL2RenderingContext, program?: WebGLProgram | null, attributes?: Attribute[] | null): WebGLVertexArrayObject;
18 | }
19 | export declare abstract class BufferBase implements Buffer {
20 | protected _glContext: WebGL2RenderingContext | null;
21 | protected _glProgram: WebGLProgram | null;
22 | protected _glBuffer: WebGLBuffer | null;
23 | protected _dataOrLength: TypedArrayLike | number | null;
24 | protected _data: TypedArrayLike | null;
25 | protected _attributes: Attribute[];
26 | protected _enabledAttributes: Attribute[];
27 | protected _attributeToLocation: Map;
28 | protected _dataType: number;
29 | protected _usage: number;
30 | protected _bufferType: number;
31 | protected _isInitialized: boolean;
32 | protected _flushData: (context: WebGL2RenderingContext, buffer: WebGLBuffer) => void;
33 | protected _totalAttributesSize: number;
34 | constructor(args: {
35 | dataOrLength?: number | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | null | undefined;
36 | attributes?: Attribute[] | undefined;
37 | dataType?: number | undefined;
38 | usage?: number | undefined;
39 | } | undefined, bufferType: number);
40 | /**
41 | * Send data to the buffer.
42 | * @param {TypedArrayLike | number} dataOrLength
43 | */
44 | bufferData(dataOrLength: TypedArrayLike | number): void;
45 | activate(): void;
46 | deactivate(): void;
47 | _flush(): void;
48 | /**
49 | * Initializes attributes.
50 | * Do not call this method manually.
51 | * @param {WebGL2RenderingContext} context
52 | * @param {WebGLProgram | null} program
53 | * @param {Attribute[] | null} attributes
54 | * @private
55 | */
56 | _initAttributes(context: WebGL2RenderingContext, program: WebGLProgram, attributes?: Attribute[] | null): void;
57 | _enableAttributes(): void;
58 | _disableAttributes(): void;
59 | /**
60 | * Initializes the buffer.
61 | * Do not call this method manually.
62 | * @param {WebGL2RenderingContext} context
63 | * @param {WebGLProgram | null} program
64 | * @param {Attribute[] | null} attributes
65 | * @private
66 | */
67 | _init(context: WebGL2RenderingContext, program?: WebGLProgram | null, attributes?: Attribute[] | null): void;
68 | /**
69 | * Initializes the buffer.
70 | * Do not call this method manually.
71 | * @param {WebGL2RenderingContext} context
72 | * @param {WebGLProgram | null} program
73 | * @param {Attribute[] | null} attributes
74 | * @private
75 | */
76 | _initOnce(context: WebGL2RenderingContext, program?: WebGLProgram | null, attributes?: Attribute[] | null): void;
77 | /**
78 | * Creates and return `WebGLVertexArrayObject`.
79 | * You don't have to call this method manually.
80 | * @param {WebGL2RenderingContext} context
81 | * @param {WebGLProgram | null} program
82 | * @param {Attribute[] | null} attributes
83 | * @returns {WebGLVertexArrayObject}
84 | * @private
85 | */
86 | _createWebGLVertexArrayObject(context: WebGL2RenderingContext, program?: WebGLProgram | null, attributes?: Attribute[] | null): WebGLVertexArrayObject;
87 | /**
88 | * Returns data of the buffer.
89 | * @returns {TypedArrayLike | null}
90 | */
91 | readonly data: TypedArrayLike | null;
92 | /**
93 | * Returns data type of the buffer.
94 | * @returns {number}
95 | */
96 | readonly dataType: number;
97 | /**
98 | * Returns how many data set stored in the buffer.
99 | * @returns {number}
100 | */
101 | readonly dataCount: number;
102 | /**
103 | * Returns usage of the buffer.
104 | * @returns {number}
105 | */
106 | readonly usage: number;
107 | /**
108 | * Returns if the buffer is initialized.
109 | * @returns {boolean}
110 | */
111 | readonly isInitialized: boolean;
112 | /**
113 | * Returns total size of attributes.
114 | * @returns {number}
115 | */
116 | readonly totalAttributesSize: number;
117 | /**
118 | * Returns type of the buffer.
119 | * It can be `XenoGL..ARRAY_BUFFER` or `XenoGL..ELEMENT_ARRAY_BUFFER`.
120 | * @returns {number}
121 | */
122 | readonly bufferType: number;
123 | /**
124 | * Returns `WebGLBuffer` if the buffer is initialized.
125 | * Otherwise, throws an error.
126 | * @returns {WebGLBuffer}
127 | */
128 | readonly glBuffer: WebGLBuffer;
129 | }
130 | /**
131 | * ArrayBuffer.
132 | */
133 | export declare class ArrayBuffer extends BufferBase {
134 | constructor(args?: {
135 | dataOrLength?: TypedArrayLike | number | null;
136 | attributes?: Attribute[];
137 | dataType?: number;
138 | usage?: number;
139 | });
140 | }
141 | /**
142 | * ElementArrayBuffer.
143 | */
144 | export declare class ElementArrayBuffer extends BufferBase {
145 | constructor(args?: {
146 | dataOrLength?: TypedArrayLike | number | null;
147 | attributes?: Attribute[];
148 | dataType?: number;
149 | usage?: number;
150 | });
151 | }
152 | /**
153 | * UniformBuffer.
154 | */
155 | export declare class UniformBuffer extends BufferBase {
156 | constructor(args?: {
157 | dataOrLength?: TypedArrayLike | number | null;
158 | dataType?: number;
159 | usage?: number;
160 | });
161 | }
162 |
--------------------------------------------------------------------------------
/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './constants';
2 | export * from './webgl2';
3 | export * from './variable';
4 | export * from './shader_program';
5 | export * from './buffer';
6 | export * from './vertex_array_object';
7 | export * from './uniform_buffer_object';
8 | export * from './transform_feedback';
9 | export * from './texture';
10 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | function __export(m) {
3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4 | }
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | __export(require("./constants"));
7 | __export(require("./webgl2"));
8 | __export(require("./variable"));
9 | __export(require("./shader_program"));
10 | __export(require("./buffer"));
11 | __export(require("./vertex_array_object"));
12 | __export(require("./uniform_buffer_object"));
13 | __export(require("./transform_feedback"));
14 | __export(require("./texture"));
15 |
--------------------------------------------------------------------------------
/lib/shader_program.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Buffer, ElementArrayBuffer } from './buffer';
3 | import { Uniform } from './variable';
4 | import { VertexArrayObject } from './vertex_array_object';
5 | import { UniformBufferObject } from './uniform_buffer_object';
6 | export declare abstract class ShaderBase {
7 | protected _source: string;
8 | protected _glShader: WebGLShader | null;
9 | protected _isCompiled: boolean;
10 | protected _shaderType: number;
11 | constructor(source: string, shaderType: number);
12 | _compile(context: WebGL2RenderingContext): WebGLShader | null;
13 | /**
14 | * Returns if the shader is compiled.
15 | * @returns {boolean}
16 | */
17 | readonly isCompiled: boolean;
18 | /**
19 | * Returns `WebGLShader` when the shader is already compiled.
20 | * Otherwise throws an error.
21 | * @returns {WebGLShader}
22 | */
23 | readonly glShader: WebGLShader;
24 | }
25 | /**
26 | * A vertex shader.
27 | */
28 | export declare class VertexShader extends ShaderBase {
29 | constructor(source: string);
30 | }
31 | /**
32 | * A fragment shader.
33 | */
34 | export declare class FragmentShader extends ShaderBase {
35 | constructor(source: string);
36 | }
37 | /**
38 | * A shader program.
39 | */
40 | export declare class Program {
41 | protected _vertexShader: VertexShader;
42 | protected _fragmentShader: FragmentShader;
43 | protected _feedbackVaryings: string[];
44 | protected _feedbackBufferMode: number;
45 | protected _isLinked: boolean;
46 | protected _glContext: WebGL2RenderingContext | null;
47 | protected _glProgram: WebGLProgram | null;
48 | protected _initializedBuffers: Buffer[];
49 | protected _uninitializedBuffers: Buffer[];
50 | protected _currentIndexBuffer: ElementArrayBuffer | null;
51 | protected _initializedUniforms: Uniform[];
52 | protected _uninitializedUniforms: Uniform[];
53 | protected _initializedVertexArrayObjects: VertexArrayObject[];
54 | protected _uninitializedVertexArrayObject: VertexArrayObject[];
55 | protected _currentVertexArrayObject: VertexArrayObject | null;
56 | protected _initializedUniformBufferObjects: UniformBufferObject[];
57 | protected _uninitializedUniformBufferObjects: UniformBufferObject[];
58 | id: number | null;
59 | constructor(args: {
60 | vertexShader: VertexShader;
61 | fragmentShader: FragmentShader;
62 | feedbackVaryings?: string[];
63 | feedbackBufferMode?: number;
64 | });
65 | /**
66 | * Adds a buffer to the program.
67 | * @param {Buffer} buffer
68 | */
69 | addBuffer(buffer: Buffer): void;
70 | /**
71 | * Activates the `ElementArrayBuffer` as a index buffer.
72 | * @param {ElementArrayBuffer} buffer
73 | */
74 | activateElementArrayBuffer(buffer: ElementArrayBuffer): void;
75 | /**
76 | * Adds an uniform variable to the program.
77 | * @param {Uniform} uniform
78 | */
79 | addUniform(uniform: Uniform): void;
80 | /**
81 | * Adds a `VertexArrayObject` to the program.
82 | * @param {VertexArrayObject} vao
83 | */
84 | addVertexArrayObject(vao: VertexArrayObject): void;
85 | /**
86 | * Activates the `VertexArrayObject`.
87 | * @param {VertexArrayObject} vao
88 | */
89 | activateVertexArrayObject(vao: VertexArrayObject): void;
90 | /**
91 | * Adds an `UniformBufferObject` to the program.
92 | * @param {UniformBufferObject} ubo
93 | */
94 | addUniformBufferObject(ubo: UniformBufferObject): void;
95 | /**
96 | * Issues a draw call, which draws graphics.
97 | * @param {number} mode
98 | * @param {number | null} count
99 | */
100 | draw(mode: number, count?: number | null): void;
101 | activate(): void;
102 | deactivate(): void;
103 | /**
104 | * Links the shader program.
105 | * This method is called internally. So you don't have to call this method manually.
106 | * @param {WebGL2RenderingContext} context
107 | */
108 | _link(context: WebGL2RenderingContext): void;
109 | /**
110 | * Returns if the program is linked.
111 | * @returns {boolean}
112 | */
113 | readonly isLinked: boolean;
114 | /**
115 | * Returns `WebGLProgram` when the program is already linked.
116 | * Otherwise throws an error.
117 | * @returns {WebGLProgram}
118 | */
119 | readonly glProgram: WebGLProgram;
120 | }
121 |
--------------------------------------------------------------------------------
/lib/texture.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare type TextureSource = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData;
3 | export interface Texture {
4 | activate(): void;
5 | _init(context: WebGL2RenderingContext, textureNumber: number): void;
6 | }
7 | export declare abstract class TextureBase implements Texture {
8 | abstract activate(): void;
9 | abstract _init(context: WebGL2RenderingContext, textureNumber: number): void;
10 | protected _getTextureIdFromNumber(n: number): number;
11 | }
12 | export declare class Texture2D extends TextureBase {
13 | protected _source: TextureSource | ArrayBufferView;
14 | protected _glContext: WebGL2RenderingContext | null;
15 | protected _glTexture: WebGLTexture | null;
16 | protected _textureID: number | null;
17 | protected _target: number;
18 | protected _mipmapLevel: number;
19 | protected _internalFormat: number;
20 | protected _format: number;
21 | protected _dataType: number;
22 | protected _width?: number;
23 | protected _height?: number;
24 | protected _flushData: Function;
25 | constructor(dataSource: TextureSource | ArrayBufferView, options?: {
26 | target?: number;
27 | mipmapLevel?: number;
28 | internalFormat?: number;
29 | format?: number;
30 | dataType?: number;
31 | width?: number;
32 | height?: number;
33 | });
34 | activate(): void;
35 | _init(context: WebGL2RenderingContext, textureNumber: number): void;
36 | _flush(): void;
37 | }
38 |
--------------------------------------------------------------------------------
/lib/texture.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __extends = (this && this.__extends) || (function () {
3 | var extendStatics = Object.setPrototypeOf ||
4 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6 | return function (d, b) {
7 | extendStatics(d, b);
8 | function __() { this.constructor = d; }
9 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10 | };
11 | })();
12 | Object.defineProperty(exports, "__esModule", { value: true });
13 | var constants_1 = require("./constants");
14 | var TextureBase = /** @class */ (function () {
15 | function TextureBase() {
16 | }
17 | TextureBase.prototype._getTextureIdFromNumber = function (n) {
18 | return constants_1.TEXTURE0 + n;
19 | };
20 | return TextureBase;
21 | }());
22 | exports.TextureBase = TextureBase;
23 | var Texture2D = /** @class */ (function (_super) {
24 | __extends(Texture2D, _super);
25 | function Texture2D(dataSource, options) {
26 | if (options === void 0) { options = {}; }
27 | var _this = _super.call(this) || this;
28 | _this._source = dataSource;
29 | _this._glContext = null;
30 | _this._glTexture = null;
31 | _this._textureID = null;
32 | _this._target = ('target' in options) ? options.target : constants_1.TEXTURE_2D;
33 | _this._mipmapLevel = ('mipmapLevel' in options) ? options.mipmapLevel : 0;
34 | _this._internalFormat = ('internalFormat' in options) ? options.internalFormat : constants_1.RGBA;
35 | _this._format = ('format' in options) ? options.mipmapLevel : constants_1.RGBA;
36 | _this._dataType = ('dataType' in options) ? options.mipmapLevel : constants_1.UNSIGNED_BYTE;
37 | _this._width = ('width' in options) ? options.width : undefined;
38 | _this._height = ('height' in options) ? options.height : undefined;
39 | _this._flushData = function () { };
40 | return _this;
41 | }
42 | Texture2D.prototype.activate = function () {
43 | var _this = this;
44 | this._flushData = function (context) {
45 | context.activeTexture(_this._textureID);
46 | };
47 | };
48 | Texture2D.prototype._init = function (context, textureNumber) {
49 | this._glContext = context;
50 | this._textureID = this._getTextureIdFromNumber(textureNumber);
51 | context.activeTexture(this._textureID);
52 | this._glTexture = context.createTexture();
53 | context.bindTexture(this._target, this._glTexture);
54 | if (typeof this._width === 'undefined' || typeof this._height === 'undefined') {
55 | context.texImage2D(this._target, this._mipmapLevel, this._internalFormat, this._format, this._dataType, this._source);
56 | }
57 | else {
58 | context.texImage2D(this._target, this._mipmapLevel, this._internalFormat, this._width, this._height, 0, this._format, this._dataType, this._source);
59 | }
60 | context.generateMipmap(this._target);
61 | this._flush();
62 | };
63 | Texture2D.prototype._flush = function () {
64 | if (this._glContext !== null) {
65 | this._flushData(this._glContext);
66 | this._flushData = function () { };
67 | }
68 | };
69 | return Texture2D;
70 | }(TextureBase));
71 | exports.Texture2D = Texture2D;
72 |
--------------------------------------------------------------------------------
/lib/transform_feedback.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Buffer } from './buffer';
3 | export declare class TransformFeedback {
4 | protected _glContext: WebGL2RenderingContext | null;
5 | protected _glTransformFeedback: WebGLTransformFeedback | null;
6 | constructor();
7 | feedback(args: {
8 | mode: number;
9 | targetBuffers: Buffer[];
10 | count: number;
11 | }): void;
12 | _init(context: WebGL2RenderingContext): void;
13 | }
14 |
--------------------------------------------------------------------------------
/lib/transform_feedback.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var constants_1 = require("./constants");
4 | var TransformFeedback = /** @class */ (function () {
5 | function TransformFeedback() {
6 | this._glContext = null;
7 | this._glTransformFeedback = null;
8 | }
9 | TransformFeedback.prototype.feedback = function (args) {
10 | if (this._glContext === null) {
11 | throw new Error('This transform feedback is not added to any WebGL2 yet.');
12 | }
13 | for (var i = 0; i < args.targetBuffers.length; i++) {
14 | this._glContext.bindBufferBase(constants_1.TRANSFORM_FEEDBACK_BUFFER, i, args.targetBuffers[i].glBuffer);
15 | }
16 | this._glContext.beginTransformFeedback(args.mode);
17 | this._glContext.drawArrays(args.mode, 0, args.count);
18 | this._glContext.endTransformFeedback();
19 | for (var i = 0; i < args.targetBuffers.length; i++) {
20 | this._glContext.bindBufferBase(constants_1.TRANSFORM_FEEDBACK_BUFFER, i, null);
21 | }
22 | };
23 | TransformFeedback.prototype._init = function (context) {
24 | this._glContext = context;
25 | this._glTransformFeedback = context.createTransformFeedback();
26 | context.bindTransformFeedback(constants_1.TRANSFORM_FEEDBACK, this._glTransformFeedback);
27 | };
28 | return TransformFeedback;
29 | }());
30 | exports.TransformFeedback = TransformFeedback;
31 |
--------------------------------------------------------------------------------
/lib/transformfeedback.d.ts:
--------------------------------------------------------------------------------
1 | export declare class Transformfeedback {
2 | }
3 |
--------------------------------------------------------------------------------
/lib/transformfeedback.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var Transformfeedback = /** @class */ (function () {
4 | function Transformfeedback() {
5 | }
6 | return Transformfeedback;
7 | }());
8 | exports.Transformfeedback = Transformfeedback;
9 |
--------------------------------------------------------------------------------
/lib/uniform_buffer_object.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { UniformBuffer } from './buffer';
3 | import { TypedArrayLike } from './variable';
4 | /**
5 | * An uniform buffer object.
6 | */
7 | export declare class UniformBufferObject {
8 | protected _buffer: UniformBuffer;
9 | protected _blockName: string;
10 | protected _blockIndex: number | null;
11 | protected _javascriptIndex: number | null;
12 | protected _isInitialized: boolean;
13 | constructor(blockName: string, bufferOrBufferArgs?: UniformBuffer | {
14 | dataOrLength?: TypedArrayLike | number | null;
15 | dataType?: number;
16 | usage?: number;
17 | });
18 | /**
19 | * Initializes the uniform buffer object.
20 | * Do not call this method manually.
21 | * @param {WebGL2RenderingContext} context
22 | * @param {WebGLProgram} program
23 | * @param {number} jsIndex
24 | * @private
25 | */
26 | _init(context: WebGL2RenderingContext, program: WebGLProgram, jsIndex: number): void;
27 | }
28 |
--------------------------------------------------------------------------------
/lib/uniform_buffer_object.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var buffer_1 = require("./buffer");
4 | var constants_1 = require("./constants");
5 | /**
6 | * An uniform buffer object.
7 | */
8 | var UniformBufferObject = /** @class */ (function () {
9 | function UniformBufferObject(blockName, bufferOrBufferArgs) {
10 | if (bufferOrBufferArgs === void 0) { bufferOrBufferArgs = { dataOrLength: null, dataType: constants_1.FLOAT, usage: constants_1.STATIC_DRAW }; }
11 | this._blockName = blockName;
12 | this._blockIndex = null;
13 | this._javascriptIndex = null;
14 | this._isInitialized = false;
15 | if (bufferOrBufferArgs instanceof buffer_1.UniformBuffer) {
16 | this._buffer = bufferOrBufferArgs;
17 | }
18 | else {
19 | this._buffer = new buffer_1.UniformBuffer(bufferOrBufferArgs);
20 | }
21 | }
22 | /**
23 | * Initializes the uniform buffer object.
24 | * Do not call this method manually.
25 | * @param {WebGL2RenderingContext} context
26 | * @param {WebGLProgram} program
27 | * @param {number} jsIndex
28 | * @private
29 | */
30 | UniformBufferObject.prototype._init = function (context, program, jsIndex) {
31 | this._blockIndex = context.getUniformBlockIndex(program, this._blockName);
32 | this._javascriptIndex = jsIndex;
33 | context.uniformBlockBinding(program, this._blockIndex, jsIndex);
34 | this._buffer._initOnce(context, program);
35 | context.bindBufferBase(constants_1.UNIFORM_BUFFER, jsIndex, this._buffer.glBuffer);
36 | };
37 | return UniformBufferObject;
38 | }());
39 | exports.UniformBufferObject = UniformBufferObject;
40 |
--------------------------------------------------------------------------------
/lib/utils.d.ts:
--------------------------------------------------------------------------------
1 | export declare function getBytesPerElementByGlType(type: number): number | null;
2 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var constants_1 = require("./constants");
4 | function getBytesPerElementByGlType(type) {
5 | if (type === constants_1.FLOAT) {
6 | return 4;
7 | }
8 | else if (type === constants_1.BYTE || type === constants_1.UNSIGNED_BYTE) {
9 | return 1;
10 | }
11 | else if (type === constants_1.SHORT || type === constants_1.UNSIGNED_SHORT || type === constants_1.HALF_FLOAT) {
12 | return 2;
13 | }
14 | else {
15 | return null;
16 | }
17 | }
18 | exports.getBytesPerElementByGlType = getBytesPerElementByGlType;
19 |
--------------------------------------------------------------------------------
/lib/variable.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | export declare type TypedArrayLike = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
3 | /**
4 | * An attribute variable.
5 | */
6 | export declare class Attribute {
7 | protected _name: string;
8 | protected _size: number;
9 | constructor(name: string, size: number);
10 | equals(other: Attribute): boolean;
11 | readonly name: string;
12 | readonly size: number;
13 | }
14 | /**
15 | * An uniform variable.
16 | */
17 | export declare class Uniform {
18 | protected _name: string;
19 | protected _location: WebGLUniformLocation | null;
20 | protected _glContext: WebGL2RenderingContext | null;
21 | protected _glProgram: WebGLProgram | null;
22 | protected _flushData: (context: WebGL2RenderingContext, location: WebGLUniformLocation) => void;
23 | constructor(name: string);
24 | /**
25 | * Sets the uniform variable to the value.
26 | * @param {number} value
27 | * @param {number} type
28 | */
29 | setValue(value: number, type: number): void;
30 | /**
31 | * Sets the uniform variable to the vector.
32 | * @param {TypedArrayLike} value
33 | * @param {number} type
34 | */
35 | setVector(value: TypedArrayLike, type: number): void;
36 | setVector1(value: TypedArrayLike, type: number): void;
37 | setVector2(value: TypedArrayLike, type: number): void;
38 | setVector3(value: TypedArrayLike, type: number): void;
39 | setVector4(value: TypedArrayLike, type: number): void;
40 | /**
41 | * Sets the uniform variable to the matrix.
42 | * @param {Float32Array} value
43 | */
44 | setMatrix(value: Float32Array): void;
45 | setMatrix2(value: Float32Array): void;
46 | setMatrix3(value: Float32Array): void;
47 | setMatrix4(value: Float32Array): void;
48 | _flush(): void;
49 | _init(context: WebGL2RenderingContext, program: WebGLProgram): void;
50 | readonly isLocated: boolean;
51 | }
52 |
--------------------------------------------------------------------------------
/lib/variable.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var constants_1 = require("./constants");
4 | /**
5 | * An attribute variable.
6 | */
7 | var Attribute = /** @class */ (function () {
8 | function Attribute(name, size) {
9 | this._name = name;
10 | this._size = size;
11 | }
12 | Attribute.prototype.equals = function (other) {
13 | return this.name === other.name && this.size === other.size;
14 | };
15 | Object.defineProperty(Attribute.prototype, "name", {
16 | get: function () {
17 | return this._name;
18 | },
19 | enumerable: true,
20 | configurable: true
21 | });
22 | Object.defineProperty(Attribute.prototype, "size", {
23 | get: function () {
24 | return this._size;
25 | },
26 | enumerable: true,
27 | configurable: true
28 | });
29 | return Attribute;
30 | }());
31 | exports.Attribute = Attribute;
32 | /**
33 | * An uniform variable.
34 | */
35 | var Uniform = /** @class */ (function () {
36 | function Uniform(name) {
37 | this._name = name;
38 | this._location = null;
39 | this._glContext = null;
40 | this._glProgram = null;
41 | this._flushData = function (context, location) { };
42 | }
43 | /**
44 | * Sets the uniform variable to the value.
45 | * @param {number} value
46 | * @param {number} type
47 | */
48 | Uniform.prototype.setValue = function (value, type) {
49 | if (type === constants_1.FLOAT) {
50 | this._flushData = function (context, location) {
51 | context.uniform1f(location, value);
52 | };
53 | }
54 | else if (type === constants_1.INT) {
55 | this._flushData = function (context, location) {
56 | context.uniform1i(location, value);
57 | };
58 | }
59 | else if (type === constants_1.UNSIGNED_INT) {
60 | this._flushData = function (context, location) {
61 | context.uniform1ui(location, value);
62 | };
63 | }
64 | this._flush();
65 | };
66 | /**
67 | * Sets the uniform variable to the vector.
68 | * @param {TypedArrayLike} value
69 | * @param {number} type
70 | */
71 | Uniform.prototype.setVector = function (value, type) {
72 | var length = value.length;
73 | if (length === 1) {
74 | this.setVector1(value, type);
75 | }
76 | else if (length === 2) {
77 | this.setVector2(value, type);
78 | }
79 | else if (length === 3) {
80 | this.setVector3(value, type);
81 | }
82 | else if (length === 4) {
83 | this.setVector4(value, type);
84 | }
85 | else {
86 | throw new Error("Length of value must be 1, 2, 3 or 4. Your value length is " + length);
87 | }
88 | };
89 | Uniform.prototype.setVector1 = function (value, type) {
90 | if (type === constants_1.FLOAT) {
91 | this._flushData = function (context, location) {
92 | context.uniform1fv(location, value);
93 | };
94 | }
95 | else if (type === constants_1.INT) {
96 | this._flushData = function (context, location) {
97 | context.uniform1iv(location, value);
98 | };
99 | }
100 | else if (type === constants_1.UNSIGNED_INT) {
101 | this._flushData = function (context, location) {
102 | context.uniform1uiv(location, value);
103 | };
104 | }
105 | this._flush();
106 | };
107 | Uniform.prototype.setVector2 = function (value, type) {
108 | if (type === constants_1.FLOAT) {
109 | this._flushData = function (context, location) {
110 | context.uniform2fv(location, value);
111 | };
112 | }
113 | else if (type === constants_1.INT) {
114 | this._flushData = function (context, location) {
115 | context.uniform2iv(location, value);
116 | };
117 | }
118 | else if (type === constants_1.UNSIGNED_INT) {
119 | this._flushData = function (context, location) {
120 | context.uniform2uiv(location, value);
121 | };
122 | }
123 | this._flush();
124 | };
125 | Uniform.prototype.setVector3 = function (value, type) {
126 | if (type === constants_1.FLOAT) {
127 | this._flushData = function (context, location) {
128 | context.uniform3fv(location, value);
129 | };
130 | }
131 | else if (type === constants_1.INT) {
132 | this._flushData = function (context, location) {
133 | context.uniform3iv(location, value);
134 | };
135 | }
136 | else if (type === constants_1.UNSIGNED_INT) {
137 | this._flushData = function (context, location) {
138 | context.uniform3uiv(location, value);
139 | };
140 | }
141 | this._flush();
142 | };
143 | Uniform.prototype.setVector4 = function (value, type) {
144 | if (type === constants_1.FLOAT) {
145 | this._flushData = function (context, location) {
146 | context.uniform4fv(location, value);
147 | };
148 | }
149 | else if (type === constants_1.INT) {
150 | this._flushData = function (context, location) {
151 | context.uniform4iv(location, value);
152 | };
153 | }
154 | else if (type === constants_1.UNSIGNED_INT) {
155 | this._flushData = function (context, location) {
156 | context.uniform4uiv(location, value);
157 | };
158 | }
159 | this._flush();
160 | };
161 | /**
162 | * Sets the uniform variable to the matrix.
163 | * @param {Float32Array} value
164 | */
165 | Uniform.prototype.setMatrix = function (value) {
166 | var size = value.length;
167 | if (size === 4) {
168 | this.setMatrix2(value);
169 | }
170 | else if (size === 9) {
171 | this.setMatrix3(value);
172 | }
173 | else if (size === 16) {
174 | this.setMatrix4(value);
175 | }
176 | else {
177 | throw new Error("Failed to detect size of the matrix. If you use a non-square matrix, use setMatrixNxN instead.");
178 | }
179 | };
180 | Uniform.prototype.setMatrix2 = function (value) {
181 | this._flushData = function (context, location) {
182 | context.uniformMatrix2fv(location, false, value);
183 | };
184 | this._flush();
185 | };
186 | Uniform.prototype.setMatrix3 = function (value) {
187 | this._flushData = function (context, location) {
188 | context.uniformMatrix3fv(location, false, value);
189 | };
190 | this._flush();
191 | };
192 | Uniform.prototype.setMatrix4 = function (value) {
193 | this._flushData = function (context, location) {
194 | context.uniformMatrix4fv(location, false, value);
195 | };
196 | this._flush();
197 | };
198 | Uniform.prototype._flush = function () {
199 | if (this.isLocated && this._glContext !== null) {
200 | this._flushData(this._glContext, this._location);
201 | }
202 | };
203 | Uniform.prototype._init = function (context, program) {
204 | this._location = context.getUniformLocation(program, this._name);
205 | this._glContext = context;
206 | this._glProgram = program;
207 | this._flush();
208 | };
209 | Object.defineProperty(Uniform.prototype, "isLocated", {
210 | get: function () {
211 | return this._location !== null;
212 | },
213 | enumerable: true,
214 | configurable: true
215 | });
216 | return Uniform;
217 | }());
218 | exports.Uniform = Uniform;
219 |
--------------------------------------------------------------------------------
/lib/vertex_array_object.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Attribute, TypedArrayLike } from './variable';
3 | import { Buffer } from './buffer';
4 | export declare class VertexArrayObject {
5 | protected _buffer: Buffer;
6 | protected _glContext: WebGL2RenderingContext | null;
7 | protected _glVertexArrayObject: WebGLVertexArrayObject | null;
8 | protected _enabledAttributes: Attribute[] | null;
9 | protected _mustWriteData: boolean;
10 | protected _dataOrLength?: TypedArrayLike | number;
11 | protected _isInitialized: boolean;
12 | constructor(buffer: Buffer, options?: {
13 | dataOrLength?: TypedArrayLike | number;
14 | attributes?: Attribute[];
15 | });
16 | /**
17 | * Initializes the vertex array object.
18 | * Do not call this method manually.
19 | * @param {WebGL2RenderingContext} context
20 | * @param {WebGLProgram} program
21 | * @private
22 | */
23 | _init(context: WebGL2RenderingContext, program: WebGLProgram): void;
24 | /**
25 | * Returns buffer bound to the vertex array object.
26 | * @returns {Buffer}
27 | */
28 | readonly buffer: Buffer;
29 | /**
30 | * Returns `WebGLVertexArrayObject` if the vertex array object is initialized.
31 | * Otherwise, throws an error.
32 | * @returns {WebGLVertexArrayObject}
33 | */
34 | readonly glVertexArrayObject: WebGLVertexArrayObject;
35 | }
36 |
--------------------------------------------------------------------------------
/lib/vertex_array_object.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var VertexArrayObject = /** @class */ (function () {
4 | function VertexArrayObject(buffer, options) {
5 | if (options === void 0) { options = {}; }
6 | this._buffer = buffer;
7 | this._glContext = null;
8 | this._glVertexArrayObject = null;
9 | this._enabledAttributes = ('attributes' in options) ? options.attributes : null;
10 | this._mustWriteData = 'dataOrLength' in options;
11 | if (this._mustWriteData) {
12 | this._dataOrLength = options.dataOrLength;
13 | }
14 | this._isInitialized = false;
15 | }
16 | /**
17 | * Initializes the vertex array object.
18 | * Do not call this method manually.
19 | * @param {WebGL2RenderingContext} context
20 | * @param {WebGLProgram} program
21 | * @private
22 | */
23 | VertexArrayObject.prototype._init = function (context, program) {
24 | if (this._mustWriteData) {
25 | this._buffer.bufferData(this._dataOrLength);
26 | }
27 | this._buffer._initOnce(context, program, this._enabledAttributes);
28 | var vao = this._buffer._createWebGLVertexArrayObject(context, program, this._enabledAttributes);
29 | this._glContext = context;
30 | this._glVertexArrayObject = vao;
31 | this._isInitialized = true;
32 | };
33 | Object.defineProperty(VertexArrayObject.prototype, "buffer", {
34 | /**
35 | * Returns buffer bound to the vertex array object.
36 | * @returns {Buffer}
37 | */
38 | get: function () {
39 | return this._buffer;
40 | },
41 | enumerable: true,
42 | configurable: true
43 | });
44 | Object.defineProperty(VertexArrayObject.prototype, "glVertexArrayObject", {
45 | /**
46 | * Returns `WebGLVertexArrayObject` if the vertex array object is initialized.
47 | * Otherwise, throws an error.
48 | * @returns {WebGLVertexArrayObject}
49 | */
50 | get: function () {
51 | if (this._isInitialized) {
52 | return this._glVertexArrayObject;
53 | }
54 | else {
55 | throw new Error('This vertex array object is not added to any program yet.');
56 | }
57 | },
58 | enumerable: true,
59 | configurable: true
60 | });
61 | return VertexArrayObject;
62 | }());
63 | exports.VertexArrayObject = VertexArrayObject;
64 |
--------------------------------------------------------------------------------
/lib/webgl2.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { Program } from './shader_program';
3 | import { TransformFeedback } from './transform_feedback';
4 | import { Texture } from './texture';
5 | export declare class WebGL2 {
6 | protected _context: WebGL2RenderingContext;
7 | protected _programs: Array;
8 | protected _activeProgram: Program | null;
9 | protected _transformFeedbacks: Array;
10 | protected _textures: Texture[];
11 | protected _activeTexture: Texture | null;
12 | constructor(canvas: HTMLCanvasElement);
13 | /**
14 | * Adds the program to the `WebGL2` and returns ID number of the program.
15 | * If any program is activated yet, this method activates the program.
16 | * @param {Program} program
17 | * @returns {number} Program ID
18 | */
19 | addProgram(program: Program): number;
20 | /**
21 | * Adds the transform feedback to `WebGL2`.
22 | * @param {TransformFeedback} tf
23 | */
24 | addTransformFeedback(tf: TransformFeedback): void;
25 | addTexture(texture: Texture): void;
26 | /**
27 | * Activates a program and deactivates the previous program.
28 | * Throws an error when the program is not attached to WebGL2.
29 | * @param {Program} program
30 | */
31 | activateProgram(program: Program): void;
32 | /**
33 | * Activates a program by ID and deactivates the previous program.
34 | * Throws an error when the ID does not exist.
35 | * @param {number} id
36 | */
37 | activateProgramByID(id: number): void;
38 | /**
39 | * Uses the program as a current program.
40 | * @param {Program} program
41 | */
42 | useProgram(program: Program): void;
43 | /**
44 | * Uses the program as a current program.
45 | * @param {number} id
46 | */
47 | useProgramByID(id: number): void;
48 | activateTexture(texture: Texture): void;
49 | /**
50 | * Deactivates the program.
51 | * @param {Program} program
52 | */
53 | deactivateProgram(program: Program): void;
54 | draw(mode: number, count?: number | null): void;
55 | clear(mask?: number): void;
56 | clearColor(r: number, g: number, b: number, a: number): void;
57 | enable(cap: number): void;
58 | disable(cap: number): void;
59 | viewport(x: number, y: number, width: number, height: number): void;
60 | }
61 |
--------------------------------------------------------------------------------
/lib/webgl2.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | var constants_1 = require("./constants");
4 | var WebGL2 = /** @class */ (function () {
5 | function WebGL2(canvas) {
6 | this._context = canvas.getContext('webgl2');
7 | this._programs = [];
8 | this._activeProgram = null;
9 | this._transformFeedbacks = [];
10 | this._textures = [];
11 | this._activeTexture = null;
12 | }
13 | /**
14 | * Adds the program to the `WebGL2` and returns ID number of the program.
15 | * If any program is activated yet, this method activates the program.
16 | * @param {Program} program
17 | * @returns {number} Program ID
18 | */
19 | WebGL2.prototype.addProgram = function (program) {
20 | if (!program.isLinked) {
21 | program._link(this._context);
22 | }
23 | this._programs.push(program);
24 | if (this._activeProgram === null) {
25 | this._activeProgram = program;
26 | this._context.useProgram(program.glProgram);
27 | }
28 | var id = this._programs.length - 1;
29 | program.id = id;
30 | return id;
31 | };
32 | /**
33 | * Adds the transform feedback to `WebGL2`.
34 | * @param {TransformFeedback} tf
35 | */
36 | WebGL2.prototype.addTransformFeedback = function (tf) {
37 | this._transformFeedbacks.push(tf);
38 | tf._init(this._context);
39 | };
40 | WebGL2.prototype.addTexture = function (texture) {
41 | var id = this._textures.length;
42 | this._textures.push(texture);
43 | texture._init(this._context, id);
44 | if (this._activeTexture === null) {
45 | texture.activate();
46 | }
47 | };
48 | /**
49 | * Activates a program and deactivates the previous program.
50 | * Throws an error when the program is not attached to WebGL2.
51 | * @param {Program} program
52 | */
53 | WebGL2.prototype.activateProgram = function (program) {
54 | if (program.id === null) {
55 | throw new Error("This program is not added to WebGL2 yet. Add it by using addProgram method.");
56 | }
57 | else {
58 | this.activateProgramByID(program.id);
59 | }
60 | };
61 | /**
62 | * Activates a program by ID and deactivates the previous program.
63 | * Throws an error when the ID does not exist.
64 | * @param {number} id
65 | */
66 | WebGL2.prototype.activateProgramByID = function (id) {
67 | if (id > this._programs.length) {
68 | throw new Error("ID " + id + " does not exist.");
69 | }
70 | if (this._activeProgram !== null) {
71 | this._activeProgram.deactivate();
72 | }
73 | var program = this._programs[id];
74 | this._context.useProgram(program.glProgram);
75 | program.activate();
76 | this._activeProgram = program;
77 | };
78 | /**
79 | * Uses the program as a current program.
80 | * @param {Program} program
81 | */
82 | WebGL2.prototype.useProgram = function (program) {
83 | if (program.id === null) {
84 | throw new Error("This program is not added to WebGL2 yet. Add it by using addProgram method.");
85 | }
86 | else {
87 | this.useProgramByID(program.id);
88 | }
89 | };
90 | /**
91 | * Uses the program as a current program.
92 | * @param {number} id
93 | */
94 | WebGL2.prototype.useProgramByID = function (id) {
95 | if (id > this._programs.length) {
96 | throw new Error("ID " + id + " does not exist.");
97 | }
98 | var program = this._programs[id];
99 | this._context.useProgram(program.glProgram);
100 | this._activeProgram = program;
101 | };
102 | WebGL2.prototype.activateTexture = function (texture) {
103 | };
104 | /**
105 | * Deactivates the program.
106 | * @param {Program} program
107 | */
108 | WebGL2.prototype.deactivateProgram = function (program) {
109 | program.deactivate();
110 | };
111 | WebGL2.prototype.draw = function (mode, count) {
112 | if (count === void 0) { count = null; }
113 | if (this._activeProgram !== null) {
114 | this._activeProgram.draw(mode, count);
115 | }
116 | };
117 | WebGL2.prototype.clear = function (mask) {
118 | if (mask === void 0) { mask = constants_1.COLOR_BUFFER_BIT; }
119 | this._context.clear(mask);
120 | };
121 | WebGL2.prototype.clearColor = function (r, g, b, a) {
122 | this._context.clearColor(r, b, g, a);
123 | };
124 | WebGL2.prototype.enable = function (cap) {
125 | this._context.enable(cap);
126 | };
127 | WebGL2.prototype.disable = function (cap) {
128 | this._context.disable(cap);
129 | };
130 | WebGL2.prototype.viewport = function (x, y, width, height) {
131 | this._context.viewport(x, y, width, height);
132 | };
133 | return WebGL2;
134 | }());
135 | exports.WebGL2 = WebGL2;
136 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "xenogl",
3 | "version": "0.1.1",
4 | "description": "A lightweight Object-Oriented wrapper for WebGL2",
5 | "main": "./lib/index.js",
6 | "types": "./lib/index.d.ts",
7 | "scripts": {
8 | "typedoc": "typedoc ./src --out ./docs --readme README.md && nodetouch ./docs/.nojekyll",
9 | "test": "jest",
10 | "webpack": "webpack",
11 | "build": "tsc && npm run typedoc && webpack"
12 | },
13 | "keywords": [
14 | "webgl"
15 | ],
16 | "author": "Koto Furumiya (https://sbfl.net/)",
17 | "license": "MIT",
18 | "files": [
19 | "lib/"
20 | ],
21 | "repository": {
22 | "type": "git",
23 | "url": "https://github.com/kotofurumiya/xenogl.git"
24 | },
25 | "bugs": {
26 | "url": "https://github.com/kotofurumiya/xenogl/issues",
27 | "email": "kotofurumiya@gmail.com"
28 | },
29 | "devDependencies": {
30 | "@types/jest": "^22.1.2",
31 | "@types/webgl2": "0.0.2",
32 | "jest": "^22.2.2",
33 | "touch": "^3.1.0",
34 | "ts-jest": "^22.0.3",
35 | "typedoc": "^0.10.0",
36 | "typescript": "^2.7.1",
37 | "webpack": "^3.10.0"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './constants';
2 | export * from './webgl2';
3 | export * from './variable';
4 | export * from './shader_program';
5 | export * from './buffer';
6 | export * from './vertex_array_object';
7 | export * from './uniform_buffer_object';
8 | export * from './transform_feedback';
9 | export * from './texture';
--------------------------------------------------------------------------------
/src/shader_program.ts:
--------------------------------------------------------------------------------
1 | import { Buffer, ElementArrayBuffer } from './buffer';
2 | import { Uniform } from './variable';
3 | import { SEPARATE_ATTRIBS, INTERLEAVED_ATTRIBS, VERTEX_SHADER, FRAGMENT_SHADER, ELEMENT_ARRAY_BUFFER } from './constants';
4 | import { VertexArrayObject } from './vertex_array_object';
5 | import { UniformBufferObject } from './uniform_buffer_object';
6 |
7 | export abstract class ShaderBase {
8 | protected _source: string;
9 | protected _glShader: WebGLShader | null;
10 | protected _isCompiled: boolean;
11 | protected _shaderType: number;
12 |
13 | constructor(source: string, shaderType: number) {
14 | this._source = source;
15 | this._glShader = null;
16 | this._isCompiled = false;
17 | this._shaderType = shaderType;
18 | }
19 |
20 | _compile(context: WebGL2RenderingContext) {
21 | const shader = context.createShader(this._shaderType);
22 | context.shaderSource(shader, this._source);
23 | context.compileShader(shader);
24 |
25 | const compileStatus = context.getShaderParameter(shader, context.COMPILE_STATUS);
26 | if(!compileStatus) {
27 | const info = context.getShaderInfoLog(shader);
28 | throw new Error(info);
29 | }
30 |
31 | this._glShader = shader;
32 | this._isCompiled = true;
33 | return shader;
34 | }
35 |
36 | /**
37 | * Returns if the shader is compiled.
38 | * @returns {boolean}
39 | */
40 | get isCompiled(): boolean {
41 | return this._isCompiled;
42 | }
43 |
44 | /**
45 | * Returns `WebGLShader` when the shader is already compiled.
46 | * Otherwise throws an error.
47 | * @returns {WebGLShader}
48 | */
49 | get glShader(): WebGLShader {
50 | if(!this._glShader === null) {
51 | throw new Error('This shader is not compiled yet.');
52 | }
53 |
54 | return this._glShader;
55 | }
56 | }
57 |
58 | /**
59 | * A vertex shader.
60 | */
61 | export class VertexShader extends ShaderBase {
62 | constructor(source: string) {
63 | super(source, VERTEX_SHADER);
64 | }
65 | }
66 |
67 | /**
68 | * A fragment shader.
69 | */
70 | export class FragmentShader extends ShaderBase {
71 | constructor(source: string) {
72 | super(source, FRAGMENT_SHADER);
73 | }
74 | }
75 |
76 | /**
77 | * A shader program.
78 | */
79 | export class Program {
80 | protected _vertexShader: VertexShader;
81 | protected _fragmentShader: FragmentShader;
82 | protected _feedbackVaryings: string[];
83 | protected _feedbackBufferMode: number;
84 | protected _isLinked: boolean;
85 |
86 | protected _glContext: WebGL2RenderingContext | null;
87 | protected _glProgram: WebGLProgram | null;
88 |
89 | protected _initializedBuffers: Buffer[];
90 | protected _uninitializedBuffers: Buffer[];
91 | protected _currentIndexBuffer: ElementArrayBuffer | null;
92 |
93 | protected _initializedUniforms: Uniform[];
94 | protected _uninitializedUniforms: Uniform[];
95 |
96 | protected _initializedVertexArrayObjects: VertexArrayObject[];
97 | protected _uninitializedVertexArrayObject: VertexArrayObject[];
98 | protected _currentVertexArrayObject: VertexArrayObject | null;
99 |
100 | protected _initializedUniformBufferObjects: UniformBufferObject[];
101 | protected _uninitializedUniformBufferObjects: UniformBufferObject[];
102 |
103 | id: number | null;
104 |
105 | constructor(args: {
106 | vertexShader: VertexShader;
107 | fragmentShader: FragmentShader;
108 | feedbackVaryings?: string[];
109 | feedbackBufferMode?: number
110 | }) {
111 | this._vertexShader = args.vertexShader;
112 | this._fragmentShader = args.fragmentShader;
113 | this._feedbackVaryings = ('feedbackVaryings' in args) ? args.feedbackVaryings : [];
114 | this._feedbackBufferMode = ('feedbackBufferMode' in args) ? args.feedbackBufferMode : INTERLEAVED_ATTRIBS;
115 | this._isLinked = false;
116 |
117 | this._glContext = null;
118 | this._glProgram = null;
119 |
120 | this._initializedBuffers = [];
121 | this._uninitializedBuffers = [];
122 |
123 | this._initializedUniforms = [];
124 | this._uninitializedUniforms = [];
125 |
126 | this._initializedVertexArrayObjects = [];
127 | this._uninitializedVertexArrayObject = [];
128 |
129 | this._initializedUniformBufferObjects = [];
130 | this._uninitializedUniformBufferObjects = [];
131 |
132 | this._currentIndexBuffer = null;
133 | this._currentVertexArrayObject = null;
134 |
135 | this.id = null;
136 | }
137 |
138 | /**
139 | * Adds a buffer to the program.
140 | * @param {Buffer} buffer
141 | */
142 | addBuffer(buffer: Buffer): void {
143 | if(buffer.bufferType === ELEMENT_ARRAY_BUFFER) {
144 | this._currentIndexBuffer = buffer;
145 | }
146 |
147 | if(this.isLinked) {
148 | buffer._initOnce(this._glContext, this._glProgram);
149 | if(buffer.bufferType === ELEMENT_ARRAY_BUFFER && this._glContext !== null) {
150 | this._glContext.bindBuffer(ELEMENT_ARRAY_BUFFER, buffer.glBuffer);
151 | }
152 | this._initializedBuffers.push(buffer);
153 | } else {
154 | if(buffer.isInitialized) {
155 | this._initializedBuffers.push(buffer);
156 | } else {
157 | this._uninitializedBuffers.push(buffer);
158 | }
159 | }
160 | }
161 |
162 | /**
163 | * Activates the `ElementArrayBuffer` as a index buffer.
164 | * @param {ElementArrayBuffer} buffer
165 | */
166 | activateElementArrayBuffer(buffer: ElementArrayBuffer) {
167 | this._currentIndexBuffer = buffer;
168 |
169 | if(this.isLinked && this._glContext !== null) {
170 | this._glContext.bindBuffer(ELEMENT_ARRAY_BUFFER, buffer.glBuffer);
171 | }
172 | }
173 |
174 | /**
175 | * Adds an uniform variable to the program.
176 | * @param {Uniform} uniform
177 | */
178 | addUniform(uniform: Uniform): void {
179 | if(this.isLinked) {
180 | uniform._init(this._glContext, this._glProgram);
181 | this._initializedUniforms.push(uniform);
182 | } else {
183 | this._uninitializedUniforms.push(uniform);
184 | }
185 | }
186 |
187 | /**
188 | * Adds a `VertexArrayObject` to the program.
189 | * @param {VertexArrayObject} vao
190 | */
191 | addVertexArrayObject(vao: VertexArrayObject): void {
192 | if(this.isLinked) {
193 | vao._init(this._glContext, this._glProgram);
194 | this._initializedVertexArrayObjects.push(vao);
195 | this._initializedBuffers.push(vao.buffer);
196 | } else {
197 | this._uninitializedVertexArrayObject.push(vao);
198 | }
199 | }
200 |
201 | /**
202 | * Activates the `VertexArrayObject`.
203 | * @param {VertexArrayObject} vao
204 | */
205 | activateVertexArrayObject(vao: VertexArrayObject): void {
206 | this._currentVertexArrayObject = vao;
207 | if(this.isLinked) {
208 | const context = this._glContext;
209 | context.bindVertexArray(vao.glVertexArrayObject);
210 | }
211 | }
212 |
213 | /**
214 | * Adds an `UniformBufferObject` to the program.
215 | * @param {UniformBufferObject} ubo
216 | */
217 | addUniformBufferObject(ubo: UniformBufferObject) {
218 | if(this.isLinked) {
219 | const index = this._initializedUniformBufferObjects.length;
220 | ubo._init(this._glContext, this._glProgram, index);
221 | this._initializedUniformBufferObjects.push(ubo);
222 | } else {
223 | this._uninitializedUniformBufferObjects.push(ubo);
224 | }
225 | }
226 |
227 | /**
228 | * Issues a draw call, which draws graphics.
229 | * @param {number} mode
230 | * @param {number | null} count
231 | */
232 | draw(mode: number, count: number | null = null): void {
233 | if(this._glContext !== null) {
234 | if(this._currentIndexBuffer !== null && this._currentIndexBuffer.data !== null) {
235 | this._glContext.drawElements(mode, this._currentIndexBuffer.data.length, this._currentIndexBuffer.dataType, 0);
236 | } else if(this._initializedBuffers.length > 0){
237 | const c = (count !== null) ? count : this._initializedBuffers[0].dataCount;
238 | this._glContext.drawArrays(mode, 0, c);
239 | }
240 | }
241 | }
242 |
243 | activate(): void {
244 | this._initializedBuffers.forEach((b) => b.activate());
245 | }
246 |
247 | deactivate(): void {
248 | this._initializedBuffers.forEach((b) => b.deactivate());
249 | }
250 |
251 | /**
252 | * Links the shader program.
253 | * This method is called internally. So you don't have to call this method manually.
254 | * @param {WebGL2RenderingContext} context
255 | */
256 | _link(context: WebGL2RenderingContext) {
257 | // compile shaders.
258 | this._vertexShader._compile(context);
259 | this._fragmentShader._compile(context);
260 |
261 | // create a program.
262 | const program = context.createProgram();
263 | context.attachShader(program, this._vertexShader.glShader);
264 | context.attachShader(program, this._fragmentShader.glShader);
265 |
266 | if(this._feedbackVaryings.length > 0) {
267 | context.transformFeedbackVaryings(program, this._feedbackVaryings, this._feedbackBufferMode);
268 | }
269 |
270 | context.linkProgram(program);
271 |
272 | const linkStatus = context.getProgramParameter(program, context.LINK_STATUS);
273 | if(!linkStatus) {
274 | const info = context.getProgramInfoLog(program);
275 | throw new Error(info);
276 | }
277 |
278 | this._glContext = context;
279 | this._glProgram = program;
280 | this._isLinked = true;
281 |
282 | // initialize buffers.
283 | let buffer = null;
284 | while(buffer = this._uninitializedBuffers.shift()) {
285 | buffer._init(context, program);
286 | if(buffer.bufferType === ELEMENT_ARRAY_BUFFER && this._currentIndexBuffer === null) {
287 | this._currentIndexBuffer = buffer;
288 | }
289 | this._initializedBuffers.push(buffer);
290 | }
291 |
292 | if(this._currentIndexBuffer !== null) {
293 | context.bindBuffer(ELEMENT_ARRAY_BUFFER, this._currentIndexBuffer);
294 | }
295 |
296 | // initialize uniforms.
297 | let uniform = null;
298 | while(uniform = this._uninitializedUniforms.shift()) {
299 | uniform._init(context, program);
300 | this._initializedUniforms.push(uniform);
301 | }
302 |
303 | // initialize VertexArrayObjects.
304 | let vao = null;
305 | while(vao = this._uninitializedVertexArrayObject.shift()) {
306 | vao._init(context, program);
307 | this._initializedVertexArrayObjects.push(vao);
308 | this._initializedBuffers.push(vao.buffer);
309 | }
310 |
311 | if(this._currentVertexArrayObject !== null) {
312 | context.bindVertexArray(this._currentVertexArrayObject.glVertexArrayObject);
313 | }
314 |
315 | // initialize UniformBufferObjects
316 | let ubo = null;
317 | while(ubo = this._uninitializedUniformBufferObjects.shift()) {
318 | const index = this._initializedUniformBufferObjects.length;
319 | ubo._init(context, program, index);
320 | this._initializedUniformBufferObjects.push(ubo);
321 | }
322 | }
323 |
324 | /**
325 | * Returns if the program is linked.
326 | * @returns {boolean}
327 | */
328 | get isLinked(): boolean {
329 | return this._isLinked;
330 | }
331 |
332 | /**
333 | * Returns `WebGLProgram` when the program is already linked.
334 | * Otherwise throws an error.
335 | * @returns {WebGLProgram}
336 | */
337 | get glProgram(): WebGLProgram {
338 | if(this._glProgram === null) {
339 | throw new Error(`This program is not linked yet.`);
340 | }
341 |
342 | return this._glProgram;
343 | }
344 | }
--------------------------------------------------------------------------------
/src/texture.ts:
--------------------------------------------------------------------------------
1 | import { TEXTURE_2D, RGBA, UNSIGNED_BYTE, TEXTURE0 } from './constants';
2 |
3 | export type TextureSource = HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData;
4 |
5 | export interface Texture {
6 | activate(): void;
7 | _init(context: WebGL2RenderingContext, textureNumber: number): void;
8 | }
9 |
10 | export abstract class TextureBase implements Texture {
11 | abstract activate(): void;
12 | abstract _init(context: WebGL2RenderingContext, textureNumber: number): void;
13 |
14 | protected _getTextureIdFromNumber(n: number) {
15 | return TEXTURE0 + n;
16 | }
17 | }
18 |
19 | export class Texture2D extends TextureBase {
20 | protected _source: TextureSource | ArrayBufferView;
21 | protected _glContext: WebGL2RenderingContext | null;
22 | protected _glTexture: WebGLTexture | null;
23 | protected _textureID: number | null;
24 |
25 | protected _target: number;
26 | protected _mipmapLevel: number;
27 | protected _internalFormat: number;
28 | protected _format: number;
29 | protected _dataType: number;
30 | protected _width?: number;
31 | protected _height?: number;
32 |
33 | protected _flushData: Function;
34 |
35 | constructor(dataSource: TextureSource | ArrayBufferView, options: {
36 | target?: number,
37 | mipmapLevel?: number,
38 | internalFormat?: number,
39 | format?: number,
40 | dataType?: number,
41 | width?: number,
42 | height?: number
43 | } = {}) {
44 | super();
45 | this._source = dataSource;
46 | this._glContext = null;
47 | this._glTexture = null;
48 | this._textureID = null;
49 |
50 | this._target = ('target' in options) ? options.target : TEXTURE_2D;
51 | this._mipmapLevel = ('mipmapLevel' in options) ? options.mipmapLevel : 0;
52 | this._internalFormat = ('internalFormat' in options) ? options.internalFormat : RGBA;
53 | this._format = ('format' in options) ? options.mipmapLevel : RGBA;
54 | this._dataType = ('dataType' in options) ? options.mipmapLevel : UNSIGNED_BYTE;
55 |
56 | this._width = ('width' in options) ? options.width : undefined;
57 | this._height = ('height' in options) ? options.height : undefined;
58 |
59 | this._flushData = () => {};
60 | }
61 |
62 | activate(): void {
63 | this._flushData = (context: WebGL2RenderingContext) => {
64 | context.activeTexture(this._textureID);
65 | };
66 | }
67 |
68 | _init(context: WebGL2RenderingContext, textureNumber: number): void {
69 | this._glContext = context;
70 | this._textureID = this._getTextureIdFromNumber(textureNumber);
71 | context.activeTexture(this._textureID);
72 |
73 | this._glTexture = context.createTexture();
74 | context.bindTexture(this._target, this._glTexture);
75 |
76 | if(typeof this._width === 'undefined' || typeof this._height === 'undefined') {
77 | context.texImage2D(this._target, this._mipmapLevel, this._internalFormat,
78 | this._format, this._dataType, this._source);
79 | } else {
80 | context.texImage2D(this._target, this._mipmapLevel, this._internalFormat,
81 | this._width, this._height, 0, this._format,
82 | this._dataType, this._source);
83 | }
84 |
85 | context.generateMipmap(this._target);
86 |
87 | this._flush();
88 | }
89 |
90 | _flush() {
91 | if(this._glContext !== null) {
92 | this._flushData(this._glContext);
93 | this._flushData = () => {};
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/src/transform_feedback.ts:
--------------------------------------------------------------------------------
1 | import { TRANSFORM_FEEDBACK, TRANSFORM_FEEDBACK_BUFFER } from './constants';
2 | import { Buffer } from './buffer';
3 |
4 | export class TransformFeedback {
5 | protected _glContext: WebGL2RenderingContext | null;
6 | protected _glTransformFeedback: WebGLTransformFeedback | null;
7 |
8 | constructor() {
9 | this._glContext = null;
10 | this._glTransformFeedback = null;
11 | }
12 |
13 | feedback(args: {mode: number, targetBuffers: Buffer[], count: number}) {
14 | if(this._glContext === null) {
15 | throw new Error('This transform feedback is not added to any WebGL2 yet.');
16 | }
17 |
18 | for(let i = 0; i < args.targetBuffers.length; i++) {
19 | this._glContext.bindBufferBase(TRANSFORM_FEEDBACK_BUFFER, i, args.targetBuffers[i].glBuffer);
20 | }
21 |
22 | this._glContext.beginTransformFeedback(args.mode);
23 | this._glContext.drawArrays(args.mode, 0, args.count);
24 | this._glContext.endTransformFeedback();
25 |
26 | for(let i = 0; i < args.targetBuffers.length; i++) {
27 | this._glContext.bindBufferBase(TRANSFORM_FEEDBACK_BUFFER, i, null);
28 | }
29 | }
30 |
31 | _init(context: WebGL2RenderingContext) {
32 | this._glContext = context;
33 | this._glTransformFeedback = context.createTransformFeedback();
34 | context.bindTransformFeedback(TRANSFORM_FEEDBACK, this._glTransformFeedback);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/uniform_buffer_object.ts:
--------------------------------------------------------------------------------
1 | import { UniformBuffer } from './buffer'
2 | import { FLOAT, STATIC_DRAW, UNIFORM_BUFFER } from './constants';
3 | import { Attribute, TypedArrayLike } from './variable';
4 |
5 | /**
6 | * An uniform buffer object.
7 | */
8 | export class UniformBufferObject {
9 | protected _buffer: UniformBuffer;
10 | protected _blockName: string;
11 | protected _blockIndex: number | null;
12 | protected _javascriptIndex: number | null;
13 | protected _isInitialized: boolean;
14 |
15 | constructor(blockName: string, bufferOrBufferArgs: UniformBuffer | {
16 | dataOrLength?: TypedArrayLike | number | null,
17 | dataType?: number,
18 | usage?: number
19 | } = {dataOrLength: null, dataType: FLOAT, usage: STATIC_DRAW}) {
20 | this._blockName = blockName;
21 | this._blockIndex = null;
22 | this._javascriptIndex = null;
23 | this._isInitialized = false;
24 |
25 | if(bufferOrBufferArgs instanceof UniformBuffer) {
26 | this._buffer = bufferOrBufferArgs;
27 | } else {
28 | this._buffer = new UniformBuffer(bufferOrBufferArgs);
29 | }
30 | }
31 |
32 | /**
33 | * Initializes the uniform buffer object.
34 | * Do not call this method manually.
35 | * @param {WebGL2RenderingContext} context
36 | * @param {WebGLProgram} program
37 | * @param {number} jsIndex
38 | * @private
39 | */
40 | _init(context: WebGL2RenderingContext, program: WebGLProgram, jsIndex: number) {
41 | this._blockIndex = context.getUniformBlockIndex(program, this._blockName);
42 | this._javascriptIndex = jsIndex;
43 |
44 | context.uniformBlockBinding(program, this._blockIndex, jsIndex);
45 |
46 | this._buffer._initOnce(context, program);
47 |
48 | context.bindBufferBase(UNIFORM_BUFFER, jsIndex, this._buffer.glBuffer);
49 | }
50 | }
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import {FLOAT, SHORT, UNSIGNED_SHORT, BYTE, UNSIGNED_BYTE, HALF_FLOAT} from './constants';
2 |
3 | export function getBytesPerElementByGlType(type: number): number | null {
4 | if (type === FLOAT) {
5 | return 4;
6 | } else if (type === BYTE || type === UNSIGNED_BYTE) {
7 | return 1;
8 | } else if (type === SHORT || type === UNSIGNED_SHORT || type === HALF_FLOAT) {
9 | return 2;
10 | } else {
11 | return null;
12 | }
13 | }
--------------------------------------------------------------------------------
/src/variable.ts:
--------------------------------------------------------------------------------
1 | import { FLOAT, INT, UNSIGNED_INT } from './constants';
2 |
3 | export type TypedArrayLike = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array;
4 |
5 | /**
6 | * An attribute variable.
7 | */
8 | export class Attribute {
9 | protected _name: string;
10 | protected _size: number;
11 |
12 | constructor(name: string, size: number) {
13 | this._name = name;
14 | this._size = size;
15 | }
16 |
17 | equals(other: Attribute): boolean {
18 | return this.name === other.name && this.size === other.size;
19 | }
20 |
21 | get name(): string {
22 | return this._name;
23 | }
24 |
25 | get size(): number {
26 | return this._size;
27 | }
28 | }
29 |
30 | /**
31 | * An uniform variable.
32 | */
33 | export class Uniform {
34 | protected _name: string;
35 | protected _location: WebGLUniformLocation | null;
36 | protected _glContext: WebGL2RenderingContext | null;
37 | protected _glProgram: WebGLProgram | null;
38 | protected _flushData: (context: WebGL2RenderingContext, location: WebGLUniformLocation) => void;
39 |
40 | constructor(name: string) {
41 | this._name = name;
42 | this._location = null;
43 | this._glContext = null;
44 | this._glProgram = null;
45 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {};
46 | }
47 |
48 | /**
49 | * Sets the uniform variable to the value.
50 | * @param {number} value
51 | * @param {number} type
52 | */
53 | setValue(value: number, type: number) {
54 | if(type === FLOAT) {
55 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
56 | context.uniform1f(location, value);
57 | };
58 | } else if (type === INT) {
59 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
60 | context.uniform1i(location, value);
61 | };
62 | } else if (type === UNSIGNED_INT) {
63 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
64 | context.uniform1ui(location, value);
65 | };
66 | }
67 |
68 | this._flush();
69 | }
70 |
71 | /**
72 | * Sets the uniform variable to the vector.
73 | * @param {TypedArrayLike} value
74 | * @param {number} type
75 | */
76 | setVector(value: TypedArrayLike, type: number) {
77 | const length = value.length;
78 |
79 | if(length === 1) {
80 | this.setVector1(value, type);
81 | } else if(length === 2) {
82 | this.setVector2(value, type);
83 | } else if(length === 3) {
84 | this.setVector3(value, type);
85 | } else if(length === 4) {
86 | this.setVector4(value, type);
87 | } else {
88 | throw new Error(`Length of value must be 1, 2, 3 or 4. Your value length is ${length}`);
89 | }
90 | }
91 |
92 | setVector1(value: TypedArrayLike, type: number) {
93 | if(type === FLOAT) {
94 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
95 | context.uniform1fv(location, value);
96 | };
97 | } else if (type === INT) {
98 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
99 | context.uniform1iv(location, value);
100 | };
101 | } else if (type === UNSIGNED_INT) {
102 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
103 | context.uniform1uiv(location, value);
104 | };
105 | }
106 |
107 | this._flush();
108 | }
109 |
110 | setVector2(value: TypedArrayLike, type: number) {
111 | if(type === FLOAT) {
112 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
113 | context.uniform2fv(location, value);
114 | };
115 | } else if (type === INT) {
116 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
117 | context.uniform2iv(location, value);
118 | };
119 | } else if (type === UNSIGNED_INT) {
120 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
121 | context.uniform2uiv(location, value);
122 | };
123 | }
124 |
125 | this._flush();
126 | }
127 |
128 | setVector3(value: TypedArrayLike, type: number) {
129 | if(type === FLOAT) {
130 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
131 | context.uniform3fv(location, value);
132 | };
133 | } else if (type === INT) {
134 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
135 | context.uniform3iv(location, value);
136 | };
137 | } else if (type === UNSIGNED_INT) {
138 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
139 | context.uniform3uiv(location, value);
140 | };
141 | }
142 |
143 | this._flush();
144 | }
145 |
146 | setVector4(value: TypedArrayLike, type: number) {
147 | if(type === FLOAT) {
148 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
149 | context.uniform4fv(location, value);
150 | };
151 | } else if (type === INT) {
152 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
153 | context.uniform4iv(location, value);
154 | };
155 | } else if (type === UNSIGNED_INT) {
156 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
157 | context.uniform4uiv(location, value);
158 | };
159 | }
160 |
161 | this._flush();
162 | }
163 |
164 | /**
165 | * Sets the uniform variable to the matrix.
166 | * @param {Float32Array} value
167 | */
168 | setMatrix(value: Float32Array) {
169 | const size = value.length;
170 | if(size === 4) {
171 | this.setMatrix2(value);
172 | } else if(size === 9) {
173 | this.setMatrix3(value);
174 | } else if(size === 16) {
175 | this.setMatrix4(value);
176 | } else {
177 | throw new Error(`Failed to detect size of the matrix. If you use a non-square matrix, use setMatrixNxN instead.`);
178 | }
179 | }
180 |
181 | setMatrix2(value: Float32Array): void {
182 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
183 | context.uniformMatrix2fv(location, false, value);
184 | };
185 |
186 | this._flush();
187 | }
188 |
189 | setMatrix3(value: Float32Array): void {
190 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
191 | context.uniformMatrix3fv(location, false, value);
192 | };
193 |
194 | this._flush();
195 | }
196 |
197 | setMatrix4(value: Float32Array): void {
198 | this._flushData = (context: WebGL2RenderingContext, location: WebGLUniformLocation) => {
199 | context.uniformMatrix4fv(location, false, value);
200 | };
201 |
202 | this._flush();
203 | }
204 |
205 | _flush() {
206 | if(this.isLocated && this._glContext !== null) {
207 | this._flushData(this._glContext, this._location);
208 | }
209 | }
210 |
211 | _init(context: WebGL2RenderingContext, program: WebGLProgram) {
212 | this._location = context.getUniformLocation(program, this._name);
213 | this._glContext = context;
214 | this._glProgram = program;
215 | this._flush();
216 | }
217 |
218 | get isLocated(): boolean {
219 | return this._location !== null;
220 | }
221 | }
--------------------------------------------------------------------------------
/src/vertex_array_object.ts:
--------------------------------------------------------------------------------
1 | import { Attribute, TypedArrayLike } from './variable';
2 | import { Buffer } from './buffer';
3 | import { ARRAY_BUFFER, STATIC_DRAW } from './constants';
4 | import { getBytesPerElementByGlType } from './utils';
5 |
6 | export class VertexArrayObject {
7 | protected _buffer: Buffer;
8 | protected _glContext: WebGL2RenderingContext | null;
9 | protected _glVertexArrayObject: WebGLVertexArrayObject | null;
10 | protected _enabledAttributes: Attribute[] | null;
11 |
12 | protected _mustWriteData: boolean;
13 | protected _dataOrLength?: TypedArrayLike | number;
14 |
15 | protected _isInitialized: boolean;
16 |
17 | constructor(buffer: Buffer, options: {
18 | dataOrLength?: TypedArrayLike | number,
19 | attributes?: Attribute[]
20 | } = {}) {
21 | this._buffer = buffer;
22 | this._glContext = null;
23 | this._glVertexArrayObject = null;
24 | this._enabledAttributes = ('attributes' in options) ? options.attributes : null;
25 | this._mustWriteData = 'dataOrLength' in options;
26 |
27 | if(this._mustWriteData) {
28 | this._dataOrLength = options.dataOrLength;
29 | }
30 |
31 | this._isInitialized = false;
32 | }
33 |
34 | /**
35 | * Initializes the vertex array object.
36 | * Do not call this method manually.
37 | * @param {WebGL2RenderingContext} context
38 | * @param {WebGLProgram} program
39 | * @private
40 | */
41 | _init(context: WebGL2RenderingContext, program: WebGLProgram) {
42 | if(this._mustWriteData) {
43 | this._buffer.bufferData(this._dataOrLength);
44 | }
45 |
46 | this._buffer._initOnce(context, program, this._enabledAttributes);
47 |
48 | const vao = this._buffer._createWebGLVertexArrayObject(context, program, this._enabledAttributes);
49 |
50 | this._glContext = context;
51 | this._glVertexArrayObject = vao;
52 |
53 | this._isInitialized = true;
54 | }
55 |
56 | /**
57 | * Returns buffer bound to the vertex array object.
58 | * @returns {Buffer}
59 | */
60 | get buffer(): Buffer {
61 | return this._buffer;
62 | }
63 |
64 | /**
65 | * Returns `WebGLVertexArrayObject` if the vertex array object is initialized.
66 | * Otherwise, throws an error.
67 | * @returns {WebGLVertexArrayObject}
68 | */
69 | get glVertexArrayObject(): WebGLVertexArrayObject {
70 | if(this._isInitialized) {
71 | return this._glVertexArrayObject;
72 | } else {
73 | throw new Error('This vertex array object is not added to any program yet.');
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/src/webgl2.ts:
--------------------------------------------------------------------------------
1 | import { Program } from './shader_program';
2 | import { COLOR_BUFFER_BIT } from './constants';
3 | import { TransformFeedback } from './transform_feedback';
4 | import { Texture } from './texture';
5 |
6 | export class WebGL2 {
7 | protected _context: WebGL2RenderingContext;
8 | protected _programs: Array;
9 | protected _activeProgram: Program | null;
10 | protected _transformFeedbacks: Array;
11 | protected _textures: Texture[];
12 | protected _activeTexture: Texture | null;
13 |
14 | constructor(canvas: HTMLCanvasElement) {
15 | this._context = canvas.getContext('webgl2');
16 | this._programs = [];
17 | this._activeProgram = null;
18 | this._transformFeedbacks = [];
19 | this._textures = [];
20 | this._activeTexture = null;
21 | }
22 |
23 | /**
24 | * Adds the program to the `WebGL2` and returns ID number of the program.
25 | * If any program is activated yet, this method activates the program.
26 | * @param {Program} program
27 | * @returns {number} Program ID
28 | */
29 | addProgram(program: Program): number {
30 | if(!program.isLinked) {
31 | program._link(this._context);
32 | }
33 |
34 | this._programs.push(program);
35 |
36 | if(this._activeProgram === null) {
37 | this._activeProgram = program;
38 | this._context.useProgram(program.glProgram);
39 | }
40 |
41 | const id = this._programs.length - 1;
42 | program.id = id;
43 |
44 | return id;
45 | }
46 |
47 | /**
48 | * Adds the transform feedback to `WebGL2`.
49 | * @param {TransformFeedback} tf
50 | */
51 | addTransformFeedback(tf: TransformFeedback) {
52 | this._transformFeedbacks.push(tf);
53 | tf._init(this._context);
54 | }
55 |
56 | addTexture(texture: Texture) {
57 | const id = this._textures.length;
58 | this._textures.push(texture);
59 | texture._init(this._context, id);
60 |
61 | if(this._activeTexture === null) {
62 | texture.activate();
63 | }
64 | }
65 |
66 | /**
67 | * Activates a program and deactivates the previous program.
68 | * Throws an error when the program is not attached to WebGL2.
69 | * @param {Program} program
70 | */
71 | activateProgram(program: Program) {
72 | if(program.id === null) {
73 | throw new Error(`This program is not added to WebGL2 yet. Add it by using addProgram method.`);
74 | } else {
75 | this.activateProgramByID(program.id);
76 | }
77 | }
78 |
79 | /**
80 | * Activates a program by ID and deactivates the previous program.
81 | * Throws an error when the ID does not exist.
82 | * @param {number} id
83 | */
84 | activateProgramByID(id: number): void {
85 | if(id > this._programs.length) {
86 | throw new Error(`ID ${id} does not exist.`);
87 | }
88 |
89 | if(this._activeProgram !== null) {
90 | this._activeProgram.deactivate();
91 | }
92 |
93 | const program = this._programs[id];
94 | this._context.useProgram(program.glProgram);
95 | program.activate();
96 |
97 | this._activeProgram = program;
98 | }
99 |
100 | /**
101 | * Uses the program as a current program.
102 | * @param {Program} program
103 | */
104 | useProgram(program: Program) {
105 | if(program.id === null) {
106 | throw new Error(`This program is not added to WebGL2 yet. Add it by using addProgram method.`);
107 | } else {
108 | this.useProgramByID(program.id);
109 | }
110 | }
111 |
112 | /**
113 | * Uses the program as a current program.
114 | * @param {number} id
115 | */
116 | useProgramByID(id: number) {
117 | if(id > this._programs.length) {
118 | throw new Error(`ID ${id} does not exist.`);
119 | }
120 |
121 | const program = this._programs[id];
122 | this._context.useProgram(program.glProgram);
123 |
124 | this._activeProgram = program;
125 | }
126 |
127 | activateTexture(texture: Texture) {
128 |
129 | }
130 |
131 | /**
132 | * Deactivates the program.
133 | * @param {Program} program
134 | */
135 | deactivateProgram(program: Program): void {
136 | program.deactivate();
137 | }
138 |
139 | draw(mode: number, count: number | null = null): void {
140 | if(this._activeProgram !== null) {
141 | this._activeProgram.draw(mode, count);
142 | }
143 | }
144 |
145 | clear(mask: number = COLOR_BUFFER_BIT): void {
146 | this._context.clear(mask);
147 | }
148 |
149 | clearColor(r: number, g: number, b: number, a: number) {
150 | this._context.clearColor(r, b, g, a);
151 | }
152 |
153 | enable(cap: number): void {
154 | this._context.enable(cap);
155 | }
156 |
157 | disable(cap: number): void {
158 | this._context.disable(cap);
159 | }
160 |
161 | viewport(x: number, y: number, width: number, height: number): void {
162 | this._context.viewport(x, y, width, height);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "outDir": "lib",
6 | "newLine": "LF",
7 | "sourceMap": false,
8 | "declaration": true,
9 | "strict": true,
10 | "suppressImplicitAnyIndexErrors": true,
11 |
12 | "lib": [ "dom", "es2016" ]
13 | },
14 |
15 | "include": [ "src/**/*" ],
16 |
17 | "exclude": [ "node_modules" ]
18 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 |
4 | module.exports = {
5 | entry: './lib/index.js',
6 | output: {
7 | filename: 'xenogl.min.js',
8 | path: path.resolve('build'),
9 | library: "XenoGL",
10 | libraryTarget: "window",
11 | },
12 | plugins: [
13 | new webpack.DefinePlugin({'process.env': { NODE_ENV: JSON.stringify('production') }}),
14 | new webpack.optimize.UglifyJsPlugin()
15 | ]
16 | };
--------------------------------------------------------------------------------