(redblobgames updated this block to use premultiplied alpha - http://apoorvaj.io/alpha-compositing-opengl-blending-and-premultiplied-alpha.html)
I can’t figure out why points with gl_FragColor = vec4(255, 255, 255, .1);
get darker and then lighter when overlaid with increasing density. (note: it should be vec4(1.0, 1.0, 1.0, 0.1) not 0-255 –redblobgames)
I’m using these blending settings:
blend: {
enable: true,
func: {
srcRGB: 'src alpha',
srcAlpha: 1,
dstRGB: 'one minus src alpha',
dstAlpha: 1
},
equation: {
rgb: 'add',
alpha: 'add'
},
color: [0, 0, 0, 0]
},
Tweaking them hasn’t fixed the problem, but I’m not sure what I’m doing…
try { window.regltick.cancel() } catch(e){}
console.clear()
var sel = d3.select('#graph').html('')
var c = d3.conventions({sel, layers: 'ds', margin: {left: 30, bottom: 30}, totalHeight: innerHeight})
c.x.domain([0, 1]).range([-1, 1])
c.y.domain([0, 1]).range([-1, 1])
var data = d3.range(100000).map(d => {
var y = Math.random()
var x = Math.random()
var uniform = [
c.x(x),
c.y(y),
1
]
var left = [
c.x(y*x),
c.y(y),
1
]
return {d, y, uniform, left}
})
c.x.range([0, c.width])
c.y.range([c.height, 0])
d3.drawAxis(c)
reglLib({onDone, container: c.layers[0].node()})
function onDone(err, regl){
if (err) return console.log(err)
window.regl = regl
var count = data.length
var curIndex = 0
datasets = ['uniform', 'left'].map(str => {
var pos = data.map(d => d[str])
return {str, pos}
})
const fbo_texture = regl.texture({width: 2*960, height: 2*500, min: 'linear', mag: 'linear'}) // to match the size of the canvas
const fbo = regl.framebuffer({color: [fbo_texture]})
var drawPoints = regl({
vert: `
precision mediump float;
attribute vec3 xyz0, xyz1;
varying float c;
uniform float interp, radius;
void main() {
vec3 pos = mix(xyz0, xyz1, interp);
gl_Position = vec4(pos.xy, 0, 1);
gl_PointSize = radius;
}`,
frag: `
precision mediump float;
varying float c;
void main() {
vec4 color = vec4(1.0, 0.0, 1.0, 0.1);
gl_FragColor = vec4(color.rgb * color.a, color.a);
}`,
attributes: {
xyz0: () => datasets[curIndex % datasets.length].pos,
xyz1: () => datasets[(curIndex + 1) % datasets.length].pos
},
uniforms: {
radius: () => 8,
interp: (ctx, props) => Math.max(0, Math.min(1, props.interp))
},
primitive: 'point',
count: count,
framebuffer: fbo,
depth: {
enable: false
},
blend: {
enable: true,
func: {
srcRGB: 'one',
srcAlpha: 1,
dstRGB: 'one minus src alpha',
dstAlpha: 1
},
equation: {
rgb: 'add',
alpha: 'add'
},
color: [0, 0, 0, 0] // only needed for 'constant' blend color
},
})
const demultiply = regl({
frag: `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 v_uv;
void main() {
vec4 premultiplied_color = texture2D(u_texture, v_uv);
gl_FragColor = premultiplied_color / premultiplied_color.a;
}`,
vert: `
precision highp float;
attribute vec2 a_uv;
varying vec2 v_uv;
void main() {
v_uv = a_uv;
gl_Position = vec4(2.0 * v_uv - 1.0, 0.0, 1.0);
}`,
uniforms: {
u_texture: fbo_texture,
},
depth: {
enable: false,
},
count: 3,
attributes: {
a_uv: [-2, 0, 0, -2, 2, 2]
},
})
var lastSwitchTime = 0
var switchInterval = 5
var switchDuration = 5
window.regltick = regl.frame(({time}) => {
if ((time - lastSwitchTime) > switchInterval) {
lastSwitchTime = time
curIndex = (curIndex + 1) % datasets.length
}
fbo.use(() => { regl.clear({color: [1, 1, 1, 0]}) })
drawPoints({interp: d3.easeBackOut((time - lastSwitchTime) / switchDuration)})
demultiply()
})
}
<!DOCTYPE html>
<html>
<head>
<body>
<div id='graph'></div>
</body>
<script src='d3+_.js'></script>
<script src='lib-build.js'></script>
<script src='_script.js'></script>
</html>
var libs = {
reglLib: require('regl'),
}
for (key in libs) window[key] = libs[key]