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

Ability to target ShaderMaterial uniforms via animations #28333

Closed
Bug-Reaper opened this issue May 10, 2024 · 7 comments
Closed

Ability to target ShaderMaterial uniforms via animations #28333

Bug-Reaper opened this issue May 10, 2024 · 7 comments
Milestone

Comments

@Bug-Reaper
Copy link
Contributor

Bug-Reaper commented May 10, 2024

Description

Tried to target arbitrary THREE.ShaderMaterial <float> uniform value with an animation, doesn't work.

let starsTrack = new THREE.NumberKeyframeTrack(".material.uniforms.res.value", [0,1], [.1,.05]);
// Doesn't work :(

Or hacky work-around (also didn't work):

obj.value = obj.material.uniforms.res.value
let starsTrack = new THREE.NumberKeyframeTrack(".value", [0,1], [.1,.05]);
// obj.value changes but obj.material.uniforms.res.value does not change

Solution A

Upgrade THREE.PropertyBinding.parseTrackName() to support binds to material.uniforms.name.value. Can we just have a fallback that allows to target any property (no matter how deeply nested) as long as that property exists?

Solution B

Hoist a shared reference of all THREE.ShaderMaterial uniform values to the top-level of the material object. This would hoist a reference to uniform values high enough to be targeted by the current animation implementation.

Additional context

I'd imagine solution A is more desirable. Unclear to me if there's a limitation that prevents how deep the animation targeting can reach.

@Bug-Reaper
Copy link
Contributor Author

Dug into parseTrackName, bind, and findNode which is where most of the things break magic happens.

I think it's possible, may try to draft something when I get a chance.

@Mugen87
Copy link
Collaborator

Mugen87 commented May 11, 2024

I believe this issue is a duplicate of #25028. It is also related to KHR_animation_pointer, see #24108.

@RemusMar
Copy link
Contributor

Tried to target arbitrary THREE.ShaderMaterial uniform value with an animation, doesn't work.

Did you try this approach?
https://necromanthus.com/Test/html5/Lara_shader.html

		let uniforms1 = {
			time: { type: "f", value: 1.0 },
			resolution: { type: "v2", value: new THREE.Vector2() }
		};
// ...
		function animate() {
			let delta = clock.getDelta();
			uniforms1.time.value += delta * 5;

@Bug-Reaper
Copy link
Contributor Author

Bug-Reaper commented May 11, 2024

Thanks Mugen!

I believe this issue is a duplicate of #25028. It is also related to KHR_animation_pointer, see #24108.

Yea #25028 would address this. Looking at the code I had lost some of my ambition for fixing every nested property case since it seems easier to address just the case of uniforms.name.value as a one off. That said I think addressing this as a one-off pushes the can further down the road and could possibly impede future refactors similar to #24108.

If you think a PR for #25028 would be approved, we can close this as duplicate and I'll throw some effort to that battle.

@RemusMar
Copy link
Contributor

If you want to control the ShaderMaterial uniforms via a specific animation, all you need is a simple function based on animation.time and clip.duration.
Example: https://necromanthus.com/Test/html5/Lara_shader_controlled.html
In this case:

		function animate() {
			uniforms1.time.value = 5 * mixer1.clipAction( clip1 ).time / clip1.duration;

In you case it will be something like
uniforms.res.value = 0.1 - 0.05 * mixer.clipAction( clip ).time / clip.duration;
That's all and nothing more.

@Bug-Reaper
Copy link
Contributor Author

If you want to control the ShaderMaterial uniforms via a specific animation, all you need is a simple function based on animation.time and clip.duration. Example: https://necromanthus.com/Test/html5/Lara_shader_controlled.html In this case:

		function animate() {
			uniforms1.time.value = 5 * mixer1.clipAction( clip1 ).time / clip1.duration;

In you case it will be something like uniforms.res.value = 0.1 - 0.05 * mixer.clipAction( clip ).time / clip.duration; That's all and nothing more.

Thanks so much @RemusMar that's a really cool approach. Honestly it'd be easiest for me to just use TWEEN and call it a day (more flexibility to cycle through non-linear arbitrary values).

@Mugen87 Mugen87 closed this as not planned Won't fix, can't repro, duplicate, stale May 12, 2024
@Mugen87
Copy link
Collaborator

Mugen87 commented May 12, 2024

If you think a PR for #25028 would be approved, we can close this as duplicate and I'll throw some effort to that battle.

A solution for #25028 would be welcome. We need it anyway if we want to support the glTF extension with core features.

@Mugen87 Mugen87 added this to the r165 milestone May 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants