3

I have been trying to learn THREEJS shader materials. So far I understand how uniforms, vertexShader, and fragmentShader play a role in projecting and coloring the vertices and fragments in the world of glsl and webgl. I have been trying to find some good examples where ShaderMaterial of THREEJS is extended using the THREE.ShaderLib.

Suppose I want to extend a standard threejs material (THREE.ShaderLib['standard']) to write the envmap texture, is that possible? Or is it absolutely necessary that I write everything from scratch?

3
  • Here is a fiddle I made long ago that makes use of ShaderChunk's. Maybe it helps you? Commented Mar 2, 2018 at 4:00
  • My sincere thanks to your for the fiddle. It clarifies a lot about my query. So if suppose I wanted to extend the meshstandardmaterial or meshbasicmaterial, which I believe is written using a shader of three.js, how is that problem approached? Do you include the chunks of glsl written for these materials? This is the tricky part I am not getting at. Commented Mar 3, 2018 at 15:43
  • You would extend/alter the built in materials just how pailhead explained in the answer/comments. It may just be easier to recreate it and add your alterations. Just copying the shaderchunks you need and putting them into your own shader. Commented Mar 4, 2018 at 0:55

1 Answer 1

6

Shaders are just strings, it's up to you what you do with them and how you obtain them. With that being said, three.js has numerous tools to help you build them better.

At the highest level, there is an abstraction in form of THREE.Material. Where you describe abstract properties and three configures the shader under the hood.

//no shaders involved
var redPlastic = new THREE.MeshStandardMaterial({
   color: 'red',
   roughness: notVeryRough
}) 

ShaderMaterial expects you to write raw GLSL, but still includes some things that you would otherwise have to do manually. So "writing from scratch" is a not entirely correct. With RawShaderMaterial you would write everything from scratch. THREE.ShaderMaterial:

varying vec2 vUv;
void main(){
  vUv = uv; // <- magic! where does uv come from?
  vec4 worldPosition = modelMatrix * vec4( position, 1.); // <- more magic! where do modelMatrix and position come from?
  gl_Position = projectionMatrix * viewMatrix * worldPosition; // more!
}

At runtime, when three is compiled and included on a page, the THREE namespace has THREE.ShaderChunk dictionary. These are various named snippets of GLSL that all the materials are built out of.

You can copy these snippets from their source files, and paste them in your own shader file, or string.

You can write it with a string template:

`${THREE.ShaderChunk.some_chunk}
 void main(){
 ...
 ${anotherChunk}
 gl_Position = ...
`

But if you want to extend the built in materials, there is a (IMHO buggy and wonky :)) feature of the material called onBeforeCompile. With this, you pass a callback to any of the built in materials, and get the shader object before compilation. Here you can inject your own glsl, swap out chunks or anything else you can think of doing to a string.

In order to use this one needs to be familiar with the structure of the shaders built from: https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderChunk

Sign up to request clarification or add additional context in comments.

2 Comments

Wow, that threw a lot of clarity. Really a lot of clarity. If suppose I need to extend the threejs meshstandardmaterial by adding my own logic to the texture. Assume I want to create a reflective map using envmap texture but in a way I see fit. To do this what would be the chunks that needs to be included in my fragment shader? Am I making sense? Regards, #0K
yeah, consult the link i just added, and look at th e template for that material github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/… find what you need to replace and inject your own logic, you can also use Material.defines to wrap a chunk in #ifndef MY_LOGIC before the shader #else your logic #endif after

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.