1
$\begingroup$

I have implemented a couple of classes which are drawn using shaders where the vertex position is always calculated the same way:

gl_Position = u_worldViewProjection * a_position;

The u_worldViewProjection-uniform is calculated using a viewProjectionMatrix which comes from a camera class. This is how I calculate the viewProjectionMatrix:

const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, this._fieldOfViewRadians, this._aspect, this._zNear, this._zFar);
mat4.rotateY(projectionMatrix, projectionMatrix, MathHelper.degToRad(this._cameraAngleDeg));

// Setup camera
const cameraMatrix = mat4.create();
const up = vec3.fromValues(0, 1, 0);
mat4.lookAt(cameraMatrix, this._cameraPosition, this._viewDirection, up);

const viewProjectionMatrix = mat4.create();
mat4.multiply(viewProjectionMatrix, projectionMatrix, cameraMatrix);

return viewProjectionMatrix;

After that I would draw some component where I would set the u_worldViewProjection-uniform something like this:

protected _calculateMatrixData(viewProjectionMatrix: mat4): void {
// Set the world-matrix aka model matrix, position rotation and scaling
const worldMatrix = mat4.create();
mat4.translate(worldMatrix, worldMatrix, this.translation);
mat4.scale(worldMatrix, worldMatrix, vec3.fromValues(this._scale[0], this._scale[1], this._scale[2]));
mat4.rotateX(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[0]));
mat4.rotateY(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[1]));
mat4.rotateZ(worldMatrix, worldMatrix, MathHelper.degToRad(this._rotationAngleDegree[2]));

this._worldMatrixData.value = worldMatrix;

// Create worldViewProjection matrix
const worldViewProjectionMatrix = mat4.create();
mat4.multiply(worldViewProjectionMatrix, viewProjectionMatrix, worldMatrix);
// ...
// set the uniforms some time later

Until now this worked for every object. Now I introduced a new shader-pair:

vertex shader:

#version 300 es

in vec4 a_position;
uniform mat4 u_worldViewProjection;

void main() {

  gl_PointSize = 10.5;
  gl_Position = u_worldViewProjection * a_position;
}

fragment shader:

#version 300 es

// Set fragment shader's precision to "medium precision"
precision mediump float;

out vec4 outColor;

void main() {
  outColor = vec4(1, 0, 0.1, 0.5);
}

Seems simple. The problem is those do not render the component. I did realize that the component is being drawn if I omit the u_worldViewProjection in the gl_Position calculation.

gl_Position = a_position;

The above snippet will draw the component, but of course this will not take any changes in account that were made to the camera. Thus I guess that my u_worldViewProjection is the source of the false behaviour.

This is how I calculate the worldViewProjectionMatrix for the above shaders:

const worldMatrix = mat4.create();
mat4.scale(worldMatrix, worldMatrix, vec3.fromValues(1.0, 1.0, 1.0));

// Create worldViewProjection matrix
const worldViewProjectionMatrix = mat4.create();
mat4.multiply(worldViewProjectionMatrix, viewProjectionMatrix, worldMatrix);

The resulting matrix is not null or undefined.

I know it is kind of impossible to point out the origin of the problem but maybe there some approach to find the source or maybe I am doing something completely wrong?

Any help would be appreciated. If there is some other information I should provide please let me know.

$\endgroup$
1
  • $\begingroup$ two things that bother me with your matrix calculations: 1. you rotate your projectionMatrix around the camera angle - but you also use LookAt for your view matrix, which would include the _cameraAngleDeg, wouldn't it? in fact, I don't see why you want to rotate your projectionMatrix at all, in theory your viewing position and direction of looking is set up with the viewMatrix. The second thing is the order of transformations in your worldMatrix. You should probably scale before you rotate an object. $\endgroup$
    – Tare
    Apr 3 '18 at 6:20
-1
$\begingroup$

This was entirely my fault. I simply forgot to set the uniform locations before rendering!

I implemented a function setUniformLocations() which sets the uniform locations passed to it:

public static setUniformLocations(
    gl: WebGL2RenderingContext, 
    uniforms: IUniform[], 
    program: WebGLProgram): IUniform[] {

    const vao = gl.createVertexArray();
    gl.bindVertexArray(vao);

    for (const uniform of uniforms) {
        uniforms.find((u) => u.name === uniform.name).location = gl.getUniformLocation(program, uniform.name);
    }

    return uniforms;
}

I normally call this function in the constructor of the according class.

this._uniforms = GLHelper.setUniformLocations(this.gl, this._uniforms, this._program);

This time I forgot.

$\endgroup$
1
  • $\begingroup$ May I ask why the downvotes? $\endgroup$ Apr 11 '18 at 16:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.