Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript and React Three Fiber support #22

Open
itsdouges opened this issue Nov 14, 2022 · 10 comments
Open

TypeScript and React Three Fiber support #22

itsdouges opened this issue Nov 14, 2022 · 10 comments

Comments

@itsdouges
Copy link
Contributor

Hello! Found your library through the threejs examples, it looks great! Currently I'm trying to integrate it into my point & click game and found some friction points:

  • no TypeScript types
  • no React Three Fiber support (out of the box)

Would you consider adding support for both? Types would either be the creation of a typedef file or converting to TS, and R3F would be following https://docs.pmnd.rs/react-three-fiber/tutorials/typescript#extending-threeelements. A few libraries come with support such as https://github.com/FarazzShaikh/THREE-CustomShaderMaterial

@StrandedKitty
Copy link
Owner

I will migrate it to TS soon. Basically, I'm nearly finished, but there are some issues with rollup I can't figure out ;-;
Regarding React stuff: sorry, I'm not really interested in this. Feel free to contribute though, I will merge a PR if someone implements this stuff you are talking about.

@itsdouges
Copy link
Contributor Author

Sweet! TS stuff sounds great, and no worries with the React stuff. I'll put something up in the future when I get things working 😄

@StrandedKitty
Copy link
Owner

TS migration done in v3.0.0

@itsdouges
Copy link
Contributor Author

itsdouges commented Nov 15, 2022

Thanks mate! For the type defs you'll need to do some work https://github.com/StrandedKitty/three-csm/blob/master/package.json#L7

They're currently pointing to a file that doesn't exist. Pointing to CSM.d.ts gets it working.

Looking at the generated types some are off:

// Should take Camera (as it could be an orth camera too no?)
camera: PerspectiveCamera;

// Would be great to type the args
customSplitsCallback: (cascadeCount: any, nearDistance: any, farDistance: any) => number[];
  • Would also be great to export Params for consumer use too (I'd use it to make a React component props type).
  • It would be great to add tsdoc descriptions to each property so they have in context info for new people like me 😄

I can contribute anything here if you'd like.

@itsdouges
Copy link
Contributor Author

Raised #29 and #28

@drcmda
Copy link

drcmda commented Jan 20, 2023

@itsdouges regarding react, it wouldn't need changes from a library, it will work ootb. trying it here but getting shaders errors from csm, did you figure this out? https://codesandbox.io/s/exemple-basique-avec-tentative-csm-ver2-forked-5cywrd?file=/src/App.js

ERROR: 0:1703: '[]' : array index out of range
ERROR: 0:1703: '[]' : array index out of range
ERROR: 0:1705: '[]' : array index out of range
ERROR: 0:1705: '[]' : array index out of range

  1698: 			getDirectionalLightInfo( directionalLight, geometry, directLight );
  1699: 
  1700: 			#if defined( USE_SHADOWMAP ) && ( 4 < 5 )
  1701: 
  1702: 			directionalLightShadow = directionalLightShadows[ 4 ];
> 1703: 			if(linearDepth >= CSM_cascades[4].x && linearDepth < CSM_cascades[4].y) directLight.color *= all( bvec2(

@drcmda
Copy link

drcmda commented Jan 20, 2023

figured it out from another github issue about that

@itsdouges
Copy link
Contributor Author

I can link code if you want - I had to defer instantiation of the class similar to some three Controls. Which issue did you use?

@drcmda
Copy link

drcmda commented Jan 20, 2023

someone had the same issue above, you can't have lights that castShadow in your scene, that's now disallowed with csm.

@itsdouges
Copy link
Contributor Author

itsdouges commented Jan 20, 2023

This is the code I used for CSM, your shader errors are probably from CSM instantiating a few times because it adds scene objects immediately... when instantiated.

import { useFrame, useThree } from '@react-three/fiber';
import { useLayoutEffect, useMemo } from 'react';
import { OrthographicCamera, PerspectiveCamera, Vector3, Vector3Tuple } from 'three';
import CSM, { CSMParams } from 'three-csm';

interface CascadedShadowMapProps extends Omit<CSMParams, 'lightDirection' | 'camera' | 'parent'> {
  fade?: boolean;
  lightDirection?: Vector3Tuple;
}

class CSMProxy {
  instance: CSM | undefined;
  args: CSMParams;

  constructor(args: CSMParams) {
    this.args = args;
  }

  set fade(fade: boolean) {
    if (this.instance) {
      this.instance.fade = fade;
    }
  }

  set camera(camera: PerspectiveCamera | OrthographicCamera) {
    if (this.instance) {
      this.instance.camera = camera;
    }
  }

  set lightDirection(vector: Vector3 | Vector3Tuple) {
    if (this.instance) {
      this.instance.lightDirection = Array.isArray(vector)
        ? new Vector3().fromArray(vector).normalize()
        : vector;
    }
  }

  attach() {
    this.instance = new CSM(this.args);
  }

  dispose() {
    if (this.instance) {
      this.instance.dispose();
    }
  }
}

export function CascadedShadowMap({
  maxFar = 50,
  shadowMapSize = 1024,
  lightIntensity = 0.25,
  cascades = 2,
  fade,
  lightDirection = [1, -1, 1],
  shadowBias = 0.000001,
  customSplitsCallback,
  lightFar,
  lightMargin,
  lightNear,
  mode,
}: CascadedShadowMapProps) {
  const camera = useThree((three) => three.camera);
  const parent = useThree((three) => three.scene);
  const proxyInstance = useMemo(
    () =>
      new CSMProxy({
        camera,
        cascades,
        customSplitsCallback,
        lightDirection: new Vector3().fromArray(lightDirection).normalize(),
        lightFar,
        lightIntensity,
        lightMargin,
        lightNear,
        maxFar,
        mode,
        parent,
        shadowBias,
        shadowMapSize,
      }),
    // These values will cause CSM to re-instantiate itself.
    // This is an expensive operation and should be avoided.
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [
      // Values that can be updated during runtime are omitted from this deps check.
      cascades,
      customSplitsCallback,
      fade,
      lightFar,
      lightIntensity,
      lightMargin,
      lightNear,
      maxFar,
      mode,
      shadowBias,
      shadowMapSize,
    ]
  );

  useFrame(() => {
    if (proxyInstance && proxyInstance.instance) {
      proxyInstance.instance.update();
    }
  });

  useLayoutEffect(() => {
    proxyInstance.attach();

    return () => {
      proxyInstance.dispose();
    };
  }, [proxyInstance]);

  return (
    <primitive object={proxyInstance} camera={camera} fade={fade} lightDirection={lightDirection} />
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants