Как заставить работать второй шейдер в webGL? - PullRequest
1 голос
/ 02 мая 2020

Я установил в своей программе два шейдера, которые будут использоваться для разных объектов в коде. Шейдеры по отдельности были протестированы и работают, поэтому проблема заключается в коде webgl. Вот что у меня есть в исходном коде затенения.

    var vertexShader = this.getShader("VertexShader2");

    this.shaderProgram = gl.createProgram();
    gl.attachShader(this.shaderProgram, vertexShader);
    gl.attachShader(this.shaderProgram, fragmentShader);
    gl.linkProgram(this.shaderProgram);

    if(!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)){
        console.log("unable to init shader program");
    }

    gl.useProgram(GC.canvas.shaderProgram);

    GC.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, "vPos");
    gl.enableVertexAttribArray(GC.vertexPositionAttribute);

    GC.barycentricAttribute = gl.getAttribLocation(this.shaderProgram, "bary");
    gl.enableVertexAttribArray(GC.barycentricAttribute);

    GC.normalAttribute = gl.getAttribLocation(this.shaderProgram, "norm");
    gl.enableVertexAttribArray(GC.normalAttribute);

    var fragmentShader2 = this.getShader("FragmentShader1");
    var vertexShader2 = this.getShader("VertexShader1");

    this.shaderProgram2 = gl.createProgram();
    gl.attachShader(this.shaderProgram2, vertexShader2);
    gl.attachShader(this.shaderProgram2, fragmentShader2);
    gl.linkProgram(this.shaderProgram2);

    if(!gl.getProgramParameter(this.shaderProgram2, gl.LINK_STATUS)){
        console.log("unable to init shader program 2");
    }




    GC.shaderProgram = this.shaderProgram;
    GC.shaderProgram2 = this.shaderProgram2;

И в отдельной функции для инициализации шейдеров ...

    gl.useProgram(GC.canvas.shaderProgram2);
    GC.vertexPositionAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "vPos");
    gl.enableVertexAttribArray(GC.vertexPositionAttribute2);

    GC.barycentricAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "bary");
    gl.enableVertexAttribArray(GC.barycentricAttribute2);

    GC.textureCoordAttribute = gl.getAttribLocation(GC.shaderProgram2, "aTextureCoord");
    gl.enableVertexAttribArray(GC.textureCoordAttribute);

    GC.vert_tangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_tang");
    gl.enableVertexAttribArray(GC.vert_tangPtr);

    GC.vert_bitangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_bitang");
    gl.enableVertexAttribArray(GC.vert_bitangPtr);

    GC.vert_uvPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_uv");
    gl.enableVertexAttribArray(GC.vert_uvPtr); 
}

И код webgl позже для переключения шейдера и настроить объект.

    gl.useProgram(GC.shaderProgram2);
    setupShader2();
    mvTranslate([(m1.minX+m1.maxX)/2.0,(m1.minY+m1.maxY)/2.0,(m1.minZ+m1.maxZ)/2.0],GC);

    mvMultMatrix(camera.Transform,GC);//multiply by the transformation

    //translate back to original origin
    mvTranslate([-(m1.minX+m1.maxX)/2.0,-(m1.minY+m1.maxY)/2.0,-(m1.minZ+m1.maxZ)/2.0],GC);
    //---------

    //passes modelview and projection matrices to the vertex shader
    setMatrixUniforms(GC);

    GC.norm_mtx = GC.mvMatrix;
    GC.norm_mtx = GC.norm_mtx.inverse();
    GC.norm_mtx = GC.norm_mtx.transpose();

    var pnormal = gl.getUniformLocation(GC.shaderProgram2, "norm_mtx");
    gl.uniformMatrix4fv(pnormal, false, new Float32Array(GC.norm_mtx.flatten()));


    //pass the vertex buffer to the shader
    gl.bindBuffer(gl.ARRAY_BUFFER, m1.vertexBuffer);
    gl.vertexAttribPointer(GC.vertexPositionAttribute2, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(GC.vertexPositionAttribute2);

    //pass the barycentric coords to the shader for edge detection
    gl.bindBuffer(gl.ARRAY_BUFFER, GC.barycentricBuffer);
    gl.vertexAttribPointer(GC.barycentricAttribute2, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(GC.barycentricAttribute2);

    gl.bindBuffer(gl.ARRAY_BUFFER, GC.textureCoordBuffer);
    gl.vertexAttribPointer(GC.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(GC.vtextureCoordAttribute);

    gl.bindBuffer(gl.ARRAY_BUFFER, GC.vert_tang);
    gl.vertexAttribPointer(GC.vert_tangPtr, 3, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, GC.vert_bitang);
    gl.vertexAttribPointer(GC.vert_bitangPtr, 3, gl.FLOAT, false, 0, 0);

    gl.bindBuffer(gl.ARRAY_BUFFER, GC.vert_uv);
    gl.vertexAttribPointer(GC.vert_uvPtr, 2, gl.FLOAT, false, 0, 0);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, GC.tex_norm);
    var uni = gl.getUniformLocation(GC.shaderProgram2, "tex_norm");
    gl.uniform1i(uni, 0);

    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_2D, GC.tex_diffuse);
    uni = gl.getUniformLocation(GC.shaderProgram2, "tex_diffuse");
    gl.uniform1i(uni, 1);

    gl.activeTexture(gl.TEXTURE2);
    gl.bindTexture(gl.TEXTURE_2D, GC.tex_depth);
    uni = gl.getUniformLocation(GC.shaderProgram2, "tex_depth");
    gl.uniform1i(uni, 2);

    gl.uniform1i(GC.uSampler, 0);

    var scale = 0.01 * 1.0;
    uni = gl.getUniformLocation(GC.shaderProgram2, "depth_scale");
    gl.uniform1f(uni, scale);

    var steps = 1.0;
    uni = gl.getUniformLocation(GC.shaderProgram2, "num_layers");
    gl.uniform1f(uni, steps);

    var show_tex = true;
    uni = gl. getUniformLocation(GC.shaderProgram2, "show_tex");
    gl.uniform1i(uni, show_tex);
    //draw everything
    gl.drawArrays(gl.TRIANGLES,0,m1.indices.length);

Пожалуйста, посмотрите и помогите - в настоящее время он не показывает никаких объектов после первого.

1 Ответ

1 голос
/ 03 мая 2020

В коде, которым вы поделились, я вижу, что разные вещи отсутствуют. Вы связываете программу и используете другую для получения местоположения атрибутов вершины

gl.linkProgram(this.shaderProgram);

// ...

gl.useProgram(GC.canvas.shaderProgram);

Вы получаете атрибуты вершины для второй программы в отдельной функции, но мы не знаем, когда она вызывается. Я думаю, что было бы легче читать и понимать, если бы вы создали 2 функции для инициализации каждой программы

function setProgram()
{
    fragmentShader = this.getShader("VertexShader2");
    vertexShader = this.getShader("VertexShader2");

    this.shaderProgram = gl.createProgram();
    gl.attachShader(this.shaderProgram, vertexShader);
    gl.attachShader(this.shaderProgram, fragmentShader);
    gl.linkProgram(this.shaderProgram);

    if(!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)){
        console.log("unable to init shader program");
    }

    gl.useProgram(this.shaderProgram);

    GC.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, "vPos");
    gl.enableVertexAttribArray(GC.vertexPositionAttribute);

    GC.barycentricAttribute = gl.getAttribLocation(this.shaderProgram, "bary");
    gl.enableVertexAttribArray(GC.barycentricAttribute);

    GC.normalAttribute = gl.getAttribLocation(this.shaderProgram, "norm");
    gl.enableVertexAttribArray(GC.normalAttribute);

    GC.shaderProgram = this.shaderProgram;
}

function setProgram2()
{
    var fragmentShader2 = this.getShader("FragmentShader1");
    var vertexShader2 = this.getShader("VertexShader1");

    this.shaderProgram2 = gl.createProgram();
    gl.attachShader(this.shaderProgram2, vertexShader2);
    gl.attachShader(this.shaderProgram2, fragmentShader2);
    gl.linkProgram(this.shaderProgram2);

    if(!gl.getProgramParameter(this.shaderProgram2, gl.LINK_STATUS)){
        console.log("unable to init shader program 2");
    }

    gl.useProgram(this.shaderProgram2);

    GC.vertexPositionAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "vPos");
    gl.enableVertexAttribArray(GC.vertexPositionAttribute2);

    GC.barycentricAttribute2 = gl.getAttribLocation(GC.shaderProgram2, "bary");
    gl.enableVertexAttribArray(GC.barycentricAttribute2);

    GC.textureCoordAttribute = gl.getAttribLocation(GC.shaderProgram2, "aTextureCoord");
    gl.enableVertexAttribArray(GC.textureCoordAttribute);

    GC.vert_tangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_tang");
    gl.enableVertexAttribArray(GC.vert_tangPtr);

    GC.vert_bitangPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_bitang");
    gl.enableVertexAttribArray(GC.vert_bitangPtr);

    GC.vert_uvPtr = gl.getAttribLocation(GC.shaderProgram2, "vert_uv");
    gl.enableVertexAttribArray(GC.vert_uvPtr); 

    GC.shaderProgram2 = this.shaderProgram2;
}

И я не вижу, где вы используете вторую программу в анимации l oop.

Помните, что WebGL является своего рода конечным автоматом. Все, что установлено при вызове функции draw, используется. Вы можете разбить код на 2 части: что должно выполняться во время инициализации и после запуска анимации l oop.

Во время инициализации Вам необходимо настроить геометрию объектов и создать программы

  • создание буферов
  • подача им данных
  • создание программ и для каждой из них: получение унифицированных и вершинных атрибутов
function init()
{
    // for each buffer, create, bind and set data
    gl.createBuffer(...)
    gl.bindBuffer(gl.ARRAY_BUFFER, ...)
    gl.bufferData(...)

    // Do the same with every buffer

    // for each program, create, compile and validate shaders, create the program, attach shaders, link and validate
    var program = createProgram()

    // Use the program
    gl.useProgram(program)

    // Get vertex attribute locations
    gl.getAttribLocation(...)

    // Get uniform locations
    gl.getUniformLocation(...)

    // Do the same with every program
}

В анимация l oop, вам нужно установить текущее состояние перед рисованием каждого me sh в одном кадре:

  • установить требования к состоянию (включить / отключить материал)
  • bind буферы (ARRAY и ELEMENT_ARRAY, если вы используете индексированную геометрию)
  • связывание текстур
  • использование программы (она должна быть связана и проверена)
  • извлекать местоположения атрибутов вершин, указывать их расположение и включите их
  • установите одинаковые значения (матрицы в вашем случае)

Если чего-то не хватает, оно будет использовано из предыдущего состояния. Это может объяснить, почему вы не видите свои объекты.

function renderObject()
{
    // State requirements (if needed)
    gl.enable(...)
    gl.disable(...)

    // Bind textures
    gl.bindTexture(gl.TEXTURE_2D, ...) // repeat this for each texture your program needs

    // Using program
    gl.useProgram(program) // this enable the program you need for the draw

    // Bind buffers
    gl.bindBuffer(gl.ARRAY_BUFFER, ...) // repeat this for each buffer your program needs
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ...)

    // Specify attributes layout (use stored locations)
    gl.vertexAttribPointer(...)

    // Enable vertex attributes
    gl.enableVertexAttribArray(...)

    // Set uniform values (use stored locations)
    gl.uniform1234fv(...)

    // And finally draw your mesh
    gl.drawArrays(...)

    // Clear what you won't need anymore (bind things to null, disable...)
    gl.disableVertexAttribArray(...)
}
...