Point cloud texture alpha blending (THREEJS) - three.js

I use ShaderMaterial to create point cloud with attribute based size and opacity.
I also need to texture map. The problem is that texture is rendered without transparency.
Looks like each texture pixel color is blended somehow with background color (white in this case);
How to avoid this this?
I use svg texture:
<div id="circle-texture" style="width: 0; height: 0; display: none">
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="16" cy="16" r="13" stroke="none" fill="white" fill-opacity="1" />
</svg>
</div>
Here is my fragment shader:
<script type="x-shader/x-fragment" id="point-cloud-fragment-shader">
...
uniform sampler2D texture;
varying vec3 vColor;
varying float vOpacity;
#include <clipping_planes_pars_fragment>
void main() {
#include <clipping_planes_fragment>
vec3 outgoingLight = vec3( 0.0 );
vec4 diffuseColor = vec4( diffuse, vOpacity );
if (enableTexture) {
vec4 mapTexel = texture2D( texture, gl_PointCoord );
diffuseColor *= mapTexelToLinear( mapTexel );
}
diffuseColor.rgb *= vColor;
outgoingLight = diffuseColor.rgb;
gl_FragColor = vec4( outgoingLight, diffuseColor.a );
}
Discarding fixes if:
if ( gl_FragColor.a < 0.001 ) discard;
But is it possible without discarding? (with custom blending or something else) I've played with custom blending but without success so far.

The setup that works when dealing with partially-transparent point-clouds is to turn transparent: true, depthTest: false and a blending mode if necessary. Additive or multiplicative blending look nice, depending on your use-case, and it removes the need to sort the depth of your sprites, since blending removes the need to place a color "in front" of the other:
const spriteMat = new THREE.ShaderMaterial({
uniforms: {
// List of uniforms
},
vertexShader: spriteVert,
fragmentShader: spriteFrag,
blending: THREE.AdditiveBlending,
depthTest: false,
transparent: true
});
Turning transparent: true respects the alpha channel in your fragment shader, so you'll no longer need to discard pixels.

Related

THREE.JS: How to rotate object around its centre in vertex shader?

I have a simple THREE.Points object. Have to rotate it around its Y centre axis via shader (green line), as well as general object position. I have commented it by now, so it doesn't affect the rotation issue.
Now it has the wrong "orbital" rotation. Pretty sure that I need to play with tPos. Have tried without any success.
var stats, scene, renderer;
var camera, cameraControl, mesh;
if( !init() ) animate();
function init(){
renderer = new THREE.WebGLRenderer({
antialias : true,
preserveDrawingBuffer : true
});
renderer.setClearColor( 0xBBBBBB, 1 );
renderer.setSize( window.innerWidth, window.innerHeight );
document.getElementById('container').appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0, 0, 5);
scene.add(camera);
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array( [
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, -1.0, 1.0
] );
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.ShaderMaterial( {
side : THREE.DoubleSide,
uniforms: {
parentPosition: { value: new THREE.Vector3(0.0, 0.0, 0.0) },
rotation: { type: "f", value: 0.0 },
texture: { value: new THREE.TextureLoader().load( "assets/blob.png" ) }
},
vertexShader: document.getElementById( "vertexshader" ).textContent,
fragmentShader: document.getElementById( "fragmentshader" ).textContent,
alphaTest: 0.9
} );
mesh = new THREE.Mesh( geometry, material );
scene.add(mesh);
}
function animate() {
//mesh.material.uniforms.parentPosition.value.x += 0.01;
mesh.material.uniforms.rotation.value += 0.01;
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
body{ margin: 0px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.js"></script>
<!doctype html>
<html>
<head>
<title>three.js template</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script type="x-shader/x-vertex" id="vertexshader">
uniform vec3 parentPosition;
uniform float rotation;
varying vec4 vColor;
varying mat4 vPosition;
void main() {
mat4 tPos = mat4(vec4(1.0,0.0,0.0,0.0),
vec4(0.0,1.0,0.0,0.0),
vec4(0.0,0.0,1.0,0.0),
vec4(0,0,0,1.0));
mat4 rYPos = mat4(vec4(cos(rotation),0.0,sin(rotation),0.0),
vec4(0.0,1.0,0.0,0.0),
vec4(-sin(rotation),0.0,cos(rotation),0.0),
vec4(0.0,0.0,0.0,1.0));
vPosition = tPos * rYPos;
vColor = vec4(1.0, 0.0, 1.0, 1.0);
vec3 newPosition = position + parentPosition;
vec4 mvPosition = modelViewMatrix * vPosition * vec4( newPosition, 1.0 );
gl_PointSize = 32.0 * ( 300.0 / -mvPosition.z );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D texture;
varying vec4 vColor;
varying mat4 vPosition;
void main() {
gl_FragColor = vColor;
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
}
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
mat4 tPos = mat4(vec4(1.0,0.0,0.0,0.0),
vec4(0.0,1.0,0.0,0.0),
vec4(0.0,0.0,1.0,0.0),
vec4(0,0,0,1.0));
mat4 rYPos = mat4(vec4(cos(rotation),0.0,sin(rotation),0.0),
vec4(0.0,1.0,0.0,0.0),
vec4(-sin(rotation),0.0,cos(rotation),0.0),
vec4(0.0,0.0,0.0,1.0));
vPosition = tPos * rYPos;
vColor = vec4(1.0, 0.0, 1.0, 1.0);
vec3 newPosition = position + parentPosition;
vec4 mvPosition = modelViewMatrix * vPosition * vec4( newPosition, 1.0 );
Can someone help me?
It's my fault. The code works fine. Have to set all Z values to 0.0.
var vertices = new Float32Array( [
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
-1.0, -1.0, 0.0
] );

How can I change the height of a cylinder with "a-animation"?

I want to increase the height of a cylinder on aframe as an animation.
How can this be achieved?
I'd use ngoKevins animation component:
1) either animate the scale:
animation__scale="property: scale; dir: alternate; dur: 200;
easing: easeInSine; loop: true; to: 1 2 1"
2) or animate the height:
animation__height="property: height; dir: alternate; dur: 200;
easing: easeInSine; loop: true; to: 3"
Fiddle here.
Using <a-animation> it would be like this:
<a-animation attribute="scale"
dur="1000"
direction="alternate"
to="1 2 1"
repeat="indefinite"></a-animation>
or
<a-animation attribute="height"
dur="1000"
direction="alternate"
to="3"
repeat="indefinite"></a-animation>
fiddle here

Putting image on a sphere using ShaderMaterial in three.js

I tried to put image on a sphere by using ShaderMaterial in three.js. But I only get a black sphere by my code below. What is the problem?
main.js
(function(){
var width = window.innerWidth;
var height = window.innerHeight;
//scene
var scene = new THREE.Scene();
//geo
var geometry = new THREE.SphereGeometry( 5, 60, 40 );
geometry.scale( -1, 1, 1);
//mesh
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('images/image.jpeg');
var uniforms = {
color: { type: "3v", value: new THREE.Vector3(0.3, 1.0, 1.0) },
texture: { type: "t", value: 0, texture: texture },
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
//camera
var camera = new THREE.PerspectiveCamera(75, width / height, 1, 1000);
camera.position.set(0,0,30);
camera.lookAt(mesh.position);
//render
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width,height);
renderer.setClearColor(0xffffff);
document.getElementById('stage').appendChild(renderer.domElement);
renderer.render(scene,camera);
function render(){
requestAnimationFrame(render);
renderer.render(scene,camera);
}
render();
})();
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
<div id="stage"></div>
<script src="lib/three.min.js"></script>
<script src="lib/OrbitControls.js"></script>
<script type="x-shader/x-vertex" id="vertexShader">
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragmentShader">
uniform vec3 color;
uniform sampler2D texture;
varying vec2 vUv;
void main(){
vec4 samplerColor = texture2D(texture, vUv);
gl_FragColor = vec4(1.0) * samplerColor;
}
</script>
<script src="main.js"></script>
</body>
</html>
When I tried to use MeshBasicMaterial like below, it is OK. So I guess it is not a problem of asynchronous loading..
var material = new THREE.MeshBasicMaterial( {
map: texture
} );
Please help me

Three.js wireframe option not working with MeshBasicMaterial

I'm using .stl file. For some files it worked perfect but for some it doesn't.
Here is the code.
Any solution??
Thanks in advance.
`material = new THREE.MeshBasicMaterial( { color: 0x009d28, opacity: 1.0, wireframe: true, wireframeLinewidth: 1.0, transparent: true } );`

IE8. overflow hidden + min-width: is there a workaround to this strange behavior?

If we have floated div A, and div B with overflow: hidden next to it - div B should take all available space next to floated div. And if we have min-width set on the div B and window size is too small to keep this two divs on the same line - div B should wrap under the div A and take all available width of parent. This exact behaviour we can see in all major browsers except IE8, even IE7 handles it as expected. In IE8 when window size small enough so div B wraps under div A - div B not taking all available width but only have its min-width. The question is: is that a bug, or standard behavior? If this is a bug, how can we work around it?
I have a test case here: http://jsfiddle.net/BJM4s/2/ , resize the window to see it in action.
HTML:
<div class="parent">
<div class="A">
<img src="http://placekitten.com/g/100/100 " />
</div>
<div class="B">
float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float
</div>
</div>​
CSS:
.parent {
overflow:hidden;
margin: 20px;
border: 1px solid;
}
.A {
float:left;
margin-right: 10px;
}
.B {
overflow:hidden;
min-width: 200px;
background: lime;
}​
It seems that adding display: table-cell to .B makes it behave. I did not fully test in all other browsers to see if it would cause an issue. It might be best to just have it set for IE8 (though it did not seem to affect IE7/9 or Firefox).

Resources