How can I project a 2d shader in a 3d object - three.js

the title make it looks easy but I'm struggling to get this pie chart shader on my 3d model. For this I'm using three js. here is my code till now:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Site Prof Matheus</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='./styles/main.css'>
<script type='module' src='./src/main.js'></script>
</head>
<body>
</body>
</html>
main.js:
import * as THREE from 'https://cdn.skypack.dev/three'
import { OrbitControls } from 'https://cdn.skypack.dev/three-stdlib/controls/OrbitControls'
import { GLTFLoader } from 'https://cdn.skypack.dev/three-stdlib/loaders/GLTFLoader'
import { vertexShader } from '../shaders/vertex.glsl.js'
import { fragmentShader } from '../shaders/fragment.glsl.js'
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const loader = new GLTFLoader();
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor(0x002653, 0.5)
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.setPixelRatio(window.devicePixelRatio);
const r_material = new THREE.ShaderMaterial({ //Roulette material
uniforms: {
iTime: { value: 1.0 },
resolution: { value: new THREE.Vector2 }
},
vertexShader,
fragmentShader
})
loader.load(
'../roulette.glb',
function (gltf) {
gltf.scene.traverse((o) => {
if (o.isMesh) o.material = r_material;
});
scene.add(gltf.scene);
},
function () { },
function (err) {
console.log('error: ' + err);
}
)
camera.position.z = 5;
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
controls.enableDamping = true;
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
};
animate();
vertex.glsl.js:
const vertexShader = /* glsl */`
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
// uniform vec3 iResolution;
// uniform int SEGMENTCOUNT;
export { vertexShader };
fragment.glsl.js:
const fragmentShader = /* glsl */`
void main() {
gl_FragColor = vec4(0, 1, 0, 1);
gl_Position
}
`
export { fragmentShader };
and here is my roulette.gbl model
the intended result is to have a shader with colors that I choose, all the parts equal, the colors can repeat and the shader should covers the whole mesh, less the bottom. intended result
PS. i see my object looks a flat plain on the image, i guess just need to add some proper light, here is my object geometry just for sake of curiosity: my mesh geometry
PSS. some antialiasing on the pie chart shader would be very welcome

This is how you can do it, modifying a material with .onBeforeCompile():
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.136.0";
import {
OrbitControls
} from "https://cdn.skypack.dev/three#0.136.0/examples/jsm/controls/OrbitControls";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 2000);
camera.position.set(0, 1, 1).setLength(12);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", onWindowResize);
let controls = new OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper());
let light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let path = new THREE.Path();
path.moveTo(0, -1);
path.lineTo(4, -1);
path.absarc(4, -0.5, 0.5, Math.PI * 1.5, 0);
path.absarc(4, 0.5, 0.5, 0, Math.PI * 0.5);
path.lineTo(0, -0.5);
let g = new THREE.LatheGeometry(path.getPoints(50), 72);
let m = new THREE.MeshLambertMaterial({
color: 0x00ff7f,
//wireframe: true,
onBeforeCompile: shader => {
shader.vertexShader = `
varying vec3 vPos;
${shader.vertexShader}
`.replace(
`#include <begin_vertex>`,
`#include <begin_vertex>
vPos = position;
`
);
//console.log(shader.vertexShader);
shader.fragmentShader = `
#define ss(a, b, c) smoothstep(a, b, c)
varying vec3 vPos;
${shader.fragmentShader}
`.replace(
`vec4 diffuseColor = vec4( diffuse, opacity );`,
`
vec3 col = diffuse;
int N = 37;
float a = atan(vPos.x,-vPos.z)+PI;
float r = PI2/float(N);
float cId = floor(a/r);
vec3 br = mod(cId, 2.) == 0. ? vec3(0) : vec3(1, 0, 0); // black / red
br = cId == 0. ? vec3(0, 0.75, 0) : br; // green
float d = length(vPos.xz);
float fw = length(fwidth(vPos.xz));
col = mix(col, br, ss(3. - fw, 3., d) - ss(4., 4. + fw, d));
col = mix(diffuse, col, clamp(sign(vPos.y), 0., 1.));
vec4 diffuseColor = vec4( col, opacity );
`
);
//console.log(shader.fragmentShader);
}
})
let o = new THREE.Mesh(g, m);
o.position.y = 0.5;
o.rotation.y = Math.PI;
scene.add(o);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
function onWindowResize() {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
}
</script>

Related

THREE.JS UV map over entire THREE.BufferGeometry

Here is a very simple Three.JS sketch, resulting following render:
As you may see this THREE.BufferGeometry is a 8x8 matrix and by setting UVs in this way:
for(var i = 0; i < points.length; i += 4){ quad_uvs.push(...[0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]); }
uvs = new Float32Array(quad_uvs);
geometry.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
It applies texture to each 8x8 segment, however I need to place texture over the entire geometry.
How I could update uv mapping for achieving it?
var img = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAIAAgADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDwSiiivxo/0tCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiuq8I/Crxj49Xd4d8MarrEWcGa0tHeIH3fG0fiaqMZTdoq7Ma1elhoOpWmoxXVtJfezlaK9gf9kT4wRweafA1+VxnCywlv8AvkPn9K8/8V/D3xP4EmWPxF4e1PRGY7UN/avErn/ZLDDfhWs6Famrzg16pnBhs2y/GT9nhsRCcu0ZRb+5M5+iiisD1QooooAKKKKACiiigAooooAKKKKACitrwx4J8Q+Nbprbw/oeo63OuNyafavMVz0ztBx+Nei2/wCyL8YLmDzk8C34TGcSSRI3/fLOD+lbQoVaivCDfomeZic1y/BS5MViIQfaUop/i0eQUV2Pi34O+OPAcTTeIPCer6Vbr1uZ7RxCP+2gG39a46s5QlB2krM66GIo4qHtKE1OPdNNfegoooqToCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACii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AUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB//Z";
var renderer, scene, camera, controls, glsl;
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.crossOrigin = "";
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 51200);
camera.position.set(-2048, 2048, -2048);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 8;
controls.maxDistance = 5120;
camera.position.set(208.48355078304965, 45.28894677815297, 310.34089790619583);
controls.target.set(0, 0, 0);
var points = [], indices = [], quad_uvs = [];
for(var x = -512; x < 512; x += 128){
for(var z = -512; z < 512; z += 128){
points.push(new THREE.Vector3(x, 0, z));
points.push(new THREE.Vector3(x + 128 , 0, z));
points.push(new THREE.Vector3(x + 128, 0, z + 128));
points.push(new THREE.Vector3(x, 0, z + 128));
}
}
for(var i = 0; i < points.length; i += 4){
indices.push(i, i + 1, i + 2);
indices.push(i + 2, i + 3, i);
}
var geometry = new THREE.BufferGeometry().setFromPoints(points);
for(var i = 0; i < points.length; i += 4){ quad_uvs.push(...[0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]); }
uvs = new Float32Array(quad_uvs);
geometry.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
geometry.setIndex( indices );
geometry.computeVertexNormals();
glsl = new THREE.ShaderMaterial( {
uniforms: {
textureA: { type: 't', value: new THREE.TextureLoader().load(img) }
},
vertexShader: document.getElementById( "vertexShader" ).textContent,
fragmentShader: document.getElementById( "fragmentShader" ).textContent
} );
glsl.side = THREE.DoubleSide;
var plane = new THREE.Mesh(geometry, glsl);
scene.add(plane);
animate();
function animate(){
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
body { margin: 0; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/three#0.116.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.116.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
varying vec2 vUv;
uniform sampler2D textureA;
void main() {
gl_FragColor = texture2D(textureA, vUv);
}
</script>
</body>
</html>
I've updated your code with a possible solution. You will see that the geometry is now generated slightly differently. The most important part is that you have to generate your texture coordinates in the range [0,1] across the entire geometry and not just for each quad.
var img = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAIAAgADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDwSiiivxo/0tCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiuq8I/Crxj49Xd4d8MarrEWcGa0tHeIH3fG0fiaqMZTdoq7Ma1elhoOpWmoxXVtJfezlaK9gf9kT4wRweafA1+VxnCywlv8AvkPn9K8/8V/D3xP4EmWPxF4e1PRGY7UN/avErn/ZLDDfhWs6Famrzg16pnBhs2y/GT9nhsRCcu0ZRb+5M5+iiisD1QooooAKKKKACiiigAooooAKKKKACitrwx4J8Q+Nbprbw/oeo63OuNyafavMVz0ztBx+Nei2/wCyL8YLmDzk8C34TGcSSRI3/fLOD+lbQoVaivCDfomeZic1y/BS5MViIQfaUop/i0eQUV2Pi34O+OPAcTTeIPCer6Vbr1uZ7RxCP+2gG39a46s5QlB2krM66GIo4qHtKE1OPdNNfegoooqToCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACii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AUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQB//Z";
var renderer, scene, camera, controls, glsl;
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
loader = new THREE.TextureLoader();
loader.crossOrigin = "";
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 51200);
camera.position.set(-2048, 2048, -2048);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 8;
controls.maxDistance = 5120;
camera.position.set(208.48355078304965, 45.28894677815297, 310.34089790619583);
controls.target.set(0, 0, 0);
var points = [], indices = [], uvs = [];
var step = 128;
for(var x = -512; x < 512; x += step){
for(var z = -512; z < 512; z += step){
points.push(x, 0, z);
points.push(x + step , 0, z);
points.push(x + step, 0, z + step);
points.push(x, 0, z + step);
var u = x + 512;
var v = z + 512;
uvs.push(u / 1024, v / 1024);
uvs.push((u + step) / 1024 , v / 1024);
uvs.push((u + step) / 1024 ,(v + step) / 1024);
uvs.push(u / 1024, (v + step) / 1024);
}
}
var geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( points, 3 ) );
geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
var positionAttribute = geometry.getAttribute( 'position' );
for(var i = 0; i < positionAttribute.count; i += 4){
indices.push(i, i + 1, i + 2);
indices.push(i + 2, i + 3, i);
}
geometry.setIndex( indices );
geometry.computeVertexNormals();
glsl = new THREE.ShaderMaterial( {
uniforms: {
textureA: { type: 't', value: new THREE.TextureLoader().load(img) }
},
vertexShader: document.getElementById( "vertexShader" ).textContent,
fragmentShader: document.getElementById( "fragmentShader" ).textContent
} );
glsl.side = THREE.DoubleSide;
var plane = new THREE.Mesh(geometry, glsl);
scene.add(plane);
animate();
function animate(){
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
body { margin: 0; }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/three#0.116.0/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.116.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
varying vec2 vUv;
uniform sampler2D textureA;
void main() {
gl_FragColor = texture2D(textureA, vUv);
}
</script>
</body>
</html>

Not getting expect result from THREE.js/GLSL code

Apologies for the vague question but I wasn't sure how to phrase this. I'm trying to write some THREE.js/GLSL code that produces a circular gradient (for some SDF stuff). With the code below I would expect to see the gradient on the plane, but the plane remains white and nothing else renders on it. Can anyone tell me where I'm going wrong?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script type="x-shader/x-vertex" id="sdfVS">
varying vec2 vUv; // pass the uv coordinates of each pixel to the frag shader
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="sdfFS">
precision mediump float;
uniform vec2 u_resolution;
varying vec2 vUv;
float circle(vec2 pos, float radius)
{
return distance(pos, vec2(radius));
}
void main()
{
vec2 pos = (gl_FragCoord.xy / vUv) * 2.0 - 1.0;
float circle1 = circle(pos, 0.5);
vec3 color = vec3(circle1);
gl_FragColor = vec4(color, 1.0);
}
</script>
<script src="../../js/three.min.js"></script>
<script>
var scene, camera, renderer, aspect, geometry, material, plane;
var container;
var frustumSize = 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0000ff);
aspect = window.innerWidth / window.innerHeight;
camera = new THREE.OrthographicCamera( 0.5 * frustumSize * aspect / - 2, 0.5 * frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 0.1, 1 );
cameraOrthoHelper = new THREE.CameraHelper( camera );
scene.add( cameraOrthoHelper );
var width = 1;
var height = 1;
geometry = new THREE.PlaneGeometry(width, height);
material = new THREE.ShaderMaterial( {
vertexShader: document.getElementById('sdfVS').textContent,
fragmentShader: document.getElementById('sdfFS').textContent,
side: THREE.DoubleSide
} );
plane = new THREE.Mesh( geometry, material );
plane.rotation.x = 0;
plane.rotation.y = THREE.Math.degToRad( -90 );
plane.rotation.z = 0;
scene.add( plane )
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
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 );
render();
}
function render() {
camera.position.x = -1;
camera.position.y = 0;
camera.position.z = 0;
camera.lookAt( scene.position );
camera.updateMatrixWorld();
renderer.render( scene, camera );
}
</script>
</body>
</html>
Can't get this line:
vec2 pos = (gl_FragCoord.xy / vUv) * 2.0 - 1.0;
Seems like you want to calculate uv coordinates, but if so, then you already have uvs (passed in vUv).
You can do the thing this way, as an option:
var scene, camera, renderer, aspect, geometry, material, plane;
var container;
var clock = new THREE.Clock();
var frustumSize = 2;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0000ff);
aspect = window.innerWidth / window.innerHeight;
camera = new THREE.OrthographicCamera(0.5 * frustumSize * aspect / -2, 0.5 * frustumSize * aspect / 2, frustumSize / 2, frustumSize / -2, 0.1, 1);
cameraOrthoHelper = new THREE.CameraHelper(camera);
scene.add(cameraOrthoHelper);
var width = 1;
var height = 1;
geometry = new THREE.PlaneGeometry(width, height);
material = new THREE.ShaderMaterial({
uniforms: {time: {value: 0}},
vertexShader: document.getElementById('sdfVS').textContent,
fragmentShader: document.getElementById('sdfFS').textContent,
side: THREE.DoubleSide
});
plane = new THREE.Mesh(geometry, material);
plane.rotation.x = 0;
plane.rotation.y = THREE.Math.degToRad(-90);
plane.rotation.z = 0;
scene.add(plane)
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
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);
render();
}
function render() {
camera.position.x = -1;
camera.position.y = 0;
camera.position.z = 0;
camera.lookAt(scene.position);
camera.updateMatrixWorld();
var t = clock.getElapsedTime();
material.uniforms.time.value = t;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script type="x-shader/x-vertex" id="sdfVS">
varying vec2 vUv; // pass the uv coordinates of each pixel to the frag shader
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="sdfFS">
precision mediump float;
uniform float time;
uniform vec2 u_resolution;
varying vec2 vUv;
float circle(vec2 uv, vec2 pos, float radius) {
return smoothstep(radius, 0., length(uv - pos));
}
void main()
{
vec2 uv = vUv * 2. - 1.;
vec2 pos = vec2(cos(time), sin(time));
float circle1 = circle(uv, pos, 1.0);
vec3 color = vec3(circle1);
gl_FragColor = vec4(color, 1.0);
}
</script>

GLSL/THREE.js Math to turn a shape into a cube issue

I am making code to turn a sphere into a cube in a vertex shader, but it seems to turn into this weird shape, my logic was this:
The commented out code was the iterative version.
vec3 p = position;
if(true)
{
if(p.y<s&&p.y>-s){
p.x = -(p.x-s);//p.x-=(p.x-s)*t*0.1;
}
if(p.x<s&&p.x>-s){
p.y = -(p.y-s);//p.y-=(p.y-s)*t*0.1;
}
}
gl_Position = projectionMatrix * modelViewMatrix * vec4( p, 1.0 );
But then that turns this:
Into this:
Any help appreciated.
Use THREE.BoxBufferGeometry() as a base, then add another buffer attribute with coodinates for a sphere formation, then interpolate (mix) those coordinates of the box and the sphere in the shader:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(1, 3, 5);
var renderer = new THREE.WebGLRenderer();
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 side = 2;
var rad = Math.sqrt(3) * 0.5 * side; // radius of the sphere is a half of cube's diagonal
var geom = new THREE.BoxBufferGeometry(side, side, side, 10, 10, 10);
var pos = geom.attributes.position;
var spherePos = []; // array of coordinates for the sphere formation
var vec3 = new THREE.Vector3(); // vector for re-use
for (let i = 0; i < pos.count; i++) {
vec3.fromBufferAttribute(pos, i).setLength(rad); // create coordinate for the sphere formation
spherePos.push(vec3.x, vec3.y, vec3.z);
}
geom.addAttribute("spherePos", new THREE.BufferAttribute(new Float32Array(spherePos), 3));
var mat = new THREE.ShaderMaterial({
uniforms: {
mixShapes: {
value: 0
}
},
vertexShader: `
uniform float mixShapes;
attribute vec3 spherePos;
void main() {
vec3 pos = mix(position, spherePos, mixShapes); // interpolation between shapes
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0,1.0);
}
`,
wireframe: true
});
var shape = new THREE.Mesh(geom, mat);
scene.add(shape);
var gui = new dat.GUI();
gui.add(mat.uniforms.mixShapes, "value", 0.0, 1.0).name("mixShapes");
renderer.setAnimationLoop(() => {
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 src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
If you want to get a cube from a sphere, you can clamp vertices to min and max vectors of a bounding box you need (but accuracy of this approach depends on the amount of vertices of the sphere):
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(1, 3, 5);
var renderer = new THREE.WebGLRenderer();
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 side = 2;
var rad = Math.sqrt(3) * 0.5 * side; // radius of the sphere is a half of cube's diagonal
var geom = new THREE.SphereBufferGeometry(rad, 36, 36);
var mat = new THREE.ShaderMaterial({
uniforms: {
mixShapes: {
value: 0
}
},
vertexShader: `
uniform float mixShapes;
attribute vec3 spherePos;
void main() {
vec3 pos = clamp(position, vec3(${-side * 0.5}), vec3(${side * 0.5})); // clamp to min and max vectors
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0,1.0);
}
`,
wireframe: true
});
var shape = new THREE.Mesh(geom, mat);
scene.add(shape);
renderer.setAnimationLoop(() => {
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>

Buffer geometry custom attribute material leaking into other objects

I'm making a visualization and want soft edged particles to represent data points.
I've gathered code from various examples and have something working except for a transparency issue. I tried out the the new Stack Overflow snippet system and made a simple example of what I'm seeing.
As you'll notice, the sphere picks up the transparency from the particle system. Is there a way to turn this off - in my application, this is a required feature. I tried applying attributes to the material I use for the sphere but that didn't appear to help.
Any ideas what I'm doing wrong?
var camera, scene, renderer, controls;
var uniforms;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene = new THREE.Scene();
var ambient_light = new THREE.AmbientLight(0x333333);
scene.add(ambient_light);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 10, 1000);
camera.position.z = 80;
var num_particles = 5000;
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array(num_particles * 3);
var colors = new Float32Array(num_particles * 3);
var sizes = new Float32Array(num_particles);
for (var i = 0; i < num_particles; i++) {
positions[3 * i + 0] = Math.random() * 100 - 50;
positions[3 * i + 1] = Math.random() * 100 - 50;
positions[3 * i + 2] = Math.random() * 100 - 50;
colors[3 * i + 0] = Math.random();
colors[3 * i + 1] = Math.random();
colors[3 * i + 2] = Math.random();
sizes[i] = 2.5;
}
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.addAttribute('customColor', new THREE.BufferAttribute(colors, 3));
geometry.addAttribute('size', new THREE.BufferAttribute(sizes, 1));
var attributes = {
size: {
type: 'f',
value: null
},
customColor: {
type: 'c',
value: null
}
};
uniforms = {
color: {
type: "c",
value: new THREE.Color(0xffffff)
},
texture: {
type: "t",
value: THREE.ImageUtils.loadTexture("data:image/png;base64,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")
}
};
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
attributes: attributes,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
blending: THREE.AdditiveBlending,
depthTest: true,
depthWrite: false,
transparent: true
});
var pointcloud = new THREE.PointCloud(geometry, shaderMaterial);
scene.add(pointcloud);
scene.add(new THREE.Mesh(
new THREE.SphereGeometry(50.0, 16, 16),
new THREE.MeshNormalMaterial({ })
))
controls = new THREE.TrackballControls(camera);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script type="x-shader/x-vertex" id="vertexshader">
attribute float size;
attribute vec3 customColor;
varying vec3 vColor;
void main() {
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform vec3 color;
uniform sampler2D texture;
varying vec3 vColor;
void main() {
gl_FragColor = vec4( color * vColor, 1.0 );
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
}
</script>
Edit: WestLangley's suggestion in comments of turning on depth test results in this: (Don't know how to add an image to a comment so adding here)
The point cloud material attribute I was missing was depthWrite:false and as #WestLangley correctly said, depthTest: true;
I don't know how to version the embedded code so I updated it to work with these values.

Can't send a texture to a custom shader (ShaderPass/EffectComposer)

I'm currently playing with this great library, but I have some difficulties with the EffectComposer.
I can't send a texture to a postprocess shader introduced by a ShaderPass.
I think this is a bug... or I'm doing something stupid (needUpDate, warp,... ??)
(r54, W7, Nv9700mGT, FF 17.0.1 and Chrome 24.0.1312.52)
I used the "webgl_postprocessing.html" example to reproduce the phenomenon just by adding these shaders :
<script id="vertexShaderBasic" type="x-shader/x-vertex">
varying vec2 glTexCoord;
void main() {
glTexCoord = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShaderBlender" type="x-shader/x-fragment">
varying vec2 glTexCoord;
uniform sampler2D sprite1;
uniform sampler2D previousRender;
void main() {
vec3 color = texture2D( previousRender, glTexCoord ).rgb;
color += texture2D( sprite1, glTexCoord ).rgb;
gl_FragColor.rgb = color;
gl_FragColor.a = 1.0;
}
</script>
this at the begining of the main script to be sure the sprite is loaded :
var composer2;
function start() {
init();
animate();
}
var sprite1 = THREE.ImageUtils.loadTexture( "textures/sprite1.jpg", null, start );
this in the composer field, after :
composer.addPass( new THREE.RenderPass( scene, camera ) );
composer2 = new THREE.EffectComposer( renderer );
var uniforms1 = {
sprite1: { type: "t", value: sprite1 }, // <- something wrong here
previousRender: { type: "t", value: null }
};
var blenderShader = {
uniforms: uniforms1,
vertexShader: $( 'vertexShaderBasic' ).textContent,
fragmentShader: $( 'fragmentShaderBlender' ).textContent
};
// link with the previous render
blenderShader.uniforms.previousRender.value = composer.renderTarget2;
// the custom shader
var blenderPass = new THREE.ShaderPass( blenderShader );
blenderPass.renderToScreen = true;
composer2.addPass( blenderPass );
I also coment this, beacause it's not relevent any more :
//effect.renderToScreen = true;
and I add this at the end :
composer2.render();
The link between the two passes work well, but the sprite never appear on the EffectComposer quad that cover the screen...
Thanks and sorry for my english.
EDIT to recap :
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - postprocessing</title>
<meta charset="utf-8">
<style>
body {
margin: 0px;
background-color: #000000;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/three.min.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/DotScreenShader.js"></script>
<script src="js/shaders/RGBShiftShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script id="vertexShaderBasic" type="x-shader/x-vertex">
varying vec2 glTexCoord;
void main() {
glTexCoord = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShaderBlender" type="x-shader/x-fragment">
varying vec2 glTexCoord;
uniform sampler2D sprite1;
uniform sampler2D previousRender;
void main() {
vec3 color = texture2D( previousRender, glTexCoord ).rgb;
color += texture2D( sprite1, glTexCoord ).rgb;
gl_FragColor.rgb = color;
gl_FragColor.a = 1.0;
}
</script>
<script>
var camera, scene, renderer, composer;
var composer2;
var object, light;
function start() {
init();
animate();
}
var sprite1 = THREE.ImageUtils.loadTexture( "textures/sprite1.jpg", null, start );
//var sprite1 = THREE.ImageUtils.loadTexture( "textures/sprite1.jpg", new THREE.UVMapping(), start ); // change anything
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x000000, 1, 1000 );
object = new THREE.Object3D();
scene.add( object );
var geometry = new THREE.SphereGeometry( 1, 4, 4 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
for ( var i = 0; i < 100; i ++ ) {
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 ).normalize();
mesh.position.multiplyScalar( Math.random() * 400 );
mesh.rotation.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 50;
object.add( mesh );
}
scene.add( new THREE.AmbientLight( 0x222222 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
// postprocessing
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );
/////////////////////////////////////
/////////////////////////////////////
composer2 = new THREE.EffectComposer( renderer );
var uniforms1 = {
sprite1: { type: "t", value: sprite1 },
previousRender: { type: "t", value: null }
};
//uniforms1.sprite1.value.wrapS = uniforms1.sprite1.value.wrapT = THREE.RepeatWrapping;
var blenderShader = {
uniforms: uniforms1,
vertexShader: $( 'vertexShaderBasic' ).textContent,
fragmentShader: $( 'fragmentShaderBlender' ).textContent
};
blenderShader.uniforms.previousRender.value = composer.renderTarget2;
var blenderPass = new THREE.ShaderPass( blenderShader );
blenderPass.renderToScreen = true;
composer2.addPass( blenderPass );
/////////////////////////////////////
/////////////////////////////////////
var effect = new THREE.ShaderPass( THREE.DotScreenShader );
effect.uniforms[ 'scale' ].value = 4;
composer.addPass( effect );
var effect = new THREE.ShaderPass( THREE.RGBShiftShader );
effect.uniforms[ 'amount' ].value = 0.0015;
//effect.renderToScreen = true;
composer.addPass( effect );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function $( id ) {
return document.getElementById( id );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
var time = Date.now();
object.rotation.x += 0.005;
object.rotation.y += 0.01;
composer.render();
composer2.render();
}
</script>
</body>
</html>
What I want :
Good
What I get :
NotGood
I had this issue too, and found a workaround.
I debugged it to determine that the texture ID for the extra texture is different in the shader pass than expected, which is bad. If you look in the ShaderPass constructor, you'll see it clones the uniforms. That seems to be the cause. If I edit that code to restore the original texture object in the cloned uniforms, it works as expected. So that should work for you too.
I'm trying to get some kind of (proper) bug fix integrated into the actual release.
Try this
var sprite1 = THREE.ImageUtils.loadTexture( "textures/sprite1.jpg", new THREE.UVMapping(), start );
three.js r.54

Resources