Manual selection lod of mipmaps in a fragment shader using three.js - three.js

I'm writing a physically based shader using glsl es in three.js. For the addition of specular global illumination I use a cubemap dds texture with mipmap chain inside (precalculate with CubeMapGen as it's explained here). I need to access this texture in fragment shader and I would like to select manually the index of mipmap. The correct function for doing this is
vec4 textureCubeLod(samplerCube sampler, vec3 coord, float lod)
but it's available only in vertex shader. In my fragment shader I'm using the similar function
vec4 textureCube(samplerCube sampler, vec3 coord, float bias)
but it doesn't work well, because the bias parameter is just added to the automatically calculated level of detail. So, when I zoom in or zoom out on the scene the LOD of mipmap change, but for my shader it must be the same (it must depends only on the rough parameter, as explained in the link above).
I would like to select manually the level of mipmap in fragment shader only depends on the roughness of the material (for example using the formula mipMapIndex = roughness*numMipMap), so it must be costant with the distance and no automatically changed when zooming. How can I solve this?

It wont work with webGL atm, because there is no support for this feature. You can experiment with textureLOD extensions though with recent builds of chrome canary, but it still needs some tweaking. Go about flags and look for this:
Enable WebGL Draft Extensions
WebGL textureCube bias causing seams

Related

Is there a way to access a vector by coordinates as you would a texture in GLSL?

I am implementing a feature extraction algorithm with OpenGL ES 3.0 (given an input texture with some 1's and mostly 0's, produce an output texture that has feature regions labeled). The problem I face in my fragment shader is how to perform a “lookup” on an intermediate vec or float rather than a sampler.
Conceptually every vec or float is just a texel-valued function, so there ought to be a way to get its value given texel coordinates, something like textureLikeLookup(texel_valued, v_color) - but I haven’t found anything that parallels the texture* functions.
The options I see are:
Render my vector to a framebuffer and pass that as a texture into another shader/rendering pass - undesirable because I have many such passes in a loop, and I want to avoid interleaving CPU calls;
Switch to ES 3.1 and take advantage of imageStore (https://www.khronos.org/registry/OpenGL-Refpages/es3.1/html/imageStore.xhtml) - it seems clear that if I can update an intermediate image within my shader then I can achieve this within the fragment shader (cf. https://www.reddit.com/r/opengl/comments/279fc7/glsl_frag_update_values_to_a_texturemap_within/), but I would rather stick to 3.0 if possible.
Is there a better/natural way to deal with this problem? In other words, do something like this
// works, because tex_sampler is a sampler2D
vec4 texel_valued = texture(tex_sampler, v_color);
when the data is not a sampler2D but a vec:
// doesn't work, because texel_valued is not a sampler but a vec4
vec4 oops = texture(texel_valued, v_color);

Add clipping to THREE.ShaderMaterial

I'm trying to create a shader that takes into account the clipping planes I'm defining in the scene. These clipping planes work fine for all of the 'vanilla' materials I'm using: THREE.MeshLambertMaterial, THREE.MeshPhongMaterial, and THREE.MeshPhysicalMaterial, but THREE.ShaderMaterial is missing this implementation. This is an example of what I mean: https://jsfiddle.net/fraguada/27LrLsv5/
In this example there are two cubes, one with a THREE.MeshStandardMaterial and one with a material defined by THREE.ShaderMaterial. The cube with a THREE.MeshStandardMaterial clips ok. The cube with THREE.ShaderMaterial does not clip.
(I'm not typically defining the vertex/fragment shader in script tags as I show in the jsfiddle, instead I'm defining them in a similar manner to this: https://github.com/mrdoob/three.js/blob/dev/examples/js/shaders/BasicShader.js.)
So, a few questions:
Should THREE.ShaderMaterial include Clipping Planes out of the box? (there is a clipping property, but not sure what it enables)
If not, how could I modify this shader to include the necessary params and shader chunks to enable clipping?
Actually, clipping is done inside the Three.js shaders.
To make it work, you have to handle it inside your shader, by adding those 4 "shader chunks" :
clipping_planes_pars_vertex.glsl at the top of your vertex shader ;
clipping_planes_vertex.glsl inside the main() of your vertex shader ;
clipping_planes_pars_fragment.glsl at the top of your fragment shader ;
clipping_planes_fragment.glsl inside the main() of your fragment shader.
You can access those chunks by simply adding #include <(chunk name)> to your shaders.
Then, set material.clipping = true; and it should work.
Check this fiddle.
Note
To make your shader work, I also added begin_vertex.glsl and project_vertex.glsl.
I checked the current phong shader implementation to understand where to put those chunks.
Note 2
This code should work with a shader implemented with an array of strings but note that you can also reference shader chunks with THREE.ShaderChunk[(chunk name)].
This should be more suitable in your case.

Compute normals from displacement map in three.js r.58?

I'm using the normal shader in three.js r.58, which I understand requires a normal map. However, I'm using a dynamic displacement map, so a pre-computed normal map won't work in this situation.
All the examples I've found of lit displacement maps either use flat shading or pre-computed normal maps. Is it possible to calculate the normals dynamically based on the displaced vertices instead?
Edit: I've posted a demo of a sphere with a displacement map showing flat normals:
Here's a link to the github repo with all of my examples illustrating this problem, and the solutions I eventually found:
https://github.com/meetar/three.js-normal-map-0
This answer is based on your comments above.
You can do what you want, but it is quite sophisticated, and you will of course have to modify the three.js 'normal' shader.
Have a look at http://alteredqualia.com/three/examples/webgl_cubes_indexed.html. Look at the fragment shader, and you will see
vec3 normal = normalize( cross( dFdx( vViewPosition ), dFdy( vViewPosition ) ) );
Alteredqualia is using a derivative normal in the fragment shader ( instead of an attribute normal ) because the vertex positions are changing in the vertex shader, and the normal is not known.
What he is doing is calculating the normal using the cross product of the x and y screen-space derivatives of the fragment position.
This will set the normal as the face normal. It will be discontinuous at hard edges.
three.js r.58
What I was describing above is called a "bump map" and it comes as a default with the three.js phong shader. I combined the normalmap shader with chunks of the phong shader responsible for bump mapping:
http://meetar.github.io/three.js-normal-map-0/bump.html
Though the normals are a bit noisy they are basically correct.
You can also calculate a normal map from the displacement map with JavaScript. This results in smooth normals, and is a good option if your displacement map isn't changing too often.
This method uses the code found in this demo: http://mrdoob.com/lab/javascript/height2normal/
Demo here:
http://meetar.github.io/three.js-normal-map-0/index14.html

Subrect drawing to texture FBO within OpenGL ES Fragment Shader

I'm trying to draw to a subrect of a texture based FBO, but am having difficulty. The FBO has dimensions of say 500x500 and I am trying to have the fragment shader only redraw say a 20x20 pixel subrect. Modiyfing the full texture works without difficulty.
At first I tried setting glViewport to the needed subrect, but it doesn't look to be that simple. I'm suspecting that the Vertex attributes affecting gl_Position and the varying texture coordinates are involved, but I can't figure out how.
Turns out that I was trying to modify the texture coordinate attributes, but was more easily able to just modify the viewport using glViewport and gl_FlagCoord within the shader.

Relation between shader and UV texture mapping

I'm using OpenGL ES + GLKit. I've never been this low-level before in my life so I still have to learn a lot of things. I've developed a Unity games before and you just give it a .obj file and corresponding texture and it's done. (UV mapping happens to be inside the .obj file?)
I want to develop a kind of special Toon Shader with some different characteristics for use with 3D model. So I need to write a vertex shader (.vsh) and fragment shader (.fsh) right?
However, I just know that in order to apply a texture to a model with correct UV coordinate, you have to do this in shader? (am I right?) With "Texture Shader".
So, If I want to both apply the texture with UV mapping then apply my special Toon Shader, I have to write both in the same shader? There is no way I can create a plug-and-play Toon shader so I can use it with anything?
As a side question, which file format is a UV coordinate and how can I take that in to a shader program? What kind of attribute variable?
So I need to write a vertex shader (.vsh) and fragment shader (.fsh)
right?
Yes.
However, I just know that in order to apply a texture to a model with
correct UV coordinate
True
There is no way I can create a plug-and-play Toon shader so I can use
it with anything?
Check Uber-Shaders
and how can I take that in to a shader program? What kind of attribute
variable?
You are defining your attributes in shader by yourself. Check this GLSL tutorial

Resources