0

My goal is to render two different textures on one object.

I'm trying to render the earth with a night texture and a day texture, similar to this: http://stuffin.space .

The problem is that I'd still like to use the Three.js classes, so that I can add a bump map and phong reflection using the MeshPhongMaterial class, without having to write the whole shaders.

I thought about having two objects with one being transparent on one side or extend the MeshPhongMaterial class, but it seems to be pretty hard.

Is there a simple solution to solve this with three.js ?

gman
  • 100,619
  • 31
  • 269
  • 393
Mattia
  • 179
  • 15
  • 1
    3 ways I can think of. Create your own shader. Alter a built in shader. Combine the textures on a canvas and use the resulting image as the texture. – 2pha Oct 06 '19 at 23:24

1 Answers1

2

You can assign a function to a material's onBeforeCompile property.

It get's passed an object that has the source for both the vertex and fragment shaders and the uniforms. As in

someMaterial.onBeforeCompile = function(shader) {
  console.log(shader.vertexShader);
  console.log(shader.fragmentShader);
});

You modify the shaders as in

someMaterial.onBeforeCompile = function(shader) {
  shader.fragmentShader = shader.fragmentShader.replace(thingToReplace, replacement);
});

The shader source is "pre expanded" meaning it's a three.js specific format. For example the default fragment shader source when run above might look something like

#include <common>
#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 <envmap_pars_fragment>
#include <fog_pars_fragment>
#include <specularmap_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
void main() {
    #include <clipping_planes_fragment>
    vec4 diffuseColor = vec4( diffuse, opacity );
    #include <logdepthbuf_fragment>
    #include <map_fragment>
    #include <color_fragment>
    #include <alphamap_fragment>
    #include <alphatest_fragment>
    #include <specularmap_fragment>
    ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
    #ifdef USE_LIGHTMAP
        reflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
    #else
        reflectedLight.indirectDiffuse += vec3( 1.0 );
    #endif
    #include <aomap_fragment>
    reflectedLight.indirectDiffuse *= diffuseColor.rgb;
    vec3 outgoingLight = reflectedLight.indirectDiffuse;
    #include <envmap_fragment>
    gl_FragColor = vec4( outgoingLight, diffuseColor.a );
    #include <premultiplied_alpha_fragment>
    #include <tonemapping_fragment>
    #include <encodings_fragment>
    #include <fog_fragment>
}

Looking through all those snippets you can try to figure out which part to replace. My guess for you is the #include <color_fragment> part based on this article

gman
  • 100,619
  • 31
  • 269
  • 393