Custom render loop

I’m trying to get a custom render function to work. For starters, I just want to render one object that is within the camera’s viewfrustum with a basic one color shader. The following is my code, it doesn’t generate errors, however except for clearing the backbuffer to blue, it doesn’t render anything:

var RenderControl = pc.createScript('renderControl');

RenderControl.attributes.add('vertexShaderSource', {
    type: 'string',
    default: "" +
"attribute vec3 aPosition;" +

"uniform mat4 matrix_model;" +
"uniform mat4 matrix_viewProjection;" +

"void main(void)" +
"{" +
    "gl_Position = matrix_viewProjection * matrix_model * vec4(aPosition, 1.0);" +
"}"});

RenderControl.attributes.add('fragmentShaderSource', {
    type: 'string',
    default: "" +

"void main(void)" +
"{" +
    "gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);" +
"}"});

RenderControl.attributes.add('renderObject', {
    type: 'entity',
    title: 'renderObject',
    description: 'The Object to Render'
});

// initialize code called once per entity
RenderControl.prototype.initialize = function() {
    var app = pc.Application.getApplication();
    var gd = app.graphicsDevice;
    
    app.render = this.render.bind(this);
    
    this.fragmentShaderSource = "precision " + gd.precision + " float;\n" + this.fragmentShaderSource;

    // A shader definition used to create a new shader.
    var shaderDefinition = {
        attributes: {
            aPosition: pc.SEMANTIC_POSITION,
        },
        vshader: this.vertexShaderSource,
        fshader: this.fragmentShaderSource
    };
    // Create the shader from the definition
    this.shader = new pc.Shader(gd, shaderDefinition);
};

RenderControl.prototype.render = function() {
    var gd = pc.Application.getApplication().graphicsDevice;
    // render to backbuffer.
    gd.setRenderTarget(null);
    gd.updateBegin();
    gd.setViewport(0, 0, gd.width, gd.height);
    gd.setScissor(0, 0, gd.width, gd.height);
    // backup state
    var oldDepthTest = gd.getDepthTest();
    var oldDepthWrite = gd.getDepthWrite();
    var oldBlending = gd.getBlending();
    gd.setDepthTest(true);
    gd.setDepthWrite(true);
    gd.setBlending(false);
    // Clear background to blue.
    gd.clear({color: [0, 0, 1, 1]});
    gd.setShader(this.shader);

    // Set uniforms.
    gd.scope.resolve("matrix_model").setValue(this.renderObject.getWorldTransform().data);

    var viewMatrix = this.entity.camera.viewMatrix; // inverse of cameras worldTransform
    var projectionMatrix = this.entity.camera.projectionMatrix;
    var viewProjectionMatrix = new pc.Mat4();
    viewProjectionMatrix.mul2(projectionMatrix, viewMatrix);
    gd.scope.resolve("matrix_viewProjection").setValue(viewProjectionMatrix.data);
    
    // Iterate over all meshes of the renderObject and draw them.
    for (var i = 0; i < this.renderObject.model.model.meshInstances.length; i++) {
        var mesh = this.renderObject.model.model.meshInstances[i].mesh;
        var vb = mesh.vertexBuffer;
        gd.setVertexBuffer(vb, 0);  // what exactly is "stream index" argument?
        var ib = mesh.indexBuffer;  // array of indexbuffers
        var isIndexed = !(ib === undefined || ib.length == 0);
        if (isIndexed) {
            gd.setIndexBuffer(ib[0]); // first index buffer is for solid geometry, second for wireframes
        }
        var numIndices = isIndexed ? ib[0].getNumIndices() : vb.getNumVertices();
        gd.draw({
            type: mesh.primitive[0], // first primitive should correspond to first index buffer
            base: 0,
            count: numIndices,
            indexed: isIndexed
        });
    }
    
    gd.setDepthTest(oldDepthTest);
    gd.setDepthWrite(oldDepthWrite);
    gd.setBlending(oldBlending);
            
    gd.updateEnd();
};

My most likely guess is that something with the matrices is wrong, however, if ‘getWorldTransform’ returns the matrix mapping from mesh to world coordinates, if camera.viewMatrix returns the matrix mapping from world coordinates to local camera coordinates and if camera.projectionMatrix returns the matrix mapping from local camera coordinates to clip space, then it looks right to me…

Am I missing something?

If I just render a simple triangle in clipspace, that works.

1 Like