我有一个对象,其中随机开放的粒子和其他是固体。如何在物体内部放置假太阳并使用threejs通过开放粒子获得光线。当物体旋转X,Y光线应该通过开放的粒子(POST PROCESSING)?
My Object three.Js代码如下:
var camera, scene, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 10, 10000);
camera.position.z = 200;
scene = new THREE.Scene();
hemiLight = new THREE.HemisphereLight( 0x0000ff, 0x00ff00, 0.6 );
scene.add(hemiLight);
var geometry = new THREE.DodecahedronGeometry(80, 0);
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
specular: 0xffffff,
shininess: 1,
shading: THREE.FlatShading,
polygonOffset: true,
polygonOffsetFactor: 1,
wireframe:true
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
var geo = new THREE.EdgesGeometry( mesh.geometry ); // or WireframeGeometry
var mat = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
var wireframe = new THREE.LineSegments( geo, mat );
mesh.add( wireframe );
//outer frame end
//inner world like object start
var sphere_material = [
new THREE.MeshLambertMaterial( { color: 0xffff00, side: THREE.DoubleSide } ),
new THREE.MeshBasicMaterial( { transparent: true, opacity: 0 } )
];
var sphere_geometry = new THREE.OctahedronGeometry( 60, 3 );
// assign material to each face
for( var i = 0; i < sphere_geometry.faces.length; i++ ) {
sphere_geometry.faces[ i ].materialIndex = THREE.Math.randInt( 0, 1 );
}
sphere_geometry.sortFacesByMaterialIndex();
var sphere_mesh = new THREE.Mesh( sphere_geometry, sphere_material );
sphere_mesh.position.set(0, 0, 0)
mesh.add(sphere_mesh);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
renderer.gammaInput = true;
renderer.gammaOutput = true;
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.003;
mesh.rotation.y += 0.003;
renderer.render(scene, camera);
}
答案 0 :(得分:3)
您正在寻找volumetric lights。请查看下面的代码示例,或者最好在jsfiddle上查看它(以完全尺寸查看它,而不是通过控制台日志过度显示)。
它基于this文章。我略微调整了代码并更新了颜色以及一些值和代码。它仍然需要一些播放(例如面部数量,浅色,着色器属性等),但希望能帮到你。这一切都取决于你希望如何使它看起来像。
THREE.VolumetericLightShader = {
uniforms: {
tDiffuse: {value:null},
lightPosition: {value: new THREE.Vector2(0.5, 0.5)},
exposure: {value: 0.18},
decay: {value: 0.95},
density: {value: 0.8},
weight: {value: 0.4},
samples: {value: 50}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"varying vec2 vUv;",
"uniform sampler2D tDiffuse;",
"uniform vec2 lightPosition;",
"uniform float exposure;",
"uniform float decay;",
"uniform float density;",
"uniform float weight;",
"uniform int samples;",
"const int MAX_SAMPLES = 100;",
"void main()",
"{",
"vec2 texCoord = vUv;",
"vec2 deltaTextCoord = texCoord - lightPosition;",
"deltaTextCoord *= 1.0 / float(samples) * density;",
"vec4 color = texture2D(tDiffuse, texCoord);",
"float illuminationDecay = 1.0;",
"for(int i=0; i < MAX_SAMPLES; i++)",
"{",
"if(i == samples){",
"break;",
"}",
"texCoord -= deltaTextCoord;",
"vec4 sample = texture2D(tDiffuse, texCoord);",
"sample *= illuminationDecay * weight;",
"color += sample;",
"illuminationDecay *= decay;",
"}",
"gl_FragColor = color * exposure;",
"}"
].join("\n")
};
THREE.AdditiveBlendingShader = {
uniforms: {
tDiffuse: { value:null },
tAdd: { value:null }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform sampler2D tDiffuse;",
"uniform sampler2D tAdd;",
"varying vec2 vUv;",
"void main() {",
"vec4 color = texture2D( tDiffuse, vUv );",
"vec4 add = texture2D( tAdd, vUv );",
"gl_FragColor = color + add;",
"}"
].join("\n")
};
THREE.PassThroughShader = {
uniforms: {
tDiffuse: { value: null }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform sampler2D tDiffuse;",
"varying vec2 vUv;",
"void main() {",
"gl_FragColor = texture2D( tDiffuse, vec2( vUv.x, vUv.y ) );",
"}"
].join( "\n" )
};
(function(){
var scene, camera, renderer, composer, box, pointLight,
occlusionComposer, occlusionRenderTarget, occlusionBox, lightSphere,
volumetericLightShaderUniforms,
DEFAULT_LAYER = 0,
OCCLUSION_LAYER = 1,
renderScale = 0.5,
angle = 0,
sphere_mesh,
mesh;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
function setupScene(){
var ambientLight,
geometry,
material;
ambientLight = new THREE.AmbientLight(0x2c3e50);
scene.add(ambientLight);
pointLight = new THREE.PointLight(0xddddff);
scene.add(pointLight);
geometry = new THREE.SphereBufferGeometry( 1, 32, 32 );
material = new THREE.MeshBasicMaterial( { color: 0x99ddff } );
lightSphere = new THREE.Mesh( geometry, material );
lightSphere.layers.set( OCCLUSION_LAYER );
scene.add( lightSphere );
camera.position.z = 6;
}
function addFragmentedSphere(){
var geometry = new THREE.DodecahedronGeometry(2.9, 0);
var material = new THREE.MeshPhongMaterial({
color: 0x000000,
specular: 0xffffff,
shininess: 1,
shading: THREE.FlatShading,
polygonOffset: true,
polygonOffsetFactor: 1,
wireframe:true
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
//outer frame end
//inner world like object start
var sphere_material = [
new THREE.MeshLambertMaterial( { color: 0xffff00, side: THREE.DoubleSide } ),
new THREE.MeshBasicMaterial( { transparent: true, opacity: 0 } )
];
var sphere_geometry = new THREE.OctahedronGeometry( 2.7, 4 );
// assign material to each face
for( var i = 0; i < sphere_geometry.faces.length; i++ ) {
sphere_geometry.faces[ i ].materialIndex = THREE.Math.randInt( 0, 1 );
}
sphere_geometry.sortFacesByMaterialIndex();
sphere_mesh = new THREE.Mesh( sphere_geometry, sphere_material );
sphere_mesh.position.set(0, 0, 0)
mesh.add(sphere_mesh);
sphere_mesh.layers.set( OCCLUSION_LAYER );
}
function setupPostprocessing(){
var pass;
occlusionRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth * renderScale, window.innerHeight * renderScale );
occlusionComposer = new THREE.EffectComposer( renderer, occlusionRenderTarget);
occlusionComposer.addPass( new THREE.RenderPass( scene, camera ) );
pass = new THREE.ShaderPass( THREE.VolumetericLightShader );
pass.needsSwap = false;
occlusionComposer.addPass( pass );
volumetericLightShaderUniforms = pass.uniforms;
volumetericLightShaderUniforms.exposure.value = 0.5;
volumetericLightShaderUniforms.decay.value = 0.96;
volumetericLightShaderUniforms.density.value = 0.95;
volumetericLightShaderUniforms.weight.value = 0.59;
volumetericLightShaderUniforms.samples.value = 100;
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );
pass = new THREE.ShaderPass( THREE.AdditiveBlendingShader );
pass.uniforms.tAdd.value = occlusionRenderTarget.texture;
composer.addPass( pass );
pass.renderToScreen = true;
}
function onFrame(){
requestAnimationFrame( onFrame );
update();
render();
}
function update(){
mesh.rotation.x += 0.003;
mesh.rotation.y += 0.003;
}
function render(){
camera.layers.set(OCCLUSION_LAYER);
renderer.setClearColor(0x000000);
occlusionComposer.render();
camera.layers.set(DEFAULT_LAYER);
renderer.setClearColor(0x090611);
composer.render();
}
function addRenderTargetImage(){
var material,
mesh,
folder;
material = new THREE.ShaderMaterial( THREE.PassThroughShader );
material.uniforms.tDiffuse.value = occlusionRenderTarget.texture;
mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), material );
composer.passes[1].scene.add( mesh );
mesh.visible = false;
}
window.addEventListener( 'resize', function(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
var pixelRatio = renderer.getPixelRatio(),
newWidth = Math.floor( window.innerWidth / pixelRatio ) || 1,
newHeight = Math.floor( window.innerHeight / pixelRatio ) || 1;
composer.setSize( newWidth, newHeight );
occlusionComposer.setSize( newWidth * renderScale, newHeight * renderScale );
}, false );
setupScene();
setupPostprocessing();
addFragmentedSphere();//
addRenderTargetImage();
onFrame();
}())
&#13;
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://abberg.github.io/lib/shaders/CopyShader.js"></script>
<script src="https://abberg.github.io/lib/postprocessing/EffectComposer.js"></script>
<script src="https://abberg.github.io/lib/postprocessing/RenderPass.js"></script>
<script src="https://abberg.github.io/lib/postprocessing/ShaderPass.js"></script>
&#13;