how to achieve this motion blur shader effect? - javascript

I tried to create the snow effect like the one on the bottom page of this link http://blog.edankwan.com/post/my-first-christmas-experiment. Everything else works fine But just can't make the motion blur effect work. Any ideas?
the texture sprite used to achieve the motion blur effect
here is the code:
(function(global) {
var img = 'https://i.imgur.com/hlmsgWA.png'
var renderer, scene, camera
var w = 800, h = 320
var uniforms
var geometry
var texture, material
var gui
var conf = {
amount: 200,
speed: 0.5,
time: 0
}
var obj = {
init: function() {
renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(w, h)
camera = new THREE.Camera
scene = new THREE.Scene()
geometry = new THREE.BufferGeometry()
var positions = []
for(var i = 0, l = conf.amount; i < l; i++) {
positions[i * 3] = Math.random() * 800 - 400
positions[i * 3 + 1] = i
positions[i * 3 + 2] = Math.random() * 800
}
geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3))
var vs = document.getElementById('vertexShader').textContent
var fs = document.getElementById('fragmentShader').textContent
uniforms = {
u_amount: {
type: 'f',
value: conf.amount
},
u_speed: {
type: 'f',
value: conf.speed
},
u_time: {
type: 'f',
value: conf.time
},
u_resolution: {
type: 'vec2',
value: new THREE.Vector2(w, h)
},
u_texture : {
value: new THREE.TextureLoader().load(img)
}
}
material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vs,
fragmentShader: fs,
transparent: true
})
var points = new THREE.Points(geometry, material)
scene.add(points)
document.body.appendChild(renderer.domElement)
this.render()
this.createGui()
},
createGui: function() {
gui = new dat.GUI()
gui.add(conf, 'speed', -1, 1)
},
render: function() {
requestAnimationFrame(this.render.bind(this))
uniforms.u_time.value += conf.speed * 0.003
renderer.render(scene, camera)
}
}
obj.init()
})(window)
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
vec3 getPosOffset(float ratio, float thershold) {
return vec3(
cos((ratio * 80.0 + 10.0) * thershold) * 20.0 * thershold,
(sin((ratio * 90.0 + 30.0) * thershold) + 1.0) * 5.0 * thershold + mix(500.0, -500.0, ratio / thershold),
sin((ratio * 70.0 + 20.0) * thershold) * 20.0 * thershold
);
}
uniform vec2 u_resolution;
uniform float u_amount;
uniform float u_speed;
uniform float u_time;
varying float v_alpha;
varying float v_rotation;
varying float v_index;
void main() {
float indexRatio = position.y / u_amount;
float thershold = 0.7 + indexRatio * 0.3;
float ratio = mod(u_time - indexRatio * 3.0, thershold);
float prevRatio = mod(u_time - u_speed - indexRatio * 3.0, thershold);
vec3 offsetPos = getPosOffset(ratio, thershold);
vec3 prevOffsetPos = getPosOffset(prevRatio, thershold);
vec3 pos = position;
pos += offsetPos;
float perspective = (2000.0 - pos.z) / 2000.0;
pos.x *= perspective;
pos.y *= perspective;
float delta = length(offsetPos.xy - prevOffsetPos.xy);
float maxDelta = 2.7;
v_index = floor(pow(clamp(delta, 0.0, maxDelta) / maxDelta, 5.0) * 15.99);
v_rotation = atan((offsetPos.x - prevOffsetPos.x) / (offsetPos.y - prevOffsetPos.y));
pos.x *= 2.0 / u_resolution.x;
pos.y *= 2.0 / u_resolution.y;
pos.z = 0.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
gl_PointSize = 24.0 * perspective;
v_alpha = perspective;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D u_texture;
varying float v_rotation;
varying float v_index;
varying float v_alpha;
void main() {
vec2 coord = gl_PointCoord.xy;
coord = vec2(
clamp(cos(v_rotation) * (coord.x - 0.5) + sin(v_rotation) * (coord.y - 0.5) + 0.5, 0.0, 1.0),
clamp(cos(v_rotation) * (coord.y - 0.5) - sin(v_rotation) * (coord.x - 0.5) + 0.5, 0.0, 1.0)
);
float index = floor(v_index + 0.5);
coord.y = - coord.y + 4.0;
coord.x += (index - floor(index / 4.0) * 4.0);
coord.y -= floor(index / 4.0);
coord *= 0.25;
vec4 color = texture2D(u_texture, coord);
color.a *= v_alpha;
gl_FragColor = color;
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.3/dat.gui.js"></script>
http://blog.edankwan.com/post/my-first-christmas-experiment.

In snippet code you treat variable speed differently in your update loop and in vertex shader.
Update: uniforms.u_time.value += conf.speed * 0.003
Shader usage: float prevRatio = mod(u_time - u_speed - indexRatio * 3.0, thershold);
You'll get desired result if you change u_speed to u_speed * 0.003 in shader code (or better move that multiplication to definition in javascript).
Fast way to debug such things - pass your values to output color and check if it is what you expect.
==================
If someone wants to make tails with non-flat curvature - you can store last N points of each particle path. Then you can fully compute trail mesh geometry on CPU and stream it to GPU.
Or another way: you can upload all paths to single Uniform Buffer Object and find right point to fetch with pointId and uv of tail mesh vertex.

Related

How to manipulate the background color of a scene in three.js with shaders?

I'd like to change the background color of a simple three.js scene, like the one you change with
renderer.setClearColor(/*insert color here*/)
or
scene.background = new THREE.Color(/*insert color here*/)
with fragment shaders,
but including glsl code or ShaderMaterial inside the brackets doesnt work.
How can I do it?
Here is an approach with WebGLRenderTarget.texture as scene.background:
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", event => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
gu.resolution.set(innerWidth, innerHeight);
});
let gu = {
time: {value: 0},
resolution: {value: new THREE.Vector2(innerWidth, innerHeight)}
}
let light = new THREE.DirectionalLight(0xffffff, 0.8);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.2));
let ico = new THREE.Mesh(new THREE.IcosahedronGeometry(3, 0), new THREE.MeshLambertMaterial({color: 0xff4488}));
scene.add(ico);
// <background stuff>
let backScene = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), new THREE.MeshBasicMaterial({
color: 0x004488,
onBeforeCompile: shader => {
shader.uniforms.time = gu.time;
shader.uniforms.resolution = gu.resolution;
shader.vertexShader = `
varying vec2 vUv;
` + shader.vertexShader;
shader.vertexShader = shader.vertexShader.replace(
`#include <uv_vertex>`,
`vUv = uv;`
);
shader.fragmentShader = `
${noise}
uniform float time;
uniform vec2 resolution;
varying vec2 vUv;
` + shader.fragmentShader;
shader.fragmentShader = shader.fragmentShader.replace(
`vec4 diffuseColor = vec4( diffuse, opacity );`,
`
vec2 tUv = vUv * 5.0;
tUv.x *= resolution.x / resolution.y;
float t = time * 0.5;
tUv -= vec2(t * 0.25, t);
float n1 = snoise(vec3(tUv, time * 0.125));
n1 = (n1 + 1.0) * 0.5;
float n2 = snoise(vec3(n1 * 10., 1, 1));
n2 = sin(((n2 + 1.0) * 0.5) * 3.1415926 * 2.);
float effect = smoothstep(0.1, 0.125, n1) * (1. - smoothstep(0.375, 0.4, n2));
float coef = sin(n2 * 3.141526 * 0.5) * 0.125;
float e = effect - abs(coef);
e = n1 > 0.25 && n1 < 0.75? e * e : pow(e, 16.);
vec4 diffuseColor = vec4(diffuse * e, opacity);
`
);
}
}));
let backCamera = new THREE.Camera();
let backRT = new THREE.WebGLRenderTarget(innerWidth, innerHeight);
scene.background = backRT.texture; // assign to background
// </background stuff>
let clock = new THREE.Clock();
renderer.setAnimationLoop( _ => {
let t = clock.getElapsedTime();
gu.time.value = t;
ico.rotation.x = t * 0.31;
ico.rotation.y = t * 0.27;
renderer.setRenderTarget(backRT); // set render target
renderer.render(backScene, backCamera); //render background
renderer.setRenderTarget(null); // remove render target, render to default buffer
renderer.render(scene, camera); // render scene
renderer.render(scene, camera);
})
body{
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
var noise = `
//
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : stegu
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com/ashima/webgl-noise
// https://github.com/stegu/webgl-noise
//
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 mod289(vec4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 permute(vec4 x) {
return mod289(((x*34.0)+1.0)*x);
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float snoise(vec3 v)
{
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy) );
vec3 x0 = v - i + dot(i, C.xxx) ;
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod289(i);
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0)*2.0 + 1.0;
vec4 s1 = floor(b1)*2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
vec3 p0 = vec3(a0.xy,h.x);
vec3 p1 = vec3(a0.zw,h.y);
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );
}
`;
</script>

How is it possible to change the position of an object consisted of points floating around a center in Three Js?

So I have made this galaxy object consisted of points floating around its center
const parameters = {}
parameters.count = 4500
parameters.size = 0.005
parameters.radius = 0.7
parameters.branches = 4
parameters.spin = 1
parameters.randomness = 0.1
parameters.randomnessPower = 5
parameters.insideColor = '#d42b2b'
parameters.outsideColor = '#14be4c'
let galaxyGeometry = null
let galaxyMaterial = null
let galaxyPoints = null
const generateGalaxy = () =>
{
//DESTROY STUFF
if(galaxyPoints !== null)
{
galaxyGeometry.dispose()
galaxyMaterial.dispose()
scene.remove(galaxyPoints)
}
//GALAXY GEOM AND PARTICLES
galaxyGeometry = new THREE.BufferGeometry()
const positions = new Float32Array(parameters.count * 3)
const randomness = new Float32Array(parameters.count * 3)
const galaxyColors = new Float32Array(parameters.count * 3)
const galaxyScales = new Float32Array(parameters.count * 1)
const colorInside = new THREE.Color(parameters.insideColor)
const colorOutside = new THREE.Color(parameters.outsideColor)
for(let i = 0; i < parameters.count; i++)
{
const i3 = i * 3
//POSITION
const radius = Math.random() * parameters.radius
const branchAngle = (i % parameters.branches) / parameters.branches * Math.PI * 2
const randomX = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1: -1) * parameters.randomness * radius
const randomY = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1: -1) * parameters.randomness * radius
const randomZ = Math.pow(Math.random(), parameters.randomnessPower) * (Math.random() < 0.5 ? 1: -1) * parameters.randomness * radius
positions[i3 ] = Math.cos(branchAngle) * radius
positions[i3 + 1] = 0
positions[i3 + 2] = Math.sin(branchAngle) * radius
randomness[i3 ] = randomX
randomness[i3 + 1] = randomY
randomness[i3 + 2] = randomZ
//COLORS
// Color
const mixedColor = colorInside.clone()
mixedColor.lerp(colorOutside, radius / parameters.radius)
galaxyColors[i3 ] = mixedColor.r
galaxyColors[i3 + 1] = mixedColor.g
galaxyColors[i3 + 2] = mixedColor.b
// Scale
galaxyScales[i] = Math.random()
}
galaxyGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
galaxyGeometry.setAttribute('aRandomness', new THREE.BufferAttribute(randomness, 3))
galaxyGeometry.setAttribute('color', new THREE.BufferAttribute(galaxyColors, 3))
galaxyGeometry.setAttribute('aScale', new THREE.BufferAttribute(galaxyColors, 3))
//GALAXY PARTICLE MATERIALS
galaxyMaterial = new THREE.ShaderMaterial({
depthWrite: false,
blending: THREE.AdditiveBlending,
vertexColors: true,
uniforms:
{
vAlpha: { value: 1.0 },
uTime: { value: 0 },
uSize: { value: 40 * renderer.getPixelRatio() }
},
vertexShader: galaxyVertex,
fragmentShader: galaxyFragment,
})
if(galaxyMaterial.uniforms.vAlpha.value !== 1.0)
{
galaxyGeometry.dispose()
galaxyMaterial.dispose()
scene.remove(galaxyPoints)
}
//GALAXY MESH
galaxyPoints = new THREE.Points(galaxyGeometry, galaxyMaterial)
console.log(galaxyPoints.position)
scene.add(galaxyPoints)
}
along with its vertex
uniform float uTime;
uniform float uSize;
attribute vec3 aRandomness;
attribute float aScale;
varying vec3 vColor;
void main()
{
//POSITION
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
// Rotate
float angle = atan(modelPosition.x, modelPosition.z);
float distanceToCenter = length(modelPosition.xz);
float angleOffset = (1.0 / distanceToCenter) * uTime * 3.0;
angle += angleOffset;
modelPosition.x = cos(angle) * distanceToCenter;
modelPosition.y = sin(angle) * distanceToCenter;
// Randomness
modelPosition.xyz += aRandomness;
vec4 viewPosition = viewMatrix * modelPosition;
vec4 projectedPosition = projectionMatrix * viewPosition;
gl_Position = projectedPosition;
//SIZE
gl_PointSize = uSize * aScale;
gl_PointSize *= (1.0 / - viewPosition.z);
//COLOR
vColor = color;
}
and fragment shader
varying vec3 vColor;
uniform float vAlpha;
void main()
{
//LIGHT PATTERN
float strength = distance(gl_PointCoord, vec2(0.5));
strength = 1.0 - strength;
strength = pow(strength, 8.0);
//FINAL COLOR
vec3 color = mix(vec3(0.0), vColor, strength);
gl_FragColor = vec4(color, vAlpha);
}
. So my question here is this.How is it possible to move the object around the scene without changing its original look (galaxy/portal like). As I am new to Three js the only way I've known to move an object around is picking up the mesh and setting its position to whatever needed. The problem I'm having right now though is that the points are moving around a central point. When I try to move the mesh around the whole galaxy is breaking up. What is the correct approach here in order to move the whole galaxy thing, let's say by 2.0 in the x , y or z axis? I would really appreciate an explanation to why this is happening as well. Thank you in advance.

Three.js (GLSL) — Canvas resize

I am trying to preserve the proportions at least a little when the window is resized to smaller sizes at the CodePen here. Currently it turns out to be really hard to see the lines and the interaction on mobile. Do you have a solution for this? Maybe it makes sense to double the scale on resize based on the window but I am a bit lost on how I can implement it.
The responsible part of the JS:
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(event) {
container.style.height = window.innerHeight+"px";
container.style.width = window.innerWidth+"px";
canvasWidth = container.offsetWidth;
canvasHeight = container.offsetHeight;
//send new size value to the shader and resize the window
uniforms.resolution.value.x = canvasWidth;
uniforms.resolution.value.y = canvasHeight;
//var res = canvasWidth / cols;
//rows = canvasHeight / res;
uniforms.colsrows.value.x = cols;
uniforms.colsrows.value.y = rows;//rows;
renderer.setSize(canvasWidth, canvasHeight);
}
Here is the pen:
//Create var for the contenair, the webGL 3D scene, uniforms to bind into shader and timer
var container;
var camera, scene, renderer;
var uniforms;
var startTime;
var cols = 50.;
var rows = 50.0;
init(); //init scene
animate(); //updateScene
function init() {
//get contenaire
container = document.getElementById('container');
//Create THREE.JS scene and timer
startTime = Date.now();
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
//create a simple plance
var geometry = new THREE.PlaneBufferGeometry(16, 9);
//create uniform table which provide all our GLSL binding
uniforms = {
time: { type: "f", value: 1.0 },
resolution: { type: "v2", value: new THREE.Vector2() },
colsrows: {type: "v2", value: new THREE.Vector2()},
mouse: {type: "v2", value: new THREE.Vector2()}
};
//create THREE.JS material
var material = new THREE.ShaderMaterial( {
//set shaders and uniforms into material
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
} );
//create mesh, add it to the scene
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
//create renderer and add it to the DOM
renderer = new THREE.WebGLRenderer();
container.appendChild(renderer.domElement);
//check window for resize This will give us the proper resolution values to bind
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(event) {
container.style.height = window.innerHeight+"px";
container.style.width = window.innerWidth+"px";
canvasWidth = container.offsetWidth;
canvasHeight = container.offsetHeight;
//send new size value to the shader and resize the window
uniforms.resolution.value.x = canvasWidth;
uniforms.resolution.value.y = canvasHeight;
//var res = canvasWidth / cols;
//rows = canvasHeight / res;
uniforms.colsrows.value.x = cols;
uniforms.colsrows.value.y = rows;//rows;
renderer.setSize(canvasWidth, canvasHeight);
}
function animate() {
render();
requestAnimationFrame(animate);
}
function render() {
var currentTime = Date.now();
var elaspedSeconds = (currentTime - startTime) / 1000.0;
var maxTime = 4.0;
var normTime = (elaspedSeconds % maxTime) / maxTime;
uniforms.time.value = elaspedSeconds * 1.0;
renderer.render(scene, camera);
}
function move(ev){
mx = ev.clientX
my = ev.clientY;
// console.log(mx+" , "+my);
uniforms.mouse.value.x = mx;
uniforms.mouse.value.y = my;
}
document.addEventListener('mousemove', move)
html, body {
margin: 0;
height: 100%;
background : #1a1a1a;
}
canvas {
display: block;
cursor: none;
}
#container{
background : black;
color : white;
margin: auto;
width : 500px;
height : 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<div id="container"></div>
<!-- GLSL SCRIPT -->
<!-- vertex shader -->
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4(position, 1.0);
}
</script>
<!-- fragment shader -->
<script id="fragmentShader" type="x-shader/x-fragment">
#define TWO_PI 6.28318530718
#define EPSILON 0.000011
uniform vec2 resolution;
uniform float time;
uniform vec2 colsrows;
uniform vec2 mouse;
float HueToRGB(float f1, float f2, float hue)
{
if (hue < 0.0)
hue += 1.0;
else if (hue > 1.0)
hue -= 1.0;
float res;
if ((6.0 * hue) < 1.0)
res = f1 + (f2 - f1) * 6.0 * hue;
else if ((2.0 * hue) < 1.0)
res = f2;
else if ((3.0 * hue) < 2.0)
res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
else
res = f1;
return res;
}
vec3 HSLToRGB(vec3 hsl)
{
vec3 rgb;
if (hsl.y == 0.0)
rgb = vec3(hsl.z); // Luminance
else
{
float f2;
if (hsl.z < 0.5)
f2 = hsl.z * (1.0 + hsl.y);
else
f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);
float f1 = 2.0 * hsl.z - f2;
rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));
rgb.g = HueToRGB(f1, f2, hsl.x);
rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));
}
return rgb;
}
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
vec2 rotateFrom(vec2 uv, vec2 center, float angle){
vec2 uv_ = uv - center;
uv_ = rotate2d(angle) * uv_;
uv_ = uv_ + center;
return uv_;
}
float random(float value){
return fract(sin(value) * 43758.5453123);
}
float random(vec2 tex){
return fract(sin(dot(tex.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}
vec2 random2D(vec2 uv){
uv = vec2(dot(uv, vec2(127.1, 311.7)), dot(uv, vec2(269.5, 183.3)));
//return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
return fract(sin(uv) * 43758.5453123); //return without offset on x, y
}
vec3 random3D(vec3 uv){
uv = vec3(dot(uv, vec3(127.1, 311.7, 120.9898)), dot(uv, vec3(269.5, 183.3, 150.457)), dot(uv, vec3(380.5, 182.3, 170.457)));
return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
}
float cubicCurve(float value){
return value * value * (3.0 - 2.0 * value); // custom cubic curve
}
vec2 cubicCurve(vec2 value){
return value * value * (3.0 - 2.0 * value); // custom cubic curve
}
vec3 cubicCurve(vec3 value){
return value * value * (3.0 - 2.0 * value); // custom cubic curve
}
float noise(vec2 uv){
vec2 iuv = floor(uv);
vec2 fuv = fract(uv);
vec2 suv = cubicCurve(fuv);
float dotAA_ = dot(random2D(iuv + vec2(0.0)), fuv - vec2(0.0));
float dotBB_ = dot(random2D(iuv + vec2(1.0, 0.0)), fuv - vec2(1.0, 0.0));
float dotCC_ = dot(random2D(iuv + vec2(0.0, 1.0)), fuv - vec2(0.0, 1.0));
float dotDD_ = dot(random2D(iuv + vec2(1.0, 1.0)), fuv - vec2(1.0, 1.0));
return mix(
mix(dotAA_, dotBB_, suv.x),
mix(dotCC_, dotDD_, suv.x),
suv.y);
}
float noise(vec3 uv){
vec3 iuv = floor(uv);
vec3 fuv = fract(uv);
vec3 suv = cubicCurve(fuv);
float dotAA_ = dot(random3D(iuv + vec3(0.0)), fuv - vec3(0.0));
float dotBB_ = dot(random3D(iuv + vec3(1.0, 0.0, 0.0)), fuv - vec3(1.0, 0.0, 0.0));
float dotCC_ = dot(random3D(iuv + vec3(0.0, 1.0, 0.0)), fuv - vec3(0.0, 1.0, 0.0));
float dotDD_ = dot(random3D(iuv + vec3(1.0, 1.0, 0.0)), fuv - vec3(1.0, 1.0, 0.0));
float dotEE_ = dot(random3D(iuv + vec3(0.0, 0.0, 1.0)), fuv - vec3(0.0, 0.0, 1.0));
float dotFF_ = dot(random3D(iuv + vec3(1.0, 0.0, 1.0)), fuv - vec3(1.0, 0.0, 1.0));
float dotGG_ = dot(random3D(iuv + vec3(0.0, 1.0, 1.0)), fuv - vec3(0.0, 1.0, 1.0));
float dotHH_ = dot(random3D(iuv + vec3(1.0, 1.0, 1.0)), fuv - vec3(1.0, 1.0, 1.0));
float passH0 = mix(
mix(dotAA_, dotBB_, suv.x),
mix(dotCC_, dotDD_, suv.x),
suv.y);
float passH1 = mix(
mix(dotEE_, dotFF_, suv.x),
mix(dotGG_, dotHH_, suv.x),
suv.y);
return mix(passH0, passH1, suv.z);
}
float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
//from https://www.shadertoy.com/view/MtlSDr
vec2 l = p2 - p1;
float L = length(l);
float L2 = L*L;
float d1 = length(uv - p1);
float d2 = length(uv - p2);
float d = min(d1, d2);
float ds = dot(uv - p1, l);
if (ds >= 0.0 && ds <= L2)
{
vec2 n = vec2(-l.y, l.x) / L;
d = min(d, abs(dot(uv - p1, n)));
}
return 1.0 - smoothstep(0.0, 0.01, d - r);
}
vec2 fishey(vec2 uv, vec2 center, float ratio, float dist){
vec2 puv = uv + vec2(1.0);
//center coords
vec2 m = vec2(center.x, center.y/ratio) + vec2(1.0);
//vector from center to current fragment
vec2 d = puv - m;
// distance of pixel from center
float r = sqrt(dot(d, d));
//amount of effect
float power = ( TWO_PI / (2.0 * sqrt(dot(m, m)))) * mix(0.1, 0.4, pow(dist, 0.75));
//radius of 1:1 effect
float bind;
if (power > 0.0) bind = sqrt(dot(m, m));//stick to corners
//else {if (ratio < 1.0) bind = m.x; else bind = m.y;}//stick to borders
//Weird formulas
vec2 nuv;
if (power > 0.0)//fisheye
nuv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
else if (power < 0.0)//antifisheye
nuv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
else
nuv = puv;//no effect for power = 1.0
return nuv - vec2(1.0);
}
vec4 addGrain(vec2 uv, float time, float grainIntensity){
float grain = random(fract(uv * time)) * grainIntensity;
return vec4(vec3(grain), 1.0);
}
void main(){
vec2 ouv = gl_FragCoord.xy / resolution.xy;
vec2 uv = ouv;
float ratio = resolution.x / resolution.y;
vec2 nmouse = vec2(mouse.x, mouse.y) / resolution.xy;
nmouse.y = 1.0 - nmouse.y;
float maxDist = 0.35;
float blurEdge = maxDist * 0.5;
float blurEdge2 = maxDist * 1.0;
vec2 mouseToUV = (uv - nmouse) / vec2(1.0, ratio);
float mouseDistance = 1.0 - smoothstep(maxDist - blurEdge, maxDist, length(mouseToUV));
float mouseDistance2 = 1.0 - smoothstep(maxDist - blurEdge2, maxDist, length(mouseToUV));
uv = fishey(uv, nmouse, ratio, mouseDistance2);
uv = rotateFrom(uv, vec2(0.5), time * 0.1);
//animate y
//wave
uv.y /= ratio;
vec2 basedUV = uv + vec2(1.0);
float complexityX = 10.0;
float complexityY = 10.0;
float maxAmp = mix(0.05, 0.75, mouseDistance);
float amp = 0.01 * mouseDistance + noise(vec3(basedUV.x * complexityX, basedUV.y * complexityY, time * 0.1)) * maxAmp;
float theta = time + mouseDistance + basedUV.y * (TWO_PI);
uv.x = fract(uv.x + sin(theta) * amp);
//divide into cols rows
vec2 nuv = uv * colsrows;
vec2 fuv = fract(nuv);
vec2 iuv = floor(nuv);
float minSpeed = 1.0;
float maxSpeed = 5.0;
float speed = minSpeed + random(floor(uv.x * colsrows.x)) * (maxSpeed - minSpeed);
fuv.y = fract(fuv.y + time * speed);
//draw dash line
float minWeight = 0.005 + random(vec2(iuv.x, 0.0)) * 0.05;
float strokeWeight = mix(minWeight, minWeight * 5.0, mouseDistance);
float dlineWidth = mix(1.0, 0.25 - strokeWeight, mouseDistance);//0.5 - strokeWeight;
float dline = drawLine(fuv, vec2(0.5, 0.5 - dlineWidth * 0.5), vec2(0.5, 0.5 + dlineWidth * 0.5), strokeWeight);
float randIndexHue = random(vec2(iuv.x + floor(time), 0.0));
float noiseHue = noise(vec3(randIndexHue, randIndexHue, time));
float hue = mix(0.111, 0.138, randIndexHue + (noiseHue * 0.5));
vec4 grain = addGrain(ouv, time, 0.15);
//vec3 color = HSLToRGB(vec3(hue, 1.0, 0.5));
//vec3 bgColor = HSLToRGB(vec3(0.772, mix(0.75, 1.0, mouseDistance), mix(0.1, 0.25, mouseDistance)));
vec3 color = vec3(1.0);
vec3 bgColor = vec3(0.0);
float val = dline * (mouseDistance * 0.5 + 0.5);
vec3 albedo = mix(bgColor, color, val);
gl_FragColor = vec4(albedo, 1.0) + grain;
}
</script>
The thickness of the lines is computed in drawLine and depends on the parameters to smoothstep:
float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
// [...]
return 1.0 - smoothstep(0.0, 0.01, d - r);
}
Increase the parameter to edge1, to generate "thicker" lines (e.g. 0.1):
float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
// [...]
return 1.0 - smoothstep(0.0, 0.1, d - r);
}
You can add an additional uniform variable for the line:
uniform float thickness;
float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
// [...]
return 1.0 - smoothstep(0.0, thickness, d - r);
}
uniforms = {
// [...]
thickness: { type: "f", value: 0.1 },
};

Smoothly mapping a 2D uv point onto a 3D xyz sphere

I have been trying to procedurally generate a sphere's surface using simplex noise, and I figured that in order to get smooth, non-distorted noise I need to map each uv pixel to an xyz coordinate. I have tried a few different algorithms, with the following being my favourite:
function convert2d3d(r1, r2, x, y) {
let z = -1 + 2 * x / r1;
let phi = 2 * Math.PI * y / r1;
let theta = Math.asin(z);
return {
x: r2 * Math.cos(theta) * Math.cos(phi),
y: r2 * Math.cos(theta) * Math.sin(phi),
z: r2 * z,
}
}
While the points generated look continuous, there is severe distortion around the texture seams, and where the texture is stretched the most:
I am aware what I am trying to do is called UV mapping, yet I'm struggling to implement it correctly. Either I get severe distortion, or ugly seams. To render the sphere I am using Three.JS MeshPhongMaterial and for the noise I am using noisejs.
Do you want something like THIS?
In the gui at the top right under scene -> geometry select the sphere.
No need to mess with UVs :)
Vertex shader from the demo linked above:
varying vec3 vPosition;
void main() {
vPosition = normalize(position);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
Fragment Shader from the demo linked above:
varying vec3 vPosition;
uniform float scale;
//
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com/ashima/webgl-noise
//
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 mod289(vec4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}
vec4 permute(vec4 x) {
return mod289(((x*34.0)+1.0)*x);
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float snoise(vec3 v)
{
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
vec3 i = floor(v + dot(v, C.yyy) );
vec3 x0 = v - i + dot(i, C.xxx) ;
// Other corners
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx;
vec3 x1 = x0 - i1 + C.xxx;
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod289(i);
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
// Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs(x) - abs(y);
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0)*2.0 + 1.0;
vec4 s1 = floor(b1)*2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
vec3 p0 = vec3(a0.xy,h.x);
vec3 p1 = vec3(a0.zw,h.y);
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );
}
void main() {
float n = snoise(vPosition * scale);
gl_FragColor = vec4(1.0 * n, 1.0 * n, 1.0 * n, 1.0);
}
The above takes a scale uniform of type float.
var uniforms = {
scale: { type: "f", value: 10.0 }
};
More ShaderMaterial demos
Weighing the pros and cons of WebGL vs Textures, I decided on using the following function:
function convert2d3d(r, x, y) {
let lat = y / r * Math.PI - Math.PI / 2;
let long = x / r * 2 * Math.PI - Math.PI;
return {
x: Math.cos(lat) * Math.cos(long),
y: Math.sin(lat),
z: Math.cos(lat) * Math.sin(long),
}
}
Given a point on a square texture of size r×r, convert to lat/long, returning a 3d coordinate where the texture is mapped onto a sphere of radius 1.
I adapted the function from a blog post on inear.se, converting it to use degrees throughout. I wouldn't of managed it without 2phas answer showing me an alternative, and helping me look for what I needed. Here is what it looks like:
Right now it's ugly, but this was the first step.

Overlapping Edges With Transparent Shader Material - Three.js

Im newbie at webgl world and trying to learn something. while after i figured out how shaders work, wanted to go a step further and make a smooth, transparent cloud. Actually i made it, but as you see in the images below, there is some overlaping edges look jagged.
can you explain why this is happening and how to solve it?
thank you
v77
Snippet
var camera, controls, scene, renderer;
var sceneCss, rendererCss;
var dirLight, ambientLight, pointLight;
var displacementMaterial;
var wH = window.innerHeight;
var wW = window.innerWidth;
var start = Date.now();
var properties;
var cloudRadius = 150;
var cloudMesh;
var noiseMaterial, noiseMap;
var uniforms, displamentUniforms;
$(document).ready(function() {
//init Core Engine;
init();
//init All Engines;
onLoaded();
animateAll();
});
//Give it life;
function init() {
properties = {
smoke: 2.0,
heat: 0.0007,
shapeBiasX: 1.5,
shapeBiasY: 2.5,
displacementScale: 40,
displacementBias: -22,
turbulence: 40,
twist: 0,
wireframes: false,
rotationX: .5,
rotationY: 0,
rotationZ: 0,
opacity: 1.0
}
// add camera and controls
camera = new THREE.PerspectiveCamera(70, wW / wH, 0.1, 20000);
camera.position.set(0, 0, 400);
//PostProcess Materials
sceneRenderTarget = new THREE.Scene();
cameraOrtho = new THREE.OrthographicCamera(wW / -2, wW / 2, wH / 2, wH / -2, -10000, 10000);
cameraOrtho.position.z = 100;
cameraOrtho.updateProjectionMatrix();
var plane = new THREE.PlaneGeometry(wW, wH);
quadTarget = new THREE.Mesh(plane, new THREE.MeshBasicMaterial({ transparent: true, opacity: .1, color: 0x000000 }));
quadTarget.position.z = -500;
sceneRenderTarget.add(quadTarget);
//
//scene
scene = new THREE.Scene();
sceneCss = new THREE.Scene();
fog = new THREE.FogExp2(0x212121, 0.002);
scene.fog = fog;
//renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(wW, wH);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.sortObjects = false;
renderer.domElement.style.zIndex = 0;
renderer.setClearColor(0x222222);
document.body.appendChild(renderer.domElement);
}
function onLoaded() {
//Will Check Processes
createClouds();
}
function createClouds() {
uniforms = {
time: {
type: "f",
value: 1.0
},
uSpeed: {
type: "f",
value: 1.0
},
scale: {
type: "v2",
value: new THREE.Vector2(1, 1)
},
opacity: {
type: "f",
value: 1.0
}
};
noiseMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('noise_vertex').textContent,
fragmentShader: document.getElementById('noise_fragment').textContent,
lights: false,
wireframe: properties.wireframes
});
noiseMap = new THREE.WebGLRenderTarget(512, 512, {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat,
wrapS: THREE.RepeatWrapping
});
displacementUniforms = {
time: {
type: "f",
value: 1.0
},
tHeightMap: {
type: "t",
value: noiseMap.texture
},
uDisplacementBias: {
type: "f",
value: properties.displacementBias
},
uDisplacementScale: {
type: "f",
value: properties.displacementScale
},
uColor1: {
type: "c",
value: new THREE.Color(0xffff00)
},
uColor2: {
type: "c",
value: new THREE.Color(0x0000ff)
},
uSmoke: {
type: "f",
value: properties.smoke
},
uShapeBias: {
type: "v2",
value: new THREE.Vector2(properties.shapeBiasX, properties.shapeBiasY)
},
uScreenHeight: {
type: "f",
value: wH
},
uTurbulence: {
type: "f",
value: properties.turbulence
},
uTwist: {
type: "f",
value: properties.twist
},
opacity: {
type: "f",
value: 1.0
}
};
displacementMaterial = new THREE.ShaderMaterial({
wireframe: properties.wireframes,
transparent: true,
uniforms: displacementUniforms,
vertexShader: document.getElementById('displacement_vertex').textContent,
fragmentShader: document.getElementById('displacement_fragment').textContent,
premultipliedAlpha: true,
side: THREE.DoubleSide,
shading: THREE.SmoothShading,
depthTest: false
});
var geometrySphere = new THREE.SphereGeometry(cloudRadius, 140, 100);
geometrySphere.computeFaceNormals();
cloudMesh = new THREE.Mesh(geometrySphere, displacementMaterial);
cloudMesh.position.y = -40;
cloudMesh.renderOrder = 5;
scene.add(cloudMesh);
}
function animateAll() {
uniforms.uSpeed.value += properties.heat;
uniforms.time.value += properties.heat * .3;
displacementUniforms.opacity.value = properties.opacity;
displacementMaterial.uniforms["time"].value += properties.heat * .3;
//cloudMesh.rotation.x = properties.rotationX;
cloudMesh.rotation.z = properties.rotationZ;
//cloudMesh.rotation.y = properties.rotationY;
cloudMesh.rotation.y += 0.002;
requestAnimationFrame(animateAll);
renderAll();
}
//render
function renderAll() {
renderer.clear();
quadTarget.material = noiseMaterial;
renderer.render(sceneRenderTarget, cameraOrtho, noiseMap, true);
renderer.render(scene, camera);
}
canvas {
width: 100%;
height: 100%;
position: absolute;
z-index: -10
}
body {
overflow: hidden;
padding: 0;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.2.js"></script>
<script data-src="shaders/displacement_vertex.js" data-name="Displacement" type="x-shader/x-vertex" id="displacement_vertex">
uniform float time;
uniform vec2 scale;
uniform float uTwist;
varying vec2 vUv;
varying vec3 vNormal;
uniform vec2 uShapeBias;
uniform float uTurbulence;
#ifdef VERTEX_TEXTURES
uniform sampler2D tHeightMap;
uniform float uDisplacementScale;
uniform float uDisplacementBias;
#endif
vec4 DoTwist( vec4 pos, float t )
{
float st = sin(t);
float ct = cos(t);
vec4 new_pos;
new_pos.x = pos.x*ct - pos.z*st;
new_pos.z = pos.x*st + pos.z*ct;
new_pos.y = pos.y;
new_pos.w = pos.w;
return( new_pos );
}
void main( void ) {
vUv = uv;
vNormal = normalize( normalMatrix * normal );
//change matrix
vec4 mPosition = modelMatrix * vec4( position, 1.0 );
mPosition.x *= uShapeBias.x +1.0; // uShapeBias.x*(vUv.x+1.0);
mPosition.y *= (1.0 -(vUv.y-0.5)*-uShapeBias.y);
//mPosition.y -= 40.0;
float turbFactor = uTurbulence*(vUv.y-0.5);
//shape turbulance
mPosition.x += sin(mPosition.y/100.0 + time*20.0 )*turbFactor;
mPosition.z += cos(mPosition.y/100.0 + time*20.0 )*turbFactor;
//twist
float angle_rad = uTwist * 3.14159 / 180.0;
float height = -300.0;
float ang = (position.y-height*0.5)/height * angle_rad;
vec4 twistedPosition = DoTwist(mPosition, ang);
vec4 twistedNormal = DoTwist(vec4(vNormal,1.0), ang);
//change matrix
vec4 mvPosition = viewMatrix * twistedPosition;
#ifdef VERTEX_TEXTURES
vec3 dv = texture2D( tHeightMap, vUv ).xyz;
float df = uDisplacementScale * dv.x + uDisplacementBias;
vec4 displacedPosition = vec4( twistedNormal.xyz * df, 0.0 ) + mvPosition;
gl_Position = projectionMatrix * displacedPosition;
#else
gl_Position = projectionMatrix * mvPosition;
#endif
}
</script>
<script data-src="shaders/displacement_fragment.js" data-name="Displacement" type="x-shader/x-fragment" id="displacement_fragment">
varying vec2 vUv;
uniform sampler2D tHeightMap;
uniform float uSmoke;
uniform vec3 uColor1;
uniform vec3 uColor2;
uniform float uScreenHeight;
void main( void ) {
vec4 heightColor = texture2D( tHeightMap, vUv);
vec3 heightAlpha = texture2D( tHeightMap, vUv).xyz;
vec3 gradient1 = uColor1/(gl_FragCoord.y/uScreenHeight*4.0);
vec3 gradient2 = uColor2/(gl_FragCoord.y/uScreenHeight*4.0);
vec3 fireSumColor = (gradient1+gradient2)*heightColor.b;
float opacity = heightAlpha.x *.05;
//smoke
gl_FragColor = vec4(mix( fireSumColor, vec3(1.0), gl_FragCoord.y/uScreenHeight*uSmoke ), opacity);
float depth = gl_FragCoord.z / gl_FragCoord.w;
float fogFactor = smoothstep( 10.0, 400.0, depth* .9 );
gl_FragColor = mix( gl_FragColor, vec4( vec3(0.0,0.0,0.0), gl_FragColor.w ), fogFactor )*1.0;
// gl_FragColor = gl_FragColor*vec4(vec3(1.0), 1.0);
}
</script>
<script data-src="shaders/noise_vertex.js" data-name="Noise" type="x-shader/x-vertex" id="noise_vertex">
varying vec2 vUv;
uniform vec2 scale;
void main( void ) {
vUv = uv * scale;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script data-src="shaders/noise_fragment.js" data-name="Noise" type="x-shader/x-fragment" id="noise_fragment">
//
// Description : Array and textureless GLSL 3D simplex noise function.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110409 (stegu)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
//
uniform float time;
uniform float uSpeed;
varying vec2 vUv;
vec4 permute( vec4 x ) {
return mod( ( ( x * 34.0 ) + 1.0 ) * x, 289.0 );
}
vec4 taylorInvSqrt( vec4 r ) {
return 1.79284291400159 - 0.85373472095314 * r;
}
float PI = 3.14159265;
float TWOPI = 6.28318531;
float BaseRadius = 1.0;
vec3 sphere( float u, float v) {
u *= PI;
v *= TWOPI;
vec3 pSphere;
pSphere.x = BaseRadius * cos(v) * sin(u);
pSphere.y = BaseRadius * sin(v) * sin(u);
pSphere.z = BaseRadius * cos(u);
return pSphere;
}
float snoise( vec3 v ) {
const vec2 C = vec2( 1.0 / 6.0, 1.0 / 3.0 );
const vec4 D = vec4( 0.0, 0.5, 1.0, 2.0 );
// First corner
vec3 i = floor( v + dot( v, C.yyy ) );
vec3 x0 = v - i + dot( i, C.xxx );
// Other corners
vec3 g = step( x0.yzx, x0.xyz );
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - i1 + 1.0 * C.xxx;
vec3 x2 = x0 - i2 + 2.0 * C.xxx;
vec3 x3 = x0 - 1. + 3.0 * C.xxx;
// Permutations
i = mod( i, 289.0 );
vec4 p = permute( permute( permute(
i.z + vec4( 0.0, i1.z, i2.z, 1.0 ) )
+ i.y + vec4( 0.0, i1.y, i2.y, 1.0 ) )
+ i.x + vec4( 0.0, i1.x, i2.x, 1.0 ) );
// Gradients
// ( N*N points uniformly over a square, mapped onto an octahedron.)
float n_ = 1.0 / 7.0; // N=7
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor( p * ns.z *ns.z ); // mod(p,N*N)
vec4 x_ = floor( j * ns.z );
vec4 y_ = floor( j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
vec4 h = 1.0 - abs( x ) - abs( y );
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
vec4 s0 = floor( b0 ) * 2.0 + 1.0;
vec4 s1 = floor( b1 ) * 2.0 + 1.0;
vec4 sh = -step( h, vec4( 0.0 ) );
vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
vec3 p0 = vec3( a0.xy, h.x );
vec3 p1 = vec3( a0.zw, h.y );
vec3 p2 = vec3( a1.xy, h.z );
vec3 p3 = vec3( a1.zw, h.w );
// Normalise gradients
vec4 norm = taylorInvSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) );
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix final noise value
vec4 m = max( 0.6 - vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 );
m = m * m;
return 42.0 * dot( m*m, vec4( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ), dot( p3, x3 ) ) );
}
float surface( vec3 coord ) {
float n = 0.0;
n += 0.7 * abs( snoise( coord ) );
n += 0.25 * abs( snoise( coord * 2.0 ) );
n += 0.125 * abs( snoise( coord * 4.0 ) );
n += 0.0625 * abs( snoise( coord * 8.0 ) );
return n;
}
void main( void ) {
vec3 coord = sphere(vUv.y,vUv.x);
coord.x += uSpeed;
coord.y += -time;
coord.z += -time;
float n = surface( coord );
gl_FragColor = vec4( vec3( n, n, n ), 1.0 );
}
</script>
When you have overlapping transparent materials in three.js, you can often remove unwanted artifacts by setting
material.depthTest = false;
It depends on your use case.
It will not work well if you have opaque objects the occlude the transparent objects, however. But that is not your use case here.
EDIT: As #Bahadir points out in the comment below, you can an also try
material.depthWrite = false;
three.js r.77

Categories

Resources