图元的 Regl 颜色和 alpha 混合
Regl color and alpha blending of primitives
我正在尝试弄清楚如何使用 Regl.
在图元之间实现颜色和 alpha 混合
我知道 Regl 命令有一个 blend
property,我已经尝试复制以下 webgl 设置来解决问题:
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
在 Regl 中使用以下 blend
设置:
blend: {
enable: true,
func: { src: 'src alpha', dst:'one minus src alpha' }
},
但是混合似乎只对背景颜色起作用,对点之间不起作用。 (见下例)
示例: http://jsfiddle.net/8gyf7pek/13/
const canvas1 = document.querySelector('#c1');
const canvas2 = document.querySelector('#c2');
//////////////////////////////////////////////
// PURE WEBGL
//////////////////////////////////////////////
const gl = canvas1.getContext('webgl');
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
const vertexShaderSource = `
attribute vec2 position;
attribute vec4 color;
varying vec4 v_color;
void main() {
gl_PointSize = 50.0;
gl_Position = vec4(position, 0, 1);
v_color = color;
}
`;
const fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
const positionAttributeLocation = gl.getAttribLocation(program, 'position');
const colorAttributeLocation = gl.getAttribLocation(program, 'color');
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.enableVertexAttribArray(colorAttributeLocation);
gl.vertexAttribPointer(colorAttributeLocation, 4, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-0.05, -0.05, -0.05, 0.05, 0.05, 0.05, 0.05, -0.05,
]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
const red = [1, 0, 0, 0.5];
const blue = [0, 0, 1, 0.5];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
...red, ...red,
...blue, ...blue,
]), gl.STATIC_DRAW);
gl.drawArrays(gl.POINTS, 0, 4);
function createShader(gl, type, shaderSource) {
const shader = gl.createShader(type);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if(!success) {
console.warn(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
return shader;
}
function createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
const success = gl.getProgramParameter(program, gl.LINK_STATUS);
if(!success) {
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
return program;
}
//////////////////////////////////////////////
// REGL
//////////////////////////////////////////////
const regl = createREGL(canvas2);
regl.clear({ color: [0, 0, 0, 0], depth: 1 });
regl({
frag: `
precision mediump float;
varying vec4 fragColor;
void main () {
gl_FragColor = fragColor;
}`,
vert: `
precision mediump float;
attribute vec2 position;
attribute vec4 color;
varying vec4 fragColor;
uniform float pointWidth;
void main () {
fragColor = color;
gl_PointSize = pointWidth;
gl_Position = vec4(position, 0, 1);
}`,
attributes: {
position: [
[-0.05, -0.05],
[-0.05, 0.05],
[0.05, -0.05],
[0.05, 0.05],
],
color: [
[1, 0, 0, 0.5],
[1, 0, 0, 0.5],
[0, 0, 1, 0.5],
[0, 0, 1, 0.5]
],
},
uniforms: {
pointWidth: 50,
},
blend: {
enable: true,
func: { src: 'src alpha', dst:'one minus src alpha' }
},
count: 4,
primitive: 'points',
})();
#bg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
color: #808080;
background: black;
}
#c1, #c2 {
width: 240px;
height: 240px;
border: 1px solid white;
}
em {
display: block;
}
<div id="bg">
<canvas id="c1"></canvas>
<canvas id="c2"></canvas>
<em>Left is pure WebGL. Right is Regl.</em>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/regl/1.3.7/regl.min.js"></script>
我是不是做错了什么?我怎样才能实现与纯 webgl 代码产生的相同类型的混合?谢谢!
感谢 我想通了:
简而言之,混合功能需要调整,深度测试需要禁用。 (但我仍然不知道为什么在 vanilla WebGL 示例中起作用的混合函数在 Regl 中不起作用)
使用以下混合模式
blend: {
enable: true,
func: {
srcRGB: 'src alpha',
srcAlpha: 'src alpha',
dstRGB: 'one minus src alpha',
dstAlpha: 'one minus src alpha',
},
},
禁用深度测试
depth: { enable: false },
这是我的问题的固定示例:http://jsfiddle.net/8gyf7pek/22/
我正在尝试弄清楚如何使用 Regl.
在图元之间实现颜色和 alpha 混合我知道 Regl 命令有一个 blend
property,我已经尝试复制以下 webgl 设置来解决问题:
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
在 Regl 中使用以下 blend
设置:
blend: {
enable: true,
func: { src: 'src alpha', dst:'one minus src alpha' }
},
但是混合似乎只对背景颜色起作用,对点之间不起作用。 (见下例)
示例: http://jsfiddle.net/8gyf7pek/13/
const canvas1 = document.querySelector('#c1');
const canvas2 = document.querySelector('#c2');
//////////////////////////////////////////////
// PURE WEBGL
//////////////////////////////////////////////
const gl = canvas1.getContext('webgl');
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
const vertexShaderSource = `
attribute vec2 position;
attribute vec4 color;
varying vec4 v_color;
void main() {
gl_PointSize = 50.0;
gl_Position = vec4(position, 0, 1);
v_color = color;
}
`;
const fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
const positionAttributeLocation = gl.getAttribLocation(program, 'position');
const colorAttributeLocation = gl.getAttribLocation(program, 'color');
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.enableVertexAttribArray(colorAttributeLocation);
gl.vertexAttribPointer(colorAttributeLocation, 4, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-0.05, -0.05, -0.05, 0.05, 0.05, 0.05, 0.05, -0.05,
]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
const red = [1, 0, 0, 0.5];
const blue = [0, 0, 1, 0.5];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
...red, ...red,
...blue, ...blue,
]), gl.STATIC_DRAW);
gl.drawArrays(gl.POINTS, 0, 4);
function createShader(gl, type, shaderSource) {
const shader = gl.createShader(type);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if(!success) {
console.warn(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
return shader;
}
function createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
const success = gl.getProgramParameter(program, gl.LINK_STATUS);
if(!success) {
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
return program;
}
//////////////////////////////////////////////
// REGL
//////////////////////////////////////////////
const regl = createREGL(canvas2);
regl.clear({ color: [0, 0, 0, 0], depth: 1 });
regl({
frag: `
precision mediump float;
varying vec4 fragColor;
void main () {
gl_FragColor = fragColor;
}`,
vert: `
precision mediump float;
attribute vec2 position;
attribute vec4 color;
varying vec4 fragColor;
uniform float pointWidth;
void main () {
fragColor = color;
gl_PointSize = pointWidth;
gl_Position = vec4(position, 0, 1);
}`,
attributes: {
position: [
[-0.05, -0.05],
[-0.05, 0.05],
[0.05, -0.05],
[0.05, 0.05],
],
color: [
[1, 0, 0, 0.5],
[1, 0, 0, 0.5],
[0, 0, 1, 0.5],
[0, 0, 1, 0.5]
],
},
uniforms: {
pointWidth: 50,
},
blend: {
enable: true,
func: { src: 'src alpha', dst:'one minus src alpha' }
},
count: 4,
primitive: 'points',
})();
#bg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
color: #808080;
background: black;
}
#c1, #c2 {
width: 240px;
height: 240px;
border: 1px solid white;
}
em {
display: block;
}
<div id="bg">
<canvas id="c1"></canvas>
<canvas id="c2"></canvas>
<em>Left is pure WebGL. Right is Regl.</em>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/regl/1.3.7/regl.min.js"></script>
我是不是做错了什么?我怎样才能实现与纯 webgl 代码产生的相同类型的混合?谢谢!
感谢
简而言之,混合功能需要调整,深度测试需要禁用。 (但我仍然不知道为什么在 vanilla WebGL 示例中起作用的混合函数在 Regl 中不起作用)
使用以下混合模式
blend: { enable: true, func: { srcRGB: 'src alpha', srcAlpha: 'src alpha', dstRGB: 'one minus src alpha', dstAlpha: 'one minus src alpha', }, },
禁用深度测试
depth: { enable: false },
这是我的问题的固定示例:http://jsfiddle.net/8gyf7pek/22/