i'd create shadermaterial has lighting meshlambertmaterial. i've created vertex , fragment shader, , included uniforms three.shaderlib[ 'lambert' ].uniforms in shadermaterial.
correct me if i'm wrong, believe next step add lighting merge fragment , vertex shader code used in meshlambertmaterial custom shader code.
merging vertex shader straightforward. however, in fragment shader, how provide base color (which generated shader code) code in meshlambert_frag.glsl apply lighting calculations? fragment shader this:
// custom shader code before main function // meshlambert_frag.glsl shader code before main function void main { vec4 mybasecolor ... // set custom fragment shader code // meshlambert_frag.glsl code in main function use mybasecolor base // color lighting calculations before setting gl_fragcolor }
additionally, copying such large chunk of code (from meshlambert shaders) bad practice in case? better solution?
the way pass color fragment shader code used in meshlambertmaterial modify diffusecolor variable. can set color in fragment shader using diffusecolor.rgb *= avec3. here's shader code looks like:
// vertex #define lambert varying vec3 vlightfront; #ifdef double_sided varying vec3 vlightback; #endif #include <common> #include <uv_pars_vertex> #include <uv2_pars_vertex> #include <envmap_pars_vertex> #include <bsdfs> #include <lights_pars> #include <color_pars_vertex> #include <morphtarget_pars_vertex> #include <skinning_pars_vertex> #include <shadowmap_pars_vertex> #include <logdepthbuf_pars_vertex> #include <clipping_planes_pars_vertex> varying vec3 vertexcolor; varying vec2 vuv; varying vec4 worldposition; void main() { vertexcolor = vec3(255, 100, 0); vuv = uv; worldposition = modelmatrix * vec4( position, 1.0 ); #include <uv_vertex> #include <uv2_vertex> #include <color_vertex> #include <beginnormal_vertex> #include <morphnormal_vertex> #include <skinbase_vertex> #include <skinnormal_vertex> #include <defaultnormal_vertex> #include <begin_vertex> #include <morphtarget_vertex> #include <skinning_vertex> #include <project_vertex> #include <logdepthbuf_vertex> #include <clipping_planes_vertex> #include <worldpos_vertex> #include <envmap_vertex> #include <lights_lambert_vertex> #include <shadowmap_vertex> } // fragment uniform float time; varying vec2 vuv; vec4 permute( vec4 x ) { return mod( ( ( x * 34.0 ) + 1.0 ) * x, 289.0 ); } vec4 taylorinvsqrt( vec4 r ) { return 1.79284291400159 - 0.85373472095314 * r; } float snoise( vec3 v ) { const vec2 c = vec2( 1.0 / 6.0, 1.0 / 3.0 ); const vec4 d = vec4( 0.0, 0.5, 1.0, 2.0 ); // first corner vec3 = floor( v + dot( v, c.yyy ) ); vec3 x0 = v - + dot( i, c.xxx ); // other corners vec3 g = step( x0.yzx, x0.xyz ); vec3 l = 1.0 - g; vec3 i1 = min( g.xyz, l.zxy ); vec3 i2 = max( g.xyz, l.zxy ); vec3 x1 = x0 - i1 + 1.0 * c.xxx; vec3 x2 = x0 - i2 + 2.0 * c.xxx; vec3 x3 = x0 - 1. + 3.0 * c.xxx; // permutations = mod( i, 289.0 ); vec4 p = permute( permute( permute( i.z + vec4( 0.0, i1.z, i2.z, 1.0 ) ) + i.y + vec4( 0.0, i1.y, i2.y, 1.0 ) ) + i.x + vec4( 0.0, i1.x, i2.x, 1.0 ) ); // gradients // ( n*n points uniformly on square, mapped onto octahedron.) float n_ = 1.0 / 7.0; // n=7 vec3 ns = n_ * d.wyz - d.xzx; vec4 j = p - 49.0 * floor( p * ns.z *ns.z ); // mod(p,n*n) vec4 x_ = floor( j * ns.z ); vec4 y_ = floor( j - 7.0 * x_ ); // mod(j,n) vec4 x = x_ *ns.x + ns.yyyy; vec4 y = y_ *ns.x + ns.yyyy; vec4 h = 1.0 - abs( x ) - abs( y ); vec4 b0 = vec4( x.xy, y.xy ); vec4 b1 = vec4( x.zw, y.zw ); vec4 s0 = floor( b0 ) * 2.0 + 1.0; vec4 s1 = floor( b1 ) * 2.0 + 1.0; vec4 sh = -step( h, vec4( 0.0 ) ); vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww; vec3 p0 = vec3( a0.xy, h.x ); vec3 p1 = vec3( a0.zw, h.y ); vec3 p2 = vec3( a1.xy, h.z ); vec3 p3 = vec3( a1.zw, h.w ); // normalise gradients vec4 norm = taylorinvsqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) ); p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w; // mix final noise value vec4 m = max( 0.6 - vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 ); m = m * m; return 42.0 * dot( m*m, vec4( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ), dot( p3, x3 ) ) ); } varying vec4 worldposition; uniform vec3 diffuse; uniform vec3 emissive; uniform float opacity; varying vec3 vlightfront; #ifdef double_sided varying vec3 vlightback; #endif #include <common> #include <packing> #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 <envmap_pars_fragment> #include <bsdfs> #include <lights_pars> #include <fog_pars_fragment> #include <shadowmap_pars_fragment> #include <shadowmask_pars_fragment> #include <specularmap_pars_fragment> #include <logdepthbuf_pars_fragment> #include <clipping_planes_pars_fragment> float sigmoid(float x) { return x / (1.0 + abs(x)); } varying vec3 vertexcolor; void main() { #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> if(worldposition.y > 300.0) { //snow float noise = snoise(vec3(worldposition.x * 4.0, worldposition.y * 4.0, worldposition.z * 4.0))/20.0; diffusecolor.rgb *= vec3(1.0 - noise, 1.0 - noise, 1.0 - noise); } else if (worldposition.y > 100.0) { // dirt float scale = 5.0; float effectscale = 0.2; float noise = (snoise(vec3(worldposition.x * scale, worldposition.y * scale, worldposition.z * scale)) - 0.2) * effectscale; noise = sigmoid(noise); diffusecolor.rgb *= vec3(0.54 + noise, 0.27 + noise, 0.07 + noise); } else { // grass float scale = 4.0; float effectscale = 0.08; float noise = (snoise(vec3(worldposition.x * scale, worldposition.y * scale, worldposition.z * scale)) - 0.2) * effectscale; diffusecolor.rgb *= vec3(0, 0.48 + noise, 0.05 + noise); } #include <color_fragment> #include <alphamap_fragment> #include <alphatest_fragment> #include <specularmap_fragment> #include <emissivemap_fragment> // accumulation reflectedlight.indirectdiffuse = getambientlightirradiance( ambientlightcolor ); #include <lightmap_fragment> reflectedlight.indirectdiffuse *= brdf_diffuse_lambert( diffusecolor.rgb ); #ifdef double_sided reflectedlight.directdiffuse = ( gl_frontfacing ) ? vlightfront : vlightback; #else reflectedlight.directdiffuse = vlightfront; #endif reflectedlight.directdiffuse *= brdf_diffuse_lambert( diffusecolor.rgb ) * getshadowmask(); // modulation #include <aomap_fragment> vec3 outgoinglight = reflectedlight.directdiffuse + reflectedlight.indirectdiffuse + totalemissiveradiance; #include <normal_flip> #include <envmap_fragment> gl_fragcolor = vec4( outgoinglight, diffusecolor.a ); #include <premultiplied_alpha_fragment> #include <tonemapping_fragment> #include <encodings_fragment> #include <fog_fragment> }
result doesn't great concept of having custom shader lighting there. have copy on code used in meshlambertshader , modify
diffusecolor.rgb
. reduce amount of code in shader, add shader chunks (using three.shaderchunk array) of meshlambert shader code. add #includes in shader correspond names of shader chunks pushed. example, add following javascript file:
three.shaderchunk["meshlambert_premain_fragment"] = ` uniform vec3 diffuse; uniform vec3 emissive; uniform float opacity; varying vec3 vlightfront; #ifdef double_sided varying vec3 vlightback; #endif #include <common> #include <packing> #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 <envmap_pars_fragment> #include <bsdfs> #include <lights_pars> #include <fog_pars_fragment> #include <shadowmap_pars_fragment> #include <shadowmask_pars_fragment> #include <specularmap_pars_fragment> #include <logdepthbuf_pars_fragment> #include <clipping_planes_pars_fragment> `;
and later, in shader want use meshlambert lighting, write following, reducing amount of code in shader file:
#include <meshlambert_premain_fragment>
Comments
Post a Comment