Autor Wątek: [JS] [WebGL] Problem z VAO, wyświetla tylko jeden obiekt.  (Przeczytany 1033 razy)

Offline smajler

  • Użytkownik

# Kwiecień 22, 2020, 11:34:59
Witajcie, staram się w QT poprzez GML wyświetlić model OBJ w WebGL poprzez JavaScript. Problem polega na tym, że gdy w funkcji initializującej bufory zakomentuje uzywanie programu shadera to jeden obiekt przestaje być całkowicie wysowany, pomimo, że programy cieniujące uruchamiane są i tak w pętli rysującej.
Staram się narysować trójkąt 2D (shaderprogram2D), po czym czyszcze bufor głębi? i rysuję obiekt 3D (shaderProgram)

Przygotowywanie shaderów
function initShaders()
{
    var vertexShader = getShader(gl,
                                     "attribute highp vec3 aVertexNormal;    \
                                      attribute highp vec3 aVertexPosition;  \
                                                                             \
                                      uniform highp mat4 uNormalMatrix;      \
                                      uniform mat4 uVMatrix;                \
                                      uniform mat4 uPMatrix;                 \
                                      uniform mat4 uMMatrix;                 \
                                                                             \
                                      varying mediump vec4 vColor;           \
                                      varying highp vec3 vLighting;          \
                                                                             \
                                      void main(void) {                      \
                                          gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aVertexPosition, 1.0); \
                                          highp vec3 ambientLight = vec3(0.5, 0.5, 0.5);                   \
                                          highp vec3 directionalLightColor = vec3(0.75, 0.75, 0.75);       \
                                          highp vec3 directionalVector = vec3(0.0, 0.8,2);            \
                                          highp vec4 transformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0); \
                                          highp float directional = max(dot(transformedNormal.xyz, directionalVector), 0.0); \
                                          vLighting = ambientLight + (directionalLightColor * directional); \
                                      }", gl.VERTEX_SHADER);

    var fragmentShader = getShader(gl,
                                       "varying highp vec3 vLighting;      \
                                                                           \
                                        uniform highp vec3 ambientColor; \
                                        uniform highp vec3 difusseColor; \
                                        uniform bool transparentObj;      \
                                        uniform sampler2D uSampler;        \
                                                                           \
                                        void main(void) {\
                                            gl_FragColor = (transparentObj) ? vec4(difusseColor * vLighting, 0.5) : vec4(difusseColor * vLighting, 1.0);
                                        }", gl.FRAGMENT_SHADER);


    var vertexShader2D = getShader(gl,
                                     "attribute highp vec3 aVertexPosition;  \
                                                                             \
                                      void main(void) {                      \
                                            gl_Position = vec4(aVertexPosition,1.0);\
                                      }", gl.VERTEX_SHADER);

    var fragmentShader2D = getShader(gl,
                                       "                                 \
                                        void main(void) {\
                                            gl_FragColor = vec4(1,0,0,1);\
                                        }", gl.FRAGMENT_SHADER);

    shaderProgram = gl.createProgram();

    // Attach the shader sources to the shader program
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);

    // Link the program
    gl.linkProgram(shaderProgram);

    // Check the linking status
    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        console.log("Could not initialise shaders");
        console.log(gl.getProgramInfoLog(shaderProgram));
    }



    shaderProgram2D = gl.createProgram();

    // Attach the shader sources to the shader program
    gl.attachShader(shaderProgram2D, vertexShader2D);
    gl.attachShader(shaderProgram2D, fragmentShader2D);

    // Link the program
    gl.linkProgram(shaderProgram2D);

    // Check the linking status
    if (!gl.getProgramParameter(shaderProgram2D, gl.LINK_STATUS)) {
        console.log("Could not initialise 2D shaders");
        console.log(gl.getProgramInfoLog(shaderProgram2D));
    }


    vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
    textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
    vertexNormalAttribute = gl.getAttribLocation(shaderProgram, "aVertexNormal");

    pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
    vMatrixUniform = gl.getUniformLocation(shaderProgram, "uVMatrix");
    mMatrixUniform = gl.getUniformLocation(shaderProgram, "uMMatrix");
    nUniform = gl.getUniformLocation(shaderProgram, "uNormalMatrix");

    ambientColor = gl.getUniformLocation(shaderProgram, "ambientColor");
    difusseColor = gl.getUniformLocation(shaderProgram, "difusseColor");
    specularColor = gl.getUniformLocation(shaderProgram, "specularColor");
    shininessValue = gl.getUniformLocation(shaderProgram, "shininessValue");
    transparentObj = gl.getUniformLocation(shaderProgram, "transparentObj");



    vertexPositionAttribute2D = gl.getAttribLocation(shaderProgram2D, "aVertexPosition");
}

Przygotowanie buferów
function initBuffers(vertices, normals, uvs)
{
    Vertices = new Float32Array(vertices.length);
    for(var i =0; i<vertices.length; i++)
    {
        Vertices[i] = vertices[i];
    }

    Normals = new Float32Array(normals.length);
    for(var i =0; i<normals.length; i++)
    {
        Normals[i] = normals[i];
    }

    gl.useProgram(shaderProgram);

    cubeVertexPositionBuffer = gl.createBuffer();
    cubeVertexPositionBuffer.name = "cubeVertexPositionBuffer";
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
    gl.bufferData(
                gl.ARRAY_BUFFER,
                Vertices,
                gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);


    cubeVerticesNormalBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer);
    gl.bufferData(
                gl.ARRAY_BUFFER,
                Normals,
                gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0);

    //gl.useProgram(shaderProgram2D);

    cubeVertexPositionBuffer2D = gl.createBuffer();
    cubeVertexPositionBuffer2D.name = "cubeVertexPositionBuffer2D";
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer2D);
    gl.bufferData(
                gl.ARRAY_BUFFER,
                new Float32Array([-1.0, -1.0, 0.0,
                                  1.0, -1.0, 0.0,
                                  0.0,  1.0, 0.0
                                       ]),
                gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPositionAttribute2D, 3, gl.FLOAT, false, 0, 0);
}

Rysowanie
function paintGL(canvas) {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    var pixelRatio = canvas.devicePixelRatio;
    var currentWidth = canvas.width * pixelRatio;
    var currentHeight = canvas.height * pixelRatio;
    if (currentWidth !== width || currentHeight !== height ) {
        width = currentWidth;
        height = currentHeight;
        gl.viewport(0, 0, width, height);
        mat4.perspective(pMatrix, degToRad(45), width / height, 0.1, 500.0);
        gl.uniformMatrix4fv(pMatrixUniform, false, pMatrix);
    }


gl.useProgram(shaderProgram2D);

    gl.enableVertexAttribArray(vertexPositionAttribute2D);
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer2D);
    gl.vertexAttribPointer(vertexPositionAttribute2D, 3, gl.FLOAT, false, 0, 0);

    gl.drawArrays(gl.TRIANGLES, 0, 3);

    gl.clear(gl.DEPTH_BUFFER_BIT);

///////////////////////////////////////////////////////////
    gl.useProgram(shaderProgram);

    gl.enableVertexAttribArray(vertexPositionAttribute);
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

    gl.enableVertexAttribArray(vertexNormalAttribute);
    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesNormalBuffer);
    gl.vertexAttribPointer(vertexNormalAttribute, 3, gl.FLOAT, false, 0, 0);


    mat4.identity(vMatrix);
    mat4.translate(vMatrix, vMatrix, [0.0,
                                      0.2,
                                     -5.0]);
    gl.uniformMatrix4fv(vMatrixUniform, false, vMatrix);


    mat4.identity(mMatrix);
    mat4.rotate(mMatrix, mMatrix, degToRad(canvas.xRotAnim), [0, 1, 0]);
    gl.uniformMatrix4fv(mMatrixUniform, false, mMatrix);

    mat4.invert(nMatrix, mMatrix);//vMatrix
    mat4.transpose(nMatrix, nMatrix);
    gl.uniformMatrix4fv(nUniform, false, nMatrix);


    for(var i = 0; i<MeshesStartIdx.length; i++)
    {
        gl.uniform1i(transparentObj, false);
        if(i == 14)
            gl.uniform1i(transparentObj, true);

        gl.uniform3fv(ambientColor, Materials[i].ambient);
        gl.uniform3fv(difusseColor, Materials[i].difusse);
        gl.uniform3fv(specularColor, Materials[i].specular);
        gl.uniform1f(shininessValue, Materials[i].shininess);

        gl.drawArrays(gl.TRIANGLES, MeshesStartIdx[i], MeshesSize[i]);
    }
}

Gdy zakomentuję //gl.useProgram(shaderProgram); w funkcji przygotowującej bufory, wtedy rysuje się tylko trójkąt 2D. Czy coś skopałem z kolejnością uruchaminia funkcji OGL? Zdaję sobie sprawę, że to forum głównie o C/C++ ale tutaj funkcje OpenGL są niemal identyczne więc nie powinno być to problemem aby wychwycić złą kolejność.

Pozdrawiam

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Kyroaku

  • Użytkownik

  • +1
# Kwiecień 23, 2020, 22:16:20
Cytuj
function paintGL(canvas) {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    var pixelRatio = canvas.devicePixelRatio;
    var currentWidth = canvas.width * pixelRatio;
    var currentHeight = canvas.height * pixelRatio;
    if (currentWidth !== width || currentHeight !== height ) {
        width = currentWidth;
        height = currentHeight;
        gl.viewport(0, 0, width, height);
        mat4.perspective(pMatrix, degToRad(45), width / height, 0.1, 500.0);
        gl.uniformMatrix4fv(pMatrixUniform, false, pMatrix);
    }
...
Pewnie chodzi o ustawienie tej macierzy. Ponieważ shaderProgram2D stworzyłeś jako drugi, to właśnie on jest zbindowany.

Generalnie poleciłbym ci opakować to wszystko we wrappery, które zrobią za ciebie to, co i tak zawsze powtarzasz (attach shader, vertex attrib pointer, etc). Niepotrzebnie duplikujesz kod, plus zaraz się w tym pogubisz.

Ja też nigdy nie praktykowałem przechowywania tego, co zwraca getUniformLocation (nie wiem jak to nazwać). Robiłem sobie klasę shadera, która ustawiała 'uniform' w shaderze przyjmując stringa i wywołując getUniformLocation. Nie wiem jak bardzo zła jest to praktyka (zakładam, że tylko troszkę zła :P) więc nie traktuj tego jako radę.
« Ostatnia zmiana: Kwiecień 23, 2020, 22:30:41 wysłana przez Kyroaku »

Offline smajler

  • Użytkownik

# Kwiecień 24, 2020, 12:16:42
Pewnie chodzi o ustawienie tej macierzy. Ponieważ shaderProgram2D stworzyłeś jako drugi, to właśnie on jest zbindowany.
Tak to było to, dzięki :)