I am working on a project where I have multiple shaders applied to an object. The basic scene is lit with directional lights but when I add a point light or spotlight to the scene the object disappears entirely. I have other objects in the scene that do not disappear so I can only assume it has to do with the shaders applied and the point light. Here is an excerpt of the shaders I am using:
var shader = THREE.ShaderSkin[ "skin" ];
var uniformsUV = THREE.UniformsUtils.clone( shader.uniforms );
var textureLoader = new THREE.TextureLoader();
uniformsUV[ "tNormal" ].value = textureLoader.load( "obj/me/all_skin_hi1_normal.jpg" );
uniformsUV[ "uNormalScale" ].value = -1.5;
uniformsUV[ "tDiffuse" ].value = textureLoader.load( "obj/me/all_skin_hi1.jpg" );
uniformsUV[ "passID" ].value = 0;
uniformsUV[ "diffuse" ].value.setHex( diffuse );
uniformsUV[ "specular" ].value.setHex( specular );
uniformsUV[ "uRoughness" ].value = 0.185;
uniformsUV[ "uSpecularBrightness" ].value = 0.7;
var uniforms = THREE.UniformsUtils.clone( uniformsUV );
uniforms[ "tDiffuse" ].value = uniformsUV[ "tDiffuse" ].value;
uniforms[ "tNormal" ].value = uniformsUV[ "tNormal" ].value;
uniforms[ "passID" ].value = 1;
var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true };
var parametersUV = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShaderUV, uniforms: uniformsUV, lights: true };
var material = new THREE.ShaderMaterial( parameters );
material.extensions.derivatives = true;
var materialUV = new THREE.ShaderMaterial( parametersUV );
materialUV.extensions.derivatives = true;
Try updating to a newer version of the engine. That fixed it for me.
Related
I completely followed the translucency example(https://threejs.org/examples/?q=tran#webgl_materials_translucency), but i don't know why i failed.
" var uniforms = THREE.UniformsUtils.clone( shader.uniforms );" with this chrome said: Uncaught TypeError: Cannot read property 'uniforms' of undefined.
Please help me ~~~
Just incase i put is all my code here.
<html>
<head>
<meta charset="utf-8">
<title> 1 </title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script type="module">
import * as THREE from './js/three.module.js';
import { OrbitControls } from './js/OrbitControls.js';
import { TranslucentShader } from './js/TranslucentShader.js';
let scene, camera, renderer;
function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(70,window.innerWidth/window.innerHeight,1,15000);
camera.position.set(0,500,1000);
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
var loader = new THREE.TextureLoader();
var imgTexture = loader.load( 'white.jpg' );
imgTexture.wrapS = imgTexture.wrapT = THREE.RepeatWrapping;
var shader = THREE.TranslucentShader;
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms[ 'map' ].value = imgTexture;
uniforms[ 'diffuse' ].value = new THREE.Vector3( 1.0, 0.2, 0.2 );
uniforms[ 'shininess' ].value = 500;
uniforms[ 'thicknessMap' ].value = imgTexture;
uniforms[ 'thicknessColor' ].value = new THREE.Vector3( 0.5, 0.3, 0.0 );
uniforms[ 'thicknessDistortion' ].value = 0.1;
uniforms[ 'thicknessAmbient' ].value = 2;
uniforms[ 'thicknessAttenuation' ].value = 1.2;
uniforms[ 'thicknessPower' ].value = 3.0;
uniforms[ 'thicknessScale' ].value = 10;
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader,
lights: true
} );
material.extensions.derivatives = true;
var geo = new THREE.BoxGeometry(100,100,100);
var cube = new THREE.Mesh(geo,material);
scene.add(cube);
let control = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.PointLight( 0xffffff,1 );
scene.add(light);
}
function animate(){
requestAnimationFrame(animate);
renderer.render(scene,camera);
}
init();
animate();
</script>
</body>
</html>
coding is so hard 😢
When you import { TranslucentShader } at the top of your code, the example shows you have to access it as follows:
var shader = TranslucentShader;
No need to put THREE. in front of it. This is creating a reference to an undefined object.
Demo Can be seen here
I'm using a rather small image to make the skybox and for some reason it's being stretched instead of tiled. I found this tutorial on how to pattern a texture. I noted these lines
var crateTexture = new THREE.ImageUtils.loadTexture( 'images/crate.gif' );
crateTexture.wrapS = crateTexture.wrapT = THREE.RepeatWrapping;
crateTexture.repeat.set( 5, 5 );
var crateMaterial = new THREE.MeshBasicMaterial( { map: crateTexture } );
var crate = new THREE.Mesh( cubeGeometry.clone(), crateMaterial );
crate.position.set(60, 50, -100);
scene.add( crate );
So I tried using this method for the skybox and it didn't produce any change
var path = "/images/";
var urls = [
path + 'startile.png', path + 'startile.png',
path + 'startile.png', path + 'startile.png',
path + 'startile.png', path + 'startile.png'
];
var textureCube = THREE.ImageUtils.loadTextureCube( urls , new THREE.CubeRefractionMapping() );
textureCube.wrapS = textureCube.wrapT = THREE.RepeatWrapping;
textureCube.repeat.set( 10, 10 );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube, refractionRatio: 0.95 } );
// Skybox
var shader = THREE.ShaderLib[ "cube" ];
shader.uniforms[ "tCube" ].value = textureCube;
var material = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
side: THREE.BackSide
} ),
mesh = new THREE.Mesh( new THREE.CubeGeometry( 1200, 1200, 1200 ), material );
//mesh.overdraw = false;
// mesh.rotation.x = Math.PI * 0.1;
scene.add( mesh );
Any ideas?
Tiling is not supported for texture cubes. However, in your case, since all faces of your cube are identical, you can do something like this:
var geometry = new THREE.CubeGeometry( 1000, 1000, 1000 );
var texture = THREE.ImageUtils.loadTexture( "startile.png" );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 10, 10 );
var material = new THREE.MeshBasicMaterial( {
color: 0xffffff,
map: texture,
side: THREE.BackSide
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
three.js r.59
I have found this example with diffuse, specular and normal map:
var ambient = 0x111111, diffuse = 0xbbbbbb, specular = 0x060606, shininess = 35;
var shader = THREE.ShaderLib[ "normalmap" ];
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms[ "tNormal" ].value = THREE.ImageUtils.loadTexture( "textures/test_NRM.jpg" );
uniforms[ "uNormalScale" ].value.set( 2, 2 );
uniforms[ "tDiffuse" ].value = THREE.ImageUtils.loadTexture( "textures/test_COL.jpg" );
uniforms[ "tSpecular" ].value = THREE.ImageUtils.loadTexture( "textures/test_SPEC.jpg" );
uniforms[ "enableAO" ].value = false;
uniforms[ "enableDiffuse" ].value = true;
uniforms[ "enableSpecular" ].value = true;
uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
uniforms[ "uSpecularColor" ].value.setHex( specular );
uniforms[ "uAmbientColor" ].value.setHex( ambient );
uniforms[ "uShininess" ].value = shininess;
uniforms[ "wrapRGB" ].value.set(1, 1,1 );
var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true };
var material = new THREE.ShaderMaterial( parameters );
material.wrapAround = true;
loader = new THREE.JSONLoader( true );
document.body.appendChild( loader.statusDomElement );
loader.load( "geo/sphere.js", function( geometry ) { createScene( geometry, 100, material ) } );
renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x111111, clearAlpha: 1 } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
Now I see my textures displayed on the sphere, but only one time. I need more tiles of the texture displayed and I inserted:
tNormal.wrapS = THREE.RepeatWrapping;
tNormal.wrapT = THREE.RepeatWrapping;
tNormal.repeat.x=100;
tNormal.repeat.y=100;
But it doesn`t work, does anyone have a clue?
Best Regards
The repeat.x and repeat.y determine how many times the texture needs to be repeated on the face. In you case 100x100 times. Try setting both values to 2 and see if that works
I am looking to use a texture as an Ambient map in Three.JS - and am not sure hoe to implement this. Here is the code for my material so far:
var shader : THREE.Shader = THREE.ShaderLib[ "normalmap" ];
var uniforms : THREE.Uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms[ "enableAO" ].value = false;
uniforms[ "enableDiffuse" ].value = true;
uniforms[ "enableSpecular" ].value = true;
uniforms[ "enableReflection" ].value = true;
uniforms[ "enableDisplacement" ].value = false;
uniforms[ "tNormal" ].value = THREE.ImageUtils.loadTexture( this.earthMaterials.earthNormal );
uniforms[ "tDiffuse" ].value = THREE.ImageUtils.loadTexture( this.earthMaterials.earthMap );
uniforms[ "tSpecular" ].value = THREE.ImageUtils.loadTexture( this.earthMaterials.earthMap );
uniforms[ "uNormalScale" ].value.set( this.earthMaterials.normalScale, this.earthMaterials.normalScale );
uniforms[ "uDiffuseColor" ].value.convertGammaToLinear();
uniforms[ "uSpecularColor" ].value.convertGammaToLinear();
uniforms[ "uAmbientColor" ].value.convertGammaToLinear();
var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: false };
this.earthNormal = new THREE.ShaderMaterial( parameters );
How do I use a texture as an ambient map ?
Thank you for the help !
I am assuming that you are trying to implement ambient occlusion.
You are already using the "normal" shader, and it supports an AO map. All you have to do is enable and assign your AO map.
An alternative is to bake the AO into your diffuse map.
A third option is to treat the AO map as a lightMap. MeshPhongMaterial supports light maps, it just doesn't support displacement maps, which you do not appear to be using anyway.
three.js r.58
Below code renders the earth as BLACK globe. please note im a beginner in WebGL, also below 'Uniforms' & parameters section I found in someones code and utilized it.
If I add normal material it works, but with Shader it does not work.
Script links:
https://threejsdoc.appspot.com/doc/three.js/examples/js/ShaderExtras.js
<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/ShaderExtras.js"></script>
//Earth
var earthTexture = THREE.ImageUtils.loadTexture( "img/planets/earth_atmos_2048.jpg" );
var earthCloudsTexture = THREE.ImageUtils.loadTexture( "img/planets/earth_clouds_1024.png" );
var earthNormalTexture = THREE.ImageUtils.loadTexture( "img/planets/earth_normal_2048.jpg" );
var earthSpecularTexture = THREE.ImageUtils.loadTexture( "img/planets/earth_specular_2048.jpg" );
var earthShader = THREE.ShaderUtils.lib[ "normal" ];
var earthUniforms = THREE.UniformsUtils.clone( earthShader.uniforms );
earthUniforms[ "tNormal" ].texture = earthNormalTexture;
earthUniforms[ "uNormalScale" ].value = 0.85;
earthUniforms[ "tDiffuse" ].texture = earthNormalTexture;
earthUniforms[ "tSpecular" ].texture = earthSpecularTexture;
earthUniforms[ "enableAO" ].value = false;
earthUniforms[ "enableDiffuse" ].value = true;
earthUniforms[ "enableSpecular" ].value = true;
earthUniforms[ "uDiffuseColor" ].value.setHex( 0xffffff );
earthUniforms[ "uSpecularColor" ].value.setHex( 0x333333 );
earthUniforms[ "uAmbientColor" ].value.setHex( 0x000000 );
earthUniforms[ "uShininess" ].value = 15;
var earthParameters = {
fragmentShader: earthShader.fragmentShader,
vertexShader: earthShader.vertexShader,
uniforms: earthUniforms,
lights: true,
fog: true
};
var earth_mat = new THREE.ShaderMaterial( earthParameters );
var earth_geom = new THREE.SphereGeometry( 200, 32, 32 );
earth_geom.computeTangents();
var earth = new THREE.Mesh( earth_geom, earth_mat );
earth.position.x = 6000;
scene.add( earth );