THREE JS OcclusionComposer issues "Cannot read properties of undefined (reading 'x')" - javascript

I am trying to recreate the Volumetric Lighting example from JMSWRNR ( https://codesandbox.io/s/github/jmswrnr/website-examples/tree/master/3d-header/volumetric-lighting?from-embed=&file=/src/index.js ) but I am facing some issues with Occlusion Composer.
I don't really know GLSL so debugging is very hard especially for a beginner like me.
Here is the GitHub Repo: https://github.com/RolandTeslaru/roland-teslaru-portfolio/tree/not-working
Main Code is in the components/HomeCanvas/Scene.ts
My guess its that the VolumetricLightCylinder.js shader is causing the issue because when I change
worldPosition.xyz;
to
worldPosition
the error disappears.
import * as THREE from 'three'
export default () => ({
lights: true,
transparent: true,
depthWrite: false,
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib['lights'],
{
attenuation: { value: 25.0 },
anglePower: { value: 10.0 },
spotPosition: { value: new THREE.Vector3(0, 0, 0) },
},
]),
vertexShader: /* glsl */ `
#include <common>
struct PointLight {
vec3 position;
vec3 color;
float distance;
float decay;
int shadow;
float shadowBias;
float shadowRadius;
vec2 shadowMapSize;
float shadowCameraNear;
float shadowCameraFar;
};
uniform PointLight pointLights[NUM_POINT_LIGHTS];
uniform float viewMix;
varying vec4 vColor;
varying vec3 vNormal;
varying vec3 vWorldPosition;
float _punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
if( decayExponent > 0.0 ) {
return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
}
return 1.0;
}
void main() {
vNormal = normalize(normalMatrix * normal);
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * modelViewPosition;
vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
float dist = distance(pointLights[l].position, worldPosition.xyz);
addedLights.rgb += pointLights[l].color *
_punctualLightIntensityToIrradianceFactor(
dist,
pointLights[l].distance,
pointLights[l].decay
);
}
vWorldPosition = worldPosition.xyz;
vColor = addedLights;
}
`,
fragmentShader: /* glsl */`
varying vec3 vNormal;
varying vec3 vWorldPosition;
uniform vec3 spotPosition;
uniform float attenuation;
uniform float anglePower;
varying vec4 vColor;
void main() {
float intensity;
intensity = distance(vWorldPosition, spotPosition)/attenuation;
intensity = 1.0 - clamp(intensity, 0.0, 1.0);
vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z));
float angleIntensity = pow(dot(normal, vec3(0.0, 0.0, 1.0)), anglePower);
intensity = intensity * angleIntensity;
gl_FragColor = vec4(vColor.rgb, intensity);
}
`,
})

Related

How to have distortion effect on image using Javascript?

I'm trying to build a simple image distortion effect on mouse hover same as in this link.
I am expecting to have same output as this, the output is working, but there are 2 issues:
I want to have idle animation, but I could not find the way to
implement it in documentation.
I want to change depth of mouse when hover over image.
EDIT:
I tried to re-implement same effect using Javascript library:
body {
margin: 0;
background: #fff;
padding: 0;
}
.container {
position: relative;
}
/* canvas */
#canvas {
position: fixed;
top: 0;
right: 0;
left: 0;
height: 100vh;
z-index: 10;
}
#flowmap {
width: 100%;
height: 100vh;
}
#flowmap img {
display: none;
}
<div class="container">
<div id="canvas"></div>
<div id="flowmap">
<img src="https://i.imgur.com/wATUVc1.jpeg" alt="" data-sampler="planeTexture" />
</div>
</div>
<script>
// flowmap shaders
const flowmapVs = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
// default mandatory variables
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
// custom variables
varying vec3 vVertexPosition;
varying vec2 vTextureCoord;
void main() {
vec3 vertexPosition = aVertexPosition;
gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);
// varyings
vTextureCoord = aTextureCoord;
vVertexPosition = vertexPosition;
}
`;
const flowmapFs = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
varying vec3 vVertexPosition;
varying vec2 vTextureCoord;
uniform sampler2D uFlowMap;
uniform vec2 uMousePosition;
uniform float uFalloff;
uniform float uAlpha;
uniform float uDissipation;
uniform float uCursorGrow;
uniform vec2 uVelocity;
uniform float uAspect;
void main() {
vec2 textCoords = vTextureCoord;
/*** comment this whole block for a regular mouse flow effect ***/
// convert to -1 -> 1
textCoords = textCoords * 2.0 - 1.0;
// make the cursor grow with time
textCoords /= uCursorGrow;
// adjust cursor position based on its growth
textCoords += uCursorGrow * uMousePosition / (1.0 / (uCursorGrow - 1.0) * pow(uCursorGrow, 2.0));
// convert back to 0 -> 1
textCoords = (textCoords + 1.0) / 2.0;
/*** end of whole block commenting for a regular mouse flow effect ***/
vec4 color = texture2D(uFlowMap, textCoords) * uDissipation;
//vec4 color = vec4(0.0, 0.0, 0.0, 1.0) * uDissipation;
vec2 mouseTexPos = (uMousePosition + 1.0) * 0.5;
vec2 cursor = vTextureCoord - mouseTexPos;
cursor.x *= uAspect;
vec3 stamp = vec3(uVelocity * vec2(1.0, -1.0), 1.0 - pow(1.0 - min(1.0, length(uVelocity)), 3.0));
float falloff = smoothstep(uFalloff, 0.0, length(cursor)) * uAlpha;
color.rgb = mix(color.rgb, stamp, vec3(falloff));
// handle premultiply alpha
color.rgb = color.rgb * color.a;
gl_FragColor = color;
}
`;
const displacementVs = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
// default mandatory variables
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat4 planeTextureMatrix;
// custom variables
varying vec3 vVertexPosition;
varying vec2 vPlaneTextureCoord;
varying vec2 vTextureCoord;
void main() {
vec3 vertexPosition = aVertexPosition;
gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);
// varyings
vTextureCoord = aTextureCoord;
vPlaneTextureCoord = (planeTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy;
vVertexPosition = vertexPosition;
}
`;
const displacementFs = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
varying vec3 vVertexPosition;
varying vec2 vPlaneTextureCoord;
varying vec2 vTextureCoord;
uniform sampler2D planeTexture;
uniform sampler2D uFlowTexture;
// the uniform we declared inside our javascript
uniform float uTime;
void main() {
// our flowmap
vec4 flowTexture = texture2D(uFlowTexture, vTextureCoord);
// distort our image texture based on the flowmap values
vec2 distortedCoords = vPlaneTextureCoord;
distortedCoords -= (flowTexture.xy * 0.1);
// get our final texture based on the displaced coords
vec4 texture = texture2D(planeTexture, distortedCoords);
// get a B&W version of our image texture
vec4 textureBW = vec4(1.4);
textureBW.rgb = vec3(texture.r * 0.3 + texture.g * 0.59 + texture.b * 0.11);
// mix the BW image and the colored one based on our flowmap color values
float mixValue = clamp((abs(flowTexture.r) + abs(flowTexture.g) + abs(flowTexture.b)) * 1.5, 0.0, 0.0);
texture = mix(texture, textureBW, mixValue);
// switch between this 2 lines to see what we have drawn onto our flowmap
//gl_FragColor = flowTexture;
gl_FragColor = texture;
}
`;
</script>
<script type="module">
// add cdn of curtainsjs
import {
Curtains,
Plane,
Vec2,
PingPongPlane,
} from "https://cdn.jsdelivr.net/npm/curtainsjs#7.2.0/src/index.mjs";
window.addEventListener("load", () => {
// set up webGl contetxt or set up curtiansjs
const curtains = new Curtains({
container: "canvas",
pixelRatio: Math.min(1.5, window.devicePixelRatio),
});
// mouse/touch move
const ww = window.innerWidth;
const wh = window.innerHeight;
const mouse = new Vec2(ww / 5, wh / 5);
const lastMouse = mouse.clone();
const velocity = new Vec2();
function onMouseMove(e) {
lastMouse.copy(mouse);
// touch event
if (e.targetTouches) {
mouse.set(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
} else {
mouse.set(e.clientX, e.clientY);
}
velocity.set((mouse.x - lastMouse.x) / 16, (mouse.y - lastMouse.y) / 16);
// update the velocity
updateVelocity = true;
}
window.addEventListener("mousemove", onMouseMove);
window.addEventListener("touchmove", onMouseMove, {
passive: true,
});
// create planeElement
const planeElement = document.getElementById("flowmap");
// parameters
const flowMapParams = {
sampler: "uFlowMap",
vertexShader: flowmapVs,
fragmentShader: flowmapFs,
texturesOptions: {
floatingPoint: "half-float",
},
uniforms: {
mousePosition: {
name: "uMousePosition",
type: "2f",
value: mouse,
},
fallOff: {
name: "uFalloff",
type: "1f",
value: ww > wh ? ww / 10000 : wh / 10000,
// we can change what i want here
},
time: {
name: "uTime", // uniform name that will be passed to our shaders
type: "1f", // this means our uniform is a float
value: 0,
},
cursorGrow: {
name: "uCursorGrow",
type: "1f",
value: 1.15,
},
// alpha of the cursor
alpha: {
name: "uAlpha",
type: "1f",
value: 1.14,
},
dissipation: {
name: "uDissipation",
type: "1f",
value: 0.925,
},
velocity: {
name: "uVelocity",
type: "2f",
value: velocity,
},
aspect: {
name: "uAspect",
type: "1f",
value: ww / wh,
},
},
};
// create ping pong plane
const flowMap = new PingPongPlane(curtains, planeElement, flowMapParams);
flowMap.onRender(() => {
flowMap.uniforms.time.value++;
// update mouse position
flowMap.uniforms.mousePosition.value = flowMap.mouseToPlaneCoords(mouse);
flowMap.uniforms.velocity.value = new Vec2(
curtains.lerp(velocity.x, 0.5, 1.5),
curtains.lerp(velocity.y, 0.5, 1.5)
);
});
// add displacements shader
const params = {
vertexShader: displacementVs,
fragmentShader: displacementFs,
};
// create plane
const plane = new Plane(curtains, planeElement, params);
// create a texture that will hold our flowmap
const flowTexture = plane.createTexture({
sampler: "uFlowTexture",
fromTexture: flowMap.getTexture(), // set it based on our PingPongPlane flowmap plane's texture
});
});
</script>

Threejs blending modes doesn't work for 3 out of the 5 modes

I am trying to use three.js blending and I have been trying to get MultiplyBlending, SubtractiveBlending, NoBlending to work but all that I get are white squares:
When I use AdditiveBlending I get something that works:
fragment shader:
uniform sampler2D diffuseTexture;
varying vec4 vColor;
varying vec2 vAngle;
void main() {
vec2 coords = (gl_PointCoord - 0.5) * mat2(vAngle.x, vAngle.y, -vAngle.y, vAngle.x) + 0.5;
gl_FragColor = texture2D(diffuseTexture, coords) * vColor;
}
vertex shader:
uniform float pointMultiplier;
attribute float size;
attribute float angle;
varying vec4 vColor;
varying vec2 vAngle;
void main() {
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
gl_PointSize = size * pointMultiplier / gl_Position.w;
vAngle = vec2(cos(angle), sin(angle));
vColor = color;
}
This is how I am creating the material and geometry in the TypeScript:
this.material = new Three.ShaderMaterial({
uniforms: {
diffuseTexture: {
value: new Three.TextureLoader().load(basicParticle)
},
pointMultiplier: {
value: window.innerHeight / (2.0 * Math.tan(0.5 * 60.0 * Math.PI / 180.0))
}
},
vertexShader,
fragmentShader,
blending: Three.MultiplyBlending,
depthTest: true,
depthWrite: false,
transparent: true,
vertexColors: true
});
this.geometry = new Three.BufferGeometry();
new Three.Points(this.geometry, this.material);
What is causing me to get white squares and how can I fix it? Is it the shaders, TypeScript, or both?

THREE.js vertexShader color mix based on height

How do I set the color to the mesh only when the height is zero?
As for now, i just mixed the colors:
The problem is that this kind on mixing is not precise. I just want the color blue only when the height is zero (so only inside that red path I made with paint).
I created a custom material for the mesh, like so:
material = new THREE.ShaderMaterial({
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib['lights'],
{
lightIntensity: {type: 'f', value: 1.0},
diffuse: {type: 'c', value: new THREE.Color(0x0000ff)},
color0: {
value: new THREE.Color("blue")
},
color1: {
value: new THREE.Color("green")
},
color2: {
value: new THREE.Color("brown")
},
color3: {
value: new THREE.Color("black")
},
bboxMin: {
value: geom.boundingBox.min
},
bboxMax: {
value: geom.boundingBox.max
}
}
]),
vertexShader: `
uniform vec3 bboxMin;
uniform vec3 bboxMax;
varying vec2 vUv;
varying vec3 vPos;
varying vec3 vNormal;
void main() {
vPos = (modelMatrix * vec4(position, 1.0 )).xyz;
vNormal = normalMatrix * normal;
vUv.y = (position.y - bboxMin.y) / (bboxMax.y - bboxMin.y);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`,
fragmentShader: `
uniform vec3 color1;
uniform vec3 color2;
uniform vec3 color3;
uniform vec3 color0;
varying vec2 vUv;
uniform vec3 diffuse;
varying vec3 vPos;
varying vec3 vNormal;
struct PointLight {
vec3 position;
vec3 color;
};
uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
void main() {
vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
vec3 adjustedLight = pointLights[l].position + cameraPosition;
vec3 lightDirection = normalize(vPos - adjustedLight);
addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLights[l].color;
}
gl_FragColor = mix(vec4(mix(mix(mix(color0, color1, vUv.y), color1, vUv.y), mix(color1, color2, vUv.y), vUv.y), 1.0),addedLights, addedLights);
}
`,
lights: true
});
Try using the step() function. Here's a definition to help you understand it. Here's how it works:
float step(float edge, float x)
It takes in a constant to declare the edge, and x, which is your variable.
If x is below the edge, you get 0, and if x is above the edge, you get 1.
Here's a simplified use of it. When height is below 0.2, you'll get blue, and when height is above 0.2, you'll get green.
vec3 green = vec3(0.0, 1.0, 0.0);
vec3 blue = vec3(0.0, 0.0, 1.0);
float edge = 0.2;
float colorMix = step(edge, height);
vec3 finalColor = mix(blue, green, colorMix);
I picked 0.2 to give the blue band some thickness, otherwise it wouldn't be visible.

THREE.WebGLRenderer: Unknown uniform type: 1009

I'm using THREE.js r73, and I'm trying to make a particle system using THREE.BufferGeometery to hold the vertices and THREE.ShaderMaterial to add functionality to them. For some reason, I'm getting the error above. Here is my code (using Typescript). The error is occurring at the line gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord ); (The last one in the fragment shader).
this.particleSystem = new THREE.PointCloud(
this.particles,
new THREE.ShaderMaterial({
uniforms: {
texture: wTex
},
vertexShader: `
attribute vec3 color;
attribute float size;
varying vec3 vColor;
varying vec2 vUv;
void main() {
vUv = uv;
vColor = color; // set color associated to vertex; use later in fragment shader
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader: `
uniform sampler2D texture;
varying vec3 vColor; // colors associated to vertices; assigned by vertex shader
varying vec2 vUv;
void main() {
// calculates a color for the particle
gl_FragColor = vec4( vColor, 1.0 );
// sets particle texture to desired color
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
}
`
})
);
The code was adapted from some examples I found online, but I understand it.
You're not constructing the uniform correctly. It should be...
uniforms: {
texture: { type: 't', value: wTex }
}

Explode tessellation shader textureCube drawing not real texture

I want to make explode effect like this (http://threejs.org/examples/#webgl_modifier_tessellation), but for cube with panorama textures (cube with 6 images).
I transform vertex shader to this:
uniform float amplitude;
attribute float displacement;
varying vec3 vNormal;
varying vec2 vUv;
void main() {
vNormal = normal;
vUv = ( 0.5 + amplitude ) * uv + vec2( amplitude );
vec3 newPosition = position + amplitude * normal * vec3( displacement );
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
and fragment to this by adding samplerCube and textureCube:
varying vec3 vNormal;
varying vec2 vUv;
uniform samplerCube texture1;
void main() {
vec3 light = vec3( 0.5, 0.2, 1.0 );
light = normalize( light );
float dProd = dot( vNormal, light ) * 0.5 + 0.5;
gl_FragColor = vec4( vec3( dProd ), 1.0 );
gl_FragColor = textureCube(texture1, vNormal);
}
But result doesn't looks good, it's shows color, but not real detailed texture (look texture http://pg2.paraplan.io/_pano/cube/1024/nx.jpg).
Can you help me with shader setting, or may be know how to do explode tessellation without shaders?
DEMO: http://pg2.paraplan.io/_pano/cube/scene.html

Categories

Resources