Three.js, custom shader, fill png texture and set transparency? - javascript

The task is to change the color of the texture with a predominance of red. I'm trying to do this, but my texture completely fills the picture with red, please tell me where is the error?
I don't understand why I can't set transparency
function vertexShader(){
return `
precision mediump float;
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0 );
}
`
}
function fragmentShader(){
return `
precision mediump float;
varying vec2 vUv;
uniform sampler2D u_texture;
uniform float u_time;
void main(){
gl_FragColor = texture2D(u_texture, vUv);
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`
}
var texLoader = new THREE.TextureLoader();
var texture = texLoader.load("217.png");
const uniforms = {
u_texture: {value: texture}
}
const material = new THREE.ShaderMaterial(
{
uniforms,
vertexShader: vertexShader(),
fragmentShader: fragmentShader(),
side: THREE.DoubleSide,
//wireframe: true
}
);

The shader is setting gl_FragColor to red
gl_FragColor = texture2D(u_texture, vUv); // this line is effectively ignored
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // because this line sets glFragColor
Maybe you meant this?
gl_FragColor = texture2D(u_texture, vUv);
gl_FragColor += vec4(1.0, 0.0, 0.0, 1.0); // add red
or this?
gl_FragColor = texture2D(u_texture, vUv);
gl_FragColor *= vec4(1.0, 0.0, 0.0, 1.0); // multiply by red

Related

Three.js Shader glass effect with PNG-image-mask on a Video-Texture

some days ago I visited the site activetheory.net again. And I saw this stunning nice glass effect in the Homescreen logo border and tried to recode it. Based on the minified code I was able to see they use a PNG as a mask.
I was able to load a png inside the shader and show it up, also it was easy to get a mesh with video texture working. Now I'm stuck on the combining part (png with video) inside the shaders.
someone got experience with it and can help me?
Thank you and have a nice Day!
here is the shader-material part from:
var g = new THREE.PlaneGeometry(128.0, 72.0);
var outline = THREE.ImageUtils
.loadTexture('outline.png');
outline.magFilter = THREE.NearestFilter;
var mat = new THREE.ShaderMaterial({
uniforms: {
map: {type: "t", value: movieScreen.texture},
outline: {type: "t", outline},
aspect: {type: "fv1", value: []},
res: {type: "v2", value: new THREE.Vector2(window.innerWidth, window.innerHeight)}
},
vertexShader: document.
getElementById('vertShader').text,
fragmentShader: document.
getElementById('fragShader').text,
transparent: true,
});
here are the shaders:
<script id="vertShader" type="shader">
varying vec2 vUv;
varying vec2 nUv;
void main() {
vUv = uv;
nUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id="fragShader" type="shader">
varying vec2 vUv;
varying vec2 nUv;
uniform float color;
uniform sampler2D outline;
uniform sampler2D map;
void main(void) {
float alpha = step(0.9, texture2D(outline, vUv).a);
gl_FragColor = texture2D(outline, nUv);
gl_FragColor *= alpha;
}
</script>
Finally, I got a similar shader working. For everyone who is interested.
The shaders:
<script id="vertShader" type="shader">
varying vec2 vUv;
varying vec2 nUv;
void main() {
vUv = uv;
nUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.05);
}
</script>
<script id="fragShader" type="shader">
varying vec2 vUv;
varying vec2 nUv;
uniform float color;
uniform sampler2D outline;
uniform sampler2D map;
void main(void) {
float alpha = step(0.9, texture2D(outline, vUv).a);
gl_FragColor = texture2D(map, nUv);
gl_FragColor *= alpha;
gl_FragColor += 0.08 * alpha;
}
</script>
Have fun!

THREE.js Color texture by shader

i've added simple box to my scene, and I want to create shader that will add a texture to it and add color to this texture.
This is my vertex shader(nothing special about it):
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script>
And this is my fragment shader:
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2 resolution;
uniform float time;
uniform sampler2D texture;
varying vec2 vUv;
uniform vec3 color;
varying vec3 vColor;
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / vec2(1920.0, 1920.0);
fragColor = vec4(uv, 0.5 + 0.5 * cos(time) * sin(time) ,1.0);
}
void main( void ) {
vec4 color = vec4(0.0,0.0,0.0,1.0);
mainImage( color, gl_FragCoord.xy );
color.w = 1.0;
gl_FragColor = texture2D(texture, vUv);
gl_FragColor = color;
}
</script>
As You can see, in two last lines i've sets gl_FragColor with texture and color.
When last line is gl_FragColor = color; The result is:
When i change order and last line is gl_FragColor = texture2D(texture, vUv); The result is:
This is the code that use shader and add a box to a scene:
var geometry = new THREE.BoxGeometry(.5, 1, .5);
uniforms = {
time: { type: "f", value: 1.0 },
resolution: { type: "v2", value: new THREE.Vector2() },
texture: { type: "t", value: THREE.ImageUtils.loadTexture("../img/disc.png") }
};
var material = new THREE.ShaderMaterial({
transparent: true,
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
Is there a possibility to color my texture(mix color and texture in object) by this shader in the same way like in the picture?
Just like any other variable setting it twice just makes it the 2nd result;
var foo;
foo = 123;
foo = 456;
foo now equals 456
If you want to combine the results you need to something yourself to combine them
gl_FragColor = texture2D(texture, vUv);
gl_FragColor = color;
Just means gl_FragColor equals color;
I'm guessing you want something like
gl_FragColor = texture2D(texture, vUv) * color;
But of course what math you use is up to you depending on what you're trying to achieve.
Given your example texture and color above multiplying the texture by the color you'll get a circle with a gradient color. It's not clear if that's the result you wanted.

Three JS transparancy with ShaderMaterial

I'm drawing two geometries next to each other and have them rotate. The problem is that the first drawn one is obstructing the second one, where transparency should take effect. The two objects should have the same transparency, regardless of who was drawn first. That's why blending is turned on and depth test is off.
Here are the images:
Both geometries are point cloud using THREE.ShaderMaterial as followed:
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
attributes: attributes,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
blending: THREE.NormalBlending,
depthTest: false,
transparent: true
});
where
// attributes
attributes = {
size: { type: 'f', value: null },
alpha: { type: 'f', value: [] },
customColor: { type: 'c', value: null }
};
// uniforms
uniforms = {
color: { type: "c", value: new THREE.Color(0x00ff00) },
texture: { type: "t", value: THREE.ImageUtils.loadTexture("../textures/sprites/circle.png") }
};
and
<script type="x-shader/x-vertex" id="vertexshader">
attribute float alpha;
attribute float size;
attribute vec3 customColor;
varying float vAlpha;
varying vec3 vColor;
void main() {
vAlpha = alpha;
vColor = customColor;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_PointSize = size * ( 120.0 / length( mvPosition.xyz ));
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform vec3 color;
uniform sampler2D texture;
varying float vAlpha;
varying vec3 vColor;
void main() {
gl_FragColor = vec4( vColor, vAlpha );
gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
}
</script>
Example code with 2 textures, but can be made to work with one as well:
<script id="fragmentShaderLoader" type="x-shader/x-fragment">
uniform float percent;
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D( texture1, vUv);
vec4 tex2 = texture2D( texture2, vUv );
if(tex2.a - percent < 0.0) {
gl_FragColor.a = 0.0;
//or without transparent = true use
//discard;
}
}
</script>
<script id="vertexShaderLoader" type="x-shader/x-vertex">
varying vec2 vUv;
void main()
{
vUv = uv;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
gl_Position = projectionMatrix * mvPosition;
}
</script>
Then for init:
uniformsMove = {
percent: { type: "f", value: 1.0 },
texture1: { type: "t", value: (new THREE.TextureLoader()).load( "govr/loader-test.png" ) },
texture2: { type: "t", value: (new THREE.TextureLoader()).load( "govr/loader-mask2.png" ) }
};
material = new THREE.ShaderMaterial( {
uniforms: uniformsMove,
vertexShader: document.getElementById( 'vertexShaderLoader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShaderLoader' ).textContent
} );
material.transparent = true;

Three.js ParticleSystem transparency issue

I'm using Three.js and I have a ParticleSystem where every particle may have a different transparency and color.
Code:
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: customUniforms,
attributes: customAttributes,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
transparent: true,
alphaTest: 0.5
});
particles = new THREE.ParticleSystem(geometry, shaderMaterial);
particles.dynamic = true;
Vertex shader:
attribute float size;
attribute vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
//gl_PointSize = size;
gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
gl_Position = projectionMatrix * mvPosition;
}
Fragment shader:
uniform sampler2D texture;
uniform float alpha;
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 100);
vec4 textureColor = texture2D( texture, gl_PointCoord );
gl_FragColor = gl_FragColor * textureColor;
gl_FragColor.a = alpha;
}
Texture is a circle but when I set alpha, like this: gl_FragColor.a = alpha, my texture become a circle in a black square, alpha level is okay, but I don't need the square, only the circle if I don't set the alpha, square doesn't appear.
So how to set alpha correctly for provided texture?
Take a look at this: three.js - Adjusting opacity of individual particles
You can find jsfiddle somewhere in the page that uses ShaderMaterial for ParticleSystem with variable alpha: http://jsfiddle.net/yfSwK/27/
Also, at least change fragment shader a bit, gl_FragColor should be write-only variable, it's not usual to have it as a read-from variable:
vec4 col = vec4(vColor, 100);
vec4 tex = texture2D( texture, gl_PointCoord );
gl_FragColor = vec4( (col*tex).rgb, alpha );
...or in one line:
gl_FragColor = vec4( (vec4(vColor, 100) * texture2D( texture, gl_PointCoord )).rgb, alpha);

Three.js, GLSL, HeightMaps + Alphamaps

I am using three.js to attempt and learn more about OpenGL. Anyway, I've created a fragment shader which actually works for blending textures with an alphamap but I am having issues with the heightmap portion. If anyone has any ideas please let me know as I am stuck. Oh, I have used this as a reference: http://threejs.org/examples/webgl_terrain_dynamic.html.
<script id="vertexShader" type="x-shader/x-vertex">
uniform sampler2D tDisplacement;
varying vec2 vUv;
void main(void)
{
vUv = uv;
#ifdef VERTEX_TEXTURES
vec3 dv = texture2D( tDisplacement, uv ).xyz;
float df = 300.0 * dv.z + 1.0;
vec3 displacedPosition = normal * df + position;
vec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );
vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );
#else
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
#endif
gl_Position = projectionMatrix * mvPosition;
}
</script>
<script id="fragmentShaderNoise" type="x-shader/x-fragment">
uniform sampler2D Alpha;
uniform sampler2D Grass;
uniform sampler2D Stone;
uniform sampler2D Rock;
uniform sampler2D tDisplacement;
varying vec3 vertex_color;
varying vec2 vUv;
void main(void)
{
vec4 alpha = texture2D( Alpha, vUv.xy);
vec4 tex0 = texture2D( Grass, vUv.xy * 10.0 ); // Tile
vec4 tex1 = texture2D( Rock, vUv.xy * 10.0 ); // Tile
vec4 tex2 = texture2D( Stone, vUv.xy * 10.0 ); // Tile
tex0 *= alpha.r; // Red channel
tex1 = mix( tex0, tex1, alpha.g ); // Green channel
vec4 outColor = mix( tex1, tex2, alpha.b ); // Blue channel
gl_FragColor = outColor;
}
</script>
If a related example would help, I have written a demo that includes a vertex shader that incorporates displacement at:
http://stemkoski.github.io/Three.js/Shader-Fireball.html
Alternatively, perhaps you could start with something simpler, and then work incrementally towards your desired result. For example, I believe that the code below would allow you to change the vertex position according to the red amount of each pixel in the texture bumpTexture.
uniform sampler2D bumpTexture;
varying vec2 vUv;
void main()
{
vUv = uv;
vec4 bumpData = texture2D( bumpTexture, uv );
float displacement = 100.0 * bumpData.r;
vec3 newPosition = position + normal * displacement;
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
Hope this helps!

Categories