I have a relatively simple setup with custom shader and a custom blend mode:
Scene
and a PerspectiveCamera
IcosahedronBufferGeometry
new THREE.ShaderMaterial
with custom shadersnew THREE.Points
with the icosahedron and that custom shader materialMy shader material has a custom blend mode:
shaderMaterial.blending = THREE.CustomBlending;
shaderMaterial.blendSrc = THREE.OneFactor;
shaderMaterial.blendDst = THREE.OneFactor;
shaderMaterial.blendEquation = THREE.AddEquation;
and my fragment shader currently only does this:
gl_FragColor = vec4(0.0, 0.1, 0.0, 0.0);
Since I'm rendering into a fully black canvas, the expected color of drawn points should be, considering the blending mode:
SRC DST
r = 0 r = 0 r = 0
g = 0.1 * 1.0 + g = 0 * 1.0 = g = 0.1
b = 0 b = 0 b = 0
However, I get a totally different result:
The points are rendered much more brightly than the expected 0.1
. Using
gl_FragColor = vec4(0.0, 0.2, 0.0, 0.0);
the points become fully saturated (g = 255)
.
What causes this? I have some ideas and hopefully can push me in the right direction.
gl_FragColor
?Any help would be greatly appreciated. Thanks!
The issue is every point is being drawn 5 times because IcosahedronBufferGeometry
is designed for drawing triangles. Each vertex is shared by 5 triangles. We can test this by augmenting drawArrays
Running the code below we see it's asking to draw 60 points even though visually there would only be 12 (the code below does not draw anything visible, it's only designed to check the draw call).
WebGLRenderingContext.prototype.drawArrays = function(origFn) {
return function(...args) {
console.log('drawArrays', ...args);
origFn.call(this, ...args);
};
}(WebGLRenderingContext.prototype.drawArrays);
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const camera = new THREE.Camera();
const scene = new THREE.Scene();
const geo = new THREE.IcosahedronBufferGeometry(1);
const material = new THREE.MeshBasicMaterial();
scene.add(new THREE.Points(geo, material));
renderer.render(scene, camera);
}
main();
<canvas id="c"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r112/build/three.min.js"></script>