Объединить два канваса. Наложить один на другой
08.08.2019, 22:24. Показов 6038. Ответов 2
Есть два канваса. Нужно наложить один на другой. Для этого один нужно сделать прозрачным. Это я сделал. Но отображается работа только одного канваса. Как можно отобразить работу ещё и второго?
Раз
| HTML5 | 1
2
| <canvas id="particle"></canvas>
<canvas id="canvas"></canvas> |
|
| CSS | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| body {
margin: 0;
}
canvas {
display: block;
}
#particle {
background-image:url(https://i.**********/HiAlf85.jpg);
background-size: cover;
}
#canvas {
position: absolute;
left: 0;
top: 0;
} |
|
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
| 'use strict';
(function() {
let vertices = [];
let gl = particle.getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
resize();
function resize() {
particle.width = innerWidth;
particle.height = innerHeight;
let step = 10,
w = Math.floor(particle.width/step),
h = Math.floor(particle.height/step);
vertices = [];
for (var x=0; x<w*3; x++)
for (var y=0; y<10; y++)
vertices.push(1/w + x*10/w - 5, 1/h + y*2/h - 1)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}
let pid = gl.createProgram();
shader(`
attribute vec2 v;
uniform float time;
varying vec3 c;
mat3 rotateX(float a) {
return mat3(vec3( 1.0, 0.0, 0.0),
vec3( -1.0, cos(a), -sin(a)),
vec3( 0.0, sin(a), cos(a)));
}
mat3 rotateY(float a){
return mat3(vec3( cos(a), 0.0, sin(a)),
vec3( 0.0, 1.0, 0.0),
vec3(-sin(a), 0.0, cos(a)));
}
mat3 rotateZ(float a){
return mat3(vec3( cos(a), -sin(a), 0.0),
vec3( sin(a), cos(a), 0.0),
vec3( 0.0, 0.0, 1.0));
}
void main(void) {
vec2 p = v;
p.y += 0.3;
p.x += sin(time/4. + p.y);
vec3 pos = vec3(p.xy, 0.0)*rotateX(p.x*3. + time);
//pos.y += sin(pos.x) - sin(time/5.)*0.5 + cos(pos.y/3.1415)*0.5;
gl_Position = vec4(pos, 1.);
gl_PointSize = 2.7;
gl_Position.z = 0.0;
c.rgb=vec3(1.0, 0.5, 0.0);
}
`, gl.VERTEX_SHADER);
shader(`
precision highp float;
varying vec3 c;
void main(void) {
gl_FragColor = vec4(c, 1.);
}
`, gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let v = gl.getAttribLocation(pid, "v");
gl.vertexAttribPointer(v, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(v);
let timeUniform = gl.getUniformLocation(pid, 'time');
requestAnimationFrame(draw);
addEventListener('resize', resize)
function draw(t) {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.uniform1f(timeUniform, t/1000);
gl.drawArrays(gl.POINTS, 0, vertices.length/2);
requestAnimationFrame(draw);
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split("\n")
.map((str, i) => (""+(1+i))
.padStart(4, "0")+": "+str)
.join("\n"));
throw message;
}
}
}());
// ----------------------
(function() {
let vertices = [];
let gl = canvas.getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
resize();
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
let step = 10,
w = Math.floor(canvas.width/step),
h = Math.floor(canvas.height/step);
vertices = [];
for (var x=0; x<w*3; x++)
for (var y=0; y<10; y++)
vertices.push(1/w + x*10/w - 5, 1/h + y*2/h - 1)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}
let pid = gl.createProgram();
shader(`
attribute vec2 v;
uniform float time;
varying vec3 c;
mat3 rotateX(float a) {
return mat3(vec3( -1.0, -1.0, 0.0),
vec3( 0.0, cos(a), -sin(a)),
vec3( 0.0, sin(a), cos(a)));
}
mat3 rotateY(float a){
return mat3(vec3( cos(a), 0.0, sin(a)),
vec3( 0.0, 1.0, 0.0),
vec3(-sin(a), 0.0, cos(a)));
}
mat3 rotateZ(float a){
return mat3(vec3( cos(a), -sin(a), 0.0),
vec3( sin(a), cos(a), 0.0),
vec3( 0.0, 0.0, 1.0));
}
void main(void) {
vec2 p = v;
p.y += 0.3;
p.x += sin(time/4. + p.y);
vec3 pos = vec3(p.xy, 0.0)*rotateX(p.x*3. + time);
//pos.y += sin(pos.x) - sin(time/5.)*0.5 + cos(pos.y/3.1415)*0.5;
gl_Position = vec4(pos, 1.);
gl_PointSize = 2.7;
gl_Position.z = 0.0;
c.rgb=vec3(1., 0., 0.);
}
`, gl.VERTEX_SHADER);
shader(`
precision highp float;
varying vec3 c;
void main(void) {
gl_FragColor = vec4(c, 1.);
}
`, gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let v = gl.getAttribLocation(pid, "v");
gl.vertexAttribPointer(v, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(v);
let timeUniform = gl.getUniformLocation(pid, 'time');
requestAnimationFrame(draw);
addEventListener('resize', resize)
function draw(t) {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.uniform1f(timeUniform, t/1000);
gl.drawArrays(gl.POINTS, 0, vertices.length/2);
requestAnimationFrame(draw);
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split("\n")
.map((str, i) => (""+(1+i))
.padStart(4, "0")+": "+str)
.join("\n"));
throw message;
}
}
}()); |
|
https://codepen.io/m0nte-cr1st0/pen/ZgobqO
Два
| HTML5 | 1
| <canvas id="canvas" style="background-image:url(https://i.**********/HiAlf85.jpg)"></canvas> |
|
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
| // массив с вершинами, в которых будем рисовать точки
let vertices = [];
let gl = canvas.getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
resize();
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
let step = 15,
w = Math.floor(canvas.width/step),
h = Math.floor(canvas.height/step);
// при ресайзе заполняем массив положениями вершин
vertices = [];
for (var x=0; x<w*3; x++)
for (var y=0; y<10; y++)
vertices.push(1/w + x*2/w - 2, 1/h + y*2/h - 1)
// отправляем массив с вершинами в память видео карты
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}
// создаем новую программу для gpu, она состоит из 2х шейдеров,
// вершинного и фрагментного
let pid = gl.createProgram();
// привязываем вершинный шейдер к программе,
// вся соль этого примера в этом вершинном шейдере
shader(`
// позиция вершины, которая сейчас будет обсчитываться
attribute vec2 v;
// время, установленное в управляющем коде
uniform float time;
// переменная, которая будет передана во фрагментный шейдер, будем
// использовать ее чтобы задать цвет пикселей, в которые попадет данная вершина
varying vec3 c;
// функция, которая вернет псевдослучайное число
float rand(float n) {
return fract(sin(n) * 43758.5453123);
}
// примитивная функция шума
float noise(float p) {
float fl = floor(p);
float fc = fract(p);
return mix(rand(fl), rand(fl + 1.0), fc);
}
// поворот вдоль оси x
mat3 rotateX(float a){
return mat3(vec3( 1.0, 0.0, 0.0),
vec3( 0.0, cos(a), -sin(a)),
vec3( 0.0, sin(a), cos(a)));
}
// поворот вдоль оси y
mat3 rotateY(float a){
return mat3(vec3( cos(a), 0.0, sin(a)),
vec3( 0.0, 1.0, 0.0),
vec3(-sin(a), 0.0, cos(a)));
}
// поворот вдоль оси z
mat3 rotateZ(float a){
return mat3(vec3( cos(a), -sin(a), 0.0),
vec3( sin(a), cos(a), 0.0),
vec3( 0.0, 0.0, 1.0));
}
// основной код вершинного шейдера
void main(void) {
vec2 p = v;
// двигаем точку по y в зависимости от времени и положения по x
p.y += sin(p.x*10.)*noise(time/1000.) + 0.5;
// двигаем точку по x в зависимости от времени и положения по y
p.x -= cos(p.y) + sin(time/2.);
// считаем итоговое положение вершины, с учетом поворотов вокруг
// 3х осей в зависимости от значения функции шума и времени
gl_Position = vec4(
vec3(p.xy, 0.0) *
rotateX(p.x*3.0 + time) *
rotateY(noise(p.y + time/10.0)) *
rotateZ(noise(p.x + time/15.0)),
1.);
// размер точки устанавливаем в зависимости от ее удаления плюс шум
gl_PointSize = min(2.7, 1.5 + noise(time)-gl_Position.z);
// ставим координату по z на 0, чтобы избежать пропадания точек,
// которые при вращении как бы попали за точку наблюдателя
// (отрицательная z координата)
gl_Position.z = 0.0;
c = 0.2 + 0.8 * vec3(
noise(time/2.0 + gl_Position.x),
noise(time/3.0 + gl_Position.y),
noise(time)
);
}
`, gl.VERTEX_SHADER);
// привязываем фрагментный шейдер к программе
shader(`
precision highp float;
varying vec3 c;
void main(void) {
// тут все тривиально, просто устанавливаем цвет каждого
// пикселя в соответствии с тем значением,
// которое пришло из вершинного шейдера
gl_FragColor = vec4(c, 1.);
}
`, gl.FRAGMENT_SHADER);
// «линкуем» программу
gl.linkProgram(pid);
// устанавливаем программу как текущую
gl.useProgram(pid);
// получаем точку привязки атрибута “v” в активной программе
let v = gl.getAttribLocation(pid, "v");
// указываем как интерпретировать данные в последнем привязанном буфере
// со значениями вершин, который будет связан с атрибутом "v",
// тут важно число 2, это указание сколько элементов из буфера,
// привязано к одной вершине,
// сейчас это 2, X и Y, тут могло быть число от 1 до 4.
gl.vertexAttribPointer(v, 2, gl.FLOAT, false, 0, 0);
// включаем доступ к атрибуту "v"
gl.enableVertexAttribArray(v);
// получаем точку привязки переменной типа uniform с именем time,
// uniform переменные меняются только со стороны cpu, для gpu это постоянные данные
let timeUniform = gl.getUniformLocation(pid, 'time');
// запускаем цикл отрисовки
requestAnimationFrame(draw);
// вещаем слушатель на ресайз
addEventListener('resize', resize)
function draw(t) {
// размер области отрисовки
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
// цвет, которым очищается буфер кадра
gl.clearColor(0, 0, 0, 0);
// устанавливаем значение переменной time
gl.uniform1f(timeUniform, t/1000);
// все действия до этого были сделаны в качестве подготовки для
// этого единственного вызова, который запускает процедуру отрисовки,
// тут указываем тип рисуемого примитива и их количество, сейчас это
// точки, еще тут могут быть линии или треугольники
gl.drawArrays(gl.POINTS, 0, vertices.length/2);
// запрашиваем отрисовку следующего кадра
requestAnimationFrame(draw);
}
// функция, которая создает один шейдер и прицепляет его к программе
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split("\n")
.map((str, i) => (""+(1+i))
.padStart(4, "0")+": "+str)
.join("\n"));
throw message;
}
} |
|
https://codepen.io/m0nte-cr1st0/pen/ZgoyjW
Попытка объединить...
| HTML5 | 1
2
| <canvas id="particle"></canvas>
<canvas id="canvas"></canvas> |
|
| CSS | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| body {
margin: 0;
}
canvas {
display: block;
}
#particle {
background-image:url(https://i.**********/HiAlf85.jpg);
}
#canvas {
position: absolute;
left: 0;
top: 0;
} |
|
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
| 'use strict';
(function() {
let vertices = [];
let gl = particle.getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
resize();
function resize() {
particle.width = innerWidth;
particle.height = innerHeight;
let step = 10,
w = Math.floor(particle.width/step),
h = Math.floor(particle.height/step);
vertices = [];
for (var x=0; x<w*3; x++)
for (var y=0; y<10; y++)
vertices.push(1/w + x*10/w - 5, 1/h + y*2/h - 1)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}
let pid = gl.createProgram();
shader(`
attribute vec2 v;
uniform float time;
varying vec3 c;
mat3 rotateX(float a) {
return mat3(vec3( 1.0, 0.0, 0.0),
vec3( -1.0, cos(a), -sin(a)),
vec3( 0.0, sin(a), cos(a)));
}
mat3 rotateY(float a){
return mat3(vec3( cos(a), 0.0, sin(a)),
vec3( 0.0, 1.0, 0.0),
vec3(-sin(a), 0.0, cos(a)));
}
mat3 rotateZ(float a){
return mat3(vec3( cos(a), -sin(a), 0.0),
vec3( sin(a), cos(a), 0.0),
vec3( 0.0, 0.0, 1.0));
}
void main(void) {
vec2 p = v;
p.y += 0.3;
p.x += sin(time/4. + p.y);
vec3 pos = vec3(p.xy, 0.0)*rotateX(p.x*3. + time);
//pos.y += sin(pos.x) - sin(time/5.)*0.5 + cos(pos.y/3.1415)*0.5;
gl_Position = vec4(pos, 1.);
gl_PointSize = 2.7;
gl_Position.z = 0.0;
c.rgb=vec3(1.0, 0.5, 0.0);
}
`, gl.VERTEX_SHADER);
shader(`
precision highp float;
varying vec3 c;
void main(void) {
gl_FragColor = vec4(c, 1.);
}
`, gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let v = gl.getAttribLocation(pid, "v");
gl.vertexAttribPointer(v, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(v);
let timeUniform = gl.getUniformLocation(pid, 'time');
requestAnimationFrame(draw);
addEventListener('resize', resize)
function draw(t) {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.uniform1f(timeUniform, t/1000);
gl.drawArrays(gl.POINTS, 0, vertices.length/2);
requestAnimationFrame(draw);
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split("\n")
.map((str, i) => (""+(1+i))
.padStart(4, "0")+": "+str)
.join("\n"));
throw message;
}
}
}());
// ----------------------
(function() {
let vertices = [];
let gl = canvas.getContext('webgl');
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
resize();
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
let step = 10,
w = Math.floor(canvas.width/step),
h = Math.floor(canvas.height/step);
vertices = [];
for (var x=0; x<w*3; x++)
for (var y=0; y<10; y++)
vertices.push(1/w + x*10/w - 5, 1/h + y*2/h - 1)
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
}
let pid = gl.createProgram();
shader(`
attribute vec2 v;
uniform float time;
varying vec3 c;
mat3 rotateX(float a) {
return mat3(vec3( -1.0, -1.0, 0.0),
vec3( 0.0, cos(a), -sin(a)),
vec3( 0.0, sin(a), cos(a)));
}
mat3 rotateY(float a){
return mat3(vec3( cos(a), 0.0, sin(a)),
vec3( 0.0, 1.0, 0.0),
vec3(-sin(a), 0.0, cos(a)));
}
mat3 rotateZ(float a){
return mat3(vec3( cos(a), -sin(a), 0.0),
vec3( sin(a), cos(a), 0.0),
vec3( 0.0, 0.0, 1.0));
}
void main(void) {
vec2 p = v;
p.y += 0.3;
p.x += sin(time/4. + p.y);
vec3 pos = vec3(p.xy, 0.0)*rotateX(p.x*3. + time);
//pos.y += sin(pos.x) - sin(time/5.)*0.5 + cos(pos.y/3.1415)*0.5;
gl_Position = vec4(pos, 1.);
gl_PointSize = 2.7;
gl_Position.z = 0.0;
c.rgb=vec3(1., 0., 0.);
}
`, gl.VERTEX_SHADER);
shader(`
precision highp float;
varying vec3 c;
void main(void) {
gl_FragColor = vec4(c, 1.);
}
`, gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let v = gl.getAttribLocation(pid, "v");
gl.vertexAttribPointer(v, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(v);
let timeUniform = gl.getUniformLocation(pid, 'time');
requestAnimationFrame(draw);
addEventListener('resize', resize)
function draw(t) {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.uniform1f(timeUniform, t/1000);
gl.drawArrays(gl.POINTS, 0, vertices.length/2);
requestAnimationFrame(draw);
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split("\n")
.map((str, i) => (""+(1+i))
.padStart(4, "0")+": "+str)
.join("\n"));
throw message;
}
}
}()); |
|
https://codepen.io/m0nte-cr1st0/pen/WVJobE
0
|