Jump to content

Updating A Shader Material Frag Shader


AlexB
 Share

Recommended Posts

I think I'll be posting a lot as we port from ThreeJS over to Babylon, so apologies.

Our application allows user input to affect the appears of a 3D object. A user can change out a material on an object. Sometimes, this means that the uniforms should change. For instance, we may want to use a structure like:

 

  struct Graphic {
      vec2 flip;
      vec2 offset;
      float rotation;
      vec2 scale;
      sampler2D texture;
      sampler2D normal;
 };

However, if the graphic does not have a normal texture, we don't need that texture slot so I'll write the structure on the fly like this:

 

  struct Graphic {
      vec2 flip;
      vec2 offset;
      float rotation;
      vec2 scale;
      sampler2D texture;
      vec3 normal;
  };

So when I create a ShaderMaterial, it allows me to send in a frag shader and a vertex shader as string, like so:

 

const material: any = new BABYLON.ShaderMaterial(
          name,
          scene,
          {
            vertex: 'some vertex',
            fragment: 'some fragment',
          },
          {
            // options
          }
        );

But how can I later update that frag shader with new text?

Something like:
material.fragmentShader = newFrag;

 

Thanks!


EDIT: It also looks like I can't just set the frag and vertex code as a string. Does it have to be wrapped somehow?

Link to comment
Share on other sites

Hello, welcome and no need for apologies :)

Regarding your question: as the shaders (both) are linked into a program, you have to rebuild it entirely so this means you will have to dispose the current material and creates a new one (Also I encourage you using defines as babylon.js will be able to optimize and cache effects for you)

Link to comment
Share on other sites

Update: I have a shader loading using the ShadersStore array.

 

 BABYLON.Effect.ShadersStore[`${part.url}FragmentShader`] = `
            precision highp float;
            varying vec2 vUV;


            struct Color {
              vec3 color
            }

            Color myColor;

            void main(void) {
              gl_FragColor = vec4(1., 0., 0., 1.);
            }
        `;

This works, and I can update the fragment shader. But it appears that Babylon doesn't support GLSL structures? Is there a way to access the shader uniforms directly?

Link to comment
Share on other sites

we support all glsl data structure and we are even using struct internally. So it should work

If you can repro in the Playground I will be able to probably help

Link to comment
Share on other sites

12 minutes ago, Deltakosh said:

we support all glsl data structure and we are even using struct internally. So it should work

If you can repro in the Playground I will be able to probably help

I was referring to this bit of code in ShaderMaterial where it lists all the uniform types:

 

private _textureArrays: { [name: string]: Texture[] } = {};

private _floats: { [name: string]: number } = {};

private _ints: { [name: string]: number } = {};

private _floatsArrays: { [name: string]: number[] } = {};

private _colors3: { [name: string]: Color3 } = {};

private _colors3Arrays: { [name: string]: number[] } = {};

private _colors4: { [name: string]: Color4 } = {};

private _vectors2: { [name: string]: Vector2 } = {};

private _vectors3: { [name: string]: Vector3 } = {};

private _vectors4: { [name: string]: Vector4 } = {};

private _matrices: { [name: string]: Matrix } = {};

private _matrices3x3: { [name: string]: Float32Array } = {};

private _matrices2x2: { [name: string]: Float32Array } = {};

private _vectors2Arrays: { [name: string]: number[] } = {};

private _vectors3Arrays: { [name: string]: number[] } = {};

It doesn't appear that I can set a Struct type, like so:

https://www.babylonjs-playground.com/#ATDL99#1

* Note that I'm trying to use a myColor.color vec3 instead of fogColor

Link to comment
Share on other sites

oh ok understood.. we were not on the same page :)

It is not supported you are right as this is not a basic type..But happy to merge a PR if you want to add it

Link to comment
Share on other sites

13 minutes ago, Deltakosh said:

oh ok understood.. we were not on the same page :)

It is not supported you are right as this is not a basic type..But happy to merge a PR if you want to add it

Gotcha. I'll look into adding support for that. Would it just affect ShaderMaterial and the _checkUniform method? I don't quite understand all your code yet. It's changed a lot since I last used it ?

Link to comment
Share on other sites

I hope it is better now ;D

It will affect shaderMaterial and probably the effect class (which is used internally to communicate with shaders)

Link to comment
Share on other sites

4 hours ago, Deltakosh said:

I hope it is better now ;D

It will affect shaderMaterial and probably the effect class (which is used internally to communicate with shaders)

It turns out this is a harder problem than I thought. There is no low level method on the GL object to set structures, so what the ThreeJS implementation is doing is looping through a structure and discovering each type in a recursive loop. Then it applies each struct property one by one. I'm not sure I have time to figure it out. I got a good start on it if anyone wants to give it a try. I can push up a branch.

Link to comment
Share on other sites

28 minutes ago, Deltakosh said:

Are you sure you want to stick with a struct then?

I was hoping that adding support for structures would be faster than re-wiring my shader, but I think it'll be faster to just use arrays. But I'd still love to have support for structs at some point. They make the shaders way more readable, IMO.

Thanks for your help! 

Link to comment
Share on other sites

@AlexB

sorry, i have to pass on this one. my sketch
https://www.babylonjs-playground.com/#CNE3P8 


Babylonjs have a new shader system (or something like wise) you have to bind the uniform to createEffect not createShader somehow. Ask a questions in this forum, i have no idea how to use it.
http://doc.babylonjs.com/api/classes/babylon.engine#createshaderprogram
http://doc.babylonjs.com/api/classes/babylon.engine#createEffect


Good Luck

@Sebavan
Yeah

Link to comment
Share on other sites

On 6/19/2018 at 7:47 AM, AlexB said:

Can you give an example of how to use a uniform buffer object with Babylon? Our user base will all be on WebGL2 browsers.


I think this might help, if a uniform buffer object is the same as a VBO.

If I can find my grass simulation, it covers a lot of this... let me see if I can find that this morning when things slow down at the office.

Link to comment
Share on other sites

just to be complite

WebGL1:  https://www.babylonjs-playground.com/#CNE3P8#2

And the babylonjs createEffect is listening to PostProcess

var postProcess = new BABYLON.PostProcess("My custom post process", "custom", ["Block"], null, 0.25, camera);
   
    postProcess.onApply = function (effect) {
    

        effect.bindUniformBlock(effect.getProgram(),"Block")
  

    };
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...