ThreeJS: Problem implementing 'non-ThreeJS' shader - three.js

I'm trying to use the shader from this post https://stackoverflow.com/a/27764539/6736544 with a ThreeJS geometry, so far without success.
This is the original shader code from #gman:
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script id="vs" type="foo">
attribute vec4 a_position;
attribute float a_v;
varying float v_v;
void main() {
// PS: In a real WebGL app you'd probably need to multiply a_position by
// a matrix at a minimum
gl_Position = a_position;
v_v = a_v;
}
</script>
<script id="fs" type="foo">
precision mediump float;
varying float v_v;
uniform float u_borderSize;
uniform vec4 u_baseColor;
uniform vec4 u_borderColor;
void main() {
float mixAmount = step(u_borderSize, v_v);
gl_FragColor = mix(u_baseColor,
u_borderColor,
mixAmount);
}
</script>
<canvas id="c" width="256" height="256"></canvas>
This is my attempt:
<script>
var vertexShader = `
varying vec2 vUv;
attribute float alpha;
varying float vAlpha;
attribute vec3 center;
varying vec3 vCenter;
void main() {
vUv = uv;
vAlpha = alpha;
vCenter = center;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
var fragmentShader = `
//precision mediump float;
uniform vec3 color1;
uniform float color1Alpha;
uniform vec3 borderColor;
uniform float borderThickness;
varying vec2 vUv;
varying float vAlpha;
varying vec3 vCenter;
void main() {
float u_borderSize = borderThickness;
vec4 u_baseColor = vec4(color1, color1Alpha);
vec4 u_borderColor = vec4(borderColor, 1.0);
// This is where I get stuck. No idea how to get a correct 'v_v' value.
float v_v = vUv.y;
float mixAmount = step(u_borderSize, v_v);
gl_FragColor = mix(u_baseColor,
u_borderColor,
mixAmount);
}
`;
</script>
See the jsfiddle here: https://jsfiddle.net/vuqarejz/
This is what I'm trying to achieve:
Questions:
Not sure what I'm missing, nor where the 'v_a' attribute is coming from.
Maybe it is the way UVs are unwrapped?
Maybe this is not the correct shader to use for my purpose?

Solved by tfoller in ThreeJS forum:
https://discourse.threejs.org/t/unwrapping-a-custom-shapebuffergeometry/39565/4

Related

Geometry instancing with one shader but multiple textures

I'd like to add a second crate texture to the shader using the shader/technique provided with this example:
https://threejs.org/examples/#webgl_buffergeometry_instancing_dynamic
I figured I could pass in another uniform to add a second map.
crateMaterial = new THREE.RawShaderMaterial( {
uniforms: {
map: { value: new THREE.TextureLoader().load( './img/textures/crate/crate.gif' ),
map2: { value: new THREE.TextureLoader().load( './img/textures/crate2/crate2.gif' ) }
};
However I'm struggling to figure out how to "tag" specific crates and then use the shader to draw vertices with the correct texture, as my experience and skill with GLSL are quite limited.
Could I just pass in another uniform consisting of (vertex) indices to specify where the shader should apply the second texture? ie:
crateMaterial.uniforms.cratesTexturemap = [];
for(i=0;i<cratesToRender;i++) {
/* set position */
...
this._instancePositions.push( position.x, position.y, position.z );
if (drawCrate2) {
crateMaterial.uniforms.cratesTexturemap.push(i); /* correlates to (vertex) position index */
crateMaterial.uniforms.cratesTexturemap.push(i+1);
crateMaterial.uniforms.cratesTexturemap.push(i+2);
}
...
}
Also performance/memory-wise, is it better to have a (dynamic) array of textures passed to the shader or is passing them one by one (a uniform value for every texture as above) more advantageous?
Example shader code for reference:
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec3 offset;
attribute vec2 uv;
attribute vec4 orientation;
varying vec2 vUv;
// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
vec3 applyQuaternionToVector( vec4 q, vec3 v ){
return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );
}
void main() {
vec3 vPosition = applyQuaternionToVector( orientation, position );
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( offset + vPosition, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision highp float;
uniform sampler2D map;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D( map, vUv );
}
</script>
Can't you just pass an array of textures and choose which to apply using an index passed by a int uniform?
So for every crate you could do
crate.material.uniforms.index = 2
to choose the 3rd texture in the array

three.js animated texture in particles with custom shadermaterial

How do I make each particle animate and cycle through all the tiles in the sprite sheet?
Here's my shader program:
<script type="x-shader/x-vertex" id="vertexshader">
attribute vec2 offset;
varying vec2 vOffset;
void main()
{
vOffset = offset;
gl_PointSize = 25.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D texture;
uniform vec2 repeat;
varying vec2 vOffset;
void main()
{
vec2 uv = vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y );
vec4 tex = texture2D( texture, uv * repeat + vOffset );
if ( tex.a < 0.5 ) discard;
gl_FragColor = tex;
}
</script>
Basically an example from here: http://jsfiddle.net/myy7x4zd/4/

Shadow artifacts in opengl

I am trying to render an object and two lights, one of the lights cast shadows. Everything works ok but I noticed that there are some obvious artifacts, as shown in the below image, some shadows seem to overflow to bright areas.
Below is the shaders to render depth information into a framebuffer
<script id="shadow-shader-vertex" type="x-shader/x-vertex">
attribute vec4 aVertexPosition;
uniform mat4 uObjMVP;
void main() {
gl_Position = uObjMVP * aVertexPosition;
}
</script>
<script id="shadow-shader-fragment" type="x-shader/x-vertex">
precision mediump float;
void main() {
//pack gl_FragCoord.z
const vec4 bitShift = vec4(1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0);
const vec4 bitMask = vec4(1.0/256.0, 1.0/256.0, 1.0/256.0, 0.0);
vec4 rgbaDepth = fract(gl_FragCoord.z * bitShift);
rgbaDepth -= rgbaDepth.gbaa * bitMask;
gl_FragColor = rgbaDepth;
}
</script>
In the above shaders, uObjMVP is the MVP matrix used when looking from the position of the light that cast shadow (the warm light, the cold light does not cast shadow)
And here are the shaders to draw everything:
<script id="shader-vertex" type="x-shader/x-vertex">
//position of a vertex.
attribute vec4 aVertexPosition;
//vertex normal.
attribute vec3 aNormal;
//mvp matrix
uniform mat4 uObjMVP;
uniform mat3 uNormalMV;
//shadow mvp matrix
uniform mat4 uShadowMVP;
//interplate normals
varying vec3 vNormal;
//for shadow calculation
varying vec4 vShadowPositionFromLight;
void main() {
gl_Position = uObjMVP * aVertexPosition;
//convert normal direction from object space to view space
vNormal = uNormalMV * aNormal;
vShadowPositionFromLight = uShadowMVP * aVertexPosition;
}
</script>
<script id="shader-fragment" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D uShadowMap;
varying vec3 vNormal;
varying vec4 vShadowPositionFromLight;
struct baseColor {
vec3 ambient;
vec3 diffuse;
};
struct directLight {
vec3 direction;
vec3 color;
};
baseColor mysObjBaseColor = baseColor(
vec3(1.0, 1.0, 1.0),
vec3(1.0, 1.0, 1.0)
);
directLight warmLight = directLight(
normalize(vec3(-83.064, -1.99, -173.467)),
vec3(0.831, 0.976, 0.243)
);
directLight coldLight = directLight(
normalize(vec3(37.889, 47.864, -207.187)),
vec3(0.196, 0.361, 0.608)
);
vec3 ambientLightColor = vec3(0.3, 0.3, 0.3);
float unpackDepth(const in vec4 rgbaDepth) {
const vec4 bitShift = vec4(1.0, 1.0/256.0, 1.0/(256.0*256.0), 1.0/(256.0*256.0*256.0));
float depth = dot(rgbaDepth, bitShift);
return depth;
}
float calVisibility() {
vec3 shadowCoord = (vShadowPositionFromLight.xyz/vShadowPositionFromLight.w)/2.0 + 0.5;
float depth = unpackDepth(texture2D(uShadowMap, shadowCoord.xy));
return (shadowCoord.z > depth + 0.005) ? 0.4 : 1.0;
}
vec3 calAmbientLight(){
return ambientLightColor * mysObjBaseColor.ambient;
}
vec3 calDiffuseLight(const in directLight light, const in float visibility){
vec3 inverseLightDir = light.direction * -1.0;
float dot = max(dot(inverseLightDir, normalize(vNormal)), 0.0);
return light.color * mysObjBaseColor.diffuse * dot * visibility;
}
void main() {
vec3 ambientLight = calAmbientLight();
float visibility = calVisibility();
vec3 warmDiffuseLight = calDiffuseLight(warmLight, visibility);
// cold light does not cast shadow and hence visilibility is always 1.0
vec3 coldDiffuseLight = calDiffuseLight(coldLight, 1.0);
gl_FragColor = vec4(coldDiffuseLight + warmDiffuseLight + ambientLight, 1.0);
}
</script>
If I simply draw the depth information out on to the canvas,
void main() {
// vec3 ambientLight = calAmbientLight();
// float visibility = calVisibility();
// vec3 warmDiffuseLight = calDiffuseLight(warmLight, visibility);
// // cold light does not cast shadow and hence visilibility is always 1.0
// vec3 coldDiffuseLight = calDiffuseLight(coldLight, 1.0);
// gl_FragColor = vec4(coldDiffuseLight + warmDiffuseLight + ambientLight, 1.0);
vec3 shadowCoord = (vShadowPositionFromLight.xyz/vShadowPositionFromLight.w)/2.0 + 0.5;
gl_FragColor = vec4(unpackDepth(texture2D(uShadowMap, shadowCoord.xy)), 0.0, 0.0, 1.0);
}
I would get this image
Thanks in advance.

how to use uniform to change color in webgl

So far, I have successfully display a cube with a fix color. However, I want the color of the cube to be changeable. So I tried to replace this code:
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(vertexColors1), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor );
with:
vColor = gl.getUniformLocation(program, "vColor");
gl.uniformMatrix4fv(vColor,false,flatten(vertexColors1));
And I also change the type of vColor in my vertex-shader from attribute to uniform. in the fragment shader, I use varying. However, these method is not working. The color of the cube become white instead of the color that I have assigned in vertexColors1. any suggestion?
Shader code:
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
uniform vec4 vColor;
//attribute vec4 vColor;
varying vec4 fColor;
uniform mat4 modelViewMatrix;
void main()
{
fColor = vColor;
gl_Position = modelViewMatrix * vPosition;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>

why Particle system with shader doesn't work? three.js

Hi can anyone help me whith this? I have this shader, it works with THREE.Mesh but doesn't with THREE.Particlesystem?
I want each particle to have a portion of a given map(texture) and change their positions accordingly, something like this http://www.chromeexperiments.com/detail/webcam-displacement/?f=webgl
<script id="vs" type="x-shader/x-vertex">
uniform sampler2D map;
varying vec2 vUv;
void main() {
vUv = uv;
vec4 color = texture2D( map, vUv );
float value = ( color.r + color.g + color.b ) / 3.0;
vec4 pos = vec4( position.xy, value * 100.0, 1.0 );
gl_PointSize = 20.0;
gl_Position = projectionMatrix * modelViewMatrix * pos;
}
</script>
<script id="fs" type="x-shader/x-fragment">
uniform sampler2D map;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D( map, vUv );
}
</script>
ParticleSystem doesn't really support UVs as there aren't faces, just single points. Texture mapping particles is done with gl_PointCoord (IIRC), but that gives you same mapping for every particle. In order to give different portion of the same texture to each particle, you should use BufferGeometry, which in the latest version of three.js supports all attributes including custom ones (and it is very efficient and fast!). You'd then supply a vec2 offset attribute for each particle: you get the correct UV from this offset and the gl_PointCoord.

Resources