<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=no,minimum-scale=1.0,maximum-scale=1.0">
<style>
body{
background-color: #000000;
margin: 0px;
overflow: hidden;
}
a{
color: #0078ff;
}
</style>
</head>
<body onload="draw();">
</body>
<script src="../build/three.js"></script>
<script src="../node_modules/three/examples/js/renderers/Projector.js"></script>
<script src="../node_modules/three/examples/js/renderers/CanvasRenderer.js"></script>
<script src="../node_modules/three/examples/js/libs/stats.min.js"></script>
<script src="../node_modules/three/examples/js/libs/tween.min.js"></script>
<script src="../THREE.MeshLine/demo/js/dat.gui.min.js"></script>
<script src="../node_modules/three/examples/js/controls/OrbitControls.js"></script>
<script type="text/javascript" src="../build/three.js"></script><script id="vertexShader" type="x-shader/x-vertex">
precision mediump float;
precision mediump int;
attribute vec4 color;
uniform float blend;
uniform sampler2D gradient;
uniform sampler2D blendPattern;
varying vec2 vUv;
varying float vFade;
varying float dissolve;
void main() {
vUv = uv;
dissolve = texture2D(blendPattern, vUv).r * 0.1;
vec4 localPosition = vec4( position*(1.+(dissolve*5.)), 1);
vFade = clamp((localPosition.y + 3.0) / 6.0, 0.0, 1.0);
gl_Position = projectionMatrix * modelViewMatrix * localPosition;
}
</script>
<script id="fragmentShader" type="x-shader/x-vertex">
precision mediump float;
precision mediump int;
uniform float time;
uniform float blend;
uniform sampler2D gradient;
uniform sampler2D blendPattern;
varying float vFade;
varying vec2 vUv;
varying float dissolve;
void main() {
float spread = 0.2;
float fadeAmount = smoothstep(
max(0., vFade - spread),
min(1., vFade + spread),
blend + dissolve*1.2
);
gl_FragColor = texture2D(gradient, vec2(vUv.x, fadeAmount));
}
</script>
<script>
var fireX = 0.5;
var fireY = 0.5;
var fireZ = 0.5;
const renderer = new THREE.WebGLRenderer({
antialias: true
});
document.body.appendChild(renderer.domElement);
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight,
0.1, 2000);
camera.position.set(0, 0, 10);
let rig = new THREE.Group();
rig.add(camera);
scene.add(rig);
var texture = new THREE.TextureLoader().load(
"/example/textures/Rough.jpg",
function() {
console.log("loaded");
},
undefined,
function(e) {
console.log("error", e);
}
);
texture.crossOrigin = ""; //"anonymous";
let plane = new THREE.PlaneGeometry(100, 100, 100, 100)
let planeMaterial = new THREE.MeshStandardMaterial({
color: 0x999999,
roughness: 0.8,
displacementMap: texture,
displacementScale: 2,
displacementBias: -1.4,
map: texture,
});
let groundMesh = new THREE.Mesh(plane, planeMaterial);
groundMesh.rotateX(-90 * THREE.Math.DEG2RAD);
groundMesh.position.y = -2;
scene.add(groundMesh);
var stats;
stats = new Stats();
document.body.appendChild(stats.dom);
class fire {
constructor(density = 30, height = 8, r = 0.2, resolution = 64) {
this.object = new THREE.Group();
this.fireballs = [];
this.height = height;
this.radius = r;
//加载纹理
var texture = new THREE.TextureLoader().load(
"/example/textures/Tendrils.png",
function() {
console.log("loaded");
},
undefined,
function(e) {
console.log("error", e);
}
);
texture.crossOrigin = ""; //"anonymous";
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
var fireGradient = new THREE.TextureLoader().load(
"/example/textures/Fire2.png",
function() {
console.log("loaded");
},
undefined,
function(e) {
console.log("error", e);
}
);
texture.crossOrigin = ""; //"anonymous";
//设置属性,调用着色器
this.fireMaterial = new THREE.ShaderMaterial({
uniforms: {
time: {
value: 1.0
},
blend: {
value: 1.0
},
gradient: {
type: "t",
value: fireGradient
},
blendPattern: {
type: "t",
value: texture
},
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent,
transparent: true,
side: THREE.DoubleSide,
//blending:THREE.AdditiveBlending
});
this.light = new THREE.PointLight(0xFF5500, 1, 100)
this.light.position.set(0, 0.4, 0);
this.lightIntensity = Math.random() * 5;
this.object.add(this.light);
//this.fireMaterial = new THREE.MeshStandardMaterial(0x661100);
for (var i = 0; i < density; i++) {
let geometry = new THREE.SphereGeometry(1, resolution, resolution);
let mat = this.fireMaterial.clone();
mat.uniforms.blendPattern.value = texture;
mat.uniforms.gradient.value = fireGradient;
mat.needsUpdate = true;
let sphere = new THREE.Mesh(geometry, mat);
sphere.position.y = Math.random() * height;
sphere.position.x = (0.5 - Math.random()) * this.radius;
sphere.position.z = (0.5 - Math.random()) * this.radius;
sphere.rotateX(Math.random() * 1);
sphere.rotateZ(Math.PI + (0.5 - Math.random()));
sphere.rotateY(Math.random() * 3);
sphere.dirX = ((0.5 - Math.random()) * 0.02);
sphere.dirY = 0.02;
sphere.dirZ = ((0.5 - Math.random()) * 0.02);
this.fireballs.push(sphere);
}
this.object.add(...this.fireballs);
}
update() {
this.fireballs.forEach(ball => {
ball.position.y += ball.dirY + Math.sin(ball.position.y * 0.002);
ball.position.x += Math.sin(ball.position.y * 0.5) * ball.dirX;
ball.position.z += Math.cos(ball.position.y * 0.25) * ball.dirZ;
if (ball.position.y > this.height) {
ball.position.y = -0.01
ball.position.x = (0.5 - Math.random()) * this.radius;
ball.position.z = (0.5 - Math.random()) * this.radius;
}
let p = ball.position.y / this.height;
// ball.rotateZ((1.2-p)*0.01);
ball.rotateY((1.2 - p) * 0.01)
ball.scale.set(0.4 + p, 0.4 + p, 0.4 + p);
///ball.opacity = p;
ball.material.uniforms.blend.value = p;
//ball.material.needsUpdate = true;
})
this.light.intensity += (this.lightIntensity - this.light.intensity) * 0.02;
if (Math.random() > 0.8) {
this.lightIntensity = Math.random() * 5;
}
}
env(val, envelope = [0., 0., 0.1, 1., 1., 0.]) {
function lerp(v0, v1, t) {
return v0 * (1 - t) + v1 * t
}
}
}
let f = new fire();
f.object.position.y = -2.4;
f.object.scale.set(fireX,fireY,fireZ);
scene.add(f.object)
// let cubeGeometry = new THREE.CubeGeometry(2, 2)
// let cubeMaterial = new THREE.MeshStandardMaterial();
// let cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial);
// scene.add(cubeMesh)
//
let light = new THREE.PointLight(0xffffff, 1, 100)
light.position.set(10, 10, 20);
scene.add(light);
//
function resize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
}
function draw() {
requestAnimationFrame(draw)
stats.update();
f.update();
renderer.render(scene, camera);
}
function drawFire2() {
resize();
draw();
}
drawFire2();
</script>
</body>
</html>
THREE.JS真实火焰着色器实现
最新推荐文章于 2024-09-20 15:57:00 发布