学习threejs,打造虹彩编织球体

three.js(一)写代码做个球 最近在看three.js,每一步练习的时候用到的代码都记录一下,方便复习。第一个是最简单的球体,代码和效果如下。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Three.js</title> 阅读详情

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师



一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用ShaderMaterial自定义着色器材质,打造虹彩编织球体,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.ShaderMaterial

THREE.ShaderMaterial使用自定义shader渲染的材质。 shader是一个用GLSL编写的小程序 ,在GPU上运行。

1.1.1 ☘️注意事项

  • ShaderMaterial 只有使用 WebGLRenderer 才可以绘制正常, 因为 vertexShader 和
    fragmentShader 属性中GLSL代码必须使用WebGL来编译并运行在GPU中。
  • 从 THREE r72开始,不再支持在ShaderMaterial中直接分配属性。 必须使用
    BufferGeometry实例,使用BufferAttribute实例来定义自定义属性。
  • 从 THREE r77开始,WebGLRenderTarget 或 WebGLCubeRenderTarget
    实例不再被用作uniforms。 必须使用它们的texture 属性。
  • 内置attributes和uniforms与代码一起传递到shaders。
    如果您不希望WebGLProgram向shader代码添加任何内容,则可以使用RawShaderMaterial而不是此类。
  • 您可以使用指令#pragma unroll_loop_start,#pragma unroll_loop_end
    以便通过shader预处理器在GLSL中展开for循环。 该指令必须放在循环的正上方。循环格式必须与定义的标准相对应。
  • 循环必须标准化normalized。
  • 循环变量必须是i。
  • 对于给定的迭代,值 UNROLLED_LOOP_INDEX 将替换为 i 的显式值,并且可以在预处理器语句中使用。
#pragma unroll_loop_start
for ( int i = 0; i < 10; i ++ ) {

	// ...

}
#pragma unroll_loop_end

代码示例

const material = new THREE.ShaderMaterial( {
	uniforms: {
		time: { value: 1.0 },
		resolution: { value: new THREE.Vector2() }
	},
	vertexShader: document.getElementById( 'vertexShader' ).textContent,
	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );

1.1.2 ☘️构造函数

ShaderMaterial( parameters : Object )
parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。

1.1.3 ☘️属性

共有属性请参见其基类Material。

.clipping : Boolean
定义此材质是否支持剪裁; 如果渲染器传递clippingPlanes uniform,则为true。默认值为false。

.defaultAttributeValues : Object
当渲染的几何体不包含这些属性但材质包含这些属性时,这些默认值将传递给shaders。这可以避免在缓冲区数据丢失时出错。

this.defaultAttributeValues = {
	'color': [ 1, 1, 1 ],
	'uv': [ 0, 0 ],
	'uv2': [ 0, 0 ]
};

.defines : Object
使用 #define 指令在GLSL代码为顶点着色器和片段着色器定义自定义常量;每个键/值对产生一行定义语句:

defines: {
	FOO: 15,
	BAR: true
}

这将在GLSL代码中产生如下定义语句:

#define FOO 15
#define BAR true

.extensions : Object
一个有如下属性的对象:

this.extensions = {
	derivatives: false, // set to use derivatives
	fragDepth: false, // set to use fragment depth values
	drawBuffers: false, // set to use draw buffers
	shaderTextureLOD: false // set to use shader texture LOD
};

.fog : Boolean
定义材质颜色是否受全局雾设置的影响; 如果将fog uniforms传递给shader,则为true。默认值为false。

.fragmentShader : String
片元着色器的GLSL代码。这是shader程序的实际代码。在上面的例子中, vertexShader 和 fragmentShader 代码是从DOM(HTML文档)中获取的; 它也可以作为一个字符串直接传递或者通过AJAX加载。

.glslVersion : String
定义自定义着色器代码的 GLSL 版本。仅与 WebGL 2 相关,以便定义是否指定 GLSL 3.0。有效值为 THREE.GLSL1 或 THREE.GLSL3。默认为空。

.index0AttributeName : String
如果设置,则调用gl.bindAttribLocation 将通用顶点索引绑定到属性变量。默认值未定义。

.isShaderMaterial : Boolean
只读标志,用于检查给定对象是否属于 ShaderMaterial 类型。

.lights : Boolean
材质是否受到光照的影响。默认值为 false。如果传递与光照相关的uniform数据到这个材质,则为true。默认是false。

.linewidth : Float
控制线框宽度。默认值为1。

由于OpenGL Core Profile与大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。

.flatShading : Boolean
定义材质是否使用平面着色进行渲染。默认值为false。

.uniforms : Object
如下形式的对象:

{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }

指定要传递给shader代码的uniforms;键为uniform的名称,值(value)是如下形式:

{ value: 1.0 }

这里 value 是uniform的值。名称必须匹配 uniform 的name,和GLSL代码中的定义一样。 注意,uniforms逐帧被刷新,所以更新uniform值将立即更新GLSL代码中的相应值。

.uniformsNeedUpdate : Boolean
可用于在 Object3D.onBeforeRender() 中更改制服时强制进行制服更新。默认为假。

.vertexColors : Boolean
定义是否使用顶点着色。默认为假。

.vertexShader : String
顶点着色器的GLSL代码。这是shader程序的实际代码。 在上面的例子中,vertexShader 和 fragmentShader 代码是从DOM(HTML文档)中获取的; 它也可以作为一个字符串直接传递或者通过AJAX加载。

.wireframe : Boolean
将几何体渲染为线框(通过GL_LINES而不是GL_TRIANGLES)。默认值为false(即渲染为平面多边形)。

.wireframeLinewidth : Float
控制线框宽度。默认值为1。

由于OpenGL Core Profile与大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。

1.1.4 ☘️方法

共有方法请参见其基类Material。

.clone () : ShaderMaterial this : ShaderMaterial
创建该材质的一个浅拷贝。需要注意的是,vertexShader和fragmentShader使用引用拷贝; attributes的定义也是如此; 这意味着,克隆的材质将共享相同的编译WebGLProgram; 但是,uniforms 是 值拷贝,这样对不同的材质我们可以有不同的uniforms变量。

二、🍀打造虹彩编织球体

1. ☘️实现思路

使用 ParametricGeometry 和 GLSL 着色器渲染折射光线的虹彩编织球体;单击或点击以触发围绕其盘旋的发光能量轨道。具体代码参考代码样例,可以直接运行。

2. ☘️代码样例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>虹彩编织球体</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: radial-gradient(ellipse at center, #1b2735 0%, #090a0f 100%);
            color: white;
            font-family: 'Inter', sans-serif;
        }
        canvas {
            display: block;
        }
        .info {
            position: absolute;
            top: 10px;
            left: 10px;
            padding: 10px;
            background: rgba(0,0,0,0.5);
            border-radius: 8px;
            font-size: 14px;
        }
    </style>
    <script type="importmap">
    {
      "imports": {
        "three": "https://cdn.jsdelivr.net/npm/three@0.165.0/build/three.module.js",
        "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.165.0/examples/jsm/"
      }
    }
    </script>
</head>
<body>
    <div class="info">Drag to rotate. Click/Tap the shape for energy orbits.</div>
</body>
<script type="module">
  import * as THREE from 'three';
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js';
  import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
  import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
  import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';

  let scene, camera, renderer, controls, composer;
  let mainObject, reflectionObject, originalMaterial, reflectionMaterial;
  let godRaysRenderTarget, godRaysMaterial, godraysPass;
  const clock = new THREE.Clock();

  let particles = [];
  let particleSystem, particleGeometry, particleMaterial;
  let particlePositions, particleColors;
  const maxParticles = 2000;
  let isEmitting = false;
  let emitStartTime = 0;
  let emitDuration = 3;
  const orbitCount = 4;
  const numNewPerOrbit = 3;
  const startY = -3.5;
  const heightRange = 7;
  const speed = heightRange / 3;
  const numTurns = 3.0;


  const vertexShader = `
        uniform float uTime;
        varying vec2 vUv;
        varying vec3 vNormal;
        varying vec3 vViewDirection;
        varying vec3 vWorldPosition;
        void main() {
            vUv = uv;
            vec3 pos = position;
            vec4 worldPosition = modelMatrix * vec4(pos, 1.0);
            vWorldPosition = worldPosition.xyz;
            vNormal = normalize(normalMatrix * normal);
            vViewDirection = normalize(cameraPosition - worldPosition.xyz);
            gl_Position = projectionMatrix * viewMatrix * worldPosition;
        }
    `;

  const fragmentShader = `
        uniform float uTime;
        uniform float uReflection;
        uniform float uIOR;

        varying vec2 vUv;
        varying vec3 vNormal;
        varying vec3 vViewDirection;
        varying vec3 vWorldPosition;

        vec3 hsv2rgb(vec3 c) {
            vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
            vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
            return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
        }

        vec3 getEnvColor(vec3 dir) {
            float h = dir.y * 0.5 + 0.5;
            vec3 color1 = hsv2rgb(vec3(0.6, 1.0, 1.0));
            vec3 color2 = hsv2rgb(vec3(0.9, 1.0, 1.0));
            vec3 color3 = hsv2rgb(vec3(0.1, 1.0, 1.0));

            vec3 finalColor = mix(color1, color2, h);
            finalColor = mix(finalColor, color3, smoothstep(0.7, 1.0, h));

            return finalColor;
        }

        void main() {
            vec3 normal = normalize(vNormal);
            vec3 viewDir = normalize(vViewDirection);

            vec3 refractDirR = refract(-viewDir, normal, 1.0 / (uIOR + 0.05));
            vec3 refractDirG = refract(-viewDir, normal, 1.0 / uIOR);
            vec3 refractDirB = refract(-viewDir, normal, 1.0 / (uIOR - 0.05));

            vec3 refractedColor;
            refractedColor.r = getEnvColor(refractDirR).r;
            refractedColor.g = getEnvColor(refractDirG).g;
            refractedColor.b = getEnvColor(refractDirB).b;

            vec3 reflectDir = reflect(-viewDir, normal);
            vec3 reflectedColor = getEnvColor(reflectDir);

            float fresnel = 0.15 + 0.85 * pow(1.0 + dot(viewDir, normal), 3.0);

            vec3 baseColor = mix(refractedColor, reflectedColor, fresnel);

            float hue = vUv.x * 3.0 + uTime * 0.3;
            vec3 iridescentColor = hsv2rgb(vec3(mod(hue, 1.0), 0.8, 1.0));

            float lineFrequency = 40.0;
            float lineSharpness = 60.0;
            float line = pow(abs(sin(vUv.y * lineFrequency)), lineSharpness);

            vec3 glow = iridescentColor * line * 2.5;

            vec3 finalColor = baseColor + glow;

            float opacity = 0.5 + fresnel * 0.5;
            opacity = max(opacity, line);

            if (uReflection > 0.5) {
                float fade = smoothstep(-5.0, -3.5, vWorldPosition.y);
                finalColor *= fade;
                opacity *= fade * 0.6;
            }

            gl_FragColor = vec4(finalColor, opacity);
        }
    `;

  const GodRaysShader = {
    uniforms: {
      tDiffuse: { value: null },
      tGodRaysSource: { value: null },
      uLightPosition: { value: new THREE.Vector2(0.5, 0.5) },
      uExposure: { value: 0.15 },
      uDecay: { value: 0.95 },
      uDensity: { value: 0.97 },
      uWeight: { value: 0.6 },
    },
    vertexShader: `
            varying vec2 vUv;
            void main() {
                vUv = uv;
                gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        `,
    fragmentShader: `
            uniform sampler2D tDiffuse;
            uniform sampler2D tGodRaysSource;
            uniform vec2 uLightPosition;
            uniform float uExposure;
            uniform float uDecay;
            uniform float uDensity;
            uniform float uWeight;
            varying vec2 vUv;
            const int NUM_SAMPLES = 100;

            void main() {
                vec2 texCoord = vUv;
                vec2 delta = uLightPosition - texCoord;
                delta *= 1.0 / float(NUM_SAMPLES) * uDensity;

                float illuminationDecay = 1.0;
                vec4 accumulatedRays = vec4(0.0);

                for (int i = 0; i < NUM_SAMPLES; i++) {
                    texCoord += delta;
                    vec4 sampleColor = texture2D(tGodRaysSource, texCoord);
                    sampleColor *= illuminationDecay;
                    accumulatedRays += sampleColor;
                    illuminationDecay *= uDecay;
                }

                accumulatedRays *= uWeight;

                vec4 originalColor = texture2D(tDiffuse, vUv);

                gl_FragColor = originalColor + (accumulatedRays * uExposure);
            }
        `
  };

  function fract(x) { return x - Math.floor(x); }
  function clamp(x, min, max) { return Math.max(min, Math.min(max, x)); }
  function mix(a, b, t) { return a * (1 - t) + b * t; }
  function hsv2rgb([h, s, v]) {
    const k = [1, 2/3, 1/3, 3];
    const p = [
      Math.abs(fract(h + k[0]) * 6 - k[3]),
      Math.abs(fract(h + k[1]) * 6 - k[3]),
      Math.abs(fract(h + k[2]) * 6 - k[3])
    ];
    return [
      v * mix(1, clamp(p[0] - 1, 0, 1), s),
      v * mix(1, clamp(p[1] - 1, 0, 1), s),
      v * mix(1, clamp(p[2] - 1, 0, 1), s)
    ];
  }


  function init() {
    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
    camera.position.set(0, 0, 18);

    controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.autoRotate = true;
    controls.autoRotateSpeed = 0.5;

    godRaysRenderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);

    godRaysMaterial = new THREE.MeshBasicMaterial({ color: 0xff00ff, transparent: true, opacity: 0.6 });

    const parametricFunction = (u, v, target) => {
      u *= Math.PI;
      v *= Math.PI * 2;

      const R = 3.0;
      const weaves = 15.0;
      const thickness = 0.3;

      let mod = Math.sin(u * weaves) * Math.cos(v * weaves) * thickness;

      let x = (R + mod) * Math.sin(u) * Math.cos(v);
      let y = (R + mod) * Math.sin(u) * Math.sin(v);
      let z = (R + mod) * Math.cos(u);

      target.set(x, y, z);
    };

    const geometry = new ParametricGeometry(parametricFunction, 256, 128);

    originalMaterial = new THREE.ShaderMaterial({
      vertexShader,
      fragmentShader,
      uniforms: {
        uTime: { value: 0 },
        uReflection: { value: 0 },
        uIOR: { value: 1.3 }
      },
      transparent: true,
      side: THREE.DoubleSide,
      blending: THREE.NormalBlending,
      depthWrite: false,
    });

    mainObject = new THREE.Mesh(geometry, originalMaterial);
    scene.add(mainObject);

    reflectionMaterial = originalMaterial.clone();
    reflectionMaterial.uniforms.uReflection.value = 1;
    reflectionObject = new THREE.Mesh(geometry, reflectionMaterial);
    reflectionObject.scale.y = -1;
    reflectionObject.position.y = -7.0;
    scene.add(reflectionObject);

    particlePositions = new Float32Array(maxParticles * 3);
    particleColors = new Float32Array(maxParticles * 3);
    particleGeometry = new THREE.BufferGeometry();
    particleGeometry.setAttribute('position', new THREE.BufferAttribute(particlePositions, 3));
    particleGeometry.setAttribute('color', new THREE.BufferAttribute(particleColors, 3));
    particleGeometry.setDrawRange(0, 0);

    particleMaterial = new THREE.PointsMaterial({
      size: 0.18,
      vertexColors: true,
      transparent: true,
      blending: THREE.AdditiveBlending,
      depthWrite: false,
    });

    particleSystem = new THREE.Points(particleGeometry, particleMaterial);
    scene.add(particleSystem);


    composer = new EffectComposer(renderer);
    composer.addPass(new RenderPass(scene, camera));

    godraysPass = new ShaderPass(GodRaysShader);
    godraysPass.renderToScreen = true;

    godraysPass.uniforms.uExposure.value = 0.12;
    godraysPass.uniforms.uWeight.value = 0.5;

    composer.addPass(godraysPass);

    window.addEventListener('resize', onWindowResize, false);
    renderer.domElement.addEventListener('pointerdown', onPointerDown);
  }

  function onPointerDown(event) {
    event.preventDefault();
    const rect = renderer.domElement.getBoundingClientRect();
    const mouse = new THREE.Vector2();
    mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
    mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, camera);

    const intersects = raycaster.intersectObject(mainObject);
    if (intersects.length > 0) {
      triggerEnergyOrbits();
    }
  }

  function triggerEnergyOrbits() {
    if (!isEmitting) {
      isEmitting = true;
      emitStartTime = clock.getElapsedTime();
      particles = [];
    }
  }

  function emitParticles(time) {
    for (let orb = 0; orb < orbitCount; orb++) {
      for (let j = 0; j < numNewPerOrbit; j++) {
        if (particles.length >= maxParticles) return;
        const p = {
          orbitIndex: orb,
          startTime: time,
          speed: speed + Math.random() * 0.5,
          phase: orb * 2 * Math.PI / orbitCount + Math.random() * 0.2,
          r: 3.8 + Math.random() * 0.2,
          h: (orb / orbitCount) + 0.6 + Math.random() * 0.1
        };
        particles.push(p);
      }
    }
  }

  function updateParticles(time) {
    let activeCount = 0;
    for (let i = 0; i < particles.length; i++) {
      const p = particles[i];
      const age = time - p.startTime;
      const progress = age * p.speed / heightRange;
      if (progress > 1) continue;

      const theta = p.phase + progress * Math.PI * 2 * numTurns;
      const y = startY + progress * heightRange;
      const x = p.r * Math.cos(theta);
      const z = p.r * Math.sin(theta);

      const index = activeCount * 3;
      particlePositions[index] = x;
      particlePositions[index + 1] = y;
      particlePositions[index + 2] = z;

      const v = 1.0 - Math.pow(progress, 3.0);
      const [r, g, b] = hsv2rgb([p.h % 1, 0.8, v]);
      particleColors[index] = r;
      particleColors[index + 1] = g;
      particleColors[index + 2] = b;

      activeCount++;
    }
    particles = particles.filter(p => (time - p.startTime) * p.speed / heightRange <= 1);

    particleGeometry.setDrawRange(0, activeCount);
    if (activeCount > 0) {
      particleGeometry.attributes.position.needsUpdate = true;
      particleGeometry.attributes.color.needsUpdate = true;
    }
  }

  function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    godRaysRenderTarget.setSize(window.innerWidth, window.innerHeight);
    composer.setSize(window.innerWidth, window.innerHeight);
  }

  function animate() {
    requestAnimationFrame(animate);

    const time = clock.getElapsedTime();

    originalMaterial.uniforms.uTime.value = time;
    reflectionMaterial.uniforms.uTime.value = time;

    reflectionObject.rotation.copy(mainObject.rotation);

    controls.update();

    if (isEmitting) {
      const emitTime = time - emitStartTime;
      if (emitTime < emitDuration) {
        emitParticles(time);
      } else {
        isEmitting = false;
      }
    }

    updateParticles(time);

    mainObject.material = godRaysMaterial;
    reflectionObject.material = godRaysMaterial;

    renderer.setRenderTarget(godRaysRenderTarget);
    renderer.clear();
    renderer.render(scene, camera);

    mainObject.material = originalMaterial;
    reflectionObject.material = reflectionMaterial;

    godraysPass.uniforms.tGodRaysSource.value = godRaysRenderTarget.texture;

    renderer.setRenderTarget(null);
    composer.render();
  }

  init();
  animate();
</script>
</html>

效果如下:
在这里插入图片描述
源码

3D场景中插入新的几何体 threejs的几何体默认位于场景世界坐标的原点(0,0,0),所以绘制多个几何体的时候,主要它们的位置设置。threejs三维坐标系老版本名称是。:约束球面的水平细分数。 阅读详情

相关推荐

Javascript中彩虹条的实现

javascript中彩虹进度条的实现,notepad++中敲的代码

使用THREE.js实现材质球,材质球,定制材质

项目需求,需要自定义材质球,方便使用封装成了类,可以使用在各种项目。

six6de6的博客 863

一文读懂:CAN总线Bus-Off的触发条件与自动恢复机制

本文详细解析CAN总线Bus-Off状态的触发条件与自动恢复机制。根据ISO 11898-1标准,当发送错误计数器(TEC)超过255时节点进入Bus-Off状态,并通过检测128次总线空闲条件实现自动恢复。文章结合实战案例,探讨硬件故障、软件配置及电磁干扰等常见触发场景,并提供快慢恢复策略与调试方法,帮助工程师快速定位并解决CAN网络故障。

rgv234567的博客 353

threeJS绘制球体

使用three.js绘制球体

You_Ta的博客 8320

HDLbits找茬实战:5个Verilog仿真Bug修复案例,新手避坑指南

本文通过HDLbits平台上的5个典型Verilog仿真Bug案例,详细解析了多路选择器位宽不匹配、模块实例化端口映射错误等常见问题,提供实用的修复方案和调试技巧,帮助Verilog新手快速掌握代码验证与仿真技能,避免常见陷阱。

weixin_42653691的博客 159

高速PCB差分对布线仿真实战案例

差分对布线是高速PCB设计的关键环节,直接影响信号完整性与EMI性能。本文结合实际项目,详解等长控制、阻抗匹配、间距优化等核心技巧,并通过仿真工具验证眼图、串扰和时序裕量,助力工程师规避常见高速pcb设计陷阱。

weixin_29092787的博客 341

threejs制作上升的小球

思路:可以把这些balls放进一个group,然后可以改变group的位置,小球的位置会跟着改变。这是案例的代码,想放进项目里是这样的效果。

m0_65915285的博客 293

微生物组数据分析实战:从OTU/ASV过滤到相对丰度转换的标准化流程

本文详细介绍了微生物组数据分析中从原始OTU/ASV表格到标准化相对丰度表格的完整预处理流程。通过基于绝对丰度和出现频率的过滤步骤有效剔除测序噪音与污染,再通过相对丰度转换解决样本间测序深度差异问题,为后续的多样性分析和差异比较奠定可靠基础。文章提供了清晰的R语言实战代码与参数设置思路。

tree的博客 1249

【Three】three.js入门教程--球体的实现

radius 球体半径,默认为1widthSegments 水平分段数 (沿着经线分段)最小值为3 默认值为32。heightSegments垂直分段数(沿着纬线分段)最小值为2 默认值为16。

baekpcyyy的博客 1439

Cadence Allegro新手避坑:从原理图到PCB,解决‘netrev.lst does not exist’的完整流程

本文详细介绍了Cadence Allegro从原理图设计到PCB导入网表的完整流程,特别针对新手常见的'netrev.lst does not exist'错误提供了系统解决方案。内容包括环境准备、原理图设计规范、网表生成与导入技巧,以及设计数据管理最佳实践,帮助工程师高效完成PCB设计任务。

weixin_42685438的博客 485

SpringBoot项目搭建

SpringBoot项目搭建

私信可回答各种问题~ 1004

ThreeJs创建球体

上一章节实现了圆柱体的绘制,这节来绘制球体,球体就是圆形旋转得到,如上文一样,先要创建出基础的组件,包括场景,相机,灯光,渲染器。用于创建球体几何形状。球体是一种在三维场景中非常常见的基本形状,可用于表示天体、球体模型等各种对象。可以方便地创建不同大小和精度的球体。在 Three.js 中,

Baker的博客 943

App 抓包难?Frida Hook 实战:绕过 SSL Pinning (证书绑定) 抓取某大厂 App 核心接口

当我们使用 Charles 抓包 HTTPS 时,本质上是实施了MITM(中间人攻击)。Charles 伪装成服务器,发给 App 一个自己的证书(伪造证书)。Charles 伪装成 App,拿着真正的证书去请求服务器。如果 App 只是简单校验“证书是否由受信任的 CA 签发”,那你把 Charles 的根证书安装到手机系统里,就能骗过它。但是,是 App 内置了服务器证书的Hash(指纹)。

BUG猿的博客 900

ThreeJs-04详解材质与纹理

MeshBasicMaterial 在 Three.js 中非常重要,因为它是创建简单3D图形的常用材质之一,而且渲染速度很快,能够让您的应用程序保持流畅的交互体验。PHONG材质是Three.js中常用的一种材质,它是一种基于Phong光照模型的材质,可以用于实现高光和阴影效果。这里做一个记录,系统性的介绍一下各种贴图的作用,在之前的材质也有各种贴图,但是标准是最齐全的能够达到漫反射也能镜反射。加载模型后,开启纹理渲染,并把它的材质变为这个材质,并且贴上纹理图。

weixin_55010563的博客 427

HANA-公司间销售ICS-IDOC系统配置-保姆级配置文档

合作伙伴编号:这个客户表示收票方(销售公司在生产公司中所对应的客户代码,卖方开票,买方收票),也就是咱们在配置消息类型输出的时候合作伙伴的类型的一个具体的客户编码,这个是站在发货工厂的角度去看的,也就是EDI 输出的 BP 合作伙伴的编号;在项目实施过程中经常会遇到关联方交易的问题,有公司间采购的业务场景,也会存在公司间销售的业务场景,本文将着重讲解公司间销售在SAP系统中的实现场景。在这个过程中,销售公司向客户开票产生应收,而生产公司向销售公司开票产生自己的应收,同时销售公司向生产公司产生应付。

我小时候很黑的博客 2380

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

THREEJS第一篇,初始化和弹跳的篮球

THREEJS作为WebGL的一个开源框架,在三维可视化领域内有着广泛的应用。这里结合自己的学习经历,分享学习过程心得,希望能和想学THREEJS的伙伴一起学习成长,更希望大牛指点。 本篇介绍THREEJS(R140)的引入,相关场景搭建,Geometry球体的创建和动画的设置。 1 引入 创建vue项目,然后使用命令npm install three安装THREE,在组件内部使用下面代码引入。 //全部的THREEJS import * as THREE from 'three'; //鼠标控制 impo

u014328243的博客 754

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

three.js从入门到精通系列教程011 - three.js创建旋转球体

【代码】three.js从入门到精通系列教程011 - three.js创建旋转球体。

深南大道 627

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Three.js - 在地图上绘制飞线(二十一)

简介 在可视化开发中飞线图应该是很常见的一种。为了灵活的使用three.js,本节我们在3D地图上绘制一个简单的飞线图。 绘制 在上一节已经绘制好了一个中国地图,我们直接在此基础上开发。 起始点添加动画 在飞线图的起始点都会有醒目的标识。这里实现一个扩散光圈效果。 起始点会有很多,我们要创建一个公用方法。 先在起始点坐标,绘制一个平面圆和一个平面圆环。在渲染函数中对平面圆环放大和透明。 // 圆环网格对象组 const circleYs = [] /** * 目标位置 * *

小小的前端 6123

探索Three.js中的薄膜干涉虹彩效果

探索Three.js中的薄膜干涉虹彩效果 项目介绍 threejs-thin-film-iridescence 是一个基于Three.js的开源项目,专注于实现薄膜干涉虹彩效果。该项目灵感来源于Belcour和Barla在2017年提出的微表面理论扩展,旨在为Three.js开发者提供一种简单而强大的方式来模拟自然界中常见的虹彩现象。无论是用于游戏开发、虚拟现实还是艺术创作,这个项目都能为你的项目...

gitblog_00286的博客 1065

Three 球(Sphere)、球坐标(Spherical)

已位于球中的点将不会受到影响。返回一个新的球坐标,新的球坐标与该球坐标具有相同的 radius、phi和theta。center - 球心的位置,默认值是一个位于(0, 0, 0)的Vector3。返回球的边界到所传入的point点的最近距离。复制所传入的球坐标的radius、 phi 和theta属性到该球坐标中。返回一个新的球,新的球与这个球具有相同的center和radius。检查球体中是否包含所传入的point点,包括球的表面。复制所传入的球的center和radius到这个球上。

前端学习杂记,记录学习中的前端知识。 1099

Three.js绘制简单的立体球形

使用Three.js 添加镜面反射、控制器

qq_65325528的博客 1475

threejs 绘制球体_Three.js 第一篇:绘制一个静态的3D球体

第一篇就画一个球体吧首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的。那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地方呢?下面我就来一一列举1.场景。场景是什么,说得简单一点,场景就是一个canvas ,我们就是要在Canvas上面实现3D效果的画面而已。场景和容器,相机是息息相关的,我们就拿拍戏来说,假如我们需要演...

weixin_28733777的博客 2105

Three.js高级应用--利用Three.js实现球体或立方体形天空盒子

通过对three.js的不断学习,我们在做三维应用场景建设过程中,除了快速的加载模型或实时构建模型以外,还有一件事情需要做,一般会在整个三维空间中模拟一块空间区域,可以是球形或立方体形状、大范围平面等。这一篇主要讲述如何利用Three.js构建这两种类型的天空盒子,并在这个天空盒子中加载三维模型。

hhue2007的专栏 1571
上一篇: mapbox高阶,使用自定义图层实现立体发光墙体效果
下一篇: mapbox高阶,加载倾斜摄影
gis分享者
gis分享者 新星创作者: 前端开发技术领域 新星创作者: 前端开发技术领域 优质创作者: 编程框架技术领域 优质创作者: 编程框架技术领域
博客等级 码龄11年 1万+粉丝 676原创
评论 78
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gis分享者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值