我一直在寻找解决方案。我一直在使用这个例子https://stemkoski.github.io/Three.js/Shader-Fireball.html来尝试建立一个太阳系。
我似乎无法理解如何将当前场景灯添加到着色器材质(在本例中为customMaterial2)并获得正确的阴影?这大致是我的代码的样子。我附上了所有这些!
非常感谢有关此事的一些意见。
<html>
<head>
<title></title>
<link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/stats.min.js"></script>
<!-- VERTEX SHADER -->
<script id="vertexShader" type="x-shader/x-vertex">
uniform sampler2D noiseTexture;
uniform float noiseScale;
uniform sampler2D bumpTexture;
uniform float bumpSpeed;
uniform float bumpScale;
uniform float time;
varying vec2 vUv;
void main()
{
vUv = uv;
vec2 uvTimeShift = vUv + vec2( 1.1, 1.9 ) * time * bumpSpeed;
vec4 noiseGeneratorTimeShift = texture2D( noiseTexture, uvTimeShift );
vec2 uvNoiseTimeShift = vUv + noiseScale * vec2( noiseGeneratorTimeShift.r, noiseGeneratorTimeShift.g );
// below, using uvTimeShift seems to result in more of a "rippling" effect
// while uvNoiseTimeShift seems to result in more of a "shivering" effect
vec4 bumpData = texture2D( bumpTexture, uvTimeShift );
// move the position along the normal
// but displace the vertices at the poles by the same amount
float displacement = ( vUv.y > 0.999 || vUv.y < 0.001 ) ?
bumpScale * (0.3 + 0.02 * sin(time)) :
bumpScale * bumpData.r;
vec3 newPosition = position + normal * displacement;
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
</script>
<!-- FRAGMENT SHADER A.K.A. PIKEL SHADER -->
<script id="fragmentShader" type="x-shader/x-vertex">
uniform sampler2D baseTexture;
uniform float baseSpeed;
uniform float repeatS;
uniform float repeatT;
uniform sampler2D noiseTexture;
uniform float noiseScale;
uniform sampler2D blendTexture;
uniform float blendSpeed;
uniform float blendOffset;
uniform float time;
uniform float alpha;
varying vec2 vUv;
void main()
{
vec2 uvTimeShift = vUv + vec2( -0.7, 1.5 ) * time * baseSpeed;
vec4 noiseGeneratorTimeShift = texture2D( noiseTexture, uvTimeShift );
vec2 uvNoiseTimeShift = vUv + noiseScale * vec2( noiseGeneratorTimeShift.r, noiseGeneratorTimeShift.b );
vec4 baseColor = texture2D( baseTexture, uvNoiseTimeShift * vec2(repeatS, repeatT) );
vec2 uvTimeShift2 = vUv + vec2( 1.3, -1.7 ) * time * blendSpeed;
vec4 noiseGeneratorTimeShift2 = texture2D( noiseTexture, uvTimeShift2 );
vec2 uvNoiseTimeShift2 = vUv + noiseScale * vec2( noiseGeneratorTimeShift2.g, noiseGeneratorTimeShift2.b );
vec4 blendColor = texture2D( blendTexture, uvNoiseTimeShift2 * vec2(repeatS, repeatT) ) - blendOffset * vec4(1.0, 1.0, 1.0, 1.0);
vec4 theColor = baseColor + blendColor;
theColor.a = alpha;
gl_FragColor = theColor;
}
</script>
<script>
window.requestAnimationFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var container, stats;
var camera, scene, renderer;
var cameraControls;
var cube, materials;
var clock = new THREE.Clock();
container = document.createElement( 'div' );
container.id = 'wrapper';
document.body.appendChild( container );
init(); // INITIALIZING
animate(); // START ANIMATIONS
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 5000 );
camera.position.x = 0;
camera.position.y = 10;
camera.position.z = 50;
scene.add( new THREE.AmbientLight( 0x111111 ) );
// lens flares
var textureFlare0 = THREE.ImageUtils.loadTexture( 'img/lensflare0.png' );
var textureFlare2 = THREE.ImageUtils.loadTexture( 'img/lensflare2.png' );
var textureFlare3 = THREE.ImageUtils.loadTexture( 'img/lensflare3.png' );
/* addLight( 0.55, 0.9, 0.5, 5000, 0, -1000 );*/
addLight( 0.08, 0.8, 0.5, 0, 0, -1500 );
/* addLight( 0.995, 0.5, 0.9, 5000, 5000, -1000 );*/
function addLight( h, s, l, x, y, z ) {
var light = new THREE.PointLight( 0xffffff, 0, 4500 );
light.color.setHSL( h, s, l );
light.position.set( -700, y, -1200 );
scene.add( light );
var flareColor = new THREE.Color( 0xffffff );
flareColor.setHSL( h, s, l + 0.5 );
var lensFlare = new THREE.LensFlare( textureFlare0, 350, 0.0, THREE.AdditiveBlending, flareColor );
lensFlare.add( textureFlare2, 256, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 256, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 256, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 60, 0.6, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 0.7, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 120, 0.9, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 1.0, THREE.AdditiveBlending );
lensFlare.customUpdateCallback = lensFlareUpdateCallback;
lensFlare.position.copy( light.position );
scene.add( lensFlare );
}
spotLight = new THREE.SpotLight( 0xdfebff, 1 );
scene.add(spotLight);
sunLight = new THREE.PointLight( 0xffdea4, 1, 0 );
sunLight.position.set( 500, 200, -300 );
scene.add(sunLight);
/*********************************************** SKYBOX/SPACE */
var spaceGeometry = new THREE.SphereGeometry(2000, 32, 100);
var spaceTexture = THREE.ImageUtils.loadTexture( 'img/space.jpg' );
spaceTexture.wrapS = spaceTexture.wrapT = THREE.RepeatWrapping;
spaceTexture.repeat.set( 2, 1 );
spaceTexture.anisotropy = 5;
var spaceMesh = new THREE.MeshBasicMaterial({
map: spaceTexture,
side: THREE.BackSide
});
space = new THREE.Mesh( spaceGeometry, spaceMesh);
space.position.set( 0, 0, 0);
space.rotation.set( 0, 0, 0 );
space.scale.set( 1, 1, 1 );
scene.add( space );
/***************************************************************** SUN */
// base image texture for mesh
var lavaTexture = new THREE.ImageUtils.loadTexture( 'img/lava.jpg');
lavaTexture.wrapS = lavaTexture.wrapT = THREE.RepeatWrapping;
// multiplier for distortion speed
var baseSpeed = 0.01;
// number of times to repeat texture in each direction
var repeatS = repeatT = 10.0;
// texture used to generate "randomness", distort all other textures
var noiseTexture = new THREE.ImageUtils.loadTexture( 'img/cloud.png' );
noiseTexture.wrapS = noiseTexture.wrapT = THREE.RepeatWrapping;
// magnitude of noise effect
var noiseScale = 0.5;
// texture to additively blend with base image texture
var blendTexture = new THREE.ImageUtils.loadTexture( 'img/lava.jpg' );
blendTexture.wrapS = blendTexture.wrapT = THREE.RepeatWrapping;
// multiplier for distortion speed
var blendSpeed = 0.005;
// adjust lightness/darkness of blended texture
var blendOffset = 0.15;
// texture to determine normal displacement
var bumpTexture = noiseTexture;
bumpTexture.wrapS = bumpTexture.wrapT = THREE.RepeatWrapping;
// multiplier for distortion speed
var bumpSpeed = 0.05;
// magnitude of normal displacement
var bumpScale = 150.0;
// use "this." to create global object
this.customUniforms = {
baseTexture: { type: "t", value: lavaTexture },
baseSpeed: { type: "f", value: baseSpeed },
repeatS: { type: "f", value: repeatS },
repeatT: { type: "f", value: repeatT },
noiseTexture: { type: "t", value: noiseTexture },
noiseScale: { type: "f", value: noiseScale },
blendTexture: { type: "t", value: blendTexture },
blendSpeed: { type: "f", value: blendSpeed },
blendOffset: { type: "f", value: blendOffset },
bumpTexture: { type: "t", value: bumpTexture },
bumpSpeed: { type: "f", value: bumpSpeed },
bumpScale: { type: "f", value: bumpScale },
alpha: { type: "f", value: 1.0 },
time: { type: "f", value: 1.0 },
};
// create custom material from the shader code above
// that is within specially labeled script tags
var customMaterial = new THREE.ShaderMaterial(
{
uniforms: customUniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
});
var sunGeometry = new THREE.SphereGeometry( 400, 64, 64 );
sun = new THREE.Mesh( sunGeometry, customMaterial );
sun.position.set( 400, 200, -600 );
scene.add( sun );
/*********************************************************** EARTH */
var earthGeometry = new THREE.SphereGeometry(100, 32, 100);
var earthMesh = new THREE.MeshPhongMaterial({
map: THREE.ImageUtils.loadTexture('img/earth.jpg')
});
earth = new THREE.Mesh( earthGeometry, earthMesh);
earth.position.set( -300, 0, -300 );
earth.rotation.set( 0, 0, 0 );
earth.scale.set( 1, 1, 1 );
scene.add( earth );
/********************************************************** NEPTUNE */
var waterTexture = new THREE.ImageUtils.loadTexture( 'img/neptune2.jpg' );
var waterTexture2 = new THREE.ImageUtils.loadTexture( 'img/cloud.png' );
waterTexture.wrapS = waterTexture.wrapT = THREE.RepeatWrapping;
waterTexture2.wrapS = waterTexture2.wrapT = THREE.RepeatWrapping;
// use "this." to create global object
this.customUniforms2 = {
baseTexture: { type: "t", value: waterTexture },
baseSpeed: { type: "f", value: 0.05 },
repeatS: { type: "f", value: 3 },
repeatT: { type: "f", value: 3 },
noiseTexture: { type: "t", value: waterTexture2 },
noiseScale: { type: "f", value: 1.05 },
bumpTexture: { type: "t", value: waterTexture },
bumpSpeed: { type: "f", value: bumpSpeed },
bumpScale: { type: "f", value: 0 },
alpha: { type: "f", value: 1.0 },
time: { type: "f", value: 1.0 }
};
// create custom material from the shader code above
// that is within specially labeled script tags
var customMaterial2 = new THREE.ShaderMaterial(
{
uniforms: customUniforms2,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
});
// other material properties
customMaterial2.side = THREE.DoubleSide;
// apply the material to a surface
var neptuneGeometry = new THREE.SphereGeometry(200, 32, 100);
neptune = new THREE.Mesh( neptuneGeometry, customMaterial2 );
neptune.position.set( -1500, 0, -500 );
neptune.rotation.set( 0, 0, 0 );
neptune.scale.set( 1, 1, 1 );
scene.add( neptune );
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled = true;
stats = new Stats();
container.appendChild( stats.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function lensFlareUpdateCallback( object ) {
var f, fl = object.lensFlares.length;
var flare;
var vecX = -object.positionScreen.x ;
var vecY = -object.positionScreen.y ;
for( f = 0; f < fl; f++ ) {
flare = object.lensFlares[ f ];
flare.x = object.positionScreen.x + vecX * flare.distance;
flare.y = object.positionScreen.y + vecY * flare.distance;
flare.rotation = 1;
}
object.lensFlares[ 2 ].y += 0.025;
object.lensFlares[ 3 ].rotation = object.positionScreen.x * 0.5 + THREE.Math.degToRad( 45 );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
update();
}
function update() {
var delta = clock.getDelta(); // seconds.
customUniforms.time.value += delta;
customUniforms2.time.value += delta;
stats.update();
}
function render() {
sun.rotation.y += 0.1 / 100;
earth.rotation.y += 0.1 / 50;
neptune.rotation.y += 0.1 / 50;
renderer.render( scene, camera );
}
</script>
</body>
</html>
答案 0 :(得分:0)
如果您想创建自定义ShaderMaterial
并访问场景图中的灯光,则必须将材料lights
属性设置为true
。
例如,请参阅this three.js example。
您还必须包含代码以处理片段着色器中的灯光。
有几个three.js片段着色器示例完成此操作。例如,请参阅shaderSkin.js。