二十面体折射(Grid Icosahedron Refraction)

2023-10-17 01:50

本文主要是介绍二十面体折射(Grid Icosahedron Refraction),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二十面体折射(Grid Icosahedron Refraction)

  • 示例
  • HTML
  • CSS
  • JS

更多有趣示例 尽在 知屋安砖社区

示例

在这里插入图片描述

HTML

<div class="relative w-screen h-screen"><div class="grid-icosahedron w-full h-full bg-black"></div>
</div>

CSS

body {display: flex;justify-content: center;align-items: center;min-height: 100vh;margin: 0;background: hsl(240, 56%, 98%);
}

JS

import * as THREE from "https://cdn.skypack.dev/three@0.124.0";
import ky from "https://cdn.skypack.dev/kyouka@1.2.2";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/loaders/GLTFLoader";
import { FBXLoader } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/loaders/FBXLoader";
import { EffectComposer } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/postprocessing/EffectComposer";
import Stats from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/libs/stats.module";
import * as dat from "https://cdn.skypack.dev/dat.gui@0.7.7";
import { RenderPass } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/postprocessing/RenderPass.js";
import { ShaderPass } from "https://cdn.skypack.dev/three@0.124.0/examples/jsm/postprocessing/ShaderPass.js";
import gsap from "https://cdn.skypack.dev/gsap@3.6.0";const calcAspect = (el: HTMLElement) => el.clientWidth / el.clientHeight;const getNormalizedMousePos = (e: MouseEvent | Touch) => {return {x: (e.clientX / window.innerWidth) * 2 - 1,y: -(e.clientY / window.innerHeight) * 2 + 1};
};const gridIcosahedronTextureUrl = `https://i.loli.net/2021/03/09/1Cglerjx3yLauOo.jpg`;const gridIcosahedronShapeVertexShader = `
// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
vec4 permute(vec4 x){return mod(((x*34.)+1.)*x,289.);}
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159-.85373472095314*r;}
vec3 fade(vec3 t){return t*t*t*(t*(t*6.-15.)+10.);}float cnoise(vec3 P){vec3 Pi0=floor(P);// Integer part for indexingvec3 Pi1=Pi0+vec3(1.);// Integer part + 1Pi0=mod(Pi0,289.);Pi1=mod(Pi1,289.);vec3 Pf0=fract(P);// Fractional part for interpolationvec3 Pf1=Pf0-vec3(1.);// Fractional part - 1.0vec4 ix=vec4(Pi0.x,Pi1.x,Pi0.x,Pi1.x);vec4 iy=vec4(Pi0.yy,Pi1.yy);vec4 iz0=Pi0.zzzz;vec4 iz1=Pi1.zzzz;vec4 ixy=permute(permute(ix)+iy);vec4 ixy0=permute(ixy+iz0);vec4 ixy1=permute(ixy+iz1);vec4 gx0=ixy0/7.;vec4 gy0=fract(floor(gx0)/7.)-.5;gx0=fract(gx0);vec4 gz0=vec4(.5)-abs(gx0)-abs(gy0);vec4 sz0=step(gz0,vec4(0.));gx0-=sz0*(step(0.,gx0)-.5);gy0-=sz0*(step(0.,gy0)-.5);vec4 gx1=ixy1/7.;vec4 gy1=fract(floor(gx1)/7.)-.5;gx1=fract(gx1);vec4 gz1=vec4(.5)-abs(gx1)-abs(gy1);vec4 sz1=step(gz1,vec4(0.));gx1-=sz1*(step(0.,gx1)-.5);gy1-=sz1*(step(0.,gy1)-.5);vec3 g000=vec3(gx0.x,gy0.x,gz0.x);vec3 g100=vec3(gx0.y,gy0.y,gz0.y);vec3 g010=vec3(gx0.z,gy0.z,gz0.z);vec3 g110=vec3(gx0.w,gy0.w,gz0.w);vec3 g001=vec3(gx1.x,gy1.x,gz1.x);vec3 g101=vec3(gx1.y,gy1.y,gz1.y);vec3 g011=vec3(gx1.z,gy1.z,gz1.z);vec3 g111=vec3(gx1.w,gy1.w,gz1.w);vec4 norm0=taylorInvSqrt(vec4(dot(g000,g000),dot(g010,g010),dot(g100,g100),dot(g110,g110)));g000*=norm0.x;g010*=norm0.y;g100*=norm0.z;g110*=norm0.w;vec4 norm1=taylorInvSqrt(vec4(dot(g001,g001),dot(g011,g011),dot(g101,g101),dot(g111,g111)));g001*=norm1.x;g011*=norm1.y;g101*=norm1.z;g111*=norm1.w;float n000=dot(g000,Pf0);float n100=dot(g100,vec3(Pf1.x,Pf0.yz));float n010=dot(g010,vec3(Pf0.x,Pf1.y,Pf0.z));float n110=dot(g110,vec3(Pf1.xy,Pf0.z));float n001=dot(g001,vec3(Pf0.xy,Pf1.z));float n101=dot(g101,vec3(Pf1.x,Pf0.y,Pf1.z));float n011=dot(g011,vec3(Pf0.x,Pf1.yz));float n111=dot(g111,Pf1);vec3 fade_xyz=fade(Pf0);vec4 n_z=mix(vec4(n000,n100,n010,n110),vec4(n001,n101,n011,n111),fade_xyz.z);vec2 n_yz=mix(n_z.xy,n_z.zw,fade_xyz.y);float n_xyz=mix(n_yz.x,n_yz.y,fade_xyz.x);return 2.2*n_xyz;
}varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vEyeVector;uniform float uNoiseDensity;// https://tympanus.net/codrops/2019/10/29/real-time-multiside-refraction-in-three-steps/
vec3 getEyeVector(){vec4 worldPosition=modelMatrix*vec4(position,1.);vec3 eyeVector=normalize(worldPosition.xyz-cameraPosition);return eyeVector;
}void main(){vec3 noise=pow(cnoise(normal),3.)*normal*uNoiseDensity;vec3 newPosition=position+noise;vec4 modelPosition=modelMatrix*vec4(newPosition,1.);vec4 viewPosition=viewMatrix*modelPosition;vec4 projectedPosition=projectionMatrix*viewPosition;gl_Position=projectedPosition;vUv=uv;vNormal=normalize(normalMatrix*normal);vEyeVector=getEyeVector();
}
`;const gridIcosahedronShapeFragmentShader = `
uniform float uTime;
uniform vec2 uMouse;
uniform vec2 uResolution;
uniform sampler2D uTexture;
uniform float uRefractionStrength;varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vEyeVector;// https://community.khronos.org/t/getting-the-normal-with-dfdx-and-dfdy/70177
vec3 computeNormal(vec3 normal){vec3 X=dFdx(normal);vec3 Y=dFdy(normal);vec3 cNormal=normalize(cross(X,Y));return cNormal;
}// http://glslsandbox.com/e#47182.0
vec2 hash22(vec2 p){p=fract(p*vec2(5.3983,5.4427));p+=dot(p.yx,p.xy+vec2(21.5351,14.3137));return fract(vec2(p.x*p.y*95.4337,p.x*p.y*97.597));
}// https://www.shadertoy.com/view/4scSW4
float fresnel(float bias,float scale,float power,vec3 I,vec3 N)
{return bias+scale*pow(1.+dot(I,N),power);
}void main(){vec3 cNormal=computeNormal(vNormal);float diffuse=dot(cNormal,vec3(1.));vec2 rand=hash22(vec2(floor(diffuse*10.)));vec2 strength=vec2(sign((rand.x-.5))+(rand.x-.5)*.6,sign((rand.y-.5))+(rand.y-.5)*.6);vec2 uv=strength*gl_FragCoord.xy/vec2(1000.);vec3 refraction=uRefractionStrength*refract(vEyeVector,cNormal,1./3.);uv+=refraction.xy;vec4 color=texture2D(uTexture,uv);float F=fresnel(0.,1.,2.,vEyeVector,cNormal);color*=(1.-F);gl_FragColor=color;
}
`;const gridIcosahedronEdgeVertexShader = `
// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
vec4 permute(vec4 x){return mod(((x*34.)+1.)*x,289.);}
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159-.85373472095314*r;}
vec3 fade(vec3 t){return t*t*t*(t*(t*6.-15.)+10.);}float cnoise(vec3 P){vec3 Pi0=floor(P);// Integer part for indexingvec3 Pi1=Pi0+vec3(1.);// Integer part + 1Pi0=mod(Pi0,289.);Pi1=mod(Pi1,289.);vec3 Pf0=fract(P);// Fractional part for interpolationvec3 Pf1=Pf0-vec3(1.);// Fractional part - 1.0vec4 ix=vec4(Pi0.x,Pi1.x,Pi0.x,Pi1.x);vec4 iy=vec4(Pi0.yy,Pi1.yy);vec4 iz0=Pi0.zzzz;vec4 iz1=Pi1.zzzz;vec4 ixy=permute(permute(ix)+iy);vec4 ixy0=permute(ixy+iz0);vec4 ixy1=permute(ixy+iz1);vec4 gx0=ixy0/7.;vec4 gy0=fract(floor(gx0)/7.)-.5;gx0=fract(gx0);vec4 gz0=vec4(.5)-abs(gx0)-abs(gy0);vec4 sz0=step(gz0,vec4(0.));gx0-=sz0*(step(0.,gx0)-.5);gy0-=sz0*(step(0.,gy0)-.5);vec4 gx1=ixy1/7.;vec4 gy1=fract(floor(gx1)/7.)-.5;gx1=fract(gx1);vec4 gz1=vec4(.5)-abs(gx1)-abs(gy1);vec4 sz1=step(gz1,vec4(0.));gx1-=sz1*(step(0.,gx1)-.5);gy1-=sz1*(step(0.,gy1)-.5);vec3 g000=vec3(gx0.x,gy0.x,gz0.x);vec3 g100=vec3(gx0.y,gy0.y,gz0.y);vec3 g010=vec3(gx0.z,gy0.z,gz0.z);vec3 g110=vec3(gx0.w,gy0.w,gz0.w);vec3 g001=vec3(gx1.x,gy1.x,gz1.x);vec3 g101=vec3(gx1.y,gy1.y,gz1.y);vec3 g011=vec3(gx1.z,gy1.z,gz1.z);vec3 g111=vec3(gx1.w,gy1.w,gz1.w);vec4 norm0=taylorInvSqrt(vec4(dot(g000,g000),dot(g010,g010),dot(g100,g100),dot(g110,g110)));g000*=norm0.x;g010*=norm0.y;g100*=norm0.z;g110*=norm0.w;vec4 norm1=taylorInvSqrt(vec4(dot(g001,g001),dot(g011,g011),dot(g101,g101),dot(g111,g111)));g001*=norm1.x;g011*=norm1.y;g101*=norm1.z;g111*=norm1.w;float n000=dot(g000,Pf0);float n100=dot(g100,vec3(Pf1.x,Pf0.yz));float n010=dot(g010,vec3(Pf0.x,Pf1.y,Pf0.z));float n110=dot(g110,vec3(Pf1.xy,Pf0.z));float n001=dot(g001,vec3(Pf0.xy,Pf1.z));float n101=dot(g101,vec3(Pf1.x,Pf0.y,Pf1.z));float n011=dot(g011,vec3(Pf0.x,Pf1.yz));float n111=dot(g111,Pf1);vec3 fade_xyz=fade(Pf0);vec4 n_z=mix(vec4(n000,n100,n010,n110),vec4(n001,n101,n011,n111),fade_xyz.z);vec2 n_yz=mix(n_z.xy,n_z.zw,fade_xyz.y);float n_xyz=mix(n_yz.x,n_yz.y,fade_xyz.x);return 2.2*n_xyz;
}varying vec2 vUv;
varying vec3 vCenter;attribute vec3 aCenter;uniform float uNoiseDensity;void main(){vec3 noise=pow(cnoise(normal),3.)*normal*uNoiseDensity;vec3 newPosition=position+noise;vec4 modelPosition=modelMatrix*vec4(newPosition,1.);vec4 viewPosition=viewMatrix*modelPosition;vec4 projectedPosition=projectionMatrix*viewPosition;gl_Position=projectedPosition;vUv=uv;vCenter=aCenter;
}
`;const gridIcosahedronEdgeFragmentShader = `
uniform float uTime;
uniform vec2 uMouse;
uniform vec2 uResolution;
uniform float uWidth;varying vec2 vUv;
varying vec3 vCenter;// https://threejs.org/examples/?q=wire#webgl_materials_wireframe
float edgeFactorTri(){vec3 d=fwidth(vCenter);vec3 a3=smoothstep(d*(uWidth-.5),d*(uWidth+.5),vCenter);return min(min(a3.x,a3.y),a3.z);
}float invert(float n){return 1.-n;
}void main(){float line=invert(edgeFactorTri());if(line<.1){discard;}vec4 color=vec4(vec3(line),1.);gl_FragColor=color;
}
`;const gridIcosahedronPostprocessingVertexShader = `
varying vec2 vUv;void main(){vec4 modelPosition=modelMatrix*vec4(position,1.);vec4 viewPosition=viewMatrix*modelPosition;vec4 projectedPosition=projectionMatrix*viewPosition;gl_Position=projectedPosition;vUv=uv;
}
`;const gridIcosahedronPostprocessingFragmentShader = `
uniform float uTime;
uniform vec2 uMouse;
uniform vec2 uResolution;
uniform sampler2D tDiffuse;
uniform float uRGBShift;varying vec2 vUv;// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
float hash(vec2 p){return fract(1e4*sin(17.*p.x+p.y*.1)*(.1+abs(sin(p.y*13.+p.x))));}vec3 blackAndWhite(vec3 color){return vec3((color.r+color.g+color.b)/5.);
}// https://github.com/spite/Wagner/blob/master/fragment-shaders/rgb-split-fs.glsl
vec4 RGBShift(sampler2D tDiffuse,vec2 uv,vec2 offset,float isBlackWhite){vec4 color1=texture2D(tDiffuse,vUv-offset);vec4 color2=texture2D(tDiffuse,vUv);vec4 color3=texture2D(tDiffuse,vUv+offset);if(isBlackWhite==1.){color1.rgb=blackAndWhite(color1.rgb);color2.rgb=blackAndWhite(color2.rgb);color3.rgb=blackAndWhite(color3.rgb);}vec4 color=vec4(color1.r,color2.g,color3.b,color1.a+color2.a+color3.a);return color;
}void main(){float noise=hash(vUv+uTime)*.1;vec4 color=RGBShift(tDiffuse,vUv,vec2(.01)*uRGBShift,1.);color.rgb+=vec3(noise);gl_FragColor=color;
}
`;class Base {debug: boolean;container: HTMLElement | null;scene!: THREE.Scene;camera!: THREE.PerspectiveCamera | THREE.OrthographicCamera;rendererParams!: Record<string, any>;perspectiveCameraParams!: Record<string, any>;orthographicCameraParams!: Record<string, any>;cameraPosition!: THREE.Vector3;lookAtPosition!: THREE.Vector3;renderer!: THREE.WebGLRenderer;controls!: OrbitControls;mousePos!: THREE.Vector2;raycaster!: THREE.Raycaster;sound!: THREE.Audio;stats!: Stats;composer!: EffectComposer;constructor(sel: string, debug = false) {this.debug = debug;this.container = document.querySelector(sel);this.perspectiveCameraParams = {fov: 75,near: 0.1,far: 100};this.orthographicCameraParams = {zoom: 2,near: -100,far: 1000};this.cameraPosition = new THREE.Vector3(0, 3, 10);this.lookAtPosition = new THREE.Vector3(0, 0, 0);this.rendererParams = {outputEncoding: THREE.LinearEncoding,config: {alpha: true,antialias: true}};this.mousePos = new THREE.Vector2(0, 0);}// 初始化init() {this.createScene();this.createPerspectiveCamera();this.createRenderer();this.createMesh({});this.createLight();this.createOrbitControls();this.addListeners();this.setLoop();}// 创建场景createScene() {const scene = new THREE.Scene();if (this.debug) {scene.add(new THREE.AxesHelper());const stats = Stats();this.container!.appendChild(stats.dom);this.stats = stats;}this.scene = scene;}// 创建透视相机createPerspectiveCamera() {const { perspectiveCameraParams, cameraPosition, lookAtPosition } = this;const { fov, near, far } = perspectiveCameraParams;const aspect = calcAspect(this.container!);const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);camera.position.copy(cameraPosition);camera.lookAt(lookAtPosition);this.camera = camera;}// 创建正交相机createOrthographicCamera() {const { orthographicCameraParams, cameraPosition, lookAtPosition } = this;const { left, right, top, bottom, near, far } = orthographicCameraParams;const camera = new THREE.OrthographicCamera(left,right,top,bottom,near,far);camera.position.copy(cameraPosition);camera.lookAt(lookAtPosition);this.camera = camera;}// 更新正交相机参数updateOrthographicCameraParams() {const { container } = this;const { zoom, near, far } = this.orthographicCameraParams;const aspect = calcAspect(container!);this.orthographicCameraParams = {left: -zoom * aspect,right: zoom * aspect,top: zoom,bottom: -zoom,near,far,zoom};}// 创建渲染createRenderer(useWebGL1 = false) {const { rendererParams } = this;const { outputEncoding, config } = rendererParams;const renderer = !useWebGL1? new THREE.WebGLRenderer(config): new THREE.WebGL1Renderer(config);renderer.setSize(this.container!.clientWidth, this.container!.clientHeight);renderer.outputEncoding = outputEncoding;this.resizeRendererToDisplaySize();this.container?.appendChild(renderer.domElement);this.renderer = renderer;this.renderer.setClearColor(0x000000, 0);}// 允许投影enableShadow() {this.renderer.shadowMap.enabled = true;}// 调整渲染器尺寸resizeRendererToDisplaySize() {const { renderer } = this;if (!renderer) {return;}const canvas = renderer.domElement;const pixelRatio = window.devicePixelRatio;const { clientWidth, clientHeight } = canvas;const width = (clientWidth * pixelRatio) | 0;const height = (clientHeight * pixelRatio) | 0;const isResizeNeeded = canvas.width !== width || canvas.height !== height;if (isResizeNeeded) {renderer.setSize(width, height, false);}return isResizeNeeded;}// 创建网格createMesh(meshObject: MeshObject,container: THREE.Scene | THREE.Mesh = this.scene) {const {geometry = new THREE.BoxGeometry(1, 1, 1),material = new THREE.MeshStandardMaterial({color: new THREE.Color("#d9dfc8")}),position = new THREE.Vector3(0, 0, 0)} = meshObject;const mesh = new THREE.Mesh(geometry, material);mesh.position.copy(position);container.add(mesh);return mesh;}// 创建光源createLight() {const dirLight = new THREE.DirectionalLight(new THREE.Color("#ffffff"),0.5);dirLight.position.set(0, 50, 0);this.scene.add(dirLight);const ambiLight = new THREE.AmbientLight(new THREE.Color("#ffffff"), 0.4);this.scene.add(ambiLight);}// 创建轨道控制createOrbitControls() {const controls = new OrbitControls(this.camera, this.renderer.domElement);const { lookAtPosition } = this;controls.target.copy(lookAtPosition);controls.update();this.controls = controls;}// 监听事件addListeners() {this.onResize();}// 监听画面缩放onResize() {window.addEventListener("resize", (e) => {if (this.camera instanceof THREE.PerspectiveCamera) {const aspect = calcAspect(this.container!);const camera = this.camera as THREE.PerspectiveCamera;camera.aspect = aspect;camera.updateProjectionMatrix();} else if (this.camera instanceof THREE.OrthographicCamera) {this.updateOrthographicCameraParams();const camera = this.camera as THREE.OrthographicCamera;const {left,right,top,bottom,near,far} = this.orthographicCameraParams;camera.left = left;camera.right = right;camera.top = top;camera.bottom = bottom;camera.near = near;camera.far = far;camera.updateProjectionMatrix();}this.renderer.setSize(this.container!.clientWidth,this.container!.clientHeight);});}// 动画update() {console.log("animation");}// 渲染setLoop() {this.renderer.setAnimationLoop(() => {this.resizeRendererToDisplaySize();this.update();if (this.controls) {this.controls.update();}if (this.stats) {this.stats.update();}if (this.composer) {this.composer.render();} else {this.renderer.render(this.scene, this.camera);}});}// 创建文本createText(text = "",config: THREE.TextGeometryParameters,material: THREE.Material = new THREE.MeshStandardMaterial({color: "#ffffff"})) {const geo = new THREE.TextGeometry(text, config);const mesh = new THREE.Mesh(geo, material);return mesh;}// 创建音效源createAudioSource() {const listener = new THREE.AudioListener();this.camera.add(listener);const sound = new THREE.Audio(listener);this.sound = sound;}// 加载音效loadAudio(url: string): Promise<AudioBuffer> {const loader = new THREE.AudioLoader();return new Promise((resolve) => {loader.load(url, (buffer) => {this.sound.setBuffer(buffer);resolve(buffer);});});}// 加载模型loadModel(url: string): Promise<THREE.Object3D> {const loader = new GLTFLoader();return new Promise((resolve, reject) => {loader.load(url,(gltf) => {const model = gltf.scene;resolve(model);},undefined,(err) => {console.log(err);reject();});});}// 加载FBX模型loadFBXModel(url: string): Promise<THREE.Object3D> {const loader = new FBXLoader();return new Promise((resolve, reject) => {loader.load(url,(obj) => {resolve(obj);},undefined,(err) => {console.log(err);reject();});});}// 加载字体loadFont(url: string): Promise<THREE.Font> {const loader = new THREE.FontLoader();return new Promise((resolve) => {loader.load(url, (font) => {resolve(font);});});}// 创建点选模型createRaycaster() {this.raycaster = new THREE.Raycaster();this.trackMousePos();}// 追踪鼠标位置trackMousePos() {window.addEventListener("mousemove", (e) => {this.setMousePos(e);});window.addEventListener("mouseout", () => {this.clearMousePos();});window.addEventListener("mouseleave", () => {this.clearMousePos();});window.addEventListener("touchstart",(e: TouchEvent) => {this.setMousePos(e.touches[0]);},{ passive: false });window.addEventListener("touchmove", (e: TouchEvent) => {this.setMousePos(e.touches[0]);});window.addEventListener("touchend", () => {this.clearMousePos();});}// 设置鼠标位置setMousePos(e: MouseEvent | Touch) {const { x, y } = getNormalizedMousePos(e);this.mousePos.x = x;this.mousePos.y = y;}// 清空鼠标位置clearMousePos() {this.mousePos.x = -100000;this.mousePos.y = -100000;}// 获取点击物getInterSects(): THREE.Intersection[] {this.raycaster.setFromCamera(this.mousePos, this.camera);const intersects = this.raycaster.intersectObjects(this.scene.children,true);return intersects;}// 选中点击物时onChooseIntersect(target: THREE.Object3D) {const intersects = this.getInterSects();const intersect = intersects[0];if (!intersect || !intersect.face) {return null;}const { object } = intersect;return target === object ? intersect : null;}
}class GridIcosahedron extends Base {clock!: THREE.Clock;gridIcosahedronShapeMaterial!: THREE.ShaderMaterial;gridIcosahedronEdgeMaterial!: THREE.ShaderMaterial;customPass!: ShaderPass;params!: any;mouseSpeed!: number;constructor(sel: string, debug: boolean) {super(sel, debug);this.clock = new THREE.Clock();this.cameraPosition = new THREE.Vector3(0, 0, 2);this.params = {uNoiseDensity: 0};this.mouseSpeed = 0;}// 初始化init() {this.createScene();this.createPerspectiveCamera();this.createRenderer();this.createGridIcosahedronShapeMaterial();this.createGridIcosahedronEdgeMaterial();this.createIcoShape();this.createIcoEdge();this.createPostprocessingEffect();this.createLight();this.trackMouseSpeed();this.createOrbitControls();this.addListeners();this.setLoop();}// 创建图形材质createGridIcosahedronShapeMaterial() {const loader = new THREE.TextureLoader();const texture = loader.load(gridIcosahedronTextureUrl);texture.wrapS = texture.wrapT = THREE.MirroredRepeatWrapping;const gridIcosahedronShapeMaterial = new THREE.ShaderMaterial({vertexShader: gridIcosahedronShapeVertexShader,fragmentShader: gridIcosahedronShapeFragmentShader,side: THREE.DoubleSide,uniforms: {uTime: {value: 0},uMouse: {value: new THREE.Vector2(0, 0)},uResolution: {value: new THREE.Vector2(window.innerWidth, window.innerHeight)},uTexture: {value: texture},uRefractionStrength: {value: 0.2},uNoiseDensity: {value: this.params.uNoiseDensity}}});this.gridIcosahedronShapeMaterial = gridIcosahedronShapeMaterial;}// 创建边框材质createGridIcosahedronEdgeMaterial() {const gridIcosahedronEdgeMaterial = new THREE.ShaderMaterial({vertexShader: gridIcosahedronEdgeVertexShader,fragmentShader: gridIcosahedronEdgeFragmentShader,side: THREE.DoubleSide,uniforms: {uTime: {value: 0},uMouse: {value: new THREE.Vector2(0, 0)},uResolution: {value: new THREE.Vector2(window.innerWidth, window.innerHeight)},uWidth: {value: 2},uNoiseDensity: {value: this.params.uNoiseDensity}}});this.gridIcosahedronEdgeMaterial = gridIcosahedronEdgeMaterial;}// 创建二十面体图形createIcoShape() {const geometry = new THREE.IcosahedronBufferGeometry(1, 1);const material = this.gridIcosahedronShapeMaterial;this.createMesh({geometry,material});}// 创建二十面体边框createIcoEdge() {const geometry = new THREE.IcosahedronBufferGeometry(1.001, 1);this.getBaryCoord(geometry);const material = this.gridIcosahedronEdgeMaterial;this.createMesh({geometry,material});}// 获取重心坐标系getBaryCoord(bufferGeometry: THREE.BufferGeometry) {// https://gist.github.com/mattdesl/e399418558b2b52b58f5edeafea3c16cconst length = bufferGeometry.attributes.position.array.length;const count = length / 3;const bary = [];for (let i = 0; i < count; i++) {bary.push(0, 0, 1, 0, 1, 0, 1, 0, 0);}const aCenter = new Float32Array(bary);bufferGeometry.setAttribute("aCenter",new THREE.BufferAttribute(aCenter, 3));}// 创建后期处理特效createPostprocessingEffect() {const composer = new EffectComposer(this.renderer);const renderPass = new RenderPass(this.scene, this.camera);composer.addPass(renderPass);const customPass = new ShaderPass({vertexShader: gridIcosahedronPostprocessingVertexShader,fragmentShader: gridIcosahedronPostprocessingFragmentShader,uniforms: {tDiffuse: {value: null},uTime: {value: 0},uRGBShift: {value: 0.3}}});customPass.renderToScreen = true;composer.addPass(customPass);this.composer = composer;this.customPass = customPass;}// 动画update() {const elapsedTime = this.clock.getElapsedTime();const mousePos = this.mousePos;const mouseSpeed = this.mouseSpeed * 5;if (this.gridIcosahedronShapeMaterial) {this.gridIcosahedronShapeMaterial.uniforms.uTime.value = elapsedTime;this.gridIcosahedronShapeMaterial.uniforms.uMouse.value = mousePos;this.scene.rotation.x = elapsedTime / 15;this.scene.rotation.y = elapsedTime / 15;gsap.to(this.gridIcosahedronShapeMaterial.uniforms.uNoiseDensity, {value: mouseSpeed,duration: 2});gsap.to(this.gridIcosahedronEdgeMaterial.uniforms.uNoiseDensity, {value: mouseSpeed,duration: 2});}if (this.customPass) {this.customPass.uniforms.uTime.value = elapsedTime;gsap.to(this.customPass.uniforms.uRGBShift, {value: mouseSpeed / 10,duration: 2});}}// 追踪鼠标速度trackMouseSpeed() {// https://stackoverflow.com/questions/6417036/track-mouse-speed-with-jslet lastMouseX = -1;let lastMouseY = -1;let mouseSpeed = 0;window.addEventListener("mousemove", (e) => {const mousex = e.pageX;const mousey = e.pageY;if (lastMouseX > -1) {mouseSpeed = Math.max(Math.abs(mousex - lastMouseX),Math.abs(mousey - lastMouseY));this.mouseSpeed = mouseSpeed / 100;}lastMouseX = mousex;lastMouseY = mousey;});document.addEventListener("mouseleave", () => {this.mouseSpeed = 0;});}
}const start = () => {const gridIcosahedron = new GridIcosahedron(".grid-icosahedron", false);gridIcosahedron.init();
};start();

这篇关于二十面体折射(Grid Icosahedron Refraction)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/222141

相关文章

LibSVM学习(六)——easy.py和grid.py的使用

我们在“LibSVM学习(一)”中,讲到libSVM有一个tools文件夹,里面包含有四个python文件,是用来对参数优选的。其中,常用到的是easy.py和grid.py两个文件。其实,网上也有相应的说明,但很不系统,下面结合本人的经验,对使用方法做个说明。        这两个文件都要用python(可以在http://www.python.org上下载到,需要安装)和绘图工具gnup

extjs 获取grid的选中行的某列的值

我的情景是这样的:一个grid(就叫gridA吧),最后一列的每行都是超链接,点击超链接时会弹出一个窗体,这个窗体也需要一个grid(gridB)展示,并且呢,gridB所需的数据需要gridA里的某列的值(把这个列叫做Param)作为参数。于是就产生了点击gridA的某行的超链接,获取该行的Param列的值这样的需求。 不知道为什么,我用var param=this.grid..getSe

Extjs Grid 根据列的值(0或者1)显示“是或否”

grid中:{header:'是否解析',dataIndex:'isExplain',align:'center',sortable: true,renderer:isResend}, 写一个函数: function isResend(data, metadata, record){ var resend; if(record.data.isExplain==0){resend="否";

extjs中grid,设置CheckboxSelectionModel的默认值

Grid(命名为BasicGrid)中定义了:this.sm = new Ext.grid.CheckboxSelectionModel();。表示一列checkBox。 情景:上面Grid所在的窗口弹出之后,选择一项(我这里是只选一项)点击确定之后关闭该窗口。当需要再次弹出该窗口时,把刚刚已经选择的那一项打上勾。下面是方法:我是写在弹出该窗口的方法中的。

AngularJS的ui-grid的列表数据实现换行

在公共css中添加如下: .ui-grid-cell-contents-break { padding: 5px; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; overflow: hidden; height: 100%; word-break: break

【ag-grid】列宽设置不生效探索

发现使用sizeColumnsToFit()会覆盖默认设置的宽度 解决方案1 给某一列的列定义设置为suppressSizeToFit设置为:true 核心代码: gridColumns: (ColDef | ColGroupDef)[] = [{checkboxSelection: true,headerCheckboxSelection: true,suppressSizeToFit:

vue3 vxe-grid 当前高亮行的背景颜色+字体颜色,要求随着主题的颜色的改变而改变。

1、先上个图: 2、点击的行的颜色与字体的颜色,并没有随时主题的颜色而改变: const gridOptions = reactive<BasicTableProps>({id: 'userTable',showHeaderOverflow: false,showOverflow: true,keepSource: true,columns: userColumns,pagerConfig

F - Rook on Grid 矩阵 侧面视角 树状数组

两种走法 先下再右 吃到的就是L[i]-1个 先右再下 就吃剩的哈哈 每个L[i]挡住的阴影部分 才是有效的吃到部分 关于阴影 🔥可以想象从矩阵右侧有光线照进来。然后被障碍物挡住的那些空格。 处理方式可以按照列扫过去。一边用树状数组维护那些有阴影的行 实现的主要部分就是怎么去维护那些阴影。 小tip:>=r[i]都当做第一列开始就有阴影 题目 #include <bits/stdc++.h>

C# wpf Grid中实现控件拖动调整大小

WPF拖动改变大小系列 第一节 Grid内控件拖动调整大小(本章) 第二节 Canvas内控件拖动调整大小 第三节 窗口拖动调整大小 第四节 附加属性实现拖动调整大小 第五章 拓展更多调整大小功能 文章目录 WPF拖动改变大小系列前言一、功能说明二、如何实现?1.继承Adorner2.使用Thumb3.实现拖动逻辑 三、完整代码四、使用示例总结 前言 在《C# wpf

深入探索:Windows Edge对CSS Grid布局Subgrid特性的支持与实践

CSS Grid布局是现代网页设计中的一项革命性特性,它为开发者提供了强大的布局工具。Subgrid作为Grid布局的一个子特性,允许子元素的网格线与父元素的网格线对齐,从而实现更灵活的布局效果。然而,不同的浏览器对这些新特性的支持程度不同。本文将深入探讨Windows Edge浏览器对CSS Grid布局中Subgrid特性的支持情况,并提供实践指导。 CSS Grid布局简介 在深入了解S