I am loading a GLB file that has a map object and plane object. I have a custom shader that I am applying to the map object to create a vertical color gradient. When I load the custom shader material onto the map object, the map no longer self shadows. Shadows are being applied only from the map object onto the plane. Do I have to code my own shadows or can I use the built in shadows with my custom fragment shader somehow? The fragment shader removes self shadowing when it is applied to the material. See attached photos of before and after material is applied for reference.

without fragment shader applied - image1

with fragment shader applied - image2

// Option 1: Import the entire three.js core library.
import * as THREE from 'three';
import { Camera } from 'three';
//import "./style.css"
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import { MathUtils } from 'three';
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
import { MTLLoader } from 'three/addons/loaders/MTLLoader.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import vertexShader from "/shaders/vertex.glsl"
import fragmentShader from "/shaders/fragment.glsl"

console.log("THREE", THREE)
const loader = new THREE.TextureLoader;
    loader.setCrossOrigin( "" );

const scene = new THREE.Scene();
//Lighting
const light = new THREE.DirectionalLight(0xffffff,5);
light.position.set(-100,5,40);
// enabling casting shadows
light.castShadow = true;
light.shadow.mapSize.x = 4094;
light.shadow.mapSize.y = 4094;
light.shadow.camera.left = -60;
light.shadow.camera.right = 60;
light.shadow.camera.top = 30;
light.shadow.camera.bottom = -30;
console.log("LIGHT", light)

// create fixed lighting position
var lightHolder = new THREE.Group();
lightHolder.add(light);
scene.add(lightHolder);

// Window Size 
var sizes = {
    width: window.innerWidth,
    height: window.innerHeight
}

//Resize
window.addEventListener('resize', () => {
    sizes.width = window.innerWidth;
    sizes.height = window.innerHeight;
    //resize camera aspect ratio
    camera.aspect = sizes.width / sizes.height;
    //rerender scene on change
    renderer.setSize(sizes.width, sizes.height);
        camera.updateProjectionMatrix();
        window.requestAnimationFrame(() =>{renderer.render(scene, camera)})

})

//Camera
const camera = new THREE.PerspectiveCamera(45, sizes.width/sizes.height)
camera.position.set(7.300680296968951,68.484720409821, 49.211063761838375)
scene.add(camera)


//renderer
const canvas = document.querySelector('.webgl');
const renderer = new THREE.WebGLRenderer({canvas,antialias: true});
renderer.setSize(sizes.width,sizes.height);
renderer.setPixelRatio(2);
//TODO: fix shadows
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.shadowMap.enabled = true;

// Controls
const controls = new OrbitControls(camera, canvas);
//controls.enableDamping = true;
controls.enablePan = true;
controls.autoRotate = false;
controls.autoRotateSpeed = 0.2;

/// material loader
const gltfLoader = new GLTFLoader();
var geometry;
var mapModel;
var texture;

gltfLoader.load('models/baked-Washington-full-x-no-color.glb', function ( obj ) {
console.log("geometry", obj.scene.children[0].geometry)
console.log("objOuter", obj)
geometry = obj.scene.children[0].geometry //geometry of map model
mapModel = obj.scene.children[0];
var plane = obj.scene.children[1];

console.log("mapModel",mapModel)
//set shadows
mapModel.castShadow = true;
mapModel.receiveShadow = true;
plane.receiveShadow = true;
plane.castShadow = true;

var uniforms = {
  bboxMin: {
    value: geometry.boundingBox.min
  },
  bboxMax: {
    value: geometry.boundingBox.max
  }
}

//create color gradient through vertex and fragment
texture = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
    onBeforeCompile: function (myMaterial) {
      console.log("shader", myMaterial)
      
    }
});

texture.needsUpdate = true; // is necesarry?


//   Set color gradient on map object  
   map

Fragment shader

// void main(){
//     gl_FragColor = vec4(1,0,0,1);
// }
uniform vec3 color1;
uniform vec3 color2;
uniform vec3 color3;
uniform vec3 color4;
vec4 blue = vec4(1.0/255.0, 100.0/255.0, 156.0/255.0, 1.0);
    vec4 yellow = vec4(198.0/255.0, 154.0/255.0, 0.0, 1.0);
    vec4 lightgreen = vec4(88.0/255.0, 255.0/255.0, 94.0/255.0, 1.0);
    vec4 green = vec4(0.0, 228.0/255.0, 26.0/255.0, 1.0);
    vec4 cyan = vec4(84.0/255.0, 196.0/255.0, 138.0/255.0, 1.0);
  
varying vec2 vUv;
    
void main() {
    float step1 = 0.99999;
    float step2 = 0.995;
    float step3 = 0.955;
    float step4 = 0.402;
    float step5 = 0.114;

    vec4 color = mix(blue, yellow, smoothstep(step1, step2, vUv.y));
    color = mix(color, lightgreen, smoothstep(step2, step3, vUv.y));

Vertex shader

uniform vec3 bboxMin;
uniform vec3 bboxMax;
  
varying vec2 vUv;

void main() {
    vUv.y = (position.z - bboxMin.z) / (bboxMax.z - bboxMin.z);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
0

There are 0 best solutions below