lightMap / specularMap / shading with meshBasicMaterial - three.js

I'm currently working on something along the lines of a plugin for another program to add 3D capability to it, so I'm trying to put all the functionality i can from three.js into it, with the added goal of this being a good way to learn all the functionality of three.js firsthand.
I'm running into an issue now as i implement textures and materials that with mesh basic material, setting some things which the documentation on the main threejs.org site shows are features, doesn't actually do anything.
when i set a texture for either specularmap or lightmap nothing is actually showing up. Im pretty sure its not a mistake im making because setting the texture of the map works, but trying to set this same texture for the specularMap or lightMap is doing nothing. Does a regular texture work for these, or do i have to do something different?
I'd also like to know what the shading property does for mesh basic, because as far as i can see setting it to smoothshading/flatshading/noshading is doing nothing aswell.

MeshBasicMaterial does not respond to lights. Change your material to MeshLamberMaterial or MeshPhongMaterial, for example.
For MeshBasicMaterial and MeshLambertMaterial, the specularMap is used only to modulate the reflection when an environment map is used.
For any material, lightmaps require a second set of UVs. geometry.faceVertexUvs[ 0 ] contains the usual set of UVs; for a lightmap, you need to add geometry.faceVertexUvs[ 1 ], a second set of UVs.
For MeshBasicMaterial, the shading property only applies when an environment map is used. SmoothShading will yield smooth reflections; FlatShading will yield faceted reflections.
three.js r.66

Related

I can't get the aoMap showing in three.js using a glb/gltf asset

I’m having a hard time getting an aoMap working in three.js…
I have a glb asset with an aoMap on the red channel or something. When I bring it into to the babylon viewer, I can see the ao just fine, but it wont show up in the three.js viewer or my project. I think this has something to do with a second set of uvs, but I can't find a resource that involves doing that on top of using the gltf loader… I really don't know what to do here. Any response would be greatly appreciated!
Here is my code (I’m using a html-canvas as the texture)
And I get the model’s geometry and diffuse texture (all white) as desired, but the aomap isnt showing…
code
babylon viewer
three.js viewer
working application with shadows included in diffuse
not working, diffuse is just white, and aoMap is not showing
You're right about needing a second set of UVs. The reason behind this is that diffuse textures often repeat (think of a brick wall, or checkered t-shirt). AO shading, however, is more likely to be unique on each part of the geometry, so it's almost never repetitive. Since this often would need an alternative UV mapping method, the default is to use a second set of UVs.
You could do 2 things:
Re-export your GLTF asset with a duplicate set of UVs.
Duplicate existing UVs in Three.js by creating a new BufferAttribute in your geometry:
// Get existing `uv` data array
const uv1Array = mesh.geometry.getAttribute("uv").array;
// Use this array to create new attribute named `uv2`
mesh.geometry.setAttribute( 'uv2', new THREE.BufferAttribute( uv1Array, 2 ) );
.getAttribute and .setAttribute are methods of BufferGeometry, if you want to read more about them.

Three.js. MeshPhongMaterial has a uniform called diffuse. Why is it is not exposed nor can it be set?

In Three.js I am looking closely at the glsl source for MeshPhongMaterial. I notice the fragment shader relies on a uniform named diffuse. However there does not appear to be any way to set it. There is also an uniform named color that can be set and does indeed alter what looks like the diffuse color. Huh?
Is color copied to diffuse under the hood somehow? Can someone untangle this mystery for me.
If you look or search though the source you'll find it's set based on the color of the material
For example here
MeshPhongMaterial is not a subclass of ShaderMaterial even though they both extend Material.
Internally WebGLRenderer keeps track of / knows how to deal with two different things:
Any ShaderMaterial with any uniform. This means that you can make an exact copy of MeshPhongMaterial using ShaderMaterial and instead of myMaterial.color you'd have myMaterial.uniforms.color.
"Built-in" materials and their properties. For these, WebGLRenderer is aware of all the possible properties these materials expose. Gman has pointed out where in the code this happens (one of the places). For each material WebGLRenderer internally creates a ShaderMaterial but instead of handling it's uniforms like it would with any other such material, it manually keeps track and updates everything.
The built-in materials make little sense, since you can easily pipe foo.bar to foo.uniforms.bar using getters and setters leaving the renderer to only deal with shader materials.
If you really really want a uniform created for a built in material, you have to wait until the renderer creates them, and you can tap into this process with material.onBeforeCompile = shader=>{} (the shader object will contain the uniforms).

Render scene onto custom mesh with three.js

After messing around with this demo of Three.js rendering a scene to a texture, I successfully replicated the essence of it in my project: amidst my main scene, there's a now sphere and a secondary scene is drawn on it via a THREE.WebGLRenderTarget buffer.
I don't really need a sphere, though, and that's where I've hit a huge brick wall. When trying to map the buffer onto my simple custom mesh, I get an infinite stream of the following errors:
three.js:23444 WebGL: INVALID_VALUE: pixelStorei: invalid parameter for alignment
three.js:23557 Uncaught TypeError: Cannot read property 'width' of undefined
My geometry, approximating an annular shape, is created using this code. I've successfully UV-mapped a canvas onto it by passing {map: new THREE.Texture(canvas)} into the material options, but if I use {map: myWebGLRenderTarget} I get the errors above.
A cursory look through the call stack makes it look like three.js is assuming the presence of the texture.image attribute on myWebGLRenderTarget and attempting to call clampToMaxSize on it.
Is this a bug in three.js or am I simply doing something wrong? Since I only need flat rendering (with MeshBasicMaterial), one of the first thing I did when adapting the render-to-texture demo above was remove all trace of the shaders, and it worked great with just the sphere. Do I need those shaders back in order to use UV mapping and a custom mesh?
For what its worth, I was needlessly setting needsUpdate = true on my texture. (The handling of needsUpdate apparently assumes the presence of a <canvas> that the texture is based on.)

Ink 'n Paint Material does not work with ThreeJS?

I want to render all the vertexes and the lines in the mesh.
I tried
1) A custom shader following this link
https://github.com/mrdoob/three.js/issues/2028
2) Set transparency with the material or like:
THREE.MeshNormalMaterial( { transparent: true, opacity: 0.5 } ),
3) Set ink material to the model in 3dMax and export to an obj file and load it in Threejs with objloader
None of them works fine.
Is there any solution to load mashes from 3dMax model (using objloader) and apply it with ink material in Threejs, just like what we can do in 3DMax?
See below as an example
http://makeitcg.com/wireframe-rendering-techniques-in-3ds-max/160/
First of all, Number 3) will NEVER work with OBJ, because obj will not export the ink shader from 3dsMax. And just to be clear, i don't think there is ANY way you can export the 3dsMax Shader.
Then, I don't understand what 2) is about. What do you want to achieve anyway? Do you want to set an object to be transparent? What does this have to do with Ink 'n Paint? Btw. i am not sure if transparency works for MeshNormalMaterial, i guess it should but Lambert and Phong will definetly work with transparency.
The problem is that you do not state what you want to achieve. From 1) it seems you want an outline around an object. For an outline see this example: http://stemkoski.github.io/Three.js/Outline.html or this one as a more advanced example: http://stemkoski.blogspot.de/2013/07/shaders-in-threejs-glow-and-halo.html
If you want to set transparent objects, well try MeshLambert or meshBasic material if MeshNormal does not work (i am not sure Right Now and can't check)
3) if you want to have a Ink 'n Paint shader, you need a Custom Shader. See examples here:
http://www.chromeexperiments.com/detail/cel-shader/
and already done with three.js here:
http://learningthreejs.com/data/THREEx/docs/THREEx.CelShader.html
Just apply the shader, see examples for setting up a ShaderMaterial.

Flat shading OpenGL using Three.js

I am trying to simulate the OpenGL flat shading model using Three.js. My idea is creating an example like http://en.wikipedia.org/wiki/File:Phong-shading-sample.jpg. I was trying to change some different shading models but I cannot obtain the desired result.
Is it possible to create this scene in three.js?
Thanks in advance
Materials e.g. the MeshBasicMaterial have an option called "shading". It can be set to THREE.None, THREE.FlatShading, THREE.SmoothShading.
I am not sure if you need a light source in the first place or wether you have to enable shading for a the whole scene. Look at the demos at the Three.js website for something with shading.

Resources