如何在webGL中使用第二个着色器?

问题描述 投票:0回答:1

我在程序中设置了两个着色器,以用于代码中的不同对象。着色器已经过单独测试和正常工作,因此问题出在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);

[请看一下并提供帮助-目前没有显示任何对象。

shader webgl
1个回答
0
投票

在您共享的代码中,我发现缺少其他内容。您链接程序并使用另一个程序来获取顶点属性位置

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;
}

而且我看不到您在动画循环中使用第二个程序的位置。

记住WebGL是一种状态机。调用绘图函数时将使用所有设置。您可以将代码分为两部分:初始化时和动画循环运行后应执行的内容。

在初始化时间您需要设置对象的几何形状并创建程序-创建缓冲区-向他们提供数据-创建程序-获取顶点属性位置-获取统一的位置

function init()
{
    // for each buffer, create, bind and set data
    gl.createBuffer(...)
    gl.bindBuffer(gl.ARRAY_BUFFER, ...)
    gl.bufferData(...)

    // 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(...)
}

在动画循环中,需要在同一帧中绘制每个网格之前设置当前状态:

  • 设置状态要求(启用/禁用设置)
  • 绑定缓冲区(如果使用索引几何,则绑定数组(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(...)
}
© www.soinside.com 2019 - 2024. All rights reserved.