Are there any opacity maps for THREE.js ? Like:
so that I can use it on a map like
MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial and MeshStandardMaterial support an alphaMap.
Alternatively, you could bake the transparency into your color texture's alpha channel.
In either case, you need to set material.transparent = true.
EDIT: If you are implementing a cut-out (alpha is either 0 or 1), then instead of setting material.transparent = true, you can just set material.alphaTest = 0.5.
three.js r.87
Related
I need to sample the RGBA values of a texture, and I'm using the alpha channel to store custom data, not really to as opacity. The problem is that as alpha approaches 0, my RGB values also get multiplied towards 0, but I need them to remain independent.
My first render pass gets rendered into a WebGLRenderTarget, and this is how I'm storing data in GLSL into the alpha channel:
gl_FragColor.rgb = mainColor;
gl_FragColor.a = depthData;
the result shows Alpha fading to white as expected:
My second render pass gets rendered to the canvas, so I read the RGB values from from the first texture in GLSL, with alpha as 1:
gl_FragColor.rgb = texture2D(tColor, vUv).rgb;
gl_FragColor.a = 1.0;
The result should be the regular RGB values of the spheres, but it seems that the RGB values fade to black when Alpha approaches 0.
Is there a way to use the alpha channel as data storage without affecting the RGB values? I've tried setting the target texture's premultiplyAlpha = false as follows, but it doesn't change anything:
var target = new THREE.WebGLRenderTarget(
window.innerWidth,
window.innerHeight, {
format: THREE.RGBAFormat,
type: THREE.UnsignedByteType
});
target.texture.premultiplyAlpha = false;
Update:
I was building a working demo here, and I was unable to reproduce the bug. It looks like I'm going to have to rip apart my entire project until I get to the bottom of this...
So I have very basic setup:
var cubeCamera = new THREE.CubeCamera (1, 1000, 1024);
cubeCamera.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
cubeCamera.renderTarget.texture.mapping = THREE.CubeRefractionMapping;
cubeCamera.updateCubeMap (renderer, scene);
var matte = new THREE.MeshStandardMaterial({
envMap: cubeCamera.renderTarget.texture,
metalness: 0.5,
roughness: 0.4
});
and this creates correctly blurred refraction. However, driving metalness to 0 makes it vanish almost completely, making the material seem fully opaque. What is correct way to set up matte refractive material?
You are trying to use MeshStandardMaterial to create a translucent and refractive non-metallic material. You are setting metalness to zero, or near zero.
Non-metals typically have a low specular reflectance. That means the specular reflections from the environment are minimal — certainly compared to metals. Consequently, MeshStandardMaterial has been designed to have similar properties.
You have two options.
The first option is to compensate by increasing material.envMapIntensity, which defaults to 1. This simulates a brighter environment.
A second option is to use the more feature-rich MeshPhysicalMaterial, instead.
MeshPhysicalMaterial has an additional material.reflectivity property which controls the specular reflectance for non-metals. For physically-based materials, setting this property to 1 is a reasonable maximum value, but you can increase it further if you want.
three.js r.86
I use THREE.js and enable alpha canvas: (because I need to build my WebGL on top of something else)
this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas, antialias: false, alpha: true });
I set the clear color like this:
this.renderer.setClearColor(0xffffff, 0.0);
In each frame:
_render () {
renderer.clear();
gl.disable(gl.BLEND);
// ... something else doesn't need to be blended, whose alpha value is not 1.0
}
I'm curious why something else still gets blended with the white background even if I disable gl.BLEND.
three.js controls the blending. When you call renderer.render it will set the blending calling gl.enable(gl.BLEND) for each material depending on whether or not that material needs blending.
On top of that, even with blending off you can draw with a non 1.0 alpha which will end up giving use a canvas that can see through to the background.
Using Threejs (67) with a Webgl renderer, I can't seem to get a plane with a shader material to wear its texture. No matter what I do the material would just stay black.
My code at the moment looks quite basic :
var grassT = new Three.Texture(grass); // grass is an already loaded image.
grassT.wrapS = grassT.wrapT = Three.ClampToEdgeWrapping;
grassT.flipY = false;
grassT.minFilter = Three.NearestFilter;
grassT.magFilter = Three.NearestFilter;
grassT.needsUpdate = true;
var terrainUniforms = {
grassTexture : { type: "t", value: grassT},
}
Then I just have this revelant part in the vertexShader :
vUv = uv;
And on the fragmentShader side :
gl_FragColor = texture2D(grassTexture, vUv);
This results in :
Black material.
No error in console.
gl_FragColor value is always (0.0, 0.0, 0.0, 1.0).
What I tryed / checked:
Everything works fine if I just apply custom plain colors.
All is ok if I use vertexColors with plain colors too.
My texture width / height is indeed a power of 2.
The image is on the same server than the code.
Tested others images with same result.
The image is actually loading in the browser debugger.
UVS for the mesh are corrects.
Played around with wrapT, wrapS, minFilter, magFilter
Adapted the mesh size so the texture has a 1:1 ratio.
Preloaded the image with requirejs image plugin and created the texture from THREE.Texture() instead of using THREE.ImageUtils();
Played around with needsUpdate : true;
Tryed to add defines['USE_MAP'] during material instanciation.
Tryed to add material.dynamic = true.
I have a correct rendering loop (interraction with terrain is working).
What I still wonder :
It's a multiplayer game using a custom port with express + socket.io. Am I hit by any Webgl security policy ?
I have no lights logic at the moment, is that a problem ?
Maybe the shader material needs other "defines" at instanciation ?
I guess I'm overlooking something simpler, this is why I'm asking...
Thanks.
I am applying various effects on the same shader. I have a custom API that merge all different effects uniforms simply by using Three.UniformsUtils.merge() However this function is calling the clone() method on the texture and this is causing to reset needsUpdate to false before the texture reach the renderer.
It appears that you should set your texture needsUpdate property to true when reaching the material level. On the texture level, if the uniform you set get merged, and therefore cloned, later in the process, it'll lose its needsUpdate property.
The issue is also detailled here: https://github.com/mrdoob/three.js/issues/3393
In my case the following wasn't working (grassT is my texture):
grassT.needsUpdate = true
while the following is running perfectly later on in the code:
material.uniforms.grassTexture.value.needsUpdate = true;
Image loading is asynchronous. Most likely, you are rendering your scene before the texture image loads.
You must set the texture.needsUpdate flag to true after the image loads. three.js has a utility that will do that for you:
var texture = THREE.ImageUtils.loadTexture( "texture.jpg" );
Once rendered, the renderer sets the texture.needsUpdate flag back to false.
three.js r.68
Here I try to render a cube/plane geometry using THREE.ShaderMaterial with THREE.ShaderLib['lambert'], it loaded perfectly, but I am struggling to change each face color with opacity value.
As of Three.js 0.127 you can simply use vertexColors, and it supports alpha (opacity) values.
On your material, set
material.vertexColors = true
On your geometry make sure you set the itemSize to include alpha,
geometry.attributes.color.itemSize === 4
then provide 4 values (RGBA) for each vertex instead of 3 (RGB).
Docs:
Material.vertexColors
ShaderMaterial.vertexColors
Example usage:
webgl_geometry_colors
Note, the example uses itemSize 3, without opacity. Make sure you use itemSize 4, and for every value provide 4 numbers instead of 3.