Hello! Thank you very much for reply,
I have been playing around I came with the following code, which still, has problems. I have simplified the solution that I want to achieve dividing the shader that I apply to my mesh in 2 based on the Y position, one half with the classic emission and the other with the fresnel shader:
custom_material = new THREE.MeshStandardMaterial( {
emissiveMap: texture_array[counter], // animated later on
emissive: new THREE.Color(0x123fff),
emissiveIntensity : 1,
} );
custom_material.onBeforeCompile = function ( shader ) {
var a = shader.uniforms;
var b = {
"mRefractionRatio": { value: 1.02 },
"mFresnelBias": { value: 0.1 },
"mFresnelPower": { value: 2.0 },
"mFresnelScale": { value: 1.0 },
"tCube": { value: null }
}
shader.uniforms = THREE.UniformsUtils.merge( [ a, b ] );
shader.vertexShader =
[
"#define PHYSICAL",
"varying vec3 vViewPosition;",
"#ifndef FLAT_SHADED",
"varying vec3 vNormal;",
"#endif",
"#include <common>",
"#include <uv_pars_vertex>",
"#include <uv2_pars_vertex>",
"#include <displacementmap_pars_vertex>",
"#include <color_pars_vertex>",
"#include <fog_pars_vertex>",
"#include <morphtarget_pars_vertex>",
"#include <skinning_pars_vertex>",
"#include <shadowmap_pars_vertex>",
"#include <logdepthbuf_pars_vertex>",
"#include <clipping_planes_pars_vertex>",
// FRESNEL SHADER
"uniform float mRefractionRatio;",
"uniform float mFresnelBias;",
"uniform float mFresnelScale;",
"uniform float mFresnelPower;",
"varying vec3 vReflect;",
"varying vec3 vRefract[3];",
"varying float vReflectionFactor;",
///////
"void main() {",
"#include <begin_vertex>",
"#include <project_vertex>",
"vViewPosition = - mvPosition.xyz;",
"if(vViewPosition.y < 0.0){",
// FRESNEL SHADER
"mvPosition = modelViewMatrix * vec4( position, 1.0 );",
"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
"vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
"vec3 I = worldPosition.xyz - cameraPosition;",
"vReflect = reflect( I, worldNormal );",
"vRefract[0] = refract( normalize( I ), worldNormal, mRefractionRatio );",
"vRefract[1] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.99 );",
"vRefract[2] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.98 );",
"vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), mFresnelPower );",
"gl_Position = projectionMatrix * mvPosition;",
//////////////////
"}",
"else{",
"#include <displacementmap_vertex>",
"#include <morphtarget_vertex>",
"#include <skinning_vertex>",
"#include <logdepthbuf_vertex>",
"#include <clipping_planes_vertex>",
"#include <uv_vertex>",
"#include <uv2_vertex>",
"#include <color_vertex>",
"#include <beginnormal_vertex>",
"#include <morphnormal_vertex>",
"#include <skinbase_vertex>",
"#include <skinnormal_vertex>",
"#include <defaultnormal_vertex>",
"#ifndef FLAT_SHADED",
"vNormal = normalize( transformedNormal );",
"#endif",
"#include <worldpos_vertex>",
"#include <shadowmap_vertex>",
"#include <fog_vertex>",
"}",
"}",
].join( '\n' )
shader.fragmentShader =
[
"#define PHYSICAL",
"uniform vec3 diffuse;",
"uniform vec3 emissive;",
"uniform float roughness;",
"uniform float metalness;",
"uniform float opacity;",
"#ifndef STANDARD",
"uniform float clearCoat;",
"uniform float clearCoatRoughness;",
"#endif",
"varying vec3 vViewPosition;",
"#ifndef FLAT_SHADED",
"varying vec3 vNormal;",
"#endif",
"#include <common>",
"#include <packing>",
"#include <dithering_pars_fragment>",
"#include <color_pars_fragment>",
"#include <uv_pars_fragment>",
"#include <uv2_pars_fragment>",
"#include <map_pars_fragment>",
"#include <alphamap_pars_fragment>",
"#include <aomap_pars_fragment>",
"#include <lightmap_pars_fragment>",
"#include <emissivemap_pars_fragment>",
"#include <bsdfs>",
"#include <cube_uv_reflection_fragment>",
"#include <envmap_pars_fragment>",
"#include <envmap_physical_pars_fragment>",
"#include <fog_pars_fragment>",
"#include <lights_pars_begin>",
"#include <lights_physical_pars_fragment>",
"#include <shadowmap_pars_fragment>",
"#include <bumpmap_pars_fragment>",
"#include <normalmap_pars_fragment>",
"#include <roughnessmap_pars_fragment>",
"#include <metalnessmap_pars_fragment>",
"#include <logdepthbuf_pars_fragment>",
"#include <clipping_planes_pars_fragment>",
// FRESNEL SHADER
"uniform samplerCube tCube;",
"varying vec3 vReflect;",
"varying vec3 vRefract[3];",
"varying float vReflectionFactor;",
////////////////
"void main() {",
"if(vViewPosition.y < 0.0){",
// FRESNEL SHADER
"vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
"vec4 refractedColor = vec4( 1.0 );",
"refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;",
"refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;",
"refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;",
"gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );",
//////
"}",
"else{",
"#include <clipping_planes_fragment>",
"vec4 diffuseColor = vec4( diffuse, opacity );",
"ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
"vec3 totalEmissiveRadiance = emissive;",
"#include <logdepthbuf_fragment>",
"#include <map_fragment>",
"#include <color_fragment>",
"#include <alphamap_fragment>",
"#include <alphatest_fragment>",
"#include <roughnessmap_fragment>",
"#include <metalnessmap_fragment>",
"#include <normal_fragment_begin>",
"#include <normal_fragment_maps>",
"#include <emissivemap_fragment>",
"#include <lights_physical_fragment>",
"#include <lights_fragment_begin>",
"#include <lights_fragment_maps>",
"#include <lights_fragment_end>",
"#include <aomap_fragment>",
"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
"#include <tonemapping_fragment>",
"#include <encodings_fragment>",
"#include <fog_fragment>",
"#include <premultiplied_alpha_fragment>",
"#include <dithering_fragment>",
"}",
"}"
].join( '\n' )
};
This setup breaks completely the fresnel shader and displays the half mesh with pure black and throws the following error more than 200 times: [.WebGL-0x80eb5969c00]RENDER WARNING: there is no texture bound to the unit 1
My ideal solution though would be to have a combination with them both which outputs the gl_FragColor combining both fresnel and standard. This way, when the emission channel has something inside outputs the fresnel shader with shine, and when the emission channel has nothing to apply, then the fresnel shader is purely shown:
fresnel_gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );
standard_gl_FragColor = vec4( outgoingLight, diffuseColor.a );
// and here the magic
gl_FragColor = fresnel_gl_FragColor + standard_gl_FragColor (combining them both somehow)
But I don know how to combine the color the fresnel outputs + the emission the standard material has, which sometimes is full emision and sometimes is cero (which will show purely the fresnel).
This is my first time using GLSL and I feel quite lost in this regard.
I attach some pictures to illustrate better the issue:
This picture shows the current situation of the code: top half of the mesh should have the fresnel shader but is black and the bottom part of the mesh shows the correct emissiveMap over no map at all, that is why is white
The following picture shows the fresnel shader working correctly when I eliminate the outgoingLight
from the bottom part, therefore removing the emissiveMap and leaving only the pure white material.
As said, the perfect solution would be combining them boht, have the fresnel shader applied to the entire mesh and the emission map, which is animated, will pass sometimes in certain areas with full emission in another color and will leave the mesh like with the effect of a scanner light scanning it.
Sorry for the long post and thanks!