An open API service indexing awesome lists of open source software.

https://github.com/lesnitsky/webgl-month

🎓 Daily WebGL tutorials
https://github.com/lesnitsky/webgl-month

3d-rendering beginner code-samples javascript tutorials webgl

Last synced: 12 months ago
JSON representation

🎓 Daily WebGL tutorials

Awesome Lists containing this project

README

          

# WebGL month

Hi 👋 My name is Andrei. I have some fun experience with WebGL and I want to share it. I'm starting a month of WebGL, each day I will post a WebGL related tutorial. Not Three.js, not pixi.js, WebGL API itself.

[Follow me on twitter](https://twitter.com/lesnitsky_a) to get WebGL month updates or [join WebGL month mailing list](http://eepurl.com/gwiSeH)

## Day 1. Intro

This is a series of blog posts related to WebGL. New post will be available every day

[Subscribe](https://twitter.com/lesnitsky_a) for updates or [join mailing list](http://eepurl.com/gwiSeH)

[Soruce code available here](https://github.com/lesnitsky/webgl-month)

![GitHub stars](https://img.shields.io/github/stars/lesnitsky/webgl-month.svg?style=social)

> Built with [GitTutor](https://github.com/lesnitsky/git-tutor)

Welcome to day 1 of WebGL month. In this article we'll get into high level concepts of rendering which are improtant to understand before approaching actual WebGL API.

WebGL API is often treated as 3D rendering API, which is a wrong assumption. So what WebGL does?
To answer this question let's try to render smth with canvas 2d.

We'll need simple html

📄 index.html
```html





WebGL Month

```
and canvas

📄 index.html
```diff

WebGL Month

-
+
+
+


+


-
+


-
+

```
Now we can read body dimensions

📄 src/texture.js
```diff
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

+ const width = document.body.offsetWidth;
+ const height = document.body.offsetHeight;
+
const vShader = gl.createShader(gl.VERTEX_SHADER);
const fShader = gl.createShader(gl.FRAGMENT_SHADER);

```
And set canvas dimensions

📄 src/texture.js
```diff
const width = document.body.offsetWidth;
const height = document.body.offsetHeight;

+ canvas.width = width;
+ canvas.height = height;
+
const vShader = gl.createShader(gl.VERTEX_SHADER);
const fShader = gl.createShader(gl.FRAGMENT_SHADER);

```
Ok, canvas size changed, but our picture isn't full screen, why?

Turns out that changing canvas size isn't enought, we also need to specify a viwport. Treat viewport as a rectangle which will be used as drawing area and interpolate it to `[-1...1]` clipspace

📄 src/texture.js
```diff

gl.uniform2fv(programInfo.uniformLocations.resolution, [canvas.width, canvas.height]);

+ gl.viewport(0, 0, canvas.width, canvas.height);
+
gl.drawElements(gl.TRIANGLES, indexBuffer.data.length, gl.UNSIGNED_BYTE, 0);
});

```
Now our picture fills the whole document, but it is a bit blurry. Obvious reason – our texture is not big enough, so it should be stretched and loses quality. That's correct, but there is another reason.

Modern displays fit higher amount of actual pixels in a physical pixel size (apple calls it retina). There is a global variable `devicePixelRatio` which might help us.

📄 src/texture.js
```diff
const width = document.body.offsetWidth;
const height = document.body.offsetHeight;

- canvas.width = width;
- canvas.height = height;
+ canvas.width = width * devicePixelRatio;
+ canvas.height = height * devicePixelRatio;

const vShader = gl.createShader(gl.VERTEX_SHADER);
const fShader = gl.createShader(gl.FRAGMENT_SHADER);

```
Ok, now our canvas has an appropriate size, but it is bigger than body on retina displays. How do we fix it?
We can downscale canvas to a physical size with css `width` and `height` property

📄 src/texture.js
```diff
canvas.width = width * devicePixelRatio;
canvas.height = height * devicePixelRatio;

+ canvas.style.width = `${width}px`;
+ canvas.style.height = `${height}px`;
+
const vShader = gl.createShader(gl.VERTEX_SHADER);
const fShader = gl.createShader(gl.FRAGMENT_SHADER);

```
Just to summarize, `width` and `height` attributes of canvas specify actual size in pixels, but in order to make picture sharp on highdpi displays we need to multiply width and hegiht on `devicePixelRatio` and downscale canvas back with css

Now we can alos make our canvas resizable

📄 src/texture.js
```diff

gl.drawElements(gl.TRIANGLES, indexBuffer.data.length, gl.UNSIGNED_BYTE, 0);
});
+
+
+ window.addEventListener('resize', () => {
+ const width = document.body.offsetWidth;
+ const height = document.body.offsetHeight;
+
+ canvas.width = width * devicePixelRatio;
+ canvas.height = height * devicePixelRatio;
+
+ canvas.style.width = `${width}px`;
+ canvas.style.height = `${height}px`;
+
+ gl.viewport(0, 0, canvas.width, canvas.height);
+ });

```
Oops, canvas clears after resize. Turns out that modification of `width` or `height` attribute forces browser to clear canvas (the same for `2d` context), so we need to issue a draw call again.

📄 src/texture.js
```diff
canvas.style.height = `${height}px`;

gl.viewport(0, 0, canvas.width, canvas.height);
+
+ gl.drawElements(gl.TRIANGLES, indexBuffer.data.length, gl.UNSIGNED_BYTE, 0);
});

```
That's it for today, see you tomorrow 👋

![GitHub stars](https://img.shields.io/github/stars/lesnitsky/webgl-month.svg?style=social&hash=day12)
![Twitter Follow](https://img.shields.io/twitter/follow/lesnitsky_a.svg?label=Follow%20me&style=social&hash=day12)

[Join mailing list](http://eepurl.com/gwiSeH) to get new posts right to your inbox

[Source code available here](https://github.com/lesnitsky/webgl-month)

Built with

[![Git Tutor Logo](https://git-tutor-assets.s3.eu-west-2.amazonaws.com/git-tutor-logo-50.png)](https://github.com/lesnitsky/git-tutor)

## Day 13. Simple animation

This is a series of blog posts related to WebGL. New post will be available every day

![GitHub stars](https://img.shields.io/github/stars/lesnitsky/webgl-month.svg?style=social&hash=day11)
![Twitter Follow](https://img.shields.io/twitter/follow/lesnitsky_a.svg?label=Follow%20me&style=social&hash=day11)

[Join mailing list](http://eepurl.com/gwiSeH) to get new posts right to your inbox

[Source code available here](https://github.com/lesnitsky/webgl-month)

Built with

[![Git Tutor Logo](https://git-tutor-assets.s3.eu-west-2.amazonaws.com/git-tutor-logo-50.png)](https://github.com/lesnitsky/git-tutor)

Hey 👋 Welcome to WebGL month.

All previous tutorials where based on static images, let's add some motion!

We'll need a simple vertex shader

📄 src/shaders/rotating-square.v.glsl
```glsl
attribute vec2 position;
uniform vec2 resolution;

void main() {
gl_Position = vec4(position / resolution * 2.0 - 1.0, 0, 1);
}

```
fragment shader

📄 src/shaders/rotating-square.f.glsl
```glsl
precision mediump float;

void main() {
gl_FragColor = vec4(1, 0, 0, 1);
}

```
New entry point

📄 index.html
```diff



-
+



-
+


-
+