FunTechInc/use-shader-fx

idea of usePipeline()

takuma-hmng8 opened this issue · 2 comments

  • Generates a pipeline of fx.
  • Automatically receives one previous texture as mixSrc
const { render, texture } = compose(
    { fx: useFluid, size, dpr: 0.4 },
    { fx: useNoise, size, dpr: 0.2, mixSrcColorFactor: 0.6 }
 );
 useFrame((state) => render(state));

 return (
    <mesh>
       <planeGeometry args={[2, 2]} />
       <fxMaterialImpl key={FxMaterialImpl.key} src={texture} />
    </mesh>
 );
/*===============================================
reactive way
- fxの変更をtriggerにkeyを変更することで、reactiveにfxを変更することが可能
===============================================*/
const Composer = ({ compose }: { compose: FxConfig[] }) => {
   const { texture, render } = useComposer(...compose);
   useFrame((state) => render(state));
   return <fxMaterialImpl key={FxMaterialImpl.key} src={texture} />;
};
export const Playground = () => {
   const { size } = useThree();

   const compose: FxConfig[] = [
      { fx: useFluid, size, dpr: 0.3 },
      {
         fx: useNoise,
         size,
         dpr: 0.1,
         mixSrcColorFactor: 0.2,
      },
   ];

   // keyを変更することで、fxの変更をreactiveにすることが可能
   // UIではGUIの変更を検知して、keyを変更することで、reactiveに変更を反映するなどを想定
   const [composeCache, setComposeCache] = useState(compose.length);
   const [version, setVersion] = useState(0);
   if (compose.length !== composeCache) {
      setComposeCache(compose.length);
      setVersion(version + 1);
   }

   return (
      <mesh>
         <planeGeometry args={[2, 2]} />
         <Composer compose={compose} key={version} />
      </mesh>
   );
};

/*===============================================
non-reactive way
- resolutionはreactive
	- ただし他のhooksと同様、resolution以外はnon-reactive
===============================================*/
export const Playground = () => {
   const { size } = useThree();

   const { texture, render } = useComposer(
      {
         fx: useFluid,
         size,
         dpr: 0.2,
      },
      {
         fx: useNoise,
         size,
         dpr: 0.1,
         mixSrcColorFactor: 0.2,
      }
   );
   useFrame((state) => render(state));

   return (
      <mesh>
         <planeGeometry args={[2, 2]} />
         <fxMaterialImpl key={FxMaterialImpl.key} src={texture} />
      </mesh>
   );
};
  • usePipelineにrename
  • setPipeline関数を追加. reactiveにpipelineを操作することが可能
/*===============================================
reactive way
- fxの変更をtriggerにkeyを変更することで、reactiveにfxを変更することが可能
===============================================*/
const Pipeline = ({
   fxConfig,
   pipelineConfig,
}: {
   fxConfig: FxConfig[];
   pipelineConfig: PipelineConfig[];
}) => {
   const { texture, render, setPipeline } = usePipeline(...fxConfig);
   setPipeline(...pipelineConfig);
   useFrame((state) => render(state));
   return <fxMaterialImpl key={FxMaterialImpl.key} src={texture} />;
};
export const Playground = () => {
   const { size } = useThree();

   const fxConfig: FxConfig[] = [
      { fx: useFluid, size, dpr: 0.3 },
      {
         fx: useNoise,
         size,
         dpr: 0.2,
         mixSrcColorFactor: 0.2,
      },
   ];
   const pipelineConfig: PipelineConfig[] = [{}, { mixSrc: 0 }];

   // keyを変更することで、fxの変更をreactiveにすることが可能
   // UIではGUIの変更を検知して、keyを変更することで、reactiveに変更を反映するなどを想定
   const [pipelineCache, setPipelineCache] = useState(fxConfig.length);
   const [version, setVersion] = useState(0);
   if (fxConfig.length !== pipelineCache) {
      setPipelineCache(fxConfig.length);
      setVersion(version + 1);
   }

   return (
      <mesh>
         <planeGeometry args={[2, 2]} />
         <Pipeline
            fxConfig={fxConfig}
            pipelineConfig={pipelineConfig}
            key={version}
         />
      </mesh>
   );
};

/*===============================================
non-reactive way
- resolutionはreactive
	- ただし他のhooksと同様、resolution以外はnon-reactive
===============================================*/
export const Playground = () => {
   const { size } = useThree();

   const { texture, render, setPipeline } = usePipeline(
      {
         fx: useFluid,
         size,
         dpr: 0.2,
      },
      {
         fx: useNoise,
         size,
         dpr: 0.1,
         mixSrcColorFactor: 0.2,
      }
   );
   setPipeline({}, { mixSrc: 0 });

   useFrame((state) => render(state));

   return (
      <mesh>
         <planeGeometry args={[2, 2]} />
         <fxMaterialImpl key={FxMaterialImpl.key} src={texture} />
      </mesh>
   );
};