Fresnel Shader or similar effect

Hi,

is there already a build in Shader or alike which I could use to achieve the following effect:image005

It´s a fresnel Shader, shading the sphere/object brighter to the edges.

Or is there similar to achive this effect?

I just saw that someone has created sort of effect for Babylon.js (last Shader in the article):

Do we have similar or same same in Threejs?

No, but it’s not hard to port the code to a three.js shader material:

2 Likes

Here’s one that extends a standard material and works with transformations

https://codepen.io/Fyrestar/pen/RzVLYd

Or using standard materials with a fresnel plugin

https://codepen.io/Fyrestar/pen/oNvKGML

4 Likes

Sorry, I know absolutely nothing about writing shaders, just want to know if there is a way to change the colour of the Fresnel Effect to something else other than white with your plugin. I’ve been playing around with your plugin for a while but couldn’t figure out, thanks!

Yes, just add a uniform adding it scaled by the fresnel value

Notice it depends on how you want to use it, by adding it earlier to diffuseColor instead gl_FragColor (the final output) it would be shaded/controlled by the light system, gl_FragColor makes it independent of it.

7 Likes

Wasn’t expecting you to actually reply, thank you so much :100:

Hey Mr , why the pen look black ?

There is no gl_FragColor = vec4( outgoingLight, diffuseColor.a ); in phong frag shader anymore.
Thus, no replace:

fragment: {
        'gl_FragColor = vec4( outgoingLight, diffuseColor.a );' : `

gl_FragColor.rgb +=  ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0) ) * fresnelColor;

`
      }

solved it

fragment: {

    'vec4 diffuseColor = vec4( diffuse, opacity );': `

    diffuseColor.rgb +=  ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0) ) * fresnelColor;`},

  // Uniforms (will be applied to existing or added)

  uniforms: {

    diffuse: new THREE.Color('black'),

    fresnelColor: new THREE.Color('blue')

  }

Apologies for replying to you directly, but I think your code might be exactly what I’m trying to achieve.

I’m trying to achieve a look like the third bubble from this picture, transparent material with white fresnel basicaly. I actually found a few routes to apply a shader using ShaderFrog which is another tool that has been written to try to combine shaders from Shadertoy into ThreeJS, this is the closest one that I’ve found and I’ve got it working, but crucially it’s breaking my animations, and that seems like it’s a thing with some shaders and skinned animations.

I found these replies of yours, and I can see the preview for the Codepen, but when I actually open them, none of them are working with Fresnel effect, and I just have 0 idea about how shaders work to understand what I’m doing to try to fix them.

Is there any chance you can help me?

Thanks for the hint, i fixed it. There been changes to the code in the phong built-in material (in the latest releases of THREE), i just switched it to the standard material, for the phong just the replacement line would be required to changed to the new.

Thanks for getting back to me so quick, and thanks for updating your reply, the codepen I can see works now!

I’ve just tried copying your material code from the codepen into my example, but it’s just a solid colour for me, I’m getting this warning in the console, is this something that I’ve not installed properly about it? I’ve got ThreeJS installed from composer so if I have to patch anything I’ll have to do that manually

THREE.WebGLProgram: Program Info Log: WARNING: Output of vertex shader 'vEye' not read by fragment shader
WARNING: Output of vertex shader 'webgl_2edcd1201199cfd9' not read by fragment shader

Can you post the code? Without i can’t tell unfortunately, it looks like you might have changed something.

Does it make an difference where the js files from the ExtendMaterial.js goes? they’re not in the same location as the rest of my ThreeJS files because I’d need to make sure your code is brought in via composer if it needs to be in the same location, so your code being brought in like this (I’ve changed the relevant import function inside of your ExtendMaterial.module.js to match the location of my threejs folder too)

import { patchShader, extendMaterial, CustomMaterial } from '/path/to/my/import/js/ExtendMaterial.module.js';

So I don’t have access to use THREE.extendMaterial, because it says that THREE.extendMaterial isn’t a function, so I was just using extendMaterial on it’s own

This is the part that applying the texture to an item, the only part I changed was the THREE.extendMaterial to extendMaterial, other than that I just copy&pasted the whole lot to test

const mergedMaterial = extendMaterial(THREE.MeshStandardMaterial, {


      // Will be prepended to vertex and fragment code

      header: 'varying vec3 vNN; varying vec3 vEye;',
      fragmentHeader: 'uniform vec3 fresnelColor;',


      // Insert code lines by hinting at a existing

      vertex: {
        // Inserts the line after #include <fog_vertex>
        '#include <fog_vertex>': `


          mat4 LM = modelMatrix;
          LM[2][3] = 0.0;
          LM[3][0] = 0.0;
          LM[3][1] = 0.0;
          LM[3][2] = 0.0;

          vec4 GN = LM * vec4(objectNormal.xyz, 1.0);
          vNN = normalize(GN.xyz);
          vEye = normalize(GN.xyz-cameraPosition);`
      },
      fragment: {
        'gl_FragColor = vec4( outgoingLight, diffuseColor.a );' : `

gl_FragColor.rgb +=  ( 1.0 - -min(dot(vEye, normalize(vNN) ), 0.0) ) * fresnelColor;

`
      },


      // Uniforms (will be applied to existing or added)

      uniforms: {
        diffuse: new THREE.Color( 'black' ),
        fresnelColor: new THREE.Color( 'blue' )
      }


    });

Then later on down in my code I’ve got this, just to test adding it to something before I add it to my actual glb asset

let geometry = new THREE.TorusKnotBufferGeometry( 0.5, 0.3, 128, 16 );
        let mesh = new THREE.Mesh( geometry, mergedMaterial );
        scene.add( mesh );

Yes that’s how the module mess works :sweat_smile:there’s no dynamic monkey patching into the THREE namespacepossible, so it need to be included explicitly.

Which release of THREE are you using? It seems the line it patches

gl_FragColor = vec4( outgoingLight, diffuseColor.a );

is possibly changed, i can take a look if i know the release you’re using. I might add a check for this next to throw an error if it didn’t find a line.

Which release of THREE are you using?

I think I’ve got the dev release, but realistically that’s just because someone else provided a composer setup for me, I suppose more importantly is that a version you would recommend? I’m more than willing to try a different version

Just tested installing r129 that’s referenced from your Codepen example and that’s got rid of the error, but it’s still just a solid colour :frowning:

Do you know if anything like fog or ambient lights etc can affect it? I’m gonna try just making a new javascript code with none of the other things I’ve already got installed on my current setup to see if I can get it working at all

I got it working! (more or less)

I basically had all my current code running from an init() function, so I just made an init_2() and just pasted that whole codepen into it, and that works, the shader is running. So there’s gotta be something in my code which is causing it not to work, so I can try to figure that out.

I can see how I can change the diffuse and the fresnel colour as part of the shader, but are you possibly also able to help me understand how I can update the shader so that it’s more or less transparent into white fresnel, instead of a solid colour into the fresnel? I just have no idea how anybody writes shader code.

Hello !

i’m desperating searching a way to fresnel always look at the screen,
i had tryed many ways,
include technic talked here,
but the fresnel is not viewport faced on when object coords is far from 0,0,0.

i also tested first to via simple ShaderMaterial like :

fragment

varying vec2 vUv;
varying vec3 vPositionW;
varying vec3 vNormalW;
void main() {
  vec3 viewDirectionW = normalize( cameraPosition - vPositionW );
  float fresnelTerm = dot( viewDirectionW, vNormalW );
  fresnelTerm = clamp( 1.0 - fresnelTerm, 0., 1. );
  gl_FragColor = vec4(1.0,0.0,0.0,1.0) * vec4(fresnelTerm);
}

vertex

varying vec3 vPositionW;
varying vec3 vNormalW;

void main() {

  vPositionW = vec3( vec4( position, 1.0 ) * modelMatrix );
  vNormalW = normalize( vec3( vec4( normal, 0.0 ) * modelMatrix ) );

  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

}

Here a pen with two different technics failing :

Hope some shader hero here have an idea :slight_smile: :superhero: