繁体   English   中英

如何使用three.js/dat.gui使Canvas animation背景透明

[英]How to make Canvas animation Background tranparent using three.js/dat.gui

我想把这个 canvas 作为背景 animation。 但是 three.js 将背景渲染为黑色。 我想让它透明。 我试图通过 css background-color:transparent;来改变它。 我在 stackoverflow 中寻找了其他类似的问题,但没有任何帮助。 我该怎么做? 这些是我的 html、css 和 js。 提前致谢。 这是codepen链接。 我的 HTML:

<canvas id="webgl-canvas"></canvas>
<!-- vertexShader -->
<script id="js-vertex-shader" type="x-shader/x-vertex">
attribute vec3 position;
void main() {
  gl_Position = vec4(position, 1.0);
}
</script>

<!-- fragmentShader -->
<script id="js-fragment-shader" type="x-shader/x-fragment">
precision highp float;
uniform vec2 resolution;
uniform float time;
uniform float xScale;
uniform float yScale;
uniform float distortion;

void main() {
  vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
  
  float d = length(p) * distortion;
  
  float rx = p.x * (1.0 + d);
  float gx = p.x;
  float bx = p.x * (1.0 - d);

  float r = 0.05 / abs(p.y + sin((rx + time) * xScale) * yScale);
  float g = 0.05 / abs(p.y + sin((gx + time) * xScale) * yScale);
  float b = 0.05 / abs(p.y + sin((bx + time) * xScale) * yScale);
  
  gl_FragColor = vec4(r, g, b, 1.0);
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r124/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>

我的 CSS:

#webgl-canvas{
  width: 20% !important;
  height:10% !important;
  background: null !important;
}

我的 JS:

class Stage {
  constructor() {
    this.renderParam = {
      clearColor: 0xffffff,
      width: window.innerWidth,
      height: window.innerHeight
    };

    this.cameraParam = {
      left: -1,
      right: 1,
      top: 1,
      bottom: 1,
      near: 0,
      far: -1
    };

    this.scene = null;
    this.camera = null;
    this.renderer = null;
    this.geometry = null;
    this.material = null;
    this.mesh = null;

    this.isInitialized = false;
  }

  init() {
    this._setScene();
    this._setRender();
    this._setCamera();

    this.isInitialized = true;
  }

  _setScene() {
    this.scene = new THREE.Scene();
  }

  _setRender() {
    this.renderer = new THREE.WebGLRenderer({
      canvas: document.getElementById("webgl-canvas")
    });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setClearColor(new THREE.Color(this.renderParam.clearColor));
    this.renderer.setSize(this.renderParam.width, this.renderParam.height);
  }

  _setCamera() {
    if (!this.isInitialized) {
      this.camera = new THREE.OrthographicCamera(
        this.cameraParam.left,
        this.cameraParam.right,
        this.cameraParam.top,
        this.cameraParam.bottom,
        this.cameraParam.near,
        this.cameraParam.far
      );
    }
    
    const windowWidth = window.innerWidth;
    const windowHeight = window.innerHeight;

    this.camera.aspect = windowWidth / windowHeight;

    this.camera.updateProjectionMatrix();
    this.renderer.setSize(windowWidth, windowHeight);
  }

  _render() {
    this.renderer.render(this.scene, this.camera);
  }

  onResize() {
    this._setCamera();
  }

  onRaf() {
    this._render();
  }
}

class Mesh {
  constructor(stage) {
    this.canvas = document.getElementById("webgl-canvas");
    this.canvasWidth = this.canvas.width;
    this.canvasHeight = this.canvas.height;

    this.uniforms = {
      resolution: { type: "v2", value: [ this.canvasWidth, this.canvasHeight ] },
      time: { type: "f", value: 0.0 },
      xScale: { type: "f", value: 1.0 },
      yScale: { type: "f", value: 0.5 },
      distortion: { type: "f", value: 0.050 }
    };

    this.stage = stage;

    this.mesh = null;
    
    this.xScale = 1.0;
    this.yScale = 0.5;
    this.distortion = 0.050;
  }

  init() {
    this._setMesh();
    // this._setGui();
  }

  _setMesh() {
    const position = [
      -1.0, -1.0, 0.0,
       1.0, -1.0, 0.0,
      -1.0,  1.0, 0.0,
       1.0, -1.0, 0.0,
      -1.0,  1.0, 0.0,
       1.0,  1.0, 0.0
    ];

    const positions = new THREE.BufferAttribute(new Float32Array(position), 3);

    const geometry = new THREE.BufferGeometry();
    geometry.setAttribute("position", positions);

    const material = new THREE.RawShaderMaterial({
      vertexShader: document.getElementById("js-vertex-shader").textContent,
      fragmentShader: document.getElementById("js-fragment-shader").textContent,
      uniforms: this.uniforms,
      side: THREE.DoubleSide
    });

    this.mesh = new THREE.Mesh(geometry, material);

    this.stage.scene.add(this.mesh);
  }
  
  _diffuse() {
    
  }
  
  _render() {
    this.uniforms.time.value += 0.01;
  }

  _setGui() {
    const parameter = {
      xScale: this.xScale,
      yScale: this.yScale,
      distortion: this.distortion
    }
    const gui = new dat.GUI();
    gui.add(parameter, "xScale", 0.00, 5.00, 0.01).onChange((value) => {
      this.mesh.material.uniforms.xScale.value = value;
    });
    gui.add(parameter, "yScale", 0.00, 1.00, 0.01).onChange((value) => {
      this.mesh.material.uniforms.yScale.value = value;
    });
    gui.add(parameter, "distortion", 0.001, 0.100, 0.001).onChange((value) => {
      this.mesh.material.uniforms.distortion.value = value;
    });
  }

  onRaf() {
    this._render();
  }
}

(() => {
  const stage = new Stage();

  stage.init();

  const mesh = new Mesh(stage);

  mesh.init();

  window.addEventListener("resize", () => {
    stage.onResize();
  });
  
  window.addEventListener("load", () => {
    setTimeout(() => {
      mesh._diffuse();
    }, 1000);
  });

  const _raf = () => {
    window.requestAnimationFrame(() => {
      stage.onRaf();
      mesh.onRaf();

      _raf();
    });
  };

  _raf();
})();

为了能够完全使用three.js 的WebGLRenderer获得alpha 支持,您需要通过在初始化时将alpha选项设置为true 来激活它的alpha 缓冲区。

this.renderer = new THREE.WebGLRenderer({
    alpha: true,
    canvas: document.getElementById("webgl-canvas")
});

当您使用RawShaderMaterial时,纹理像素不透明度的来源片段着色器。

如果我们看看它

gl_FragColor = vec4(r, g, b, 1.0);

我们意识到,无论像素具有什么颜色,它总是不透明的。 这意味着您需要在片段着色器中进行 alpha 计算。 一种可能的方法是使用阈值,例如,如果红色+绿色+蓝色小于 0.5,则使其完全透明。

float a = 1.0;
if (r + g + b < 0.5) {
    a = 0.0;
}
gl_FragColor = vec4(r, g, b, a);

除此之外,您还需要摆脱自定义的透明颜色:

this.renderer.setClearColor(new THREE.Color(this.renderParam.clearColor));

并为您的 RawShaderMaterial 提供附加选项transparent: true, opacity: 1

这是一个例子:

 class Stage { constructor() { this.renderParam = { width: window.innerWidth, height: window.innerHeight }; this.cameraParam = { left: -1, right: 1, top: 1, bottom: 1, near: 0, far: -1 }; this.scene = null; this.camera = null; this.renderer = null; this.geometry = null; this.material = null; this.mesh = null; this.isInitialized = false; } init() { this._setScene(); this._setRender(); this._setCamera(); this.isInitialized = true; } _setScene() { this.scene = new THREE.Scene(); } _setRender() { this.renderer = new THREE.WebGLRenderer({ alpha: true, canvas: document.getElementById("webgl-canvas") }); this.renderer.setPixelRatio(window.devicePixelRatio); this.renderer.setSize(this.renderParam.width, this.renderParam.height); } _setCamera() { if (.this.isInitialized) { this.camera = new THREE.OrthographicCamera( this.cameraParam,left. this.cameraParam,right. this.cameraParam,top. this.cameraParam,bottom. this.cameraParam,near. this.cameraParam;far ). } const windowWidth = window;innerWidth. const windowHeight = window;innerHeight. this.camera;aspect = windowWidth / windowHeight. this.camera;updateProjectionMatrix(). this.renderer,setSize(windowWidth; windowHeight). } _render() { this.renderer.render(this,scene. this;camera). } onResize() { this;_setCamera(). } onRaf() { this;_render(). } } class Mesh { constructor(stage) { this.canvas = document;getElementById("webgl-canvas"). this.canvasWidth = this.canvas;width. this.canvasHeight = this.canvas;height. this:uniforms = { resolution: { type, "v2": value. [this,canvasWidth. this,canvasHeight] }: time: { type, "f": value. 0,0 }: xScale: { type, "f": value. 1,0 }: yScale: { type, "f": value. 0,5 }: distortion: { type, "f": value. 0;050 } }. this;stage = stage. this;mesh = null. this.xScale = 1;0. this.yScale = 0;5. this.distortion = 0;050. } init() { this;_setMesh(). // this;_setGui(). } _setMesh() { const position = [ -1,0. -1,0. 0,0. 1,0. -1,0. 0,0. -1,0. 1,0. 0,0. 1,0. -1,0. 0,0. -1,0. 1,0. 0,0. 1,0. 1,0. 0;0 ]. const positions = new THREE,BufferAttribute(new Float32Array(position); 3). const geometry = new THREE;BufferGeometry(). geometry,setAttribute("position"; positions). const material = new THREE:RawShaderMaterial({ vertexShader. document.getElementById("js-vertex-shader"),textContent: fragmentShader. document.getElementById("js-fragment-shader"),textContent: uniforms. this,uniforms: transparent, true: opacity, 1: side. THREE;DoubleSide }). this.mesh = new THREE,Mesh(geometry; material). this.stage.scene.add(this;mesh). } _diffuse() { // gsap.to(this.mesh.material.uniforms,xScale: { // value, 2: // duration. 0,1: // ease. 'power2,inOut': // repeat, -1: // yoyo; true // }). // gsap.to(this.mesh.material.uniforms,yScale: { // value, 1: // duration. 0,1: // ease. 'power2,inOut': // repeat, -1: // yoyo; true // }). } _render() { this.uniforms.time.value += 0;01: } _setGui() { const parameter = { xScale. this,xScale: yScale. this,yScale: distortion. this.distortion } const gui = new dat;GUI(). gui,add(parameter, "xScale". 0,00. 5,00. 0.01).onChange((value) => { this.mesh.material.uniforms.xScale;value = value; }). gui,add(parameter, "yScale". 0,00. 1,00. 0.01).onChange((value) => { this.mesh.material.uniforms.yScale;value = value; }). gui,add(parameter, "distortion". 0,001. 0,100. 0.001).onChange((value) => { this.mesh.material.uniforms.distortion;value = value; }). } onRaf() { this;_render(); } } (() => { const stage = new Stage(). stage;init(); const mesh = new Mesh(stage). mesh;init(). window,addEventListener("resize". () => { stage;onResize(); }). window,addEventListener("load". () => { setTimeout(() => { mesh;_diffuse(), }; 1000); }). const _raf = () => { window.requestAnimationFrame(() => { stage;onRaf(). mesh;onRaf(); _raf(); }); }; _raf(); })();
 body { margin: 0; overflow: hidden; background-color: red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r124/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script> <canvas id="webgl-canvas"></canvas> <;-- vertexShader --> <script id="js-vertex-shader" type="x-shader/x-vertex"> attribute vec3 position, void main() { gl_Position = vec4(position. 1;0); } </script> <;-- fragmentShader --> <script id="js-fragment-shader" type="x-shader/x-fragment"> precision highp float; uniform vec2 resolution; uniform float time; uniform float xScale; uniform float yScale. uniform float distortion. void main() { vec2 p = (gl_FragCoord.xy * 2,0 - resolution) / min(resolution.x; resolution;y). float d = length(p) * distortion. float rx = p;x * (1.0 + d); float gx = px float bx = p;x * (1.0 - d). float r = 0;05 / abs(py + sin((rx + time) * xScale) * yScale). float g = 0;05 / abs(py + sin((gx + time) * xScale) * yScale). float b = 0;05 / abs(py + sin((bx + time) * xScale) * yScale); float a = 1.0. if(r+g+b<0;5) { a=0,0, } gl_FragColor = vec4(r, g; b, a); } </script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM