Three.js React Fiber – 透明背景

huangapple go评论70阅读模式
英文:

Three.js React Fiber - Transparent background

问题

我使用React Fiber,但无法弄清楚如何使子场景的背景透明。

这是我的根组件,带有主要的Canvas:

export const Splash = () => {
  const { intensity, distance, color, ambientIntensity } = useControls('Main lights', {
    intensity: { value: 9, min: 0, max: 200, step: 0.5 },
    distance: { value: 100, min: -100, max: 100, step: 0.5 },
    color: "#7c0505",
    ambientIntensity: { value: 0.5, min: -3, max: 3, step: 0.1 },
  });
    
  return (
    <>
      <Canvas
        dpr={window.devicePixelRatio}
        onCreated={({ gl }) => {
          gl.setClearColor(0xFF0000, 0);
          gl.autoClear = false;
          gl.clearDepth()
        }}
        gl={{ antialias: true, alpha: true }}
        camera={{ fov: 65, position: [0, 0, 30] }}>
        <Main>
          <ambientLight intensity={ambientIntensity} color={color} />
          <RadialGradientPlane />
        </Main>
        <ApplyEffects>
          <RadialGradientPlane />
        </ApplyEffects>
      </Canvas>
    </>
  )
}

Main组件只是简单地渲染一个子场景:

function Main({ children }) {
  const scene = useRef()
  const { gl, camera } = useThree()
  useFrame(() => {
    gl.autoClear = false
    gl.clearDepth()
    gl.render(scene.current, camera)
  }, 1)
  return <scene ref={scene}>{children}</scene>
}

这是透明的,如果我删除ApplyEffects组件,我会看到RadialGradientPlane和我的普通文档背景颜色。

问题似乎与ApplyEffects组件有关,如下所示:

import { Effects } from '@react-three/drei';
import { UnrealBloomPass, RenderPass, WaterPass } from 'three-stdlib';
export default function ApplyEffects({ children }: { children: React.ReactNode }}) {
  const waterPass = useRef<WaterPass>(null!);
  const composer = useRef<EffectComposerGeneric<WebGLRenderTarget>>(null!)
  const { size, camera } = useThree();
  const aspect = useMemo(() => new Vector2(2046, 2046), [])
  const [scene, setScene] = useState<Scene>();
  const {strength, threshold, radius} = useControls('Bloom', {
    threshold: { value: 0.1, min: 0, max: 1, step: 0.01 },
    strength: { value: 1.5, min: 0, max: 10, step: 0.01 },
    radius: { value: 0.05, min: 0, max: 1, step: 0.01 },
  })
  useEffect(() => {
    if (composer.current) {
      composer.current.setSize(size.width, size.height)
    }
  }, [size])
  useFrame(() => {
    composer.current?.render();
    if (waterPass.current) {
      waterPass.current.time += 0.05;
    }
    composer.current.renderer.autoClear = false
    composer.current.renderer.clearDepth()
  }, 2);
  return <>
    <scene ref={setScene}>{children}</scene>
    <Effects ref={composer} disableGamma={true} disableRenderPass={true}>
      <renderPass scene={scene} camera={camera} />
      <waterPass ref={waterPass} attach="passes" factor={0.6} />
      <unrealBloomPass
        threshold={threshold}
        strength={strength}
        radius={radius}
        resolution={aspect} />
    </Effects>
  </>;
}

我觉得我已经尝试了一切,但无法弄清楚!

非常感谢任何帮助!

这是相同问题的示例:小示例

如果删除“Effects”,背景将变为透明并显示白色背景颜色。

Shannon

英文:

I'm using react fiber, and cannot figure out how to get the background of my child scene to be transparent

This is my root component with the main Canvas

export const Splash = () =&gt; {
  const { intensity, distance, color, ambientIntensity } = useControls(&#39;Main lights&#39;, {
    intensity: { value: 9, min: 0, max: 200, step: 0.5 },
    distance: { value: 100, min: -100, max: 100, step: 0.5 },
    color: &quot;#7c0505&quot;,
    ambientIntensity: { value: 0.5, min: -3, max: 3, step: 0.1 },
  });
    
  return (&lt;&gt;
      &lt;Canvas
        dpr={window.devicePixelRatio}
        onCreated={({ gl }) =&gt; {
          gl.setClearColor(0xFF0000, 0);
          gl.autoClear = false;
          gl.clearDepth()
        }}
        gl={{ antialias: true, alpha: true }}
        camera={{ fov: 65, position: [0, 0, 30] }}&gt;
        &lt;Main&gt;
          &lt;ambientLight intensity={ambientIntensity} color={color} /&gt;
          &lt;RadialGradientPlane /&gt;
        &lt;/Main&gt;
        &lt;ApplyEffects&gt;
         &lt;RadialGradientPlane /&gt;
        &lt;/ApplyEffects&gt;
        
      &lt;/Canvas&gt;
    &lt;/&gt;
  )
}

The Main Component simply just renders a child scene

function Main({ children }) {
  const scene = useRef()
  const { gl, camera } = useThree()
  useFrame(() =&gt; {
    gl.autoClear = false
    gl.clearDepth()
    gl.render(scene.current, camera)
  }, 1)
  return &lt;scene ref={scene}&gt;{children}&lt;/scene&gt;
}

This IS transparent, if i remove the ApplyEffects component i see the RadialGradientPlane and my normal document background colour.

It's something to do with the ApplyEffects component, which is:

import { Effects } from &#39;@react-three/drei&#39;;
import { UnrealBloomPass, RenderPass, WaterPass } from &#39;three-stdlib&#39;;
export default function ApplyEffects({ children }: { children: React.ReactNode }}) {
  const waterPass = useRef&lt;WaterPass&gt;(null!);
  const composer = useRef&lt;EffectComposerGeneric&lt;WebGLRenderTarget&gt;&gt;(null!)
  const { size, camera } = useThree();
  const aspect = useMemo(() =&gt; new Vector2(2046, 2046), [])
  const [scene, setScene] = useState&lt;Scene&gt;();
  const {strength, threshold, radius} = useControls(&#39;Bloom&#39;, {
    threshold: { value: 0.1, min: 0, max: 1, step: 0.01 },
    strength: { value: 1.5, min: 0, max: 10, step: 0.01 },
    radius: { value: 0.05, min: 0, max: 1, step: 0.01 },
  })
  useEffect(() =&gt; {
    if (composer.current) {
      composer.current.setSize(size.width, size.height)
    }
  }, [size])
  useFrame(() =&gt; {
    composer.current?.render();
    if (waterPass.current) {
      waterPass.current.time += 0.05;
    }
    composer.current.renderer.autoClear = false
    composer.current.renderer.clearDepth()
  }, 2);
  return &lt;&gt;
    &lt;scene ref={setScene}&gt;{children}&lt;/scene&gt;
    &lt;Effects ref={composer} disableGamma={true} disableRenderPass={true}&gt;
      &lt;renderPass scene={scene} camera={camera} /&gt;
      &lt;waterPass ref={waterPass} attach=&quot;passes&quot; factor={0.6} /&gt;
      &lt;unrealBloomPass
        threshold={threshold}
        strength={strength}
        radius={radius}
        resolution={aspect} /&gt;
    &lt;/Effects&gt;
  &lt;/&gt;;
}

I feel like I've tried everything here, i cannot figure it out!

Any help would be greatly appreciated!

Here's an example of the same issue: small example

If you remove the "Effects" the background is transparent and shows the white body colour.

Shannon

答案1

得分: 0

这是一个众所周知的问题,已在这里进行了广泛讨论。

其中一种解决方案在这里实现 ,并似乎根据这个演示解决了该问题。

请告诉我这是否有帮助。

英文:

This is a well-known issue reported and heavily discussed here.

One of the solutions is implemented here and seem to solve the problem based on this demo.

Please let me know if this helps.

huangapple
  • 本文由 发表于 2023年5月29日 07:47:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354009.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定