I'm new to Three Js and i do not know how to change the color of my material when i press a button on the html page.
Do you have any suggestion? I'll attach here the code
here is how i declare my material:
var color2= new THREE.Color(0xff0000)
var customMaterial = new THREE.ShaderMaterial(
{
uniforms: {
p: { type: "f", value: 2 },
glowColor: { type: "c", value: color2 },
},
vertexShader: $('#vertexShader').text,
fragmentShader: $('#fragmentShader').text,
side: THREE.DoubleSide,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false
});
here is how i update my color:
function render() {
renderer.render(scene, camera);
document.getElementById("colore").onclick= function(){
console.log("prova caramella");
var customMaterial = new THREE.ShaderMaterial(
{
uniforms: {
p: { type: "f", value: 2 },
glowColor: { type: "c", value: new THREE.Color(0x00ff00) },
},
vertexShader: $('#vertexShader').text,
fragmentShader: $('#fragmentShader').text,
side: THREE.DoubleSide,
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false
});
customMaterial.needsUpdate = true
}
and lastly this is how i link the material to my 3d model:
function petali2(){
var loaderpetali = new THREE.ColladaLoader();
loaderpetali.load('petali3.dae', function (collada) {
petali = collada.scene;
petali.traverse( function ( child ) {
if (child instanceof THREE.Mesh) {
console.log(child);
child.material = customMaterial;
}
} );
petali.scale.x = 2;
petali.scale.y = 2;
petali.scale.z = 2;
//flower = dae;
scene.add(petali);
});
}
When updating the color, it's sufficient to do this:
customMaterial.uniforms.glowColor.value.set( 0x00ff00 );
There is no need to create a new material.
Besides, when using a latest version of three.js, it's not necessary to define the type for a uniform. The type is automatically derived from the compiled shader. On app level, it's sufficient to do.
uniforms: {
p: { value: 2 },
glowColor: { value: new THREE.Color(0x00ff00) },
},
Related
I'm making obj loader in react view button clicked, I want to see obj file in modal component.This object loader component get url to modal component.
console.log is correct.This loader is get url other component.
Group {uuid: "0C86CC1D-E795-4191-A62A-72DF4A433CEB", name: "", type:
"Group", parent: null, children: Array(8), …} castShadow:
falsechildren: (8) [Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh,
Mesh]frustumCulled: truelayers: Layers {mask: 1}materialLibraries:
["patient.mtl"]matrix: Matrix4 {elements: Array(16)}matrixAutoUpdate:
truematrixWorld: Matrix4 {elements: Array(16)}matrixWorldNeedsUpdate:
falsename: ""parent: Scene {uuid:
"873E8718-F1B0-47B5-AC77-DC1B334B3637", name: "", type: "Scene",
parent: null, children: Array(5), …}position: Vector3 {x: 0, y: 0, z:
0}quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1,
_onChangeCallback: ƒ}receiveShadow: falserenderOrder: 0rotation: Euler {_x: 0, _y: 0, _z: 0, _order: "XYZ", _onChangeCallback: ƒ}scale:
Vector3 {x: 0.07, y: 0.07, z: 0.07}type: "Group"up: Vector3 {x: 0, y:
1, z: 0}userData: {}uuid:
"0C86CC1D-E795-4191-A62A-72DF4A433CEB"visible: trueeulerOrder:
(...)id: 18modelViewMatrix: Matrix4 {elements: Array(16)}normalMatrix:
Matrix3 {elements: Array(9)} useQuaternion: (...)proto: Object3D
(8) [Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh, Mesh]
Scene {uuid: "873E8718-F1B0-47B5-AC77-DC1B334B3637", name: "", type:
"Scene", parent: null, children: Array(5), …}
CODE
import React, { Component } from "react";
import * as THREE from "three";
import OBJLoader from "three-obj-loader";
import OrbitControls from "three-orbitcontrols";
OBJLoader(THREE);
let scene;
class ObjectLoader extends Component {
componentDidMount() {
const width = this.mount.clientWidth;
const height = this.mount.clientHeight;
scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, width / height, 1, 2000);
this.camera.position.z = 250;
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setClearColor("#263238");
this.renderer.setSize(width, height);
this.mount.appendChild(this.renderer.domElement);
const geometry = new THREE.BoxGeometry(5, 5, 5);
const material = new THREE.MeshBasicMaterial({
color: "#0F0",
wireframe: true
});
this.cube = new THREE.Mesh(geometry, material);
scene.add(this.cube);
const controls = new OrbitControls(this.camera, this.renderer.domElement);
//LIGHTS
var lights = [];
lights[0] = new THREE.PointLight(0x304ffe, 1, 0);
lights[1] = new THREE.PointLight(0xffffff, 1, 0);
lights[2] = new THREE.PointLight(0xffffff, 1, 0);
lights[0].position.set(0, 200, 0);
lights[1].position.set(100, 200, 100);
lights[2].position.set(-100, -200, -100);
scene.add(lights[0]);
scene.add(lights[1]);
scene.add(lights[2]);
// load Object
loadObj(this.props.url);
}
componentWillUnmount() {
this.stop();
this.mount.removeChild(this.renderer.domElement);
}
start = () => {
if (!this.frameId) {
this.frameId = requestAnimationFrame(this.animate);
}
};
stop = () => {
cancelAnimationFrame(this.frameId);
};
animate = () => {
this.renderScene();
this.frameId = window.requestAnimationFrame(this.animate);
};
renderScene = () => {
if (this.renderer) this.renderer.render(scene, this.camera);
};
onLoad = () => {
this.renderScene();
//start animation
this.start();
};
onProgress = xhr => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
};
// Function called when download errors
onError = error => {
console.log("An error happened" + error);
};
render() {
return (
<div
style={{ width: "500px", height: "500px" }}
ref={mount => {
this.mount = mount;
}}
/>
);
}
}
function loadObj(url) {
const objLoader = new THREE.OBJLoader();
objLoader.load(
url,
function(object) {
console.log(object, object.children);
let mesh = object;
scene.add(object);
console.log(scene);
mesh.position.set(0, 0, 0);
mesh.scale.set(0.07, 0.07, 0.07);
},
function(xhr) {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
// called when loading has errors
function(error) {
console.log("An error happened" + error);
});
}
export default ObjectLoader;
I'm looking to create a material with three.js identical to MeshStandardMaterial.
I want to do this because I need all of its features except with small changes to the GLSL code.
I attempted to recreate MeshStandardMaterial using ShaderMaterial.
WAFFLE.StandardMaterial = function( parameters ) {
parameters.uniforms = THREE.UniformsUtils.merge( [
THREE.UniformsLib.common,
THREE.UniformsLib.aomap,
THREE.UniformsLib.lightmap,
THREE.UniformsLib.emissivemap,
THREE.UniformsLib.bumpmap,
THREE.UniformsLib.normalmap,
THREE.UniformsLib.displacementmap,
THREE.UniformsLib.roughnessmap,
THREE.UniformsLib.metalnessmap,
THREE.UniformsLib.fog,
THREE.UniformsLib.lights,
{
emissive: { value: new THREE.Color( 0x000000 ) },
roughness: { value: 0.5 },
metalness: { value: 0 },
envMapIntensity: { value: 1 } // temporary
}
] );
parameters.vertexShader = THREE.ShaderChunk.meshphysical_vert;
parameters.fragmentShader = THREE.ShaderChunk.meshphysical_frag;
THREE.ShaderMaterial.call( this, parameters );
}
WAFFLE.StandardMaterial.prototype = Object.create( THREE.ShaderMaterial.prototype );
WAFFLE.StandardMaterial.prototype.constructor = WAFFLE.StandardMaterial;
I haven't been successful thus far.
How can I recreate MeshStandardMaterial?
I am making my first steps coding with JavaScript and playing with Three.js too.
In my code I made this function:
var loader = new THREE.BinaryLoader();
loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {
uniforms = {
color: {
type: "c",
value: new THREE.Color(0x000000),
},
envMap: {
type: "t",
value: reflectionCube
},
fresnelBias: {
type: "f",
value: 0.1
},
fresnelScale: {
type: "f",
value: 1.0
},
fresnelPower: {
type: 'f',
value: 2.0
}
};
material = new THREE.ShaderMaterial( {
uniforms : uniforms,
vertexShader : vertexShader,
fragmentShader : fragmentShader,
wireframe: false,
side: THREE.DoubleSide,
});
monogram = new THREE.Mesh( geometry, material );
monogram.scale.set( 1, 1, 1 );
monogram.position.z = -9;
scene.add( monogram );
});
and then I made this render function:
function render() {
frame += 0.1/3;
monogram.scale.z += Math.sin(frame)/600;
TWEEN.update();
targetX = mouseX * .0005;
targetY = mouseY * .0005;
if ( monogram ) {
monogram.rotation.y += 0.05 * ( targetX - monogram.rotation.y );
monogram.rotation.x += 0.05 * ( targetY - monogram.rotation.x );
}
renderer.render( scene, camera );
}
I can see everything and everything works ok. But my console says that there is an error: Uncaught ReferenceError: monogram is not defined.
I think that I have to make a Global Scope of monogram. So I wrote var before monogram and it doesnt work, then I wrote
monogram = new THREE.Mesh( geometry, material );
monogram.scale.set( 1, 1, 1 );
monogram.position.z = -9;
scene.add( monogram );
outside my function and it doesnt work.
Do you have some suggestion? My app works, even if the console says that there is n error, I think that is better if my console says that everything is ok.
here is vertex and fragmentshader material :
material = new THREE.ShaderMaterial( {
uniforms: {
textureMap: { type: 't', value: THREE.ImageUtils.loadTexture( 'img/matcap/green.jpg' ) },
normalMap: { type: 't', value: THREE.ImageUtils.loadTexture( 'img/normalmap/stamp.jpg' ) },
normalScale: { type: 'f', value: 0.5 },
texScale: { type: 'f', value: 5 },
useSSS: { type: 'f', value: 10 },
useScreen: { type: 'f', value: 0 },
color: { type: 'c', value: new THREE.Color( 0, 0, 0 ) }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
side: THREE.DoubleSide
} );
I want repeat texture use like this
material.uniforms.textureMap.value.wrapS = material.uniforms.textureMap.value.wrapT =
THREE.ClampToEdgeWrapping;
material.uniforms.normalMap.value.wrapS = material.uniforms.normalMap.value.wrapT =
THREE.RepeatWrapping;
material.uniforms.normalMap.value.repeat.set( 20, 20 );
but not work in three.js why? how fix it
thanks all friends!
By default the texture are Clamp To Edge means no wrapping to zero. Your main texture is Clamp TO Edge repeat and normal texture is Repeat Wrapping probably you normal map texture quality is not so bright to make a difference try to revert the thing or texture ( means make some bright normal map texture or dull texture map any).
your approach is correct it seems. One more thing which you can do to increase readability:
var textureMap = THREE.ImageUtils.loadTexture( 'img/matcap/green.jpg' );
var normalMap = THREE.ImageUtils.loadTexture( 'img/normalmap/stamp.jpg' )
textureMap.repeat.set(20,20);
normalMap.repeat.set(10,10);
//then shader code
I'm gonna make my SUN!!!!!!!!!!!!!!!!! SUNGOD!!! urg---!
..sorry.
It doesn't work as well.
Error message shown on console and it said;
// Uncaught TypeError: Cannot read property 'position' of undefined;
Here is source
// Constructing * The Solar *
var shape = new THREE.BufferGeometry();
shape.addAttribute('position', new THREE.Float32Attribute(6,3));
// console shows problem is here but I can't find any
shape.addAttribute('textureOrder', new THREE.Int8Attribute(6,1));
for(var i=0; i<6; i++) {
shape.attribute.position.setXYZ(i, 0, 0, 0);
shape.attribute.textureOrder.setX(i, i);
};
var d = new Date();
var mater = new THREE.ShaderMaterial({
uniforms: {
time: { type: 'f', value: d.getTime() },
tsun_core: { type: 't', value: loadTexture('./sun_core.png') },
tsun_innerglow: { type: 't', value: loadTexture('./sun_innerglow.png') },
tsun_starlight: { type: 't', value: loadTexture('./sun_starlight.png') },
tsun_outerglow: { type: 't', value: loadTexture('./sun_outerglow.png') },
tsun_shortjetlight: { type: 't', value: loadTexture('./sun_shortjetlight.png') },
tsun_longjetlight: { type: 't', value: loadTexture('./sun_longjetlight.png') }
},
vertexShader: document.getElementById('vs-sun').textContent,
fragmentShader: document.getElementById('fs-sun').textContent
});
mater.depthTest = false;
mater.vertexColor = true;
mater.transparent = true;
mater.blending = THREE.AdditiveBlending;
sun = new THREE.ParticleSystem(shape, mater);
scene.add(sun);
My goal is, change gl_FragColor opacity by uniform time in fragment shader so my sun(?) to be more dynamic...
My opinion, cause of problem be somewhere above source. Please guide me..
Calling the addAttribute method on a THREE.BufferGeometry instance creates properties under the attributes property, not attribute.
Replaces these lines
shape.attribute.position.setXYZ(i, 0, 0, 0);
shape.attribute.textureOrder.setX(i, i);
With the following lines
shape.attributes.position.setXYZ(i, 0, 0, 0);
shape.attributes.textureOrder.setX(i, i);