简体   繁体   English

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

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

I want to make this canvas as a background animation.我想把这个 canvas 作为背景 animation。 But the three.js render the background to black.但是 three.js 将背景渲染为黑色。 I want to make it transparent.我想让它透明。 I tried to change it by css background-color:transparent;我试图通过 css background-color:transparent;来改变它。 I looked for other similar issues in stackoverflow but nothing helped.我在 stackoverflow 中寻找了其他类似的问题,但没有任何帮助。 How can I do it?我该怎么做? These are my html,css and js.这些是我的 html、css 和 js。 Thanks in advance.提前致谢。 Here is the codepen link.这是codepen链接。 My HTML:我的 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>

My CSS:我的 CSS:

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

My JS:我的 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();
})();

To be able to get alpha support with three.js's WebGLRenderer at all you need to activate it's alpha buffer by setting the alpha option to true upon initialization.为了能够完全使用three.js 的WebGLRenderer获得alpha 支持,您需要通过在初始化时将alpha选项设置为true 来激活它的alpha 缓冲区。

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

As your using a RawShaderMaterial , the source of you texture's pixel opacity is the fragment shader.当您使用RawShaderMaterial时,纹理像素不透明度的来源片段着色器。

If we take a look at it如果我们看看它

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

we realize that whatever color a pixel will have, it's always opaque.我们意识到,无论像素具有什么颜色,它总是不透明的。 That means you need to do your alpha calculations inside the fragment shader.这意味着您需要在片段着色器中进行 alpha 计算。 One possible way would be using a treshold eg if red+green+blue is smaller than 0.5 make it completely transparent.一种可能的方法是使用阈值,例如,如果红色+绿色+蓝色小于 0.5,则使其完全透明。

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

Apart from that you also need to get rid of your custom clear color:除此之外,您还需要摆脱自定义的透明颜色:

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

and give your RawShaderMaterial the additional options transparent: true, opacity: 1并为您的 RawShaderMaterial 提供附加选项transparent: true, opacity: 1

Here's an example:这是一个例子:

 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