WebGL blur shader in three JS - javascript

That's kind of a long shot, but I'm hopelessly lost. I've started learning Three.JS some time ago and wanted to migrate my project from P5.js (as an exercise, but with idea to use it in the future). In P5.js I simply made a canvas and applied a shader to it, but in Three.JS it doesn't seem to work. So I figured out - I'll try it in shaders.
The idea:
to draw random circles (on transparent background)
blur the circles
use the outcome as a texture.
So far, I've managed to draw the circles (not random yet, but still working on it) and use it as a texture.
JS part:
const geometry = new THREE.PlaneGeometry( 1, 1, 1 );
const material = new THREE.ShaderMaterial( {
uniforms: {
iP: 0,
dl: { value : new THREE.Vector2(.6, 0), },
spots : { value : 5.0 },
offset : { value : new THREE.Vector2(0.5, 0.5) },
radius : { value : .25 },
},
vertexShader: _VS,
fragmentShader: _FS,
transparent: true
});
Vert shader part:
const _VS = `
precision mediump float;
attribute vec3 aPosition;
varying vec2 vTexCoord;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`;
Fragment shader part:
// fragment shader
const _FS = `
precision mediump float;
varying vec2 vTexCoord;
varying vec2 vUv;
uniform float spots;
uniform vec2 offset;
uniform float radius;
// uniform sampler2D iP; // canvas to be blurred
uniform vec2 dl;
const float Pi = 6.28318530718;
float rnd(vec3 scale, float seed) {
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
// CIRCLE;
vec4 color1 = vec4(.1, .5, .3, 1.0);
vec4 color2 = vec4(0., 0., 0., 0.01);
vec2 shift = offset;
for (float t = 0.0; t <= spots; t++) {
float p = smoothstep(radius, radius + .0001, length(vUv - shift));
vec4 col = mix(color1, color2, vec4(p));
gl_FragColor += col;
shift.x += .05;
shift.y -= .01;
}
// BLUR
vec4 col = vec4(0.0);
float tt = 0.0;
float off = rnd(vec3(12.9898, 78.233, 151.7182), 0.0);
for (float t = -30.0; t <= 30.0; t++) {
float pc = (t + off - 0.5) / 30.0;
float w = 1.0 - abs(pc);
vec4 spl = texture2D(iP, vTexCoord + dl * pc);
spl.rgb *= spl.a;
col += spl * w;
tt += w;
}
gl_FragColor = col / tt;
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
}`;
I have an issue with the line
vec4 spl = texture2D(iP, vTexCoord + dl * pc);. I don't know how I could use created circles on gl_FragColor.
I've spent hours reading and looking for a solution, but I didn't find any help.
I'd truly appreciate any directions or solutions!
Thanks in advance!

You seem to be mixing a lot of variable names between P5.js and Three.js. You should just look at the way Three.js does it, and try to forget the P5.js terminology because they're not the same. Here's an official example of a simple shader setup, you could look at the source code there.
I've copied that demo below with a much more simplified shader so you can get a feel of how to pass a time uniform from JavaScript, and read it in GLSL:
body, html {
margin: 0;
}
<div id="container"></div>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims#1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three#0.142.0/build/three.module.js",
}
}
</script>
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three#0.142.0/build/three.module.js";
let camera, scene, renderer;
let uniforms;
init();
animate();
function init() {
const container = document.getElementById( 'container' );
camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
scene = new THREE.Scene();
const geometry = new THREE.PlaneGeometry( 2, 2 );
uniforms = {
time: { value: 1.0 }
};
const _VS = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( position, 1.0 );
}
`;
const _FS = `
varying vec2 vUv;
uniform float time;
void main() {
float blue = sin(time * 5.0 + vUv.x * 10.0) * 0.5 + 0.5;
gl_FragColor = vec4( vUv.x, vUv.y, blue, 1.0 );
}
`;
const material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: _VS,
fragmentShader: _FS
} );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
uniforms[ 'time' ].value = performance.now() / 1000;
renderer.render( scene, camera );
}
</script>
From here you should be able to extrapolate and add other types of uniforms, including float, vec2, sampler2D, etc. Finally, here's a bit more details on which uniforms, attributes, and naming conventions are used by default when you use ShaderMaterial.

Every effect (post-process), that you want to apply on your whole scene, you should pass into EffectComposer.
Here is documentation: https://threejs.org/docs/#manual/en/introduction/How-to-use-post-processing.
Also sometimes you can apply some effects by setting css-rules like blur on the renderer element like this:
renderer.domElement.style.filter = `blur(10px)`;

Related

Book of shaders exercises

I am spending this winter holidays trying to learn something about shaders, I am stuck with this couple exercise:
y = sin(x);
Try the following exercises and notice what happens:
Add time (u_time) to x before computing the sin. Internalize that motion along
x.
how do I implement it?
You'll need 2 uniform variables, the resolution of the viewport (u_resolution) and the time (u_time) in seconds:
uniform vec2 u_resolution;
uniform float u_time;
x can be get by the x coordinate of the fragment. Map the x coordinate to the range [0, 2*PI]:
vec2 st = gl_FragCoord.xy/u_resolution.xy;
float x = st.x * 2.0 * 3.141529;
Calculate y. sin is the Sine function:
float y = sin(x + u_time);
Set the color channels of the fragment by y. y has to be mapped from the range [-1, 1], to [0, 1]:
gl_FragColor = vec4(vec3(y*0.5+0.5), 1.0);
The result is a sine gradient, moving from the right to the left:
var container, camera, scene, renderer, uniforms;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
uniforms = {
u_time: { type: "f", value: 1.0 },
u_resolution: { type: "v2", value: new THREE.Vector2() }
};
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 );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
(window.onresize = function() {
renderer.setSize( window.innerWidth, window.innerHeight );
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
})();
}
function animate(delta_ms) {
requestAnimationFrame( animate );
uniforms.u_time.value = delta_ms / 1000.0;
renderer.render( scene, camera );
}
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
float x = st.x * 2.0 * 3.141529;
float y = sin(x + u_time);
gl_FragColor = vec4(vec3(y*0.5+0.5), 1.0);
}
</script>
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
I believe it would be something like this:
y = sin(u_time + x);
You should see the sin wave moving along the x axis.
Explanation:
u_time is the time in seconds since the shader started. Using this variable, we can add it to the x value before calculating sin, which will give the effect of the wave moving along the x axis.
To implement it, you can change the text just under the graph.

Make pixel intensity dependant on distance from mouse

I am rendering my scene in a 512x512 canvas, my goal is to have the pixel intensity change according to how far away the pixel is from the mouse cursor. But it doesn't seem to change at all. I try multipling by a large number, then it's all white.
var ico = new THREE.Mesh(new THREE.IcosahedronGeometry(0.3,0), light_mat);
ico.position.x = 0;
ico.position.y = 0;
ico.position.z = -3;
scene.add(ico);
var render = function() {
vec.set(
( mouse_x / 512 ) * 2 - 1,
- ( mouse_y / 512 ) * 2 + 1,
0.5 );
vec.unproject( camera );
vec.sub( camera.position ).normalize();
var distance = (ico.position.z-camera.position.z ) / vec.z;
pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );
console.log(pos.x+":"+pos.y+":"+pos.z);
ico.material.uniforms.mouse.value = pos;
requestAnimationFrame(render);
renderer.render(scene, camera);
};
...
<script type="x-shader/x-vertex" id="light_f">
varying vec3 pos;
varying vec2 uv_pos;
varying vec3 norm;
uniform vec3 mouse;
void main() {
vec4 tex = vec4(1.0,1.0,1.0,1.0);
float ang = dot(mouse,norm);
float dis = 0.1*distance(mouse,pos);
gl_FragColor = tex*dis;
}
</script>
<script type="x-shader/x-vertex" id="light_v">
uniform vec3 mouse;
varying vec2 uv_pos;
varying vec3 norm;
varying vec3 pos;
void main() {
uv_pos = uv;
norm = normal;
pos = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
Any help appreciated.

Generate particle with 3 shades of the same color Three

Hello I have searched the internet but I have not found anything on, I am trying to make 1 globe in the form of particles with the mix of 3 colors pink, dark pink and white equal to that image down
I need the colors to look like this picture, normal pink, dark pink and whit
the problem is that my Globe is left with 1 single color instead of varios like the image, all help is grateful, thank you all at once
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth /
window.innerHeight, 1, 1000);
camera.position.z = 10;
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0x2675AD);
renderer.setSize(window.innerWidth, window.innerHeight);
var globe = document.getElementById('globe')
globe.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var geom = new THREE.SphereBufferGeometry(5, 320, 160);
var colors = [];
var color = new THREE.Color();
var q = 0xC83C84;
for (let i = 0; i < geom.attributes.position.count; i++) {
color.set(Math.random() * q);
color.toArray(colors, i * 3);
}
geom.addAttribute('color', new THREE.BufferAttribute(new
Float32Array(colors), 3));
var loader = new THREE.TextureLoader();
loader.setCrossOrigin('');
var texture = loader.load('../img/equirectangle_projection.png');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1, 1);
var disk = loader.load('../img/circleround.png');
var points = new THREE.Points(geom, new THREE.ShaderMaterial({
vertexColors: THREE.VertexColors,
uniforms: {
visibility: {
value: texture
},
shift: {
value: 0
},
shape: {
value: disk
},
size: {
value: 0.125
},
scale: {
value: window.innerHeight / 2
}
},
vertexShader: `
uniform float scale;
uniform float size;
varying vec2 vUv;
varying vec3 vColor;
void main() {
vUv = uv;
vColor = color;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( scale / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader: `
uniform sampler2D visibility;
uniform float shift;
uniform sampler2D shape;
varying vec2 vUv;
varying vec3 vColor;
void main() {
vec2 uv = vUv;
uv.x += shift;
vec4 v = texture2D(visibility, uv);
if (length(v.rgb) > 1.0) discard;
gl_FragColor = vec4( vColor, 1.0 );
vec4 shapeData = texture2D( shape, gl_PointCoord );
if (shapeData.a < 0.5) discard;
gl_FragColor = gl_FragColor * shapeData;
}
`,
transparent: true
}));
scene.add(points);
var blackGlobe = new THREE.Mesh(geom, new
THREE.MeshBasicMaterial({
color: 0x2675AD
}));
blackGlobe.scale.setScalar(0.99);
points.add(blackGlobe);
var clock = new THREE.Clock();
var time = 0;
render();
function render() {
requestAnimationFrame(render);
time += clock.getDelta();
points.rotation.y += 0.0009
renderer.render(scene, camera);
}
You can use an array of colour values and pick those values randomly:
var q = ["white", "pink", 0xb2497d, "gray"];
for (let i = 0; i < geom.attributes.position.count; i++) {
color.set(q[THREE.Math.randInt(0,3)]);
color.toArray(colors, i * 3);
}
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(1.25, 7, 7);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0x080808);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var geom = new THREE.SphereBufferGeometry(5, 120, 60);
var colors = [];
var color = new THREE.Color();
var q = ["white", "pink", 0xb2497d, "gray"];
for (let i = 0; i < geom.attributes.position.count; i++) {
color.set(q[THREE.Math.randInt(0,3)]);
color.toArray(colors, i * 3);
}
geom.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));
var loader = new THREE.TextureLoader();
loader.setCrossOrigin('');
var texture = loader.load('http://learningthreejs.com/data/2013-09-16-how-to-make-the-earth-in-webgl/demo/bower_components/threex.planets/images/earthspec1k.jpg');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1, 1);
var disk = loader.load('https://threejs.org/examples/textures/sprites/circle.png');
var points = new THREE.Points(geom, new THREE.ShaderMaterial({
vertexColors: THREE.VertexColors,
uniforms: {
visibility: {
value: texture
},
shift: {
value: 0
},
shape: {
value: disk
},
size: {
value: 0.125
},
scale: {
value: window.innerHeight / 2
}
},
vertexShader: `
uniform float scale;
uniform float size;
varying vec2 vUv;
varying vec3 vColor;
void main() {
vUv = uv;
vColor = color;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( scale / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader: `
uniform sampler2D visibility;
uniform float shift;
uniform sampler2D shape;
varying vec2 vUv;
varying vec3 vColor;
void main() {
vec2 uv = vUv;
uv.x += shift;
vec4 v = texture2D(visibility, uv);
if (length(v.rgb) > 1.0) discard;
gl_FragColor = vec4( vColor, 1.0 );
vec4 shapeData = texture2D( shape, gl_PointCoord );
if (shapeData.a < 0.5) discard;
gl_FragColor = gl_FragColor * shapeData;
}
`,
transparent: true
}));
scene.add(points);
var blackGlobe = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({
color: 0x000000
}));
blackGlobe.scale.setScalar(0.99);
points.add(blackGlobe);
var clock = new THREE.Clock();
var time = 0;
render();
function render() {
requestAnimationFrame(render);
time += clock.getDelta();
points.material.uniforms.shift.value = time * 0.1;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Three.js envmaps and vertex animation

I am making my first steps coding with JavaScript and playing with Three.js.
I am learning how to use Shaders and I have a week stuck with a vertex animation that doesn't work.
This one is my Vertex Shader:
uniform float fresnelBias;
uniform float amplitude;
uniform float fresnelScale;
uniform float fresnelPower;
attribute float displacement;
varying float vReflectionFactor;
varying vec3 vReflect;
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
vec3 I = worldPosition.xyz - cameraPosition;
vReflect = reflect( I, worldNormal );
vReflectionFactor = fresnelBias + fresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), fresnelPower );
gl_Position = projectionMatrix * mvPosition;
}
and this one is Fragment Shader:
uniform vec3 color;
uniform samplerCube envMap;
varying vec3 vReflect;
varying float vReflectionFactor;
void main() {
vec4 envColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );
gl_FragColor = vec4(mix(color, envColor.xyz, vec3(clamp( vReflectionFactor, 0.0, 1.0 ))), 1.0);
}
Then I declared a variable to my attributes and another to my uniforms to assign it to a geometry but when I load the site I don't see anything. The JavaScript console tells that in this line uniforms.amplitude.value = Math.sin(frame); uniforms is not defined.
Do you have some recomendation? Do you know something that I can do?
I let here my complete code I hope it could help:
<script id="vertexShader" type="x-shader/x-vertex">
uniform float fresnelBias;
uniform float amplitude;
uniform float fresnelScale;
uniform float fresnelPower;
attribute float displacement;
varying float vReflectionFactor;
varying vec3 vReflect;
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
vec3 I = worldPosition.xyz - cameraPosition;
vReflect = reflect( I, worldNormal );
vReflectionFactor = fresnelBias + fresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), fresnelPower );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec3 color;
uniform samplerCube envMap;
varying vec3 vReflect;
varying float vReflectionFactor;
void main() {
vec4 envColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );
gl_FragColor = vec4(mix(color, envColor.xyz, vec3(clamp( vReflectionFactor, 0.0, 1.0 ))), 1.0);
}
</script>
<script>
var camera, scene, renderer;
var mesh, material, controls, sky;
init();
animate();
function init(){
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0xfffff, 0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 400;
//controls = new THREE.TrackballControls( camera );
scene = new THREE.Scene();
var numberOfImages = 46, images = [];
for (var i = 1; i <= numberOfImages; i++) {
images.push('sources/instagram2/image' + i + ".jpg");
}
var urls = images.sort(function(){return .6 - Math.random()}).slice(0,6);
var textureCube = THREE.ImageUtils.loadTextureCube( urls );
// Skybox
var skyshader = THREE.ShaderLib[ "cube" ];
skyshader.uniforms[ "tCube" ].value = textureCube;
var skymaterial = new THREE.ShaderMaterial( {
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
uniforms: skyshader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
sky = new THREE.Mesh( new THREE.BoxGeometry( 1500, 1500, 1500 ), skymaterial );
sky.visible = false;
scene.add( sky );
var attributes = {
displacement: {
type: 'f', // a float
value: [] // an empty array
}
};
var uniforms = {
color: {
type: "c",
value: new THREE.Color(0x000000),
},
envMap: {
type: "t",
value: textureCube
},
fresnelBias: {
type: "f",
value: 0.1
},
fresnelScale: {
type: "f",
value: 1.0
},
fresnelPower: {
type: 'f',
value: 2.0
},
amplitude: {
type: 'f',
value: 0
}
};
var vertexShader = document.getElementById('vertexShader').text;
var fragmentShader = document.getElementById('fragmentShader').text;
material = new THREE.ShaderMaterial(
{
uniforms : uniforms,
vertexShader : vertexShader,
fragmentShader : fragmentShader,
});
var loader = new THREE.BinaryLoader();
loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {
mesh = new THREE.Mesh(geometry, material);
mesh.scale.set( 300, 300, 300 );
var vertices = mesh.geometry.vertices;
var values = attributes.displacement.value
for(var v = 0; v < vertices.length; v++) {
values.push(Math.random() * 10);
}
scene.add(mesh);
} );
var light = new THREE.AmbientLight( 0x404040 ); // soft white light
scene.add( light );
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
var frame = 0;
function animate() {
uniforms.amplitude.value = Math.sin(frame);
frame += 0.01;
requestAnimationFrame(animate);
//controls.update();
//mesh.rotation.x += 0.005;
//mesh.rotation.y += 0.005;
renderer.render(scene, camera);
stats.update();
}
Update:
I Added the uniforms variable to the global scope and now the console doesn't show me any problem but I can't see the vertex animation:
<script id="vertexShader" type="x-shader/x-vertex">
uniform float fresnelBias;
uniform float amplitude;
uniform float fresnelScale;
uniform float fresnelPower;
attribute float displacement;
varying float vReflectionFactor;
varying vec3 vReflect;
void main() {
vec3 newPosition = position + normal * vec3(displacement * amplitude);
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
vec3 I = worldPosition.xyz - cameraPosition;
vReflect = reflect( I, worldNormal );
vReflectionFactor = fresnelBias + fresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), fresnelPower );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec3 color;
uniform samplerCube envMap;
varying vec3 vReflect;
varying float vReflectionFactor;
void main() {
vec4 envColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );
gl_FragColor = vec4(mix(color, envColor.xyz, vec3(clamp( vReflectionFactor, 0.0, 1.0 ))), 1.0);
}
</script>
<script>
var camera, scene, renderer;
var mesh, material, controls, sky;
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor(0xfffff, 0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 400;
scene = new THREE.Scene();
var numberOfImages = 46, images = [];
for (var i = 1; i <= numberOfImages; i++) {
images.push('sources/instagram2/image' + i + ".jpg");
}
var urls = images.sort(function(){return .6 - Math.random()}).slice(0,6);
var textureCube = THREE.ImageUtils.loadTextureCube( urls );
var skyshader = THREE.ShaderLib[ "cube" ];
skyshader.uniforms[ "tCube" ].value = textureCube;
var skymaterial = new THREE.ShaderMaterial( {
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
uniforms: skyshader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
sky = new THREE.Mesh( new THREE.BoxGeometry( 1500, 1500, 1500 ), skymaterial );
sky.visible = false;
scene.add( sky );
var attributes = {
displacement: {
type: 'f',
value: []
}
};
var uniforms = {
color: {
type: "c",
value: new THREE.Color(0x000000),
},
envMap: {
type: "t",
value: textureCube
},
fresnelBias: {
type: "f",
value: 0.1
},
fresnelScale: {
type: "f",
value: 1.0
},
fresnelPower: {
type: 'f',
value: 2.0
},
amplitude: {
type: 'f',
value: 0
}
};
var vertexShader = document.getElementById('vertexShader').text;
var fragmentShader = document.getElementById('fragmentShader').text;
material = new THREE.ShaderMaterial(
{
uniforms : uniforms,
vertexShader : vertexShader,
fragmentShader : fragmentShader,
});
var loader = new THREE.BinaryLoader();
loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {
mesh = new THREE.Mesh(geometry, material);
mesh.scale.set( 100, 100, 100 );
var vertices = mesh.geometry.vertices;
var values = attributes.displacement.value
for(var v = 0; v < vertices.length; v++) {
values.push(Math.random() * 30);
}
scene.add(mesh);
} );
var light = new THREE.AmbientLight( 0x404040 );
scene.add( light );
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
var frame = 0;
function animate() {
uniforms.amplitude.value = Math.sin(frame);
frame += 0.1;
requestAnimationFrame(animate);
//controls.update();
//mesh.rotation.x += 0.005;
//mesh.rotation.y += 0.005;
renderer.render(scene, camera);
}
animate();
</script>
Do you have some conseil to make it?
You have defined the uniforms variable in the init() function so it's scope is within that function and can not be accessed in the animate() function.
Add the uniforms variable to the global scope and you should be fine.

Gradation color in WebGL with GLSL shader

I would have black color in the middle of my disk with a gradation from the outside.
the 2 first parts are the GLSL code to make my shader, my problem is when i do : "gl_FragColor = vec4( vec3( vUv, 0.17 ), 1. ); "
`
varying vec2 vUv;
void main()
{
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 0.8);
}
'
'
varying vec2 vUv;
void main()
{
gl_FragColor = vec4( vec3( vUv, 0.17 ), 1. );
}
'
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 45, 1024 / 860, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer({ antialias: true});
camera.position.z = 30;
var my_shad = new THREE.ShaderMaterial({
vertexShader: document.getElementById( 'vertex' ).textContent,
fragmentShader: document.getElementById( 'frag' ).textContent
});
var radius = 8;
var segments = 80;
var circleGeometry = new THREE.CircleGeometry( radius, segments );
var disk = new THREE.Mesh(circleGeometry, my_shad);
scene.add(disk);
renderer.setSize( 1024, 860 );
document.body.appendChild( renderer.domElement );
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
'
Try doing something like this for starters:
void main(){
float uvD = length(vUv);
vec3 gradient = mix(color1, color2, uvD);
gl_FragColor = vec4(gradient,1.);
}

Categories

Resources