1
votes

Is there any way to manually specify view and model matrices?

I know Three.js is not supposed to be used in this way, but I am currently developing some educational materials to teach a typical computer graphics pipeline and would like to explicitly supply model/view/projection matrices to a shader. While I understood which matrices are model/view/projection matrices in Three.js from this issue, I haven't been able to find a good way to manually control them.

So far, I was able to specify the projection matrix by using camera.projectionMatrix.makePerspective() and the model matrix by using applyMatrix(). Actually, applyMatrix() is not ideal from the educational point of view because it internally decomposes the matrix to position, quaternion and scale and probably reconstructs the model matrix from those values and supply it to a shader.

One possible solution is to use ShaderMaterial() and specify all of the three matrices as uniforms. However, I may want to avoid it because they are also passed to a shader implicitly and the name "material" might confuse students.

Does anybody have suggestions to do this kind of stuff in Three.js?

1
If naming is the only issue preventing you from using THREE.ShaderMaterial or THREE.RawShaderMaterial, you can always alias the object: THREE.CustomShader = THREE.ShaderMaterial;, var myShader = new THREE.CustomShader();TheJim01
Thank you for the suggestion. That's actually a great idea.Hayato Ikoma
RawShaderMaterial should not inject anything for you.pailhead
I would disagree with the "material" being confusing though. Within the api, what you are using is a "material" since it's not just GLSL, but also properties that get interpreted by the renderer when making draw calls. Your ShaderMaterial would consist of two different shaders. But together, they make a material in three.pailhead

1 Answers

2
votes

However, I may want to avoid it because they are also passed to a shader implicitly and the name "material" might confuse students.

I'm not sure if this is the best approach. A Material in three.js should indeed be more than a shader. It consists of two shaders, but other stuff as well. For example if you set myMaterial.transparent = true; you will trigger a completely different flow of WebGLRenderer which in turn sets up different WebGL calls. Setting the blending mode for example is not what a shader does.

It would probably be worth explaining this abstraction, rather than renaming it.

...matrices in Three.js from this issue, I haven't been able to find a good way to manually control them.

With RawShaderMaterial you should be able to write the whole shader from scratch.

uniform mat4 uMyProjectionMatrix;
uniform mat4 uMyModelMatrix;
uniform mat4 uMyViewMatrix;
uniform mat5 uMyModelViewMatrix;

attribute vec3 aMyPosition;

void main(){

  gl_Position = uMyProjectionMatrix * uMyViewMatrix * uMyModelMatrix * vec4( aMyPositon , 1.);

}

It is entirely up to you to define what those are. Is the projection matrix orthographic or not for example.

With ShaderMaterial you get these automagically:

void main(){

  gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position , 1. );

}

projectionMatrix and viewMatrix are derived from the camera's properties, as you can see in the link (btw i've no idea why that's not in the documentation, i found myself referring to that particular issue a bunch of times :) ).

Both of these can be modified. Automagically if you do

myCamera.far = newFar;
myCamera.fov = newFov;
myCamera.updateProjectionMatrix(); //this will be the new projectionMatrix in GLSL

but, nothing should be preventing you from doing

myCamera.projectionMatrix.array[3] = mySkewLogic;

Same applies to modelMatrix:

myObject.position.x = newX;
myObject.updateMatrixWorld();
//or
myObject.matrixWorld.array[3] = someXTranslationLogic;