question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Alternative to .onBeforeCompile for material extension

See original GitHub issue

Current approach of letting the user do whatever they want with the shader code from within .onBeforeCompile is very powerful, and yet, at the same time, quite messy and fragile.

One of the biggest issues is dynamic nature of the material code, if you allow making arbitrary modification to the code - you can not assume that material code will remained the same between builds, and you have to construct that code string every time to check, this creates waste both in terms of CPU cycles and in terms of GC overhead, as that string will likely end up as garbage.

My proposal is quite simple. I propose having more restrictive transformers which can be registered onto a material. Transformers can be entirely static for most usecases, and where that’s not enough, we could offer dynamic transformers - with the main difference that the library can detect that and optimize usecases where only static transformers are being used. One fairly substantial benefit also - is the added semantic information which library can use for various optimizations and error checking.

My observation boils down to the fact that most .onBeforeCompile functions do just 1 thing:

  • find a RegEx pattern in shader code string
  • replace that occurrence with a fixed string

Here is an example to illustrate current usage:

material.onBeforeCompile = function(shader){
        shader.vertex = shader.vertex.replace('a','b');
}

What i propose would be:

const transform = new ShaderTransformReplace(VertexShader, 'a','b');
material.addShaderTransform(transform);

Since there is no arbitrary code being executed anymore, we know that material shader does not change as long as list of transforms hasn’t changed (in addition to other things, like defines and lighting which we already have had).

A couple of ideas on top of this proposal:

  • if user adds transorms (‘a’,‘b’) and (‘a’,‘c’) - we can detect that and remove latter transform or warn the user, as we know that pattern will no longer be matched.
  • If shader code is ‘aaa’ and user adds transform (‘b’,‘c’) - we can detect that such transform would be pointless and remove it or warn the user

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:22 (19 by maintainers)

github_iconTop GitHub Comments

2reactions
Usnulcommented, Jun 19, 2018

@donmccurdy My takeaway from this is that there is no plan to touch onBeforeCompile currently with the expectation that Node-based shaders will be ready soon (within a 2+ months)

wrt Node-based shader in general, yes, I find the solution to be a desirable one, my issue is with how it’s done, and that’s separate from the current thread - you’re absolutely right.

@mrdoob I apologize if I come off as hard. I make no demands, merely express my wishes to clarify my position. I am thankful for the work of yourself and other capable and diverse individuals who have in the past, currently are, and will in the future be contributing to making three.js great, again - I’m sorry if that was not clear.

@pailhead Thanks for the pointer. Documentation for that code will be a substantial undertaking.

2reactions
mrdoobcommented, Jun 18, 2018

@Usnul

I believe that onBeforeCompile is harmful architecturally.

Yeah, adding that method was a mistake on my part. But sometimes you need to experiment until finding the right solution…

I want a viable replacement, and not in 2 years time.

We do what we can.

Read more comments on GitHub >

github_iconTop Results From Across the Web

[Enhancement] onBeforeCompile may break material's .clone ...
onBeforeCompile seems to be ignored when cloning materials: ... is there a simpler alternative to onBeforeCompile that could fill the void ...
Read more >
Function to extend Materials - Resources - three.js forum
This is a little helper function to create a THREE.ShaderMaterial extending a standard material. The second parameter is optional.
Read more >
Derived Materials - Troika JS
How to use Troika's createDerivedMaterial utility to extend existing Three.js materials with custom shader code. Source code with JSDoc.
Read more >
Extending three.js materials with GLSL | by Dusan Bosnjak
It's impossible to tell what's in the onBeforeCompile function if you receive an instance of a Material that has already been extended. It's ......
Read more >
Two Textures on one Object Three js - Stack Overflow
You can assign a function to a material's onBeforeCompile property. ... fragmentShader.replace(thingToReplace, replacement); });.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found