Skip to content

Depth Test not working as expected in WebGL #1014

@zanzlanz

Description

@zanzlanz

I'm having an issue with the depth test not working with WebGL. It works as expected with C++ OpenGL.
Also, this is my first post, so let me know if this is not the appropriate way to present an issue.

C++ OpenGL compiles to the following correct result:
cppversion

JS WebGL compiles to the following, which is incorrect. Simply notice the triangles are switched:
webglversion

At the bottom is the entirety of the code I am using to test. I am using the latest versions of Haxe and Lime.
Mostly note the GL calls to force the depth test, and the vertices I am passing to the program. If you switch the order the triangles are positioned in the array, the JavaScript WebGL triangles will swap depths, but the C++ triangles will not. This tells me the depth test is not working for the WebGL context.

In the meantime, is there a workaround for this issue? I've tried everything I could think of so far, but I could be missing something obvious.

Thanks!

package;

import lime.app.Application;
import lime.graphics.opengl.*;
import lime.graphics.RenderContext;
import lime.graphics.Renderer;
import lime.math.Matrix4;
import lime.utils.Float32Array;

class Main extends Application {

    public function new() {
        super();
    }

    var _firstFrame:Bool = true;
    var _vertices:Float32Array;

    public override function render(render:Renderer):Void {
        
        if (_firstFrame) {
            // Do everything here only on the first frame
        
            GL.clearColor(.08, .09, .10, 1);
            
            GL.clearDepthf(1);
            GL.depthFunc(GL.LEQUAL);
            GL.enable(GL.DEPTH_TEST);
            GL.depthMask(true);
            
            var aspect:Float = window.width / window.height;
            var FOV:Float = Math.tan(45*Math.PI/360.0);
            var near:Float = .1;
            var far:Float = 2;
            var _projectionMatrix:Matrix4 = new Float32Array([
                1 / (FOV * aspect),    0,           0,                                0,
                0,                     1 / FOV,     0,                                0,
                0,                     0,           (near + far) / (near - far),     -1,
                0,                     0,           2 * near * far / (near - far),    0
            ]);
            
            
            var _vertexShaderCode =
                #if web 
                    "precision mediump float;" + 
                #end 
                "
                attribute vec3 _vertexPosition;
                varying vec3 _vertexColor;
                uniform mat4 _projectionMatrix;
                
                void main () { 
                    _vertexColor = vec3(cos(_vertexPosition.x * 12.0 + _vertexPosition.y * 8.0), sin(_vertexPosition.x * 10.0 + _vertexPosition.y * 14.0), 1.0);
                    gl_Position = _projectionMatrix * vec4(_vertexPosition, 1.0);
                }
                ";
            var _vertexShader:GLShader = createShader(_vertexShaderCode, GL.VERTEX_SHADER);
            
            var _fragmentShaderCode =
                #if web 
                    "precision mediump float;" + 
                #end 
                "
                varying vec3 _vertexColor;
                void main () {
                    gl_FragColor = vec4(_vertexColor, 1.0);
                }
                ";
            var _fragmentShader:GLShader = createShader(_fragmentShaderCode, GL.FRAGMENT_SHADER);
            
            var _shaderProgram:GLProgram = GL.createProgram();
            GL.attachShader(_shaderProgram, _vertexShader);
            GL.attachShader(_shaderProgram, _fragmentShader);
            GL.linkProgram(_shaderProgram);
            GL.useProgram(_shaderProgram);
            
            
            // Swapping the top and bottom triangle code does not affect the image in C++
            // But in JavaScript (webGL) the triangles will swap position. This is because it is not performing the depth test.
            
            _vertices = new Float32Array([
                // Top triangle (closer to camera)
                  0,  .1, -1.0,
                -.2, -.1, -1.0,
                 .2, -.1, -1.0,
                
                // Bottom triangle (further from camera)
                  0,   0, -1.1,
                -.2, -.2, -1.1,
                 .2, -.2, -1.1
                 
            ]);
            
            
            var _vbo:GLBuffer = GL.createBuffer();
            GL.bindBuffer(GL.ARRAY_BUFFER, _vbo);
            GL.bufferData(GL.ARRAY_BUFFER, Math.floor(_vertices.length * Float32Array.BYTES_PER_ELEMENT), _vertices.toBytes(), GL.STATIC_DRAW);
            
            var _vertexPosition = GL.getAttribLocation(_shaderProgram, "_vertexPosition");
            GL.vertexAttribPointer(_vertexPosition, 3, GL.FLOAT, false, 0, 0);
            GL.enableVertexAttribArray(_vertexPosition);
            
            var _projectionMatrix_location = GL.getUniformLocation(_shaderProgram, "_projectionMatrix");
            GL.uniformMatrix4fv(_projectionMatrix_location, 1, false, new Float32Array(_projectionMatrix));
            
            GL.viewport(0, 0, window.width, window.height);
            
            _firstFrame = false;
        }
        
        // Every frame (otherwise it flickers in the C++ version)
        GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);
        GL.drawArrays(GL.TRIANGLES, 0, Math.floor(_vertices.length / 3));
    }

    private function createShader(_source:String, _type:Int):GLShader {
        var _shader = GL.createShader(_type);
        GL.shaderSource (_shader, _source);
        GL.compileShader (_shader);
        
        return _shader;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions