DstAlphaFactor doesn't work in THREE.js - three.js

I want create a circle on the plane.
The blending is (circleColor * planeAlpha). But the result is not what I expect.
First, the plane is render with background. So the Alpha in result should be Zero. Because "blendSrcAlpha blendDstAlpha" both are ZeroFactor.
Second, The Previous results is blending with circle. I set the blendSrc: THREE.DstAlphaFactor in cirlceMaterial.So the result should be
circleColor * planeAlpha = 0xff0000 * 0 = 0*000000
But it's show a red circle in reality.
How did alpha blending work here?
import * as THREE from "three";
import dat from 'dat.gui';
//创建场景.
let scene = new THREE.Scene();
//相机
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 10;
camera.position.y = 10;
camera.position.z = 50;
camera.lookAt(scene.position);
//渲染器
let renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE);
renderer.setClearAlpha(0.1);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
//第二步,创建几何体.
let planeMeometry = new THREE.PlaneGeometry(20, 20, 10);
let circleGeometry = new THREE.SphereGeometry(5, 32, 32);
let planeMaterial = new THREE.MeshBasicMaterial({
color: 0x00ff00,
opacity: 0.1,
depthTest: false,
transparent: true,
blending: THREE.CustomBlending,
blendEquation: THREE.AddEquation,
blendSrc: THREE.ZeroFactor,
blendDst: THREE.ZeroFactor,
blendEquationAlpha: THREE.AddEquation,
blendSrcAlpha: THREE.ZeroFactor,
blendDstAlpha: THREE.ZeroFactor
});
let circleMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
opacity: 0.1,
depthTest: false,
transparent: true,
blending: THREE.CustomBlending,
blendEquation: THREE.AddEquation,
blendSrc: THREE.DstAlphaFactor, //It doesn't work . Expert is Zero, but is's One in fact.
blendDst: THREE.ZeroFactor
});
let plane = new THREE.Mesh(planeMeometry, planeMaterial);
let circle = new THREE.Mesh(circleGeometry, circleMaterial);
plane.renderOrder = 200;
circle.renderOrder = 300;
//加入到场景
scene.add(camera);
scene.add(plane);
scene.add(circle);
let axes = new THREE.AxesHelper(20);
scene.add(axes);
//渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();

Three.js use glBlendFuncSeparate for CustomBlending.
https://github.com/mrdoob/three.js/blob/635179212570586f8130ce9a287b4bbc4fb4338c/src/renderers/webgl/WebGLState.js#L631
You have to also set material's blendEquationAlpha, blendSrcAlpha and blendDstAlpha

Related

Rotating a cube about an axis

In my program, I have done as:
var object = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial( 0xff0000 ) );
object.rotation.x = Math.PI / 2;
var box = new THREE.BoxHelper( object, 0xffff00 );
scene.add(box);
Here,I first try to create a wireframe box and then rotate it by 90 degrees about x axis(line 2). But I don't see any change in box's orientation.
What is correct way of doing it?
Just set rotation of the cube at 90 degrees (here it's 45) and you'll have the same cube:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 5, 10);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var cube = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
cube.position.set(0, 1, 0);
cube.rotation.x = Math.PI * 0.25;
scene.add(cube);
var box = new THREE.BoxHelper(cube, 0xff9900);
scene.add(box);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Three js - moving rotation axis

Using threejs I created a simple cylinder object and rotating it in z-axis. The object rotates around the center axis, both the ends of the cylinder rotate around the axis which is at the center of the cylinder.
How can I make it rotate in a different axis? I would like the cylinder to rotate by having one end in a fixed point while the other end goes around in circles. My code is below.
init();
function init() {
renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('myCanvas'), antialias: true });
renderer.setClearColor(0xeaebed);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(5, window.innerWidth / window.innerHeight, 0.1, 4000);
scene = new THREE.Scene();
//LIGHTS
var light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
var light1 = new THREE.PointLight(0xffffff, 0.3);
scene.add(light1);
//Gun holder
var gunHolder = new THREE.Object3D();
var gunHolderColour = 0x0f4207;
var gunHolderBaseCylinderGeometry = new THREE.CylinderGeometry(10, 10, 50, 32);
var gunHolderBaseCylinderMaterial = new THREE.MeshStandardMaterial({
color: gunHolderColour,
metalness: 0.5,
roughness: 0.5
});
var gunHolderBaseCylinderMesh = new THREE.Mesh(gunHolderBaseCylinderGeometry, gunHolderBaseCylinderMaterial);
gunHolderBaseCylinderMesh.position.set(0, -8, -3000);
scene.add(gunHolderBaseCylinderMesh);
requestAnimationFrame(render);
function render() {
gunHolderBaseCylinderMesh.rotation.z += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
}
You can use .translate() method of your geometry:
var gunHolderBaseCylinderGeometry = new THREE.CylinderGeometry(10, 10, 50, 32); // height is 50
gunHolderBaseCylinderGeometry.translate(0, 25, 0); // move upwards at half of height, 25
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xeaebed);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(5, window.innerWidth / window.innerHeight, 0.1, 4000);
scene = new THREE.Scene();
//LIGHTS
var light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
var light1 = new THREE.PointLight(0xffffff, 0.3);
scene.add(light1);
//Gun holder
var gunHolder = new THREE.Object3D();
var gunHolderColour = 0x0f4207;
var gunHolderBaseCylinderGeometry = new THREE.CylinderGeometry(10, 10, 50, 32);
gunHolderBaseCylinderGeometry.translate(0, 25, 0);
var gunHolderBaseCylinderMaterial = new THREE.MeshStandardMaterial({
color: gunHolderColour,
metalness: 0.5,
roughness: 0.5
});
var gunHolderBaseCylinderMesh = new THREE.Mesh(gunHolderBaseCylinderGeometry, gunHolderBaseCylinderMaterial);
gunHolderBaseCylinderMesh.position.set(0, -8, -3000);
scene.add(gunHolderBaseCylinderMesh);
requestAnimationFrame(render);
function render() {
requestAnimationFrame(render);
gunHolderBaseCylinderMesh.rotation.z += 0.01;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.js"></script>

Three.js self transparency, object should not be see through

Codepen demonstrating the problem
https://codepen.io/anon/pen/GjJpYw?editors=0010
I have 2 meshes, one which contains 2 cubes, and the other which is 1 cube. The mesh with 2 cubes sandwiches the mesh with one cube (so the single cube is in the center). When I set all cubes to transparent but set the opacity of the center cube to 1, I would not expect to be able to see the back cube when looking through the front cube but I can.
I was wondering is there any easy way to fix this? This is a very simplified version of the problem I'm facing so I can't easily split the geometries. I also cannot just set transparent to false since ideally I would like to be able to have the middle cube partially transparent as well. Any suggestions?
var width = window.innerWidth;
var height = window.innerHeight;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var cubeGeometry = new THREE.CubeGeometry(100, 100, 100);
var cube = new THREE.Mesh(cubeGeometry);
cube.position.set(0, 25, -200);
var cube2 = new THREE.Mesh(cubeGeometry);
cube2.position.set(0, -25, 200);
cube.updateMatrix();
cube2.updateMatrix();
var singleGeometry = new THREE.Geometry();
singleGeometry.merge(cube.geometry, cube.matrix);
singleGeometry.merge(cube2.geometry, cube2.matrix);
var combinedMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true});
var mesh = new THREE.Mesh(singleGeometry, combinedMaterial);
var cubeGeometry = new THREE.CubeGeometry(200, 200, 200);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.8, transparent: true});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube);
scene.add(mesh);
var camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
camera.position.z = 500;
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 300, 200);
scene.add(pointLight);
render();
animate();
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}

three.js transparent sphere glitch

I have a transparent sphere and a spot light and that's about it. My sphere displays visual glitches, like striations.
see: http://jsfiddle.net/blwoodley/tvcogqkg/3/
(Note the grid is not necessary to manifest the bug. I just put it in there to show that transparency is working otherwise fine).
Any thoughts on how to get rid of these glitches? They seem to depend on the relative position of the camera and spot light.
Using three.js, r71.
Here is the code from the fiddle since SO seems to want it:
var SCREEN_WIDTH = window.innerWidth - 100;
var SCREEN_HEIGHT = window.innerHeight - 100;
var camera, scene, _planeMesh;
var canvasRenderer, webglRenderer;
var container, mesh, geometry, plane;
container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.set( 380, 80, 100 );
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 180, 160, 0 );
var grid = new THREE.GridHelper(400, 40);
grid.position.y = -20;
scene.add(grid);
scene.add(spotLight);
camera.lookAt( scene.position );
var material = new THREE.MeshPhongMaterial( {
color: 0xaaaa00,
emissive: 0xaa0000,
specular: 0xaa00aa,
shininess: 10,
side: THREE.DoubleSide,
shading: THREE.SmoothShading,
opacity: .8, transparent: true } );
var size = 16.0;
var sphereGeo = new THREE.SphereGeometry( size, 32, 16 );
var mesh = new THREE.Mesh( sphereGeo, material);
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.y = 40;
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.x = 60;
scene.add(mesh);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
animate();
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
webglRenderer.render(scene, camera);
}
Remove the attribute side: THREE.DoubleSide. Since you are drawing spheres, you don't need it.

three.js box geometry opacity

Friends, I use three.js basic material and created 2 box, I don't want to see the small box inside the bigger box, but I can see all of them now. could you help me?
var cube1 = new THREE.Mesh(
new THREE.BoxGeometry(200, 200, 200),
new THREE.MeshBasicMaterial({
color: 0xffffff,
transparent: false,
opacity: 1,
overdraw: 0.5
}));
scene.add(cube1);
var cube2 = new THREE.Mesh(
new THREE.BoxGeometry(100, 100, 100),
new THREE.MeshBasicMaterial({
color: 0x000000,
transparent: false,
opacity: 1,
overdraw: 0.5
}));
scene.add(cube2);
Ideally this should not happen maybe you might have missed something, I here is the complete code in the snippet of what you are trying to achieve.
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xAAAAAA);
renderer.sortObjects = true;
document.body.appendChild(renderer.domElement);
//
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
scene = new THREE.Scene();
cube1 = new THREE.Mesh(
new THREE.BoxGeometry(200, 200, 200),
new THREE.MeshBasicMaterial({
color: 0xffffff,
transparent: false,
opacity: 1,
overdraw: 0.5
}));
scene.add(cube1);
//
cube2 = new THREE.Mesh(
new THREE.BoxGeometry(100, 100, 100),
new THREE.MeshBasicMaterial({
color: 0x000000,
transparent: false,
opacity: 1,
overdraw: 0.5
}));
scene.add(cube2);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
cube1.rotation.x += 0.005;
cube1.rotation.y += 0.01;
cube2.rotation.x += 0.010;
cube2.rotation.y += 0.01;
renderer.render(scene, camera);
}
html, body {
padding:0px;
margin:0px;
}
canvas {
width: 100%;
height: 100%
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>
I have also created a jsfiddle link if you prefer.Hoping it solves your problem,else you can edit the snippet to reproduce your problem.
find the reason:
see through example
if I put the cube position.z < 0, I'll 'see through'.
but if you want to see through, this is a tricky.
[http://jsfiddle.net/agpcn1ej/1/][1]
seems find the answer.
that's because part of the house model position.z < 0, and camera's near < 0, maybe three.js z-buffer clear negative = 0, z-buffer determines the sheltery relation.

Resources