In my scene I render complex objects, which have a complex surface structure. Furthermore I am not using light in my scene and I am trying to avoid it.
For now I am using the MeshNormalMaterial which shows perfectly the surface structures of my objects.
object with MeshNormalMaterial:
But I want to render certain objects with a unique color (e.g. from dark red to light red based on the surface structure/ similar to the MeshNormalMaterial).
I tried the MeshDepthMaterial for one object, but it rendered the whole object in almost color (no/ sparse color gradation) and not as expected like in this example. Independent of the camera position.
Same object from above with: MeshDepthMaterial
I am using a THREE.PerspectiveCamera with THREE.OrbitControls. Camera properties:
//camera attributes
public fieldOfView: number = 60;
public nearClippingPane: number = 0.1;
public farClippingPane: number = 50000;
Does the MeshNormalMaterial require light or why is this the case? Can I somehow amplify the depth effect of MeshNormalMaterial?
Is ist possible to restrict the RGB Colors of MeshNormalMaterial or do I have to use another Material for my purpose?
I just slightly modified the code of the fragment shader from this SO answer, so all credits to Rabbid76:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var colors = {
color1: "#ff0000",
color2: "#ffaaaa"
}
var geometry = new THREE.TorusKnotBufferGeometry(2, 0.5, 100, 16);
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color(colors.color1)
},
color2: {
value: new THREE.Color(colors.color2)
}
},
vertexShader: vertShader,
fragmentShader: fragShader
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
var gui = new dat.GUI();
gui.addColor(colors, "color1").onChange(function(value) {
material.uniforms.color1.value.set(value);
});
gui.addColor(colors, "color2").onChange(function(value) {
material.uniforms.color2.value.set(value);
});
render();
function render() {
requestAnimationFrame(render);
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://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script>
var vertShader = `
varying vec3 vNormal;
void main(void)
{
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`;
var fragShader = `
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void)
{
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
}
`;
</script>
Related
I am trying to write a shader that draws contour plots on meshes.
Here is an example of contour plot.
My first aim is visualizing one triangle face with different colors.
You can find the code that I am using in here.
<html lang="en">
<head>
<title>Face Contour Example</title>
</head>
<body>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec3 vColor;
void main(){
vColor = color;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
varying vec3 vColor;
void main(){
gl_FragColor = vec4( vColor.rgb, 1.0 );
}
</script>
<script type="text/javascript">
var camera, scene, renderer, mesh, material, controls;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = -400;
// Create scene.
scene = new THREE.Scene();
var colors = {
"color1" : {
type : "c",
value : new THREE.Color(0xff0000) //r
},
"color2" : {
type : "c",
value : new THREE.Color(0x00ff00) //b
},
"color3" : {
type : "c",
value : new THREE.Color(0x0000ff) //g
},
};
var fShader = document.getElementById('fragmentShader').text;
var vShader = document.getElementById('vertexShader').text;
// Create material
var material = new THREE.ShaderMaterial({
vertexShader: vShader,
fragmentShader: fShader,
vertexColors: THREE.VertexColors,
});
// var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } );
// Create cube and add to scene.
var geometry = new THREE.Geometry();
geometry.vertices=[
new THREE.Vector3(100,0,0),
new THREE.Vector3(-100,0,0),
new THREE.Vector3(50,100,0)
]
var face=new THREE.Face3();
face.a=0;
face.b=1;
face.c=2;
face.vertexColors[ 0 ] = colors["color1"].value;
face.vertexColors[ 1 ] = colors["color2"].value;
face.vertexColors[ 2 ] = colors["color3"].value;
geometry.faces=[face]
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function addWireFrame(){
//Create wireframe helper for mesh with same geometry
var wireframeMesh=new THREE.WireframeGeometry(geometry);
var line = new THREE.LineSegments( wireframeMesh );
line.material.depthTest = false;
line.material.opacity = 0.75;
line.material.transparent = true;
mesh.add( line );
}
addWireFrame();
//Orbit controls
controls = new THREE.OrbitControls( camera );
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
// Create directional light and add to scene.
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
</script>
</body>
</html>
In the code I assigned red, green and blue colors to each vertices of a face.
In vertex shader, I redirected those colors to fragment shader. And In fragment shader, I am planning to use my own formula to decide which color will be used for that instance of the fragment. (My formula will depend on the position on the face.)
However, I couldn't manage to prevent interpolation of vertex colors. Is there a way to pick vertex color from an array directly without interpolation in three.js?
Also, I appreciate alternative solutions that may be suitable for my problem.
You don't want to disable interpolation. You want, instead, to use the interpolated coordinates as an index. The interpolated color value tells you how close you are to each of the vertices. You can then quantize this interpolated value into ranges, or indexes into a color array, to produce the end color.
I modified your fiddle to show the color of the closest vertex using the following pixel shader:
void main(){
vec3 c = vColor;
gl_FragColor = vec4(c.r > c.g && c.r > c.b ? 1.0 : 0.0,
c.g > c.r && c.g > c.b ? 1.0 : 0.0,
c.b > c.r && c.b > c.g ? 1.0 : 0.0,
1.0 );
}
The result looks like this:
You will need a more complex quantization method to show a contour map, but I hope this approach gives you a good start.
I have a bunch of Object3d in the scene comprised of different meshes, e.g:
const object3d = new Object3D();
const bodyMaterial = new MeshLambertMaterial();
const bezelMaterial = new MeshBasicMaterial({ color: "0xffffff" });
const mesh = new Mesh(MeshFactory.mesh1, [ bodyMaterial, bezelMaterial ]);
const textLabel = TextFactory.createText("mesh1");
object3d.add(mesh, textLabel);
I'd like to move the position of the object3d on each frame,
currently doing that on the CPU:
render() {
object3D.position = calcPosition(); // new Vector3
}
This is slow since I have hundreds of Object3d objects and each one should move separately.
So I'd like to write a vertex shader that moves the xyz on each frame but,
how do I write a shader for Object3D? (change position for all of it's meshes)?
Sounds like you might be going about things the wrong way...
But..
Here is a basic example of vertex displacement in a shader in three.js.
Rotation is done in the render loop, but offset values are sent to the vertex shader.
var camera, scene, renderer, mesh, material;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
// Create material
var uniforms = {
xOffset: { type: "f", value: 0.0 },
yOffset: { type: "f", value: 0.0 },
zOffset: { type: "f", value: 0.0 }
};
var vertexShader = document.getElementById('vertexShader').text;
var fragmentShader = document.getElementById('fragmentShader').text;
material = new THREE.ShaderMaterial(
{
uniforms : uniforms,
vertexShader : vertexShader,
fragmentShader : fragmentShader
});
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
// Create directional light and add to scene.
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// set up gui.
var gui = new dat.GUI();
gui.add(uniforms.xOffset, 'value', -500, 500).name('X Offset');
gui.add(uniforms.yOffset, 'value', -500, 500).name('Y Offset');;
gui.add(uniforms.zOffset, 'value', -500, 500).name('Z Offset');;
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<script src="https://rawgit.com/mrdoob/three.js/r89/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/dataarts/dat.gui/v0.6.2/build/dat.gui.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
uniform float xOffset;
uniform float yOffset;
uniform float zOffset;
void main( void ) {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position + vec3(xOffset, yOffset, zOffset),1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
</script>
I have two objects that I need to render in two different textures using WebGLRenderTarget. After mapping both textures to a plane using shaders and then adding that plane to the main scene, I am having issues drawing the closer object.
I have created a jsfiddle to show my issue: https://jsfiddle.net/11qb7ay7/82/
The real magic occurs here:
void main() {
vec4 color = texture2D(tex_sphere, vUv);
vec4 color_cube = texture2D(tex_cube, vUv);
gl_FragColor = vec4(color.rgb * color_cube.rgb, 1.0);
}
The sphere is placed in front of the cube relative to the camera. How can I draw the sphere pixels instead of the cubes when they overlap?
To be clear, I am trying to find a way to compute the distance from camera of each pixel and render the closer one first
In general if tex_sphere has an alpha channel the you can mix the colors by the alpha channel:
void main()
{
vec4 color = texture2D(tex_sphere, vUv);
vec4 color_cube = texture2D(tex_cube, vUv);
vec3 mixCol = mix(color_cube.rgb, color.rgb, color.a);
gl_FragColor = vec4(mixCol.rgb, 1.0);
}
If the tex_sphere has a black background, which should be omitted, the you have to check if the color of tex_sphere is not black:
void main()
{
vec4 color = texture2D(tex_sphere, vUv);
vec4 color_cube = texture2D(tex_cube, vUv);
vec3 test = step(1.0/512.0, color.rgb);
float a = max(max(test.r, test.g), test.b);
vec3 mixCol = mix(color_cube.rgb, color.rgb, a);
gl_FragColor = vec4(mixCol.rgb, 1.0);
}
Note, mix interpolates between 2 values according to a floating point interpolation value a in the range [0.0, 1.0]. If the a is equal 0.0 then the 1st value is returned and if the a is equal 1.0 then the 2nd value is returned.
step tests whether a value is less than an edge value. If it is less then 0.0 is returned, else 1.0 is returned.
To get a black background you have to set a black "clear" color when you render the sphere to the render target:
function render() {
controls.update();
renderer.setClearColor(0x00);
renderer.render(sphereScene, camera, renderTargets.sphere, true);
renderer.setClearColor(0xccccff);
renderer.render(cubeScene, camera, renderTargets.cube, true);
renderer.setClearColor(0xccccff);
renderer.render(scene, camera);
}
If you want to use an alpha channel, the you have to set setClearAlpha before you render to the render target:
function render() {
controls.update();
renderer.setClearAlpha(0);
renderer.render(sphereScene, camera, renderTargets.sphere, true);
renderer.setClearAlpha(1);
renderer.render(cubeScene, camera, renderTargets.cube, true);
renderer.render(scene, camera);
}
var scene, renderer, camera, controls;
var cubeScene, sphereScene;
var renderTargets;
init();
animate();
function init() {
scene = new THREE.Scene();
cubeScene = new THREE.Scene();
sphereScene = new THREE.Scene();
renderer = new THREE.WebGLRenderer( { antialias: false, alpha: true } );
renderer.setClearColor(0xccccff);
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 4000 );
camera.position.set(0, 0, 200);
renderer.setSize( window.innerWidth, window.innerHeight );
controls = new THREE.OrbitControls(camera, renderer.domElement);
camera.lookAt( scene.position );
var light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
scene.add( light );
container = document.createElement('div');
document.body.appendChild(container);
container.appendChild(renderer.domElement);
initObjects();
initRenderTargets(window.innerWidth, window.innerHeight);
}
function onResize() {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderTargets.sphere.setSize( window.innerWidth, window.innerHeight );
renderTargets.cube.setSize( window.innerWidth, window.innerHeight );
}
function initObjects() {
var cGeometry = new THREE.BoxGeometry( 100, 100, 100 );
var cMaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var cube = new THREE.Mesh( cGeometry, cMaterial );
cube.position.z = -210;
cube.position.y = 100;
var sGeometry = new THREE.SphereGeometry( 75, 32, 32 );
var sMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000
});
var sphere = new THREE.Mesh( sGeometry, sMaterial );
sphere.position.z = -100;
sphereScene.add( sphere );
cubeScene.add( cube );
}
function initRenderTargets(width, height){
renderTargets = createRenderTargets(width, height);
var uniforms = {
"tex_cube": { type: "t", value: renderTargets.cube.texture },
"tex_sphere": { type: "t", value: renderTargets.sphere.texture }
}
material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vs_rt').textContent,
fragmentShader: document.getElementById('fs_rt').textContent
});
var plane = new THREE.PlaneGeometry(width, height);
quad = new THREE.Mesh(plane, material);
scene.add(quad);
}
function createRenderTargets(width, height) {
var parameters = {
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
};
return {
cube: new THREE.WebGLRenderTarget( width, height, parameters ),
sphere: new THREE.WebGLRenderTarget( width, height, parameters )
};
}
function animate() {
requestAnimationFrame(animate);
render();
}
//------------------------------------------
// Main rendering
//------------------------------------------
function render() {
controls.update();
renderer.setClearAlpha(0);
renderer.render(sphereScene, camera, renderTargets.sphere, true);
renderer.setClearAlpha(1);
renderer.render(cubeScene, camera, renderTargets.cube, true);
renderer.render(scene, camera);
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>
<script type="text/javascript" src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script id="vs_rt" type="x-shader/x-vertex">
uniform sampler2D tex_cube;
uniform sampler2D tex_sphere;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="fs_rt" type="x-shader/x-fragment">
uniform sampler2D tex_cube;
uniform sampler2D tex_sphere;
varying vec2 vUv;
void main() {
vec4 color = texture2D(tex_sphere, vUv);
vec4 color_cube = texture2D(tex_cube, vUv);
vec3 mixCol = mix(color_cube.rgb, color.rgb, color.a);
gl_FragColor = vec4(mixCol.rgb, 1.0);
}
</script>
I'm just looking to create a simple Fragment Shader that draws a specified texture to the mesh. But I can´t display it. I can display the texture file in a basic gemetry, but not work with shaders the only result in a black sphere.
I don´t know what is wrong. Any help would be appreciated!
I am using Three.js THREE.WebGLRenderer 81
<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 texture1;
void main() {
gl_FragColor = texture2D(texture1, vUv); // Displays black sphere
//gl_FragColor = vec4(0.5, 0.2, 1.0, 1.0); // Works; Displays Color
}
</script>
<script>
// Initialize WebGL Renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
//var canvas = document.getElementById('canvas').appendChild(renderer.domElement);
document.body.appendChild( renderer.domElement );
renderer.setClearColor(0x888888, 1.0);
// Initialize Scenes
var scene = new THREE.Scene();
// Initialize Camera
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100);
camera.position.z = 10;
// Create Light
var light = new THREE.PointLight(0xFFFFFF);
light.position.set(0, 0, 500);
scene.add(light);
// LIGHT
var light = new THREE.PointLight(0xffffff);
light.position.set(100,250,100);
scene.add(light);
// Create Ball
var vertShader = document.getElementById('vertexShader').textContent;
var fragShader = document.getElementById('fragmentShader').textContent;
var textura = new THREE.TextureLoader().load('./funkyGround.jpg');
var uniforms = {
texture1: { type: 't', value: textura }
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertShader,
fragmentShader: fragShader
});
var ball = new THREE.Mesh(new THREE.SphereGeometry(1, 50, 50), material);
scene.add(ball);
// Render the Scene
renderer.render(scene, camera);
</script>
</body>
After a review, I can find the solution including a render() function
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
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.