Token导航 LogoToken导航

Agent Skill · 前端设计

particles-gpu(粒子 GPU)

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

particles-gpu 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为权限未标注;许可证为 MIT,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 2,192。

总安装 2,681周安装 114GitHub Stars 8下载 939核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:particles-gpu(粒子 GPU)
来源仓库:https://github.com/bbeierle12/skill-mcp-claude
仓库路径:skills/particles-gpu
安装命令:
npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill particles-gpu
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill particles-gpu

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

particles-gpu 利用 GPU 加速粒子计算,提升前端渲染性能。适合处理复杂动画场景下的实时图形更新需求。可直接集成到 React、Vue 等现代框架项目中。使用时需确保浏览器支持 WebGL 并合理分配显存资源。

适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/particles-gpu

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill particles-…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    权限没有明确标注,第一次使用时只给一个无关紧要的任务,观察它到底读了哪些文件和网络。

常见问题

6 条

particles-gpu 怎么安装?

在终端执行 npx skills add https://github.com/bbeierle12/skill-mcp-claude --skill particles-gpu。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

particles-gpu 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

particles-gpu 需要什么权限?

权限级别没有明确标注。第一次使用时建议只给无关紧要的任务,观察它实际读写了哪些内容。

particles-gpu 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

particles-gpu 用的人多吗?

公开数据是累计安装 2,681 次,近一周安装 114 次,下载 939 次,GitHub 8 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

particles-gpu 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
particles-gpu

粒子 GPU · 本页

2,6818权限未标注MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

GPU Particles

Render massive particle counts (10k-1M+) efficiently using GPU instancing and custom shaders.

Quick Start

import { useRef, useMemo } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';

function Particles({ count = 10000 }) {
  const points = useRef<THREE.Points>(null!);

  const positions = useMemo(() => {
    const pos = new Float32Array(count * 3);
    for (let i = 0; i < count; i++) {
      pos[i * 3] = (Math.random() - 0.5) * 10;
      pos[i * 3 + 1] = (Math.random() - 0.5) * 10;
      pos[i * 3 + 2] = (Math.random() - 0.5) * 10;
    }
    return pos;
  }, [count]);

  return (
    <points ref={points}>
      <bufferGeometry>
        <bufferAttribute
          attach="attributes-position"
          count={count}
          array={positions}
          itemSize={3}
        />
      </bufferGeometry>
      <pointsMaterial size={0.05} color="#ffffff" />
    </points>
  );
}

Rendering Approaches

ApproachParticle CountComplexityUse Case
Points10k - 500kLowSimple particles, stars
Instanced Mesh1k - 100kMedium3D geometry particles
Custom Shader100k - 10MHighMaximum control

Points Geometry

Simplest approach—each particle is a screen-facing point sprite.

Basic Points

function BasicPoints({ count = 5000 }) {
  const positions = useMemo(() => {
    const pos = new Float32Array(count * 3);
    for (let i = 0; i < count; i++) {
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.acos(2 * Math.random() - 1);
      const r = Math.cbrt(Math.random()) * 5;

      pos[i * 3] = r * Math.sin(phi) * Math.cos(theta);
      pos[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta);
      pos[i * 3 + 2] = r * Math.cos(phi);
    }
    return pos;
  }, [count]);

  return (
    <points>
      <bufferGeometry>
        <bufferAttribute
          attach="attributes-position"
          count={count}
          array={positions}
          itemSize={3}
        />
      </bufferGeometry>
      <pointsMaterial
        size={0.1}
        sizeAttenuation={true}
        transparent={true}
        opacity={0.8}
        depthWrite={false}
        blending={THREE.AdditiveBlending}
      />
    </points>
  );
}

Points with Texture

function TexturedPoints({ count = 5000 }) {
  const texture = useTexture('/particle.png');

  return (
    <points>
      <bufferGeometry>
        {/* ... positions ... */}
      </bufferGeometry>
      <pointsMaterial
        size={0.5}
        map={texture}
        transparent={true}
        alphaTest={0.01}
        depthWrite={false}
        blending={THREE.AdditiveBlending}
      />
    </points>
  );
}

Custom Attributes

Add per-particle data like color, size, velocity:

function ColoredParticles({ count = 10000 }) {
  const { positions, colors, sizes } = useMemo(() => {
    const pos = new Float32Array(count * 3);
    const col = new Float32Array(count * 3);
    const siz = new Float32Array(count);

    for (let i = 0; i < count; i++) {
      // Position
      pos[i * 3] = (Math.random() - 0.5) * 10;
      pos[i * 3 + 1] = (Math.random() - 0.5) * 10;
      pos[i * 3 + 2] = (Math.random() - 0.5) * 10;

      // Color (HSL to RGB)
      const color = new THREE.Color();
      color.setHSL(Math.random(), 0.8, 0.5);
      col[i * 3] = color.r;
      col[i * 3 + 1] = color.g;
      col[i * 3 + 2] = color.b;

      // Size
      siz[i] = 0.05 + Math.random() * 0.1;
    }

    return { positions: pos, colors: col, sizes: siz };
  }, [count]);

  return (
    <points>
      <bufferGeometry>
        <bufferAttribute
          attach="attributes-position"
          count={count}
          array={positions}
          itemSize={3}
        />
        <bufferAttribute
          attach="attributes-color"
          count={count}
          array={colors}
          itemSize={3}
        />
        <bufferAttribute
          attach="attributes-size"
          count={count}
          array={sizes}
          itemSize={1}
        />
      </bufferGeometry>
      <pointsMaterial
        vertexColors
        size={0.1}
        sizeAttenuation
        transparent
        depthWrite={false}
      />
    </points>
  );
}

Custom Shader Particles

Maximum control over particle appearance and animation:

const vertexShader = `
  attribute float aSize;
  attribute vec3 aColor;
  attribute float aAlpha;

  uniform float uTime;
  uniform float uPixelRatio;

  varying vec3 vColor;
  varying float vAlpha;

  void main() {
    vColor = aColor;
    vAlpha = aAlpha;

    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);

    // Size attenuation
    gl_PointSize = aSize * uPixelRatio * (300.0 / -mvPosition.z);
    gl_Position = projectionMatrix * mvPosition;
  }
`;

const fragmentShader = `
  varying vec3 vColor;
  varying float vAlpha;

  void main() {
    // Circular particle
    float dist = length(gl_PointCoord - 0.5);
    if (dist > 0.5) discard;

    // Soft edge
    float alpha = 1.0 - smoothstep(0.4, 0.5, dist);

    gl_FragColor = vec4(vColor, alpha * vAlpha);
  }
`;

function ShaderParticles({ count = 50000 }) {
  const points = useRef<THREE.Points>(null!);

  const { positions, sizes, colors, alphas } = useMemo(() => {
    const pos = new Float32Array(count * 3);
    const siz = new Float32Array(count);
    const col = new Float32Array(count * 3);
    const alp = new Float32Array(count);

    for (let i = 0; i < count; i++) {
      pos[i * 3] = (Math.random() - 0.5) * 20;
      pos[i * 3 + 1] = (Math.random() - 0.5) * 20;
      pos[i * 3 + 2] = (Math.random() - 0.5) * 20;

      siz[i] = 10 + Math.random() * 20;

      const color = new THREE.Color();
      color.setHSL(0.6 + Math.random() * 0.2, 0.8, 0.5);
      col[i * 3] = color.r;
      col[i * 3 + 1] = color.g;
      col[i * 3 + 2] = color.b;

      alp[i] = 0.3 + Math.random() * 0.7;
    }

    return { positions: pos, sizes: siz, colors: col, alphas: alp };
  }, [count]);

  useFrame(({ clock }) => {
    points.current.material.uniforms.uTime.value = clock.elapsedTime;
  });

  return (
    <points ref={points}>
      <bufferGeometry>
        <bufferAttribute attach="attributes-position" count={count} array={positions} itemSize={3} />
        <bufferAttribute attach="attributes-aSize" count={count} array={sizes} itemSize={1} />
        <bufferAttribute attach="attributes-aColor" count={count} array={colors} itemSize={3} />
        <bufferAttribute attach="attributes-aAlpha" count={count} array={alphas} itemSize={1} />
      </bufferGeometry>
      <shaderMaterial
        vertexShader={vertexShader}
        fragmentShader={fragmentShader}
        uniforms={{
          uTime: { value: 0 },
          uPixelRatio: { value: Math.min(window.devicePixelRatio, 2) }
        }}
        transparent
        depthWrite={false}
        blending={THREE.AdditiveBlending}
      />
    </points>
  );
}

Animated Particles

Position Animation in Shader

// Vertex shader with animation
attribute vec3 aVelocity;
attribute float aPhase;

uniform float uTime;

void main() {
  vec3 pos = position;

  // Simple oscillation
  pos.y += sin(uTime * 2.0 + aPhase) * 0.5;

  // Velocity-based movement
  pos += aVelocity * uTime;

  // Wrap around bounds
  pos = mod(pos + 10.0, 20.0) - 10.0;

  vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
  gl_PointSize = 10.0 * (300.0 / -mvPosition.z);
  gl_Position = projectionMatrix * mvPosition;
}

CPU Animation (for dynamic systems)

function AnimatedParticles({ count = 10000 }) {
  const points = useRef<THREE.Points>(null!);

  const velocities = useMemo(() => {
    const vel = new Float32Array(count * 3);
    for (let i = 0; i < count; i++) {
      vel[i * 3] = (Math.random() - 0.5) * 0.02;
      vel[i * 3 + 1] = (Math.random() - 0.5) * 0.02;
      vel[i * 3 + 2] = (Math.random() - 0.5) * 0.02;
    }
    return vel;
  }, [count]);

  useFrame(() => {
    const positions = points.current.geometry.attributes.position.array as Float32Array;

    for (let i = 0; i < count; i++) {
      positions[i * 3] += velocities[i * 3];
      positions[i * 3 + 1] += velocities[i * 3 + 1];
      positions[i * 3 + 2] += velocities[i * 3 + 2];

      // Wrap around
      for (let j = 0; j < 3; j++) {
        if (positions[i * 3 + j] > 5) positions[i * 3 + j] = -5;
        if (positions[i * 3 + j] < -5) positions[i * 3 + j] = 5;
      }
    }

    points.current.geometry.attributes.position.needsUpdate = true;
  });

  // ... geometry setup
}

Instanced Mesh Particles

For 3D geometry particles (not just points):

function InstancedParticles({ count = 1000 }) {
  const mesh = useRef<THREE.InstancedMesh>(null!);
  const dummy = useMemo(() => new THREE.Object3D(), []);

  useEffect(() => {
    for (let i = 0; i < count; i++) {
      dummy.position.set(
        (Math.random() - 0.5) * 10,
        (Math.random() - 0.5) * 10,
        (Math.random() - 0.5) * 10
      );
      dummy.rotation.set(
        Math.random() * Math.PI,
        Math.random() * Math.PI,
        0
      );
      dummy.scale.setScalar(0.05 + Math.random() * 0.1);
      dummy.updateMatrix();
      mesh.current.setMatrixAt(i, dummy.matrix);
    }
    mesh.current.instanceMatrix.needsUpdate = true;
  }, [count, dummy]);

  useFrame(({ clock }) => {
    for (let i = 0; i < count; i++) {
      mesh.current.getMatrixAt(i, dummy.matrix);
      dummy.matrix.decompose(dummy.position, dummy.quaternion, dummy.scale);

      dummy.rotation.x += 0.01;
      dummy.rotation.y += 0.01;

      dummy.updateMatrix();
      mesh.current.setMatrixAt(i, dummy.matrix);
    }
    mesh.current.instanceMatrix.needsUpdate = true;
  });

  return (
    <instancedMesh ref={mesh} args={[undefined, undefined, count]}>
      <icosahedronGeometry args={[1, 0]} />
      <meshStandardMaterial color="#ff6b6b" />
    </instancedMesh>
  );
}

Buffer Geometry Patterns

Sphere Distribution

function spherePositions(count: number, radius: number) {
  const positions = new Float32Array(count * 3);

  for (let i = 0; i < count; i++) {
    const theta = Math.random() * Math.PI * 2;
    const phi = Math.acos(2 * Math.random() - 1);
    const r = Math.cbrt(Math.random()) * radius;  // Cube root for uniform volume

    positions[i * 3] = r * Math.sin(phi) * Math.cos(theta);
    positions[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta);
    positions[i * 3 + 2] = r * Math.cos(phi);
  }

  return positions;
}

Galaxy Spiral

function galaxyPositions(count: number, arms: number, spin: number) {
  const positions = new Float32Array(count * 3);

  for (let i = 0; i < count; i++) {
    const armIndex = i % arms;
    const armAngle = (armIndex / arms) * Math.PI * 2;

    const radius = Math.random() * 5;
    const spinAngle = radius * spin;
    const angle = armAngle + spinAngle;

    // Add randomness
    const randomX = (Math.random() - 0.5) * 0.5 * radius;
    const randomY = (Math.random() - 0.5) * 0.2;
    const randomZ = (Math.random() - 0.5) * 0.5 * radius;

    positions[i * 3] = Math.cos(angle) * radius + randomX;
    positions[i * 3 + 1] = randomY;
    positions[i * 3 + 2] = Math.sin(angle) * radius + randomZ;
  }

  return positions;
}

Grid Distribution

function gridPositions(countPerAxis: number, spacing: number) {
  const count = countPerAxis ** 3;
  const positions = new Float32Array(count * 3);
  const offset = (countPerAxis - 1) * spacing * 0.5;

  let index = 0;
  for (let x = 0; x < countPerAxis; x++) {
    for (let y = 0; y < countPerAxis; y++) {
      for (let z = 0; z < countPerAxis; z++) {
        positions[index * 3] = x * spacing - offset;
        positions[index * 3 + 1] = y * spacing - offset;
        positions[index * 3 + 2] = z * spacing - offset;
        index++;
      }
    }
  }

  return positions;
}

Performance Tips

TechniqueImpact
Use Points over InstancedMesh5-10x faster for simple particles
GPU animation (shader) vs CPU10-100x faster at scale
Disable depthWriteFaster blending
Use Float32ArrayRequired for buffers
Frustum culling (default on)Skip off-screen

Optimal Settings

<pointsMaterial
  transparent
  depthWrite={false}           // Faster blending
  blending={THREE.AdditiveBlending}  // Good for glowing particles
  sizeAttenuation              // Perspective-correct size
/>

File Structure

particles-gpu/
├── SKILL.md
├── references/
│   ├── buffer-patterns.md     # Distribution patterns
│   └── shader-examples.md     # Complete shader examples
└── scripts/
    ├── particles/
    │   ├── basic-points.tsx   # Simple points setup
    │   ├── shader-points.tsx  # Custom shader particles
    │   └── instanced.tsx      # Instanced mesh particles
    └── distributions/
        ├── sphere.ts          # Sphere distribution
        ├── galaxy.ts          # Galaxy spiral
        └── grid.ts            # Grid distribution

Reference

  • references/buffer-patterns.md — Position distribution patterns
  • references/shader-examples.md — Complete particle shaders

平台分布

Claude Code

28.68%
按下载量换算269

Antigravity

22.77%
按下载量换算214

OpenCode

19.89%
按下载量换算187

Codex

13.39%
按下载量换算126

Gemini CLI

7.68%
按下载量换算72

windsurf

4.02%
按下载量换算38

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

权限未标注

当前来源未能明确判断权限范围,默认进入异常复核队列。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills