Search code examples
three.jsshaderlighting

THREE JS RawShaderMaterial


I'm trying to build my own shaders using RawShaderMaterial. Right now I've created a basic lighting setup which got me thinking if I was to later on build a scene using the standard THREE.JS lights and I wanted those lights to interact with the custom shaders I built then how would I go about doing that?


Solution

  • take look at WebGLProgram

    your raw shader will be taken, parsed and modified some highlights about how to make use of lights :

    make sure you have lights enabled when creating your material

    material = new THREE.RawShaderMaterial({
         uniforms: uniforms,
         vertexShader: vertex,
         fragmentShader: fragment,
         lights: true
      });
    

    you can get the number of lights of each type in scene by including one of special strings inside of your shader code:

    string.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
            .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
            .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
            .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights );
    

    take a look at WebGLLights you will be able to acces the lights through uniforms

    for example a bit of a fragment shader pseudo code with directional lights (taken from phong material code)

    #if NUM_DIR_LIGHTS > 0
        struct DirectionalLight {
            vec3 direction;
            vec3 color;
            int shadow;
            float shadowBias;
            float shadowRadius;
            vec2 shadowMapSize;
        };
        uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
    #endif
    
    main(){
    

    . .

    GeometricContext geometry;
    geometry.position = - vViewPosition;
    geometry.normal = normal;
    geometry.viewDir = normalize( vViewPosition );
    IncidentLight directLight;
    #if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )
       DirectionalLight directionalLight;
       for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
           directionalLight = directionalLights[ i ];
           directLight = getDirectionalDirectLightIrradiance( directionalLight, geometry );        
           RE_Direct( directLight, geometry, material, reflectedLight );
       }
    #endif
    

    it is not complete but it should illustrate the main points, you can always create a material for example MeshPhong, add it to scene and look at the vertex and fragment code it compiled from(or catch it inside WebGLProgram as it is beign parsed for a more readable version as it unrolls loops and replaces the light nums...)