I've created a custom shader to be able to use a BlendMap with 4 different textures but I'm unable to get the shadows/lightning effects to work with it.
What am I missing here? Or is there some other way I can achieve same functionality?
Mesh creation method below which shows all textures blended properly.
// Creates the ground
function CreateGround() {
var uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib["lights"],
THREE.UniformsLib["shadowmap"],
{
TextureBackground: { type: "t", value: null },
TextureR: { type: "t", value: null },
TextureG: { type: "t", value: null },
TextureB: { type: "t", value: null },
TextureBlendMap: { type: "t", value: null }
}]);
var shaderMaterial;
try {
shaderMaterial = new THREE.ShaderMaterial({
lights: true,
uniforms: uniforms,
vertexShader: BlendMapVertexShader,
fragmentShader: BlendMapFragmentShader
});
} catch (e) {
alert("Error 'CreateGround' : GPU Shader couldn't compile");
}
shaderMaterial.uniforms.TextureBlendMap.value = _TextureBlendMap;
shaderMaterial.uniforms.TextureBackground.value = _TextureSand;
shaderMaterial.uniforms.TextureR.value = _TextureClay;
shaderMaterial.uniforms.TextureG.value = _TextureClay;
shaderMaterial.uniforms.TextureB.value = _TextureRock;
var geometry = new THREE.BoxGeometry(GROUND_SIZE, GROUND_HEIGHT, GROUND_SIZE);
var mesh = new THREE.Mesh(geometry, shaderMaterial);
mesh.castShadow = false;
mesh.receiveShadow = true;
return mesh;
}
And this is my current shader:
BlendMapVertexShader = [
THREE.ShaderChunk["shadowmap_pars_vertex"],
"varying vec2 vUv;",
"varying vec3 vPosition;",
"void main( void ) {",
"vUv = uv;",
"vPosition = position;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1);",
THREE.ShaderChunk["begin_vertex"],
THREE.ShaderChunk["worldpos_vertex"],
THREE.ShaderChunk["shadowmap_vertex"],
"}",
].join("\n");
BlendMapFragmentShader = [
THREE.ShaderChunk["common"],
THREE.ShaderChunk["packing"],
THREE.ShaderChunk["shadowmap_pars_fragment"],
"varying vec2 vUv;",
"varying vec3 vPosition;",
"uniform sampler2D TextureBlendMap;",
"uniform sampler2D TextureBackground;",
"uniform sampler2D TextureR;",
"uniform sampler2D TextureG;",
"uniform sampler2D TextureB;",
"void main() {",
"vec4 cBlend = texture2D(TextureBlendMap, vUv);",
"float bText = 1.0 - (cBlend.r + cBlend.g + cBlend.b);",
"vec2 tiledCoords = vUv * 40.0;",
"vec4 cBack = texture2D(TextureBackground, tiledCoords) * bText;",
"vec4 cR = texture2D(TextureR, tiledCoords) * cBlend.r;",
"vec4 cG = texture2D(TextureG, tiledCoords) * cBlend.g;",
"vec4 cB = texture2D(TextureB, tiledCoords) * cBlend.b;",
"vec4 cTot = cBack + cR + cG + cB;",
"gl_FragColor = cTot;",
THREE.ShaderChunk["shadowmap_fragment"],
"}",
].join("\n");
I have no errors nor warnings in the browser.
three.js r85Dev
Alright. I ended up copying the PHONG shader and then override the diffuse color input. Solution below.
This is the method to create the mesh with blendmapshader
// Creates the ground
function CreateGround(material) {
var uniforms = THREE.UniformsUtils.merge([
THREE.UniformsLib["common"],
THREE.UniformsLib["aomap"],
THREE.UniformsLib["lightmap"],
THREE.UniformsLib["emissivemap"],
THREE.UniformsLib["bumpmap"],
THREE.UniformsLib["normalmap"],
THREE.UniformsLib["displacementmap"],
THREE.UniformsLib["gradientmap"],
THREE.UniformsLib["fog"],
THREE.UniformsLib["lights"],
{
emissive: { type: "c", value: new THREE.Color(0x000000) },
specular: { type: "c", value: new THREE.Color(0x111111) },
shininess: { type: "f", value: 30 },
TextureBackground: { type: "t", value: null },
TextureR: { type: "t", value: null },
TextureG: { type: "t", value: null },
TextureB: { type: "t", value: null },
TextureBlendMap: { type: "t", value: null },
}]);
var shaderMaterial;
try {
shaderMaterial = new THREE.ShaderMaterial({
lights: true,
uniforms: uniforms,
vertexShader: BlendMapVertexShader,
fragmentShader: BlendMapFragmentShader
});
} catch (e) {
alert("Error 'CreateGround' : GPU Shader couldn't compile");
}
shaderMaterial.uniforms.TextureBlendMap.value = _TextureBlendMap;
shaderMaterial.uniforms.TextureBackground.value = _TextureSand;
shaderMaterial.uniforms.TextureR.value = _TextureClay;
shaderMaterial.uniforms.TextureG.value = _TextureGrass;
shaderMaterial.uniforms.TextureB.value = _TextureSandRock;
var geometry = new THREE.BoxGeometry(GROUND_SIZE, GROUND_HEIGHT, GROUND_SIZE);
var mesh = new THREE.Mesh(geometry, shaderMaterial);
mesh.castShadow = false;
mesh.receiveShadow = true;
return mesh;
}
And this is the modified PHONG shader:
BlendMapVertexShader = [
"#define PHONG",
"varying vec3 vViewPosition;",
"varying vec2 vUv;",
"#ifndef FLAT_SHADED",
"varying vec3 vNormal;",
"#endif",
THREE.ShaderChunk["common"],
THREE.ShaderChunk["uv_pars_vertex"],
THREE.ShaderChunk["uv2_pars_vertex"],
THREE.ShaderChunk["displacementmap_pars_vertex"],
THREE.ShaderChunk["envmap_pars_vertex"],
THREE.ShaderChunk["color_pars_vertex"],
THREE.ShaderChunk["morphtarget_pars_vertex"],
THREE.ShaderChunk["skinning_pars_vertex"],
THREE.ShaderChunk["shadowmap_pars_vertex"],
THREE.ShaderChunk["logdepthbuf_pars_vertex"],
THREE.ShaderChunk["clipping_planes_pars_vertex"],
"void main() {",
THREE.ShaderChunk["uv_vertex"],
THREE.ShaderChunk["uv2_vertex"],
THREE.ShaderChunk["color_vertex"],
THREE.ShaderChunk["beginnormal_vertex"],
THREE.ShaderChunk["morphnormal_vertex"],
THREE.ShaderChunk["skinbase_vertex"],
THREE.ShaderChunk["skinnormal_vertex"],
THREE.ShaderChunk["defaultnormal_vertex"],
"#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED",
"vNormal = normalize( transformedNormal );",
"#endif",
THREE.ShaderChunk["begin_vertex"],
THREE.ShaderChunk["displacementmap_vertex"],
THREE.ShaderChunk["morphtarget_vertex"],
THREE.ShaderChunk["skinning_vertex"],
THREE.ShaderChunk["project_vertex"],
THREE.ShaderChunk["logdepthbuf_vertex"],
THREE.ShaderChunk["clipping_planes_vertex"],
"vUv = uv;",
"vViewPosition = - mvPosition.xyz;",
THREE.ShaderChunk["worldpos_vertex"],
THREE.ShaderChunk["envmap_vertex"],
THREE.ShaderChunk["shadowmap_vertex"],
"}",
].join("\n");
BlendMapFragmentShader = [
"#define PHONG",
"varying vec2 vUv;",
"uniform vec3 diffuse;",
"uniform vec3 emissive;",
"uniform vec3 specular;",
"uniform float shininess;",
"uniform float opacity;",
"uniform sampler2D TextureBlendMap;",
"uniform sampler2D TextureBackground;",
"uniform sampler2D TextureR;",
"uniform sampler2D TextureG;",
"uniform sampler2D TextureB;",
THREE.ShaderChunk["common"],
THREE.ShaderChunk["packing"],
THREE.ShaderChunk["color_pars_fragment"],
THREE.ShaderChunk["uv_pars_fragment"],
THREE.ShaderChunk["uv2_pars_fragment"],
THREE.ShaderChunk["map_pars_fragment"],
THREE.ShaderChunk["alphamap_pars_fragment"],
THREE.ShaderChunk["aomap_pars_fragment"],
THREE.ShaderChunk["lightmap_pars_fragment"],
THREE.ShaderChunk["emissivemap_pars_fragment"],
THREE.ShaderChunk["envmap_pars_fragment"],
THREE.ShaderChunk["fog_pars_fragment"],
THREE.ShaderChunk["bsdfs"],
THREE.ShaderChunk["lights_pars"],
THREE.ShaderChunk["lights_phong_pars_fragment"],
THREE.ShaderChunk["shadowmap_pars_fragment"],
THREE.ShaderChunk["bumpmap_pars_fragment"],
THREE.ShaderChunk["normalmap_pars_fragment"],
THREE.ShaderChunk["specularmap_pars_fragment"],
THREE.ShaderChunk["logdepthbuf_pars_fragment"],
THREE.ShaderChunk["clipping_planes_pars_fragment"],
"void main() {",
THREE.ShaderChunk["clipping_planes_fragment"],
"// THIS IS CUSTOM CODE TO OVERRIDE THE DIFFUSE COLOR WITH BLENDMAP TEXTURES",
"vec4 cBlend = texture2D(TextureBlendMap, vUv);",
"float bText = 1.0 - (cBlend.r + cBlend.g + cBlend.b);",
"vec2 tiledCoords = vUv * 40.0;",
"vec4 cBack = texture2D(TextureBackground, tiledCoords) * bText;",
"vec4 cR = texture2D(TextureR, tiledCoords) * cBlend.r;",
"vec4 cG = texture2D(TextureG, tiledCoords) * cBlend.g;",
"vec4 cB = texture2D(TextureB, tiledCoords) * cBlend.b;",
"vec4 cTot = cBack + cR + cG + cB;",
"vec4 diffuseColor = vec4( diffuse, opacity );",
"diffuseColor.r = cTot.r;",
"diffuseColor.g = cTot.g;",
"diffuseColor.b = cTot.b;",
"ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
"vec3 totalEmissiveRadiance = emissive;",
THREE.ShaderChunk["logdepthbuf_fragment"],
THREE.ShaderChunk["map_fragment"],
THREE.ShaderChunk["color_fragment"],
THREE.ShaderChunk["alphamap_fragment"],
THREE.ShaderChunk["alphatest_fragment"],
THREE.ShaderChunk["specularmap_fragment"],
THREE.ShaderChunk["normal_flip"],
THREE.ShaderChunk["normal_fragment"],
THREE.ShaderChunk["emissivemap_fragment"],
"// accumulation",
THREE.ShaderChunk["lights_phong_fragment"],
THREE.ShaderChunk["lights_template"],
"// modulation",
THREE.ShaderChunk["aomap_fragment"],
"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",
THREE.ShaderChunk["envmap_fragment"],
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
THREE.ShaderChunk["premultiplied_alpha_fragment"],
THREE.ShaderChunk["tonemapping_fragment"],
THREE.ShaderChunk["encodings_fragment"],
THREE.ShaderChunk["fog_fragment"],
"}",
].join("\n");
just add shaderMaterial.lights = true;, i had encountered the same problem as you. here is a complete typescript class wrote by myself: threejs git issue
this is the full code:
import * as THREE from 'three';
export class TerrainMaterial extends THREE.ShaderMaterial {
public constructor() {
super({
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib.fog,
THREE.UniformsLib.lights,
{
diffuse: { value: new THREE.Color(0xeeeeee) },
opacity: { value: 1.0 },
emissive: { value: new THREE.Color(0x000000) },
specular: { value: new THREE.Color(0x111111) },
shininess: { value: 0 },
offsetRepeat: { value: new THREE.Vector4(0, 0, 1, 1) },
map1: { value: null },
map2: { value: null },
map3: { value: null },
map1Normal: { value: null },
map2Normal: { value: null },
map3Normal: { value: null },
map1HeightRange: { value: 0 },
map2HeightRange: { value: 0 },
map3HeightRange: { value: 0 }
}
]),
vertexShader: [
"varying vec3 vNormal;",
"varying vec3 vViewPosition;",
"varying vec3 fPosition;",
"varying vec2 vUv;",
"uniform vec4 offsetRepeat;",
THREE.ShaderChunk.shadowmap_pars_vertex,
//THREE.ShaderChunk.logdepthbuf_pars_vertex,
THREE.ShaderChunk.fog_pars_vertex,
"void main(){",
THREE.ShaderChunk.beginnormal_vertex,
THREE.ShaderChunk.defaultnormal_vertex,
"vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
"vNormal = normalize( transformedNormal );",
THREE.ShaderChunk.begin_vertex,
THREE.ShaderChunk.project_vertex,
//THREE.ShaderChunk.logdepthbuf_vertex,
"fPosition = position;",
"vViewPosition = - mvPosition.xyz;",
THREE.ShaderChunk.worldpos_vertex,
THREE.ShaderChunk.shadowmap_vertex,
THREE.ShaderChunk.fog_vertex,
"}"
].join("\n"),
fragmentShader: [
"uniform vec3 diffuse;",
"uniform vec3 emissive;",
"uniform vec3 specular;",
"uniform float shininess;",
"uniform float opacity;",
"uniform sampler2D map1;",
"uniform sampler2D map2;",
"uniform sampler2D map3;",
"uniform sampler2D map1Normal;",
"uniform sampler2D map2Normal;",
"uniform sampler2D map3Normal;",
"uniform float map1HeightRange;",
"uniform float map2HeightRange;",
"uniform float map3HeightRange;",
"varying vec2 vUv;",
"varying vec3 fPosition;",
THREE.ShaderChunk.common,
THREE.ShaderChunk.packing,
THREE.ShaderChunk.dithering_pars_fragment,
THREE.ShaderChunk.emissivemap_pars_fragment,
THREE.ShaderChunk.fog_pars_fragment,
THREE.ShaderChunk.bsdfs,
THREE.ShaderChunk.lights_pars,
THREE.ShaderChunk.lights_phong_pars_fragment,
THREE.ShaderChunk.shadowmap_pars_fragment,
THREE.ShaderChunk.specularmap_pars_fragment,
//THREE.ShaderChunk.logdepthbuf_pars_fragment,
"vec3 perturbNormal2Arb( vec3 normalColor, vec3 eye_pos, vec3 surf_norm ) {",
"vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );",
"vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );",
"vec2 st0 = dFdx( vUv.st );",
"vec2 st1 = dFdy( vUv.st );",
"vec3 S = normalize( q0 * st1.t - q1 * st0.t );",
"vec3 T = normalize( -q0 * st1.s + q1 * st0.s );",
"vec3 N = normalize( surf_norm );",
"vec3 mapN = normalColor * 2.0 - 1.0;",
//"mapN.xy = normalScale * mapN.xy;",
"mat3 tsn = mat3( S, T, N );",
"return normalize( tsn * mapN );",
"}",
"void main(){",
"vec4 diffuseColor = vec4( diffuse, opacity );",
"ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
"vec3 totalEmissiveRadiance = emissive;",
//THREE.ShaderChunk.logdepthbuf_fragment,
"vec3 texel;",
"vec3 texelNormal;",
"float amount;",
//need to optimize here, let's say remove if else if else?
"if(fPosition.y < map1HeightRange){",
"texel = texture2D(map1, vUv).rgb;",
"texelNormal = texture2D(map1Normal, vUv).rgb;",
"}",
"else if(fPosition.y < map2HeightRange){",
"amount = (fPosition.y - map1HeightRange) / map1HeightRange;",
"texel = mix(texture2D(map1, vUv), texture2D(map2, vUv), amount).rgb;",
"texelNormal = mix(texture2D(map1Normal, vUv), texture2D(map2Normal, vUv), amount).rgb;",
"}",
"else if(fPosition.y < map3HeightRange){",
"float hStep = map3HeightRange - map2HeightRange;",
"amount = (fPosition.y - hStep) / hStep;",
"texel = mix(texture2D(map2, vUv), texture2D(map3, vUv), amount).rgb;",
"texelNormal = mix(texture2D(map2Normal, vUv), texture2D(map3Normal, vUv), amount).rgb;",
"} else {",
"texel = texture2D(map3, vUv).rgb;",
"texelNormal = texture2D(map3Normal, vUv).rgb;",
"}",
"vec4 texelColor = vec4( texel, 1.0 );",
"texelColor = mapTexelToLinear( texelColor );",
"diffuseColor *= texelColor;",
THREE.ShaderChunk.specularmap_fragment,
"vec3 normal = normalize( vNormal );",
"normal = perturbNormal2Arb( texelNormal.rgb, -vViewPosition, normal );",
THREE.ShaderChunk.emissivemap_fragment,
THREE.ShaderChunk.lights_phong_fragment,
THREE.ShaderChunk.lights_template,
"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;",
"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
THREE.ShaderChunk.tonemapping_fragment,
THREE.ShaderChunk.encodings_fragment,
THREE.ShaderChunk.fog_fragment,
THREE.ShaderChunk.premultiplied_alpha_fragment,
THREE.ShaderChunk.dithering_fragment,
"}"
].join("\n")
});
this.defaultAttributeValues = null;
this.fog = true;
this.lights = true;
this.extensions.derivatives = true;
this.extensions.shaderTextureLOD = true;
}
public setOffsetRepeat(ofX: number, ofY: number, rpX: number, rpY: number):void {
this.uniforms["offsetRepeat"].value.set(ofX, ofY, rpX, rpY);
this.setRepeat(this.uniforms["map1"].value, this.uniforms["map1Normal"].value);
this.setRepeat(this.uniforms["map2"].value, this.uniforms["map2Normal"].value);
this.setRepeat(this.uniforms["map3"].value, this.uniforms["map3Normal"].value);
this.needsUpdate = true;
}
private setRepeat(map: THREE.Texture, normal: THREE.Texture): void {
let v4: THREE.Vector4 = this.uniforms["offsetRepeat"].value;
if (v4.y != 1 || v4.z != 1) {
if (map) map.wrapS = map.wrapT = THREE.RepeatWrapping;
if (normal) normal.wrapS = normal.wrapT = THREE.RepeatWrapping;
}
}
public setMap1(map: THREE.Texture, normal: THREE.Texture, heightRange: number) {
this.setRepeat(map, normal);
this.uniforms["map1"].value = map;
this.uniforms["map1Normal"].value = normal;
this.uniforms["map1HeightRange"].value = heightRange;
this.needsUpdate = true;
}
public setMap2(map: THREE.Texture, normal: THREE.Texture, heightRange: number) {
this.setRepeat(map, normal);
this.uniforms["map2"].value = map;
this.uniforms["map2Normal"].value = normal;
this.uniforms["map2HeightRange"].value = heightRange;
this.needsUpdate = true;
}
public setMap3(map: THREE.Texture, normal: THREE.Texture, heightRange: number) {
this.setRepeat(map, normal);
this.uniforms["map3"].value = map;
this.uniforms["map3Normal"].value = normal;
this.uniforms["map3HeightRange"].value = heightRange;
this.needsUpdate = true;
}
}
and the usage:
let loader = new THREE.TextureLoader();
let terrainMat = new TerrainMaterial();
terrainMat.dithering = Config.DITHERING;
terrainMat.setOffsetRepeat(0, 0, 80, 80);
let map1 = loader.load("images/maps/ground/shatter.jpg");
let map1Normal = loader.load("images/maps/ground/shatter_normal.png");
map1.anisotropy = map1Normal.anisotropy = anisotropy;
let map2 = loader.load("images/maps/ground/earth.jpg");
let map2Normal = loader.load("images/maps/ground/earth_normal.png");
map2.anisotropy = map2Normal.anisotropy = anisotropy;
let map3 = loader.load("images/maps/ground/moss.jpg");
let map3Normal = loader.load("images/maps/ground/moss_normal.png");
map3.anisotropy = map3Normal.anisotropy = anisotropy;
let hStep = GroundGeometry.MAX_HEIGHT / 4;
terrainMat.setMap1(map1, map1Normal, hStep);
terrainMat.setMap2(map2, map2Normal, hStep * 2);
terrainMat.setMap3(map3, map3Normal, hStep * 4);
//note: replace new THREE.PlaneGeometry with your terrain geometry so the mateiral can detect height change. otherise the plane will be filled full with the same 1 map.
let p = new THREE.Mesh(new THREE.PlaneGeometry(900, 900, 257, 257), terrainMat);
p.geometry.rotateX(-NumberConsts.PI_2);
scene.add(p);
and the result:
click to see image (i don't have the privilege to embed images yet)
This is kind of a long shot, but if all objects in your scene use this material, then there shouldn't be any shadows because nothing casts shadows.
mesh.castShadow = false;
mesh.receiveShadow = true;
But i'm guessing that in the rest of your code you have some Meshes set to cast shadows.
I don't know if i fully understand the ShaderChunk methods, but it looks like it's just a series of defined strings that you drop into the middle of your own text, this part looked a little suspicious:
"gl_FragColor = cTot;",
THREE.ShaderChunk["shadowmap_fragment"],
But I don't see how whatever the shadowmap_fragment does has a chance to mix with our existing value for gl_FragColor. In the shadowmap_fragment src it runs:
void main() {
gl_FragColor = vec4( 0.0, 0.0, 0.0, opacity * ( 1.0 - getShadowMask() ) );
}
where getShadowMask() does a lot of magic with lights to return a float. So I don't see how your assigned gl_FragColor gets mixed with what the shadowmap_fragment returns. What about changing the order:
THREE.ShaderChunk["shadowmap_fragment"],
"gl_FragColor = cTot*gl_FragColor.a;"
not sure if that'll help, but you might check out the src of shadowmap_pars_frag to see what's happening behind the scenes. Maybe we're missing something.
One last thing: try doing just the shadows with none of the texture mixing, to isolate the issue. It might be that you're hitting a GLSL limit to the number of texture samplings - because the shadow chunk also uses texture sampling.
I want to fade the scene into grayscale, but this also applies to other post-processing effects I'd like to fade in or out.
So for this example I'm using the THREE.ColorifyShader, but when activating it, the whole scene instantly receives the intended color
How can I "apply opacity/alpha" to post-processing?
Code example:
var effectColorify,
copyPass;
effectColorify = new THREE.ShaderPass(THREE.ColorifyShader);
effectColorify.uniforms['color'].value.setRGB(0.8, 0.8, 0.8); // Grayscale
copyPass = new THREE.ShaderPass(THREE.CopyShader);
copyPass.renderToScreen = true;
this.composerGrayscale = new THREE.EffectComposer(this.engine.renderer);
this.composerGrayscale.addPass(this.renderPass);
this.composerGrayscale.addPass(effectColorify);
this.composerGrayscale.addPass(copyPass);
I solved the issue by adding an "opacity" uniform to the colorify shader. This allows to smoothly blend from the normal, colored, scene to a certain color by increasing opacity or the other way round.
effectColorify.uniforms['opacity'].value = 0.5; // 50% scene-color, 50% shader-color.
Here is the adjusted shader code you can copy into ColorifyShader.js, which is backwards compatible to the previous version, since default opacity is 1.0:
THREE.ColorifyShader = {
uniforms: {
"tDiffuse": { type: "t", value: null },
"color": { type: "c", value: new THREE.Color( 0xffffff ) },
"opacity": { type: "f", value: 1.0 }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"uniform vec3 color;",
"uniform sampler2D tDiffuse;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel = texture2D( tDiffuse, vUv );",
"vec3 luma = vec3( 0.299, 0.587, 0.114 );",
"float v = dot( texel.xyz, luma );",
"vec3 finalColor = vec3(",
"(opacity * v * color.x) + ((1.0 - opacity) * texel.x),",
"(opacity * v * color.y) + ((1.0 - opacity) * texel.y),",
"(opacity * v * color.z) + ((1.0 - opacity) * texel.z)",
");",
"gl_FragColor = vec4( finalColor, texel.w );",
"}"
].join("\n")
};
You could add a timer to slowly increase the RGB values. or add it in the render loop, i'll use a timer, but the exact same loop can be applied in the render function.
var interval = 200; //interval for the animation in ms
var darkness = 1; //we'll start with a fade in, so we need the darknes at its biggest value
var fade = 'in';
var effectTimer = setInterval(function(){
switch(fade){
case 'in':
if(darkness > 0){
darkness -= 0.1;
}
else{
fade = 'off';
}
break;
case 'out':
if(darkness < 1){
darkness += 0.1;
}
else{
fade = 'off';
}
break;
}
effectColorify.uniforms['color'].value.setRGB(darkness, darkness, darkness);
}, interval)