Cross-fade using quadmaterial - ThreeJS syntax - three.js

When coding a fade transition, what does the following code mean? I'm looking to achieve the same effect as http://jsfiddle.net/DW9q4/85/ but I have 2 scenes with 2 different map cubes rendered through a PerspectiveCamera.
I'm having trouble understanding what is going on, what is code doing?
uniforms: {
tDiffuse1: {
type: "t",
value: rtTexture1
},
tDiffuse2: {
type: "t",
value: rtTexture2
},
mixRatio: {
type: "f",
value: 0.5
},
opacity: {
type: "f",
value: 1.0
}
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = vec2( uv.x, 1.0 - uv.y );",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform float opacity;",
"uniform float mixRatio;",
"uniform sampler2D tDiffuse1;",
"uniform sampler2D tDiffuse2;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel1 = texture2D( tDiffuse1, vUv );",
"vec4 texel2 = texture2D( tDiffuse2, vUv );",
"gl_FragColor = opacity * mix( texel1, texel2, mixRatio );",
"}"
].join("\n")
All help is greatly appreciated!

If you googled 'vertexShader' or 'fragmentShader' you'd get tons of hits. These shaders are core to WebGL. If you want to understand shaders and WebGl there are many online resources. Three.js generates the shader calls for you. For most normal work you can ignore shaders and work entirely with three.js.

Related

'vertexColors' parameter is undefined?

const material = new THREE.LineBasicMaterial({
vertexColors: THREE.VertexColors,
transparent: true,
side: THREE.DoubleSide,
})
why?
.vertexColors can either be true or false, nothing else. THREE.VertexColors does not exist, so it comes out as undefined.
https://threejs.org/docs/index.html#api/en/materials/Material.vertexColors
Parameters in Material vertexColors are boolean, true or false.
so if you have specified point color in float array then it can define boolean value (true or false), I will give a little example like this, and this is what I did it worked.
const myGeo = new THREE.BufferGeometry();
let vertices = new Float32Array([
-1.0, -1.0, 1.0, // 0
1.0, 1.0, 1.0, // 1
-1.0, 1.0, 1.0, // 2
1.0, -1.0, 1.0, // 3
-1.0, -1.0, -1.0, // 4
1.0, 1.0, -1.0, // 5
-1.0, 1.0, -1.0, // 6
1.0, -1.0, -1.0, // 7
]);
let colors = new Float32Array([
1.0, 0.0, 0.0, // Vertex 0 (Red)
1.0, 0.0, 0.0, // Vertex 1 (Red)
1.0, 1.0, 0.0, // Vertex 2 (Yellow)
1.0, 1.0, 0.0, // Vertex 3 (Yellow)
0.0, 1.0, 0.0, // Vertex 4 (Green)
0.0, 1.0, 0.0, // Vertex 5 (Green)
0.0, 0.0, 1.0, // Vertex 6 (Blue)
0.0, 0.0, 1.0, // Vertex 7 (Blue)
]);
myGeo.setAttribute('position', new THREE.BufferAttribute( vertices, 3 ));
myGeo.setAttribute('color', new THREE.BufferAttribute( colors, 3 ));
myGeo.setIndex([.....]);
const material= new THREE.MeshBasicMaterial({ vertexColors:true, side: THREE.DoubleSide, });
let mesh = new THREE.Mesh(myGeo, material)
scene.add(mesh);

Passing Array Of Vectors To Shader

Trying to pass an array of vec3s to the shader, Firefox gives me this warning:
WebGL warning: uniform setter: (uniform u_colors[0]) 'values' length
(4) must be a positive integer multiple of size of <enum 0x8b51>.
Also, it only renders black, not the given color.
const colrs = [
[239, 71, 111],
[255, 209, 102],
[6, 214, 160],
[17, 138, 178]
],
dmnsn = [1200, 300],
glCtx = (() => twgl.getContext(document.createElement("canvas")))(
twgl.setDefaults({ attribPrefix: "a_" })
);
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
twgl.bindFramebufferInfo(glCtx, fbi);
twgl.drawObjectList(glCtx, [
{
programInfo: pi,
bufferInfo: bfInf,
uniforms: u
}
]);
}
function prepr() {
glCtx.canvas.width = dmnsn[0];
glCtx.canvas.height = dmnsn[1];
document.body.append(glCtx.canvas);
rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
v_texcoord = a_texcoord;
gl_Position = a_position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec3 u_colors[4];
void main() {
gl_FragColor= vec4(u_colors[0], 1.0);
}
</script>
WebGL does not want an array of arrays.
const someArrayWith4ArraysOf3Values = [
[11, 22, 33],
[44, 55, 66],
[77, 88, 99],
[10, 11, 12],
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith4ArraysOf3Values); // bad
It wants a flat array.
const someArrayWith12Values = [
11, 22, 33,
44, 55, 66,
77, 88, 99,
10, 11, 12,
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith12Values); // good
Also, colors in shaders are float values that go from 0 to 1 so you probably want to set your colors to values from 0 to 1 or divide by 255 in your shader
const colrs = [
[1, 0.7, 0.5],
[255, 209, 102],
[6, 214, 160],
[17, 138, 178]
].flat(),
dmnsn = [1200, 300],
glCtx = (() => twgl.getContext(document.createElement("canvas")))(
twgl.setDefaults({ attribPrefix: "a_" })
);
var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
twgl.bindFramebufferInfo(glCtx, fbi);
twgl.drawObjectList(glCtx, [
{
programInfo: pi,
bufferInfo: bfInf,
uniforms: u
}
]);
}
function prepr() {
glCtx.canvas.width = dmnsn[0];
glCtx.canvas.height = dmnsn[1];
document.body.append(glCtx.canvas);
rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
void main() {
v_texcoord = a_texcoord;
gl_Position = a_position;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision highp float;
uniform vec3 u_colors[4];
void main() {
gl_FragColor=vec4(u_colors[0], 1.0);
}
</script>

combining shaders in THREE.JS

I'm writting a shader to render terrain from a heightmap and all goes good exept that after I have my shader I loose lights and shades. And here is when hell pain begins. It comes that I should use THREE.ShaderChunk to add default shaders chunks but not just add - mess with my shader.
So after long time googling I came to this advise
You just need to add few snippets to your custom ShaderMaterial at
proper places:
// uniforms
THREE.UniformsLib[ "shadowmap" ],
// fragment shader
THREE.ShaderChunk[ "shadowmap_pars_fragment" ], THREE.ShaderChunk[
"shadowmap_fragment" ],
// vertex shader
THREE.ShaderChunk[ "shadowmap_pars_vertex" ], THREE.ShaderChunk[
"shadowmap_vertex" ],
but for me that was not added lights and shadows. Then the best I can thought of is to look at ShaderLib.js and try to use settings from one of default shaders. So I took settings for lambert and ended up with this code:
#tileMaterial = new THREE.ShaderMaterial
uniforms: THREE.UniformsUtils.merge [
THREE.UniformsLib[ "common" ],
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
THREE.UniformsLib[ "shadowmap" ],
{
"emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
}
]
vertexShader: [
"#define LAMBERT",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
" varying vec3 vLightBack;",
"#endif",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "map_pars_vertex" ],
THREE.ShaderChunk[ "lightmap_pars_vertex" ],
THREE.ShaderChunk[ "envmap_pars_vertex" ],
THREE.ShaderChunk[ "lights_lambert_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" ],
"void main() {",
THREE.ShaderChunk[ "map_vertex" ],
THREE.ShaderChunk[ "lightmap_vertex" ],
THREE.ShaderChunk[ "color_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
THREE.ShaderChunk[ "skinbase_vertex" ],
THREE.ShaderChunk[ "skinnormal_vertex" ],
THREE.ShaderChunk[ "defaultnormal_vertex" ],
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
THREE.ShaderChunk[ "default_vertex" ],
THREE.ShaderChunk[ "logdepthbuf_vertex" ],
THREE.ShaderChunk[ "worldpos_vertex" ],
THREE.ShaderChunk[ "envmap_vertex" ],
THREE.ShaderChunk[ "lights_lambert_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ],
"}"
].join "\n"
fragmentShader: [
"uniform vec3 diffuse;",
"uniform vec3 emissive;",
"uniform float opacity;",
"varying vec3 vLightFront;",
"#ifdef DOUBLE_SIDED",
" varying vec3 vLightBack;",
"#endif",
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "map_pars_fragment" ],
THREE.ShaderChunk[ "alphamap_pars_fragment" ],
THREE.ShaderChunk[ "lightmap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "specularmap_pars_fragment" ],
THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
"void main() {",
" vec3 outgoingLight = vec3( 0.0 );",
" vec4 diffuseColor = vec4( diffuse, opacity );",
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
THREE.ShaderChunk[ "map_fragment" ],
THREE.ShaderChunk[ "color_fragment" ],
THREE.ShaderChunk[ "alphamap_fragment" ],
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
" #ifdef DOUBLE_SIDED",
" if ( gl_FrontFacing )",
" outgoingLight += diffuseColor.rgb * vLightFront + emissive;",
" else",
" outgoingLight += diffuseColor.rgb * vLightBack + emissive;",
" #else",
" outgoingLight += diffuseColor.rgb * vLightFront + emissive;",
" #endif",
THREE.ShaderChunk[ "lightmap_fragment" ],
THREE.ShaderChunk[ "envmap_fragment" ],
THREE.ShaderChunk[ "shadowmap_fragment" ],
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
" gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
"}"
].join "\n"
attributes:
height:
type: "f"
value: heightData
wireframe: no
which is still do not add lights and shadows and also throws errors:
three.js:22804 WebGL: INVALID_VALUE: uniform3fv: no array
three.js:22804 WebGL: INVALID_VALUE: uniform3fv: no array
So the question is - what are the steps to add lights and shades to custom shader (as for r71)?
jsfiddle - http://jsfiddle.net/SET001/0wzqemks/2/
The solution in my case was to add lights: yes to ShaderMaterial

Transparency in Three.js ShaderMaterial fragment shader

I've used Three.js quite a bit, but I'm just starting to learn how shaders work.
I have a green cube which is one-half transparent, as defined in a THREE.ShaderMaterial (based on the "phong" ShaderLib). I put a simple red cube inside the ShaderMaterial cube so I could tell the transparency was working (it is). The remaining problem is that the green cube's backfaces don't seem to be rendering, despite setting it to double-sided geometry.
Here's my fiddle: http://jsfiddle.net/TheJim01/kgkhvbtL/113/
// partial glass box
var hostDiv, scene, renderer, camera, root, controls, light, shape;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 0.1,
FAR = 100;
function init() {
hostDiv = document.createElement('div');
document.body.appendChild(hostDiv);
renderer = new THREE.WebGLRenderer({ antialias: true, preserverDrawingBuffer: true });
renderer.setSize(WIDTH, HEIGHT);
hostDiv.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 75;
controls = new THREE.TrackballControls(camera, renderer.domElement);
light = new THREE.PointLight(0xffffff, 2, Infinity);
light.position.copy(camera.position);
scene = new THREE.Scene();
scene.add(camera);
scene.add(light);
var geo = new THREE.BoxGeometry(10, 10, 10);
var shader = {
uniforms: THREE.UniformsUtils.merge( [
THREE.UniformsLib[ "common" ],
THREE.UniformsLib[ "bump" ],
THREE.UniformsLib[ "normalmap" ],
THREE.UniformsLib[ "fog" ],
THREE.UniformsLib[ "lights" ],
THREE.UniformsLib[ "shadowmap" ],
{
"ambient" : { type: "c", value: new THREE.Color( 0xffffff ) },
"emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
"specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
"shininess": { type: "f", value: 30 },
"wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
}
] ),
vertexShader: [
"#define PHONG",
"varying vec3 vViewPosition;",
"varying vec3 vNormal;",
THREE.ShaderChunk[ "map_pars_vertex" ],
THREE.ShaderChunk[ "lightmap_pars_vertex" ],
THREE.ShaderChunk[ "envmap_pars_vertex" ],
THREE.ShaderChunk[ "lights_phong_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" ],
"varying vec3 glassPos;", // <!-- I added this -->
"void main() {",
THREE.ShaderChunk[ "map_vertex" ],
THREE.ShaderChunk[ "lightmap_vertex" ],
THREE.ShaderChunk[ "color_vertex" ],
THREE.ShaderChunk[ "morphnormal_vertex" ],
THREE.ShaderChunk[ "skinbase_vertex" ],
THREE.ShaderChunk[ "skinnormal_vertex" ],
THREE.ShaderChunk[ "defaultnormal_vertex" ],
" vNormal = normalize( transformedNormal );",
THREE.ShaderChunk[ "morphtarget_vertex" ],
THREE.ShaderChunk[ "skinning_vertex" ],
THREE.ShaderChunk[ "default_vertex" ],
THREE.ShaderChunk[ "logdepthbuf_vertex" ],
" vViewPosition = -mvPosition.xyz;",
THREE.ShaderChunk[ "worldpos_vertex" ],
THREE.ShaderChunk[ "envmap_vertex" ],
THREE.ShaderChunk[ "lights_phong_vertex" ],
THREE.ShaderChunk[ "shadowmap_vertex" ],
" glassPos = worldPosition.xyz / worldPosition.w;", // <!-- I added this -->
"}"
].join("\n"),
fragmentShader: [
"uniform vec3 diffuse;",
"uniform float opacity;",
"uniform vec3 ambient;",
"uniform vec3 emissive;",
"uniform vec3 specular;",
"uniform float shininess;",
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "map_pars_fragment" ],
THREE.ShaderChunk[ "alphamap_pars_fragment" ],
THREE.ShaderChunk[ "lightmap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
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" ],
"varying vec3 glassPos;", // <!-- I added this -->
"void main() {",
" gl_FragColor = vec4( vec3( 1.0 ), opacity );",
// <!-- I added this
" if(glassPos.x < 0.0) {",
" gl_FragColor = gl_FragColor * vec4( vec3( 1.0 ), 0.5 );//discard;",
" }",
// end -->
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
THREE.ShaderChunk[ "map_fragment" ],
THREE.ShaderChunk[ "alphamap_fragment" ],
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
THREE.ShaderChunk[ "lights_phong_fragment" ],
THREE.ShaderChunk[ "lightmap_fragment" ],
THREE.ShaderChunk[ "color_fragment" ],
THREE.ShaderChunk[ "envmap_fragment" ],
THREE.ShaderChunk[ "shadowmap_fragment" ],
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
"}"
].join("\n")
};
//console.log(shader.vertexShader);
//console.log(shader.fragmentShader);
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
uniforms['diffuse'].value.setHex(0x00ff00);
uniforms['ambient'].value.setHex(0x002200);
uniforms['emissive'].value.setHex(0x000000);
uniforms['specular'].value.setHex(0x007f00);
uniforms['ambient'].value.convertGammaToLinear();
var parameters = {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: uniforms,
lights: true,
fog: false,
doubleSided: true,
blending: THREE.NormalBlending,
transparent: true,
depthTest: true
};
var shaderMaterial = new THREE.ShaderMaterial( parameters );
var msh = new THREE.Mesh(geo, shaderMaterial);
scene.add(msh);
var m = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({
color: 0xff0000,
ambient: 0x22000,
emissive: 0x000000,
specular: 0x7f0000
}));
m.scale.set(0.75, 0.75, 0.75);
scene.add(m);
animate();
}
function animate() {
light.position.copy(camera.position);
requestAnimationFrame(animate);
renderer.render(scene, camera);
controls.update();
}
init();
Did I do something wrong? Did I miss something? Or is this just not possible?
Thanks!
It is side: THREE.DoubleSide not doubleSided: true.
three.js r.68

WebGL/GLSL vertex shader collapses 9 points into single point when I set x coord of gl_Position to zero

I do not understand why the following two shaders produce different results when I render a vertex buffer with x coordinates equal to zero:
First:
attribute vec3 position;
void main() {
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
}
Second:
attribute vec3 position;
void main() {
gl_Position = vec4(0.0, position.y, 0.0, 1.0);
}
The result of the first is a line of nine dots. The result of the second is a single dot.
I'm drawing the following vertex array as GL_POINTS:
0.0, -1.00, 0.0,
0.0, -0.75, 0.0,
0.0, -0.50, 0.0,
0.0, -0.25, 0.0,
0.0, 0.00, 0.0,
0.0, 0.25, 0.0,
0.0, 0.50, 0.0,
0.0, 0.75, 0.0,
0.0, 1.00, 0.0
Here's the VBO preparation calls:
var a = new Float32Array([
0.0, -1.00, 0.0,
0.0, -0.75, 0.0,
0.0, -0.50, 0.0,
0.0, -0.25, 0.0,
0.0, 0.00, 0.0,
0.0, 0.25, 0.0,
0.0, 0.50, 0.0,
0.0, 0.75, 0.0,
0.0, 1.00, 0.0
]);
gl.bindBuffer(gl.ARRAY_BUFFER, b);
gl.bufferData(gl.ARRAY_BUFFER, a.byteLength, gl.STATIC_DRAW);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, a);
Here's the draw calls:
gl.bindBuffer(gl.ARRAY_BUFFER, b);
gl.vertexAttribPointer(p.position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(p.position);
gl.drawArrays(gl.POINTS, 0, 9);
That is a known problem (sorry, no link for now).
Basically, GLSL compiler thinks that attribute 'position' is not used, because the first component of it is not used. To check this try the following test:
gl_Position = vec4(0.0, position.y, 0.0, 1.0) + position.x*0.001;
Once you confirm the bug, you can either update you video driver or use an obvious workaround.

Resources