galacean / engine

A typescript interactive engine, support 2D, 3D, animation, physics, built on WebGL and glTF.
https://galacean.antgroup.com/
MIT License
4.05k stars 289 forks source link

The particle emission speed can be influenced by the type of shadow. #2060

Open jtabibito opened 3 months ago

jtabibito commented 3 months ago

Describe the bug The particle emission speed can be influenced by the type of shadow.

Smartphone (please complete the following information):

Additional context `

import {
  WebGLEngine,
  Camera,
  DirectLight,
  Entity,
  Material,
  MeshRenderer,
  PrimitiveMesh,
  Vector3,
  BlinnPhongMaterial,
  Texture2D,
  ParticleRenderer,
  ParticleMaterial,
  AssetType,
  BlendMode,
  Color,
  ParticleCurveMode,
  ParticleGradientMode,
  Scene,
  Burst,
  ParticleCompositeCurve,
  Vector2,
  BoxShape,
  Vector4,
  ShadowCascadesMode,
  ShadowType,
} from '@galacean/engine';

function createFog(engine: WebGLEngine, scene: Scene, name: string, tex: Texture2D): ParticleRenderer {
  const particleEntity = new Entity(engine, name);
  scene.addRootEntity(particleEntity);

  const renderer = particleEntity.addComponent(ParticleRenderer);

  const material = new ParticleMaterial(engine);
  material.baseTexture = tex;
  material.blendMode = BlendMode.Additive;
  material.baseColor = new Color(0.9, 0.9, 0.9, 0.35);

  renderer.setMaterial(material);

  const generator = renderer.generator;
  const { main, emission, rotationOverLifetime, textureSheetAnimation } = generator;

  main.maxParticles = params.intensity;

  const { startLifetime, startSpeed, startSize, startColor } = main;
  startLifetime.mode = ParticleCurveMode.Constant;
  startLifetime.constant = 1;
  startSpeed.mode = ParticleCurveMode.Constant;
  startSpeed.constant = 0;
  startSize.mode = ParticleCurveMode.Constant;
  startSize.constant = 1.2;
  startColor.mode = ParticleGradientMode.TwoGradients;
  startColor.constantMin = new Color(0.8, 0.8, 0.8, 0.1);
  startColor.constantMax = new Color(0.9, 0.9, 0.9, 0.35);

  emission.enabled = true;
  emission.rateOverTime = new ParticleCompositeCurve(100);

  const boxShape = new BoxShape();
  boxShape.size = new Vector3(params.rangeX, params.rangeY, params.rangeZ);
  emission.shape = boxShape;

  textureSheetAnimation.enabled = true;
  textureSheetAnimation.tiling = new Vector2(8, 8);

  return renderer;
}

WebGLEngine.create({ canvas: 'canvas' }).then((engine) => {
  engine.canvas.resizeByClientSize();
  engine.run();

  const scene = engine.sceneManager.activeScene;

  scene.castShadows = true;
  scene.shadowCascades = ShadowCascadesMode.FourCascades;

  const camEntity = scene.createRootEntity('Camera');
  const camera = camEntity.addComponent(Camera);
  camEntity.transform.setPosition(0, 0, 5);
  camEntity.transform.lookAt(new Vector3(0, 0, 0));
  camera.viewport = new Vector4(0, 0, 0.5, 1);

  const light = scene.createRootEntity('Direct Light');
  const directLight = light.addComponent(DirectLight);

  directLight.shadowType = ShadowType.Hard;

  // create a cube mesh
  const cube = new Entity(engine);
  cube.transform.setPosition(0, 0, 0);
  const cubeMR = cube.addComponent(MeshRenderer);
  cubeMR.mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1);
  const greenMat = new BlinnPhongMaterial(engine);
  greenMat.baseColor = new Color(0.3, 1, 0.3, 1);
  cubeMR.setMaterial(greenMat);
  scene.addRootEntity(cube);

  const scene2 = new Scene(engine, 'scene2');
  engine.sceneManager.addScene(scene2);

  const camEntity2 = scene2.createRootEntity('Camera');
  const camera2 = camEntity2.addComponent(Camera);
  camEntity2.transform.setPosition(0, 0, 5);
  camEntity2.transform.lookAt(new Vector3(0, 0, 0));
  camera2.viewport = new Vector4(0.5, 0, 0.5, 1);

  const light2 = scene2.createRootEntity('Direct Light');
  const directLight2 = light2.addComponent(DirectLight);

  // create a cube mesh
  const cube2 = new Entity(engine);
  cube2.transform.setPosition(0, 0, 0);
  const cubeMR2 = cube.addComponent(MeshRenderer);
  cubeMR2.mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1);
  const greenMat2 = new BlinnPhongMaterial(engine);
  greenMat2.baseColor = new Color(0.3, 1, 0.3, 1);
  cubeMR2.setMaterial(greenMat2);
  scene2.addRootEntity(cube2);

  _createFog(engine, scene, "fog");
  _createFog(engine, scene2, "fog");

});

async function _createFog(engine: WebGLEngine, scene: Scene, name: string): Promise<ParticleRenderer> {
  let particleRenderer: ParticleRenderer;
  const assets = await engine.resourceManager.load(
    [
      {
        type: AssetType.Texture2D,
        url: './smoke.png'
      }
    ]
  );
  particleRenderer = createFog(engine, scene, 'volumetric fog', assets[0] as Texture2D);
  particleRenderer.generator.main.maxParticles = 130;
  return particleRenderer;
}

`

jtabibito commented 3 months ago

If set shadowType not ShadowType.None the particle will render twice in one frame