Change shadow params dynamically

Hi! I tried to use this shadow shader in my project. All works ok, but i would be like to change some defines in shader dynamically by dat gui, to see live result:

#define LIGHT_WORLD_SIZE 0.005
#define LIGHT_FRUSTUM_WIDTH 3.75
#define NEAR_PLANE 9.5
#define NUM_SAMPLES 17
#define NUM_RINGS 11

Is it possible?

These values are right now hard coded. You can only change them manually.

Ok, but can i switch shadow between standard and shader after full loading scene?

For example like this:

function  changeShadowStyle() {
	THREE.ShaderChunk.shadowmap_pars_fragment = shader;
}
setTimeout(changeShadowStyle, 12000);

I know this example does not work, but maybe I can do it in a similar way?

This requires a recompilation of the shader. Does it work if you set needsUpdate to true of all materials?

Unfortunately doesn`t:(

Can you please demonstrate with a live example what you actually do?

Yes, ofcourse. Please, look at this codepen
https://codepen.io/vinar22/pen/GRKNPGx?editors=1010

Line 69 - 91

Actually i whant to change shadow parameters, if its possible. Maybe in some way i can replace defines by this code block dynamically?

var LIGHT_WORLD_SIZE = 0.009; 
var LIGHT_FRUSTUM_WIDTH = 2.75; 
var NEAR_PLANE = 9.5; 
var NUM_SAMPLES = 30;
var NUM_RINGS = 11; 
							
shader = shader.replace(/%LIGHT_WORLD_SIZE%/g, LIGHT_WORLD_SIZE);
shader = shader.replace(/%LIGHT_FRUSTUM_WIDTH%/g, LIGHT_FRUSTUM_WIDTH);
shader = shader.replace(/%NEAR_PLANE%/g, NEAR_PLANE);
shader = shader.replace(/%NUM_SAMPLES%/g, NUM_SAMPLES);
shader = shader.replace(/%NUM_RINGS%/g, NUM_RINGS);

I’m afraid this does not work for two reasons:

  • %NUM_SAMPLES% is a placeholder which is going to be replaced with 30. So if you try to replace %NUM_SAMPLES% again, the value does not exist anymore. This happens with all defines.
  • Even if you perform the replacement correctly, three.js will not update the shader program. Setting material.needsUpdate to true does actually not help here. The problem is that three.js caches the material inside WebGLRenderer and does not assume shader chunks are modified on-the-fly for built-in materials.

So if you still want to achieve your goal, you have to fix your regex and use a custom shader material instead.

1 Like

Thank you, Michael, I really appreciate your support!

1 Like
function reset(gl, scene, camera) {
  scene.traverse((object) => {
    if (object.material) gl.properties.remove(object.material)        
  })
  gl.info.programs.length = 0
  gl.compile(scene, camera)
}

working on the same thing, trying to make soft shadows side effect-free: