Enabling extension with onBeforeCompile

materials
shaders

#1

Hi everyone.

I was wondering if there’s a way to enable an GL extension when using onBeforeCompile method for a given material.

Let’s assume I want some customization with the build-in material. So, as per the documentation, I can use material.onBeforeCompile method to add additional snippets into the existing shaders.

material.onBeforeCompile  = function(shader, target){ 
     // additional snippets
     // defines, uniforms, lights, fog, vertex shader, fragment shader  -- all available
     // extensions not available.
 };

//resultant error
error - ‘GL_OES_standard_derivatives’ : extension is disabled

There’s seem to be no way to enable an extension.

So the question is does onBeforeCompile allows to access extension enabling?


#2

Have you added the string #extension GL_OES_standard_derivatives : enable at the beginning of the program code (fragment shader)?


#3

I tried.

shader.fragmentShader = "#extension GL_OES_standard_derivatives : enable" + shader.fragmentShader;

No luck though. Getting error

‘#’ : unexpected token

I can see the common fragment code piece getting added internally above the code that I added for enabling the extension.

I’m using r88. Haven’t seen any major update that may break the way of implementation.


#4

You need to do it like this: https://jsfiddle.net/f2Lommf5/6523/

Anyway, I’ve realized that does not solve the problem. When you inject the code, it is inserted too late. Hence, the following warning is reported:

extension directive should occur before any non-preprocessor tokens

Is the following approach acceptable to you? Obviously, you can’t use onBeforeCompile() for this.

material.extensions = {
   derivatives: true
};

https://jsfiddle.net/f2Lommf5/6524/


#5

In worst case, yes. This is acceptable. But, I ( or any general user ) would expect to have the accessibility to use material.extensions within the scope of onBeforeCompile.

Otherwise, the true meaning of customizing existing material using onBeforeCompile would not be completely unfair.

Not sure, but, would it make sense to create a feature request for this? I bet there would been already some discussion on it.


#6

I’m not sure about that. The thing is, there is already a way via material.extensions to customize extensions. It is questionable if we need an additional way via onBeforeCompile().

If you like, you can raise an issue at github. It is definitely a valid request.


#7

The extension warning is just a warning your shader will work. S


#8

You can:

var myMaterial = new Material()
var myOnBeforeCompile = shader => { myMaterial.foo = 'bar' } 
myMaterial.onBeforeCompile = myOnBeforeCompile

Given that onBeforeCompile has some issues with how it must be written and how it hashes, i see little reason for these to be declared in vastly different places / scopes.

But i’m kinda surprised you even ran into this issue. I think i used onBeforeCompile and something else enabled the derivatives in that specific material. Which material type are you using?


#10

Here are some breadcrumbs regarding this problem:

Since you can replace #include <foo> replacing stuff in global might make sense, the problem is global is injected in both vert and frag so you can’t really inject attribute vec4 foo there, one idea for solving this :

This one added a lot of new chunk names so it could be more granular (like there could be a chunk named #include <user_provided_extensions>:

The code that breaks this:

@Mugen87 is this something that could be gradually shuffled around to make it more robust, or is it a dead end because of the imminent coming of NodeMaterial? :rofl:

@Atul_Mourya

I am so incredibly glad that someone is using onBeforeCompile, i’ve used it extensively and came up with a
lot of conclusions, i would love to compare notes!

I posted another example that you might find interesting:


Shader to create an offset, inward-growing stroke?
#11

Thanks for the insight.

My use case was to try adding some custom fresnel in the existing MeshPhysicalMaterial.
The code expression that I was trying to implement had dependency on GL_OES_standard_derivatives.

The problem comes when looking to enable those extensions as these extensions are ( unlike ShaderMaterial ) parameter driven. I guess, it evaluates only those extension that would be required by the given built-in material before injecting as it into the shader program.

For me to overcome this. I had to come up with a trick rather than creating an entire custom shader.
What I ended up doing is adding a normalMap that would trigger enabling of derivatives extension.

And the problem was solved. Though not the ideal way.