Ers*_*eri 1 javascript shader canvas webgl three.js
我有这个 Codepen 演示:Codepen 演示链接,我想将其转换为比本网站英雄部分的背景效果:网站链接
以下是可能使这一点更清楚的图像:
我真的不知道该怎么办!如果有人可以帮助我,甚至创造一支新笔,那就太棒了!
太感谢了。
这是 Codepen 演示的 JavaScript 代码:
/**/ /* ---- CORE ---- */
/**/ const mainColor = '#070707',
/**/ secondaryColor = '#FF7F16',
/**/ bgColor = '#ffae1e';
/**/ let windowWidth = window.innerWidth,
/**/ windowHeight = window.innerHeight;
/**/ class Webgl {
/**/ constructor(w, h) {
/**/ this.meshCount = 0;
/**/ this.meshListeners = [];
/**/ this.renderer = new THREE.WebGLRenderer({ antialias: true });
/**/ this.renderer.setPixelRatio(window.devicePixelRatio);
/**/ this.renderer.setClearColor(new THREE.Color(bgColor));
/**/ this.scene = new THREE.Scene();
// http://stackoverflow.com/questions/23450588/isometric-camera-with-three-js
this.aspect = w / h;
this.distance = 5;
this.camera = new THREE.OrthographicCamera( - this.distance * this.aspect, this.distance * this.aspect, this.distance, - this.distance, 1, 1000 );
this.camera.position.set(20, 10, 20);
this.camera.rotation.order = 'YXZ';
this.camera.rotation.y = - Math.PI / 4;
this.camera.rotation.x = Math.atan( - 1 / Math.sqrt( 2 ) );
/**/ this.dom = this.renderer.domElement;
this.controls = new THREE.OrbitControls( this.camera, this.dom );
/**/ this.update = this.update.bind(this);
/**/ this.resize = this.resize.bind(this);
/**/ this.resize(w, h); // set render size
/**/ }
/**/ add(mesh) {
/**/ this.scene.add(mesh);
/**/ if (!mesh.update) return;
/**/ this.meshListeners.push(mesh.update);
/**/ this.meshCount++;
/**/ }
/**/ update() {
/**/ let i = this.meshCount;
/**/ while (--i >= 0) {
/**/ this.meshListeners[i].apply(this, null);
/**/ }
/**/ this.renderer.render(this.scene, this.camera);
/**/ }
/**/ resize(w, h) {
/**/ this.renderer.setSize(w, h);
this.camera.left = -w / 100;
this.camera.right = w / 100;
this.camera.top = h / 100;
this.camera.bottom = -h / 100;
this.camera.updateProjectionMatrix();
/**/ }
/**/ }
/**/ const webgl = new Webgl(windowWidth, windowHeight);
/**/ document.body.appendChild(webgl.dom);
/**/
/**/
/* ---- CREATING ZONE ---- */
// PROPS / GUI
const PRECISITION = 40;
const props = {
displacement: 0.3, // 0 - 1
displacementX: 0.8, // 0 - 1
displacementY: 1, // 0 - 1
speed: 1, // -20 - 20
speedX: 1, // -20 - 20
speedY: 1, // -20 - 20
amplitude: 1, // 0 - 2
height: 2, // -2 - 2
};
const gui = new dat.GUI();
gui.close();
gui.add(props, 'displacement', 0, 1);
gui.add(props, 'displacementX', 0, 1);
gui.add(props, 'displacementY', 0, 1);
gui.add(props, 'speed', -20, 20);
gui.add(props, 'speedX', 0, 20);
gui.add(props, 'speedY', 0, 20);
gui.add(props, 'amplitude', 0, 2);
gui.add(props, 'height', -1, 4);
// OBJECTS
class Plateau extends THREE.Object3D {
constructor(size = 5, segment = 10, depth = 1) {
super();
this.size = size;
this.segment = segment;
this.depth = depth;
this.part = this.size / this.segment;
this.updateVertice = v => v;
this.material = new THREE.MeshLambertMaterial({
color: new THREE.Color(secondaryColor),
// shading: THREE.FlatShading,
side: THREE.DoubleSide,
// wireframe: true,
});
this.geometry = new THREE.PlaneGeometry(this.size, this.size, this.segment, this.segment);
let i;
for (i = 1; i < this.segment; i++) {
this.geometry.vertices[i].add(new THREE.Vector3(0, -this.part, this.depth));
this.geometry.vertices[this.geometry.vertices.length - i - 1].add(new THREE.Vector3(0, this.part, this.depth));
const line = (i - 1) * (this.segment + 1);
this.geometry.vertices[line + (this.segment + 1)].add(new THREE.Vector3(this.part, 0, this.depth));
this.geometry.vertices[line + (this.segment * 2) + 1].add(new THREE.Vector3(-this.part, 0, this.depth));
}
this.geometry.vertices[0].add(new THREE.Vector3(this.part, -this.part, this.depth));
this.geometry.vertices[this.segment].add(new THREE.Vector3(-this.part, -this.part, this.depth));
this.geometry.vertices[this.geometry.vertices.length - this.segment - 1].add(new THREE.Vector3(this.part, this.part, this.depth));
this.geometry.vertices[this.geometry.vertices.length - 1].add(new THREE.Vector3(-this.part, this.part, this.depth));
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.add(this.mesh);
this.rotation.set(Math.PI / 2, 0, 0);
this.update = this.update.bind(this);
}
update() {
this.geometry.verticesNeedUpdate = true;
let j, k;
for (j = 2; j <= this.segment; j++) {
for (k = 0; k < (this.segment - 1); k++) {
this.updateVertice(this.geometry.vertices[(j + this.segment) + ((this.segment + 1) * k)]);
}
}
this.rotation.z += 0.002;
}
updatePlateau(callback) {
this.updateVertice = callback;
}
}
// START
const plateau = new Plateau(8, PRECISITION, 0);
plateau.position.y = -2;
const simplex = new SimplexNoise();
let t = 0;
plateau.updatePlateau((vertice) => {
t += 0.00001 * props.speed;
vertice.setZ((simplex.noise2D((vertice.x * props.displacementX * props.displacement) + (t * props.speedX), (vertice.y * props.displacementY * props.displacement) + (t *props.speedY)) * props.amplitude) - props.height);1});
const ambientLight = new THREE.AmbientLight(0xaaaaaa);
const pointLight = new THREE.PointLight(0xffffff);
pointLight.position.y = props.height;
// ADDS
webgl.add(plateau);
webgl.add(ambientLight);
webgl.add(pointLight);
/* ---- CREATING ZONE END ---- */
/**/
/**/
/**/ /* ---- ON RESIZE ---- */
/**/ function onResize() {
console.log('resize')
/**/ windowWidth = window.innerWidth;
/**/ windowHeight = window.innerHeight;
/**/ webgl.resize(windowWidth, windowHeight);
/**/ }
/**/ window.addEventListener('resize', onResize);
/**/ window.addEventListener('orientationchange', onResize);
/**/ /* ---- LOOP ---- */
/**/ function loop(){
/**/ webgl.update();
/**/ requestAnimationFrame(loop);
/**/ }
/**/ loop();Run Code Online (Sandbox Code Playgroud)
所以我确实查看了提到的网站并做了一些逆向工程,记录在这里:https ://codepen.io/usefulthink/pen/eGpgjL
\n\n正如您在笔中看到的,原始版本基于未修改的 PlaneBufferGeometry 和自定义着色器来实现所有效果。
\n\n最值得注意的是:它甚至不进行任何照明计算,而只是使几何体中的槽变暗:
\n\n// from the fragment-shader\nvoid main() {\n float val = min(quarticIn(1.0 - (vPositionY ) * (1.0 - vLL)), 1.06);\n gl_FragColor = vec4( val * mix(shadowColor, blendColor, val), 1.0);\n gl_FragColor = vec4(vPositionY * 10.0, 0.0, 0.0, 1.0);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n变化的vPositionY是沿 y 轴的位移,vLL 基本上是从中心的 0 到向外的 1 的径向梯度。
如果将顶点着色器的最后一行替换为以下内容,您可以看到这两个值:
\n\ngl_FragColor = vec4(vPositionY * 10.0, 0.0, 0.0, 1.0);\nRun Code Online (Sandbox Code Playgroud)\n\n或者
\n\ngl_FragColor = vec4(vLL, 0.0, 0.0, 1.0);\nRun Code Online (Sandbox Code Playgroud)\n\n最后一个值vLL用于将变形表面与背景混合,这基本上是重新实现中唯一缺少的东西。要查看其实际效果,请vLL从片段着色器中删除 - 组件:
float val = min(quarticIn(1.0 - vPositionY), 1.06);\ngl_FragColor = vec4( val * mix(shadowColor, blendColor, val), 1.0);\nRun Code Online (Sandbox Code Playgroud)\n\n现在,对于你的主要问题 \xe2\x80\x93 你可以做什么来实现你自己的实现:我可以想到几种方法 \xe2\x80\x93 第一个只是一些 css 来实现平滑淡入背景:https://codepen.io/usefulthink/pen/LzprZj
\n\n另一种选择可能是转向ShaderMaterial使用演示中使用的那种。您可以复制着色行为并跳过顶点着色器中的位移,因为您已经使用 javascript 执行此操作(可以说它的性能较差,但也更容易推理和操作)。
| 归档时间: |
|
| 查看次数: |
871 次 |
| 最近记录: |