In the Orb (Shaders)

Hi, community!

Here is a picture of a scene:

And there is a working demo: https://jsfiddle.net/prisoner849/4s2ch5vg

I had the idea about such scene for about two years. But I couldn’t start it as I had not enough knowledge of Three.js and had no idea where to start from at all. Years passed, I’ve opened this forum with cool people, whose posts and replies here helped me to get more experience and knowledge. Special thanks to @pailhead, because his posts gave me at least the direction where I should move to. (Cheers! :beers:)
So, I’ve spent about a day, as usual with trials end errors, reading all the stuff I could find about how to change default materials.
This scene shows how to re-create a default material (Lambert in my case) with THREE.ShaderMaterial() and add some custom functionality (for example, kind of a clipping sphere) to it. I can’t say that the approach I used here is right or correct, but, at least, it gave the result I’ve expected :slight_smile:

Have joy and relax with this scene :wink:

PS In Firefox music starts automatically. In Chrome, click the round button at the top-left corner and hit “play”.

15 Likes

Cool! Nice job with the clipping sphere, I had no idea it would be so simple. Also interesting material generator, I always like seeing people picking apart three.js in different ways. Thanks for sharing!

1 Like

@bitsofcode
Thanks :beers: :
I like to share what I’ve learned and to do it with interesting and easily readable examples. I think of them as of tutorials :slight_smile: Thus, people will spend less time for solving the same question/problem which I’ve bumped into :slight_smile:

2 Likes

Related SO answer:

1 Like

That’s a great solution.:+1:

I had to try it out right away.
It also works great with other geometries:

2 Likes

Great example - still new to shaders, how would i apply a texture to the shader being clipped?

Hi,
You might want to check out this link on some discussing that exact thing with an example fiddle to boot.
Link to thread post

Thanks for your help! I must admit im a total newb when it comes to shader and not sure how to apply this example you shared.

This is what i have so far from the orb example - how can I add params.map in this example to get the texture. Again thanks for your help and sharing the example!

Preformatted text

// where do i add params.map?

function getMaterialMap(params) {

var inside = params.inside === undefined ? true : params.inside;
inside = inside ? 1 : -1;


var diffuse = params.diffuse === undefined ? 0xffffff : params.diffuse;
var diffuseBack = params.diffuseBack === undefined ? diffuse : params.diffuseBack;

var inside = params.inside === undefined ? true : params.inside;
inside = inside ? 1 : -1;

let lambert = new THREE.ShaderMaterial({
    uniforms: THREE.UniformsUtils.merge([THREE.ShaderLib.lambert.uniforms, {
        clippingSphere: {
            value: new THREE.Vector4()
        },
        diffuseBack: {
            value: new THREE.Color()
        },
        texture: { type: 't', value: params.map }

    }]),

    vertexShader: THREE.ShaderLib.lambert.vertexShader
        .replace(/varying vec3 vLightFront;/g, 'varying vec3 vLightFront;\nvarying vec4 worldPosition;')
        .replace(/#include <worldpos_vertex>/g, 'worldPosition = modelMatrix * vec4( transformed, 1.0 );'),

    fragmentShader: THREE.ShaderLib.lambert.fragmentShader
        .replace(/uniform float opacity;/g, 'uniform float opacity;\nuniform vec4 clippingSphere;\nuniform vec3 diffuseBack;')
        .replace(/varying vec3 vLightFront;/g, 'varying vec3 vLightFront;\nvarying vec4 worldPosition;')
        .replace(/#include <clipping_planes_fragment>/g, '#include <clipping_planes_fragment>\n if (distance(worldPosition.xyz, clippingSphere.xyz) * sign(clippingSphere.w) > clippingSphere.w) discard;')
        .replace(/#include <dithering_fragment>/g, '#include <dithering_fragment>\n if (!gl_FrontFacing) gl_FragColor.xyz = diffuseBack;'),

    lights: true,

    side: THREE.DoubleSide,

    flatShading: false
});

lambert.uniforms.clippingSphere.value.set(0, 0, 0, sphereRadius.value * inside);
// lambert.map = params.map
lambert.uniforms.diffuse.value.set(diffuse);
lambert.uniforms.diffuseBack.value.set(diffuseBack);



return lambert;

}