【问题标题】:Passing an attribute to fragment shader using varying Webgl使用不同的 Webgl 将属性传递给片段着色器
【发布时间】:2020-08-29 15:18:20
【问题描述】:

我是 webgl 的新手,我一直在尝试使用可变将属性传递给片段着色器,以便将所有三角形更改为随机颜色,如下所示:

但是现在,所有的三角形都是白色的,我不确定哪里出了问题。另外,如何使三角形适合画布?请帮忙,谢谢。

// Application info.
var app = app || {};
var nbTriangles = 20;

function getContextGL(canvasElement) {
    var can = document.getElementById(canvasElement);
    if (can == null) {
        return [null, null];
    }

    var gl = can.getContext("webgl");

    return [can, gl];
}


function createShaderFromElement(gl, id) {
    // Grab the script element.
    var scriptElt = document.getElementById(id);
    if (!scriptElt) {
        return null;
    }

    // Retrieve the source.
    var scriptSource = scriptElt.textContent;

    // Identify shader type based on element type.
    var shaderObj;
    if (scriptElt.type == "x-shader/x-fragment") {
        shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
    }
    else if (scriptElt.type == "x-shader/x-vertex") {
        shaderObj = gl.createShader(gl.VERTEX_SHADER);
    }
    else {
        return null;
    }

    // Compile and check status.
    gl.shaderSource(shaderObj, scriptSource);
    gl.compileShader(shaderObj);

    var ok = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);

    if (!ok) {
        var msgError = gl.getShaderInfoLog(shaderObj);
        alert(msgError);
        gl.deleteShader(shader);

        return null;
    }

    return shaderObj;
}

function buildProgram(gl, vertexShader, fragmentShader) {
    if (!vertexShader || !fragmentShader) {
        return null;
    }

    var progObject = gl.createProgram();
    if (!progObject) {
        alert("Can't create program object.");
        return;
    }

    gl.attachShader(progObject, vertexShader);
    gl.attachShader(progObject, fragmentShader);

    gl.linkProgram(progObject);

    var ok = gl.getProgramParameter(progObject, gl.LINK_STATUS);
    if (!ok) {
        var msgError = gl.getProgramInfoLog(progObject);
        alert(msgError);

        gl.deleteProgram(progObject);
        return null;
    }

    return progObject;
}

function initGL() {
    app.gl.viewport(0, 0, app.can.width, app.can.height);


    app.gl.clearColor(0., 0., 0., 1.0);
    app.gl.clear(app.gl.COLOR_BUFFER_BIT);

    var vs = createShaderFromElement(app.gl, "vs");
    var fs = createShaderFromElement(app.gl, "fs");
    app.progObject = buildProgram(app.gl, vs, fs);

    app.gl.useProgram(app.progObject);
}

function initScene() {
    var gl = app.gl;

    // Creer le buffer de geometrie (vertex)
    //
    var positions = [];

    for (var i = 0; i < nbTriangles; ++i) {


        var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
        var scale = Math.random() * 0.2;
        var Trans = [Math.random() * 1.6, Math.random() * 1.6];
        var P0 = [
            orig[0] * scale + Trans[0],
            orig[1] * scale + Trans[1],
        ];
        var P1 = [
            orig[2] * scale + Trans[0],
            orig[3] * scale + Trans[1],
        ];
        var P2 = [
            orig[4] * scale + Trans[0],
            orig[5] * scale + Trans[1],
        ];
        positions.push(...P0, ...P1, ...P2);
    }


    var colors = [];
    for (var i = 0; i < nbTriangles; ++i) {
        
        var newColor = [Math.random() * 256, Math.random() * 256, Math.random() * 256, 1.0];
        colors.push(...newColor);


    }


    // Creer un nouveau buffer vide.
    var posBuffer = gl.createBuffer();
    var colorBuffer = gl.createBuffer();


    // Ref sur l'attribut "pos" dans le vertex shader.
    var posLocation = gl.getAttribLocation(app.progObject, "pos");
    var colorLocation = gl.getAttribLocation(app.progObject, "color");



    // Activer le buffer. Toute operation sur buffer
    // sera appliquer a posBuffer (il est actif!).
    gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
    gl.enableVertexAttribArray(posLocation);
    gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);


    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
    gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(colorLocation);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
}

function render() {
    var gl = app.gl;

    gl.clear(gl.COLOR_BUFFER_BIT)


    // Dessiner le buffer.
    gl.drawArrays(gl.TRIANGLES, 0, 3 * nbTriangles);
}

function init() {
    [app.can, app.gl] = getContextGL('can');
    if (app.can == null || app.gl == null) {
        alert("Can't init canvas or context");
        return;
    }

    app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);

    var rect = app.can.getBoundingClientRect();
    app.scaleX = app.can.width / rect.width;
    app.scaleY = app.can.height / rect.height;

    initGL();
    initScene();
    render();
}
div 
{
}

#main-div
{
display:inline-block;
}

#viewport, #manager
{
    float: left;
    margin: auto;
}

.color
{
    width:100px;
    height:50px;
}

.blue{
    background:#0f0;
}

#viewport
{
    width: 600px;
    height:700px;
}

#can
{
    width: 600px;
    height: 500px;
    border:1px solid orange;
}

#manager
{
    width: 200px;
    height:300px;
    padding: 0 0 0 5px;

}

#obj-list
{
    width: 200px;
}
<!DOCTYPE html>
<html>

<head>
    <title>Colored Quad</title>
    <link rel="stylesheet" type="text/css" href="style.css">
    <script src="colored_quad.js"></script> 

    <script id="vs" type="x-shader/x-vertex">
  precision mediump float;
    attribute vec2 pos;
    attribute vec4 color;
    varying vec4 fcolor;

  void main() 
    {
        vec4 pt = vec4(pos, 0.0, 1.0);
        gl_Position = pt;
        fcolor=color;
  }
 </script>

    <script id="fs" type="x-shader/x-fragment">
  precision mediump float;
  varying vec4 fcolor;
  void main() 
    {
        vec4 color= fcolor;
    gl_FragColor = color;
  }
  </script>

</head>

<body onload="init();">

    <div id="main-div">

            <div id="viewport">
                <canvas id="can" >Your browser doesn't seem to support canvas!</canvas>
            </div>

    </div>

</body>
</html>

【问题讨论】:

    标签: javascript html glsl shader webgl


    【解决方案1】:

    颜色属性有浮点类型:

    attribute vec4 color;
    
    gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
    

    因此必须在 [0.0, 1.0] 而不是 [0, 256] 范围内指定颜色值:

    var newColor = [Math.random() * 256, Math.random() * 256, Math.random() * 256, 1.0];

    var newColor = [Math.random(), Math.random(), Math.random(), 1.0];
    

    此外,每个三角形都有 3 个顶点(角)。每个顶点坐标必须与一个单独的颜色属性相关联。所以每个三角形也必须有 3 个颜色属性:

    var colors = [];
    for (var i = 0; i < nbTriangles; ++i) {
            
        var newColor = [Math.random(), Math.random(), Math.random(), 1.0];
        colors.push(...newColor);
        colors.push(...newColor);
        colors.push(...newColor);
    }
    

    // Application info.
    var app = app || {};
    var nbTriangles = 20;
    
    function getContextGL(canvasElement) {
        var can = document.getElementById(canvasElement);
        if (can == null) {
            return [null, null];
        }
    
        var gl = can.getContext("webgl");
    
        return [can, gl];
    }
    
    
    function createShaderFromElement(gl, id) {
        // Grab the script element.
        var scriptElt = document.getElementById(id);
        if (!scriptElt) {
            return null;
        }
    
        // Retrieve the source.
        var scriptSource = scriptElt.textContent;
    
        // Identify shader type based on element type.
        var shaderObj;
        if (scriptElt.type == "x-shader/x-fragment") {
            shaderObj = gl.createShader(gl.FRAGMENT_SHADER);
        }
        else if (scriptElt.type == "x-shader/x-vertex") {
            shaderObj = gl.createShader(gl.VERTEX_SHADER);
        }
        else {
            return null;
        }
    
        // Compile and check status.
        gl.shaderSource(shaderObj, scriptSource);
        gl.compileShader(shaderObj);
    
        var ok = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
    
        if (!ok) {
            var msgError = gl.getShaderInfoLog(shaderObj);
            alert(msgError);
            gl.deleteShader(shader);
    
            return null;
        }
    
        return shaderObj;
    }
    
    function buildProgram(gl, vertexShader, fragmentShader) {
        if (!vertexShader || !fragmentShader) {
            return null;
        }
    
        var progObject = gl.createProgram();
        if (!progObject) {
            alert("Can't create program object.");
            return;
        }
    
        gl.attachShader(progObject, vertexShader);
        gl.attachShader(progObject, fragmentShader);
    
        gl.linkProgram(progObject);
    
        var ok = gl.getProgramParameter(progObject, gl.LINK_STATUS);
        if (!ok) {
            var msgError = gl.getProgramInfoLog(progObject);
            alert(msgError);
    
            gl.deleteProgram(progObject);
            return null;
        }
    
        return progObject;
    }
    
    function initGL() {
        app.gl.viewport(0, 0, app.can.width, app.can.height);
    
    
        app.gl.clearColor(0., 0., 0., 1.0);
        app.gl.clear(app.gl.COLOR_BUFFER_BIT);
    
        var vs = createShaderFromElement(app.gl, "vs");
        var fs = createShaderFromElement(app.gl, "fs");
        app.progObject = buildProgram(app.gl, vs, fs);
    
        app.gl.useProgram(app.progObject);
    }
    
    function initScene() {
        var gl = app.gl;
    
        // Creer le buffer de geometrie (vertex)
        //
        var positions = [];
    
        for (var i = 0; i < nbTriangles; ++i) {
    
    
            var orig = [0.0, 1.0, 1.0, -1.0, -1.0, -1.0];
            var scale = Math.random() * 0.2;
            var Trans = [Math.random() * 1.6, Math.random() * 1.6];
            var P0 = [
                orig[0] * scale + Trans[0],
                orig[1] * scale + Trans[1],
            ];
            var P1 = [
                orig[2] * scale + Trans[0],
                orig[3] * scale + Trans[1],
            ];
            var P2 = [
                orig[4] * scale + Trans[0],
                orig[5] * scale + Trans[1],
            ];
            positions.push(...P0, ...P1, ...P2);
        }
    
    
        var colors = [];
        for (var i = 0; i < nbTriangles; ++i) {
            
            var newColor = [Math.random(), Math.random(), Math.random(), 1.0];
            colors.push(...newColor);
            colors.push(...newColor);
            colors.push(...newColor);
        }
    
    
        // Creer un nouveau buffer vide.
        var posBuffer = gl.createBuffer();
        var colorBuffer = gl.createBuffer();
    
    
        // Ref sur l'attribut "pos" dans le vertex shader.
        var posLocation = gl.getAttribLocation(app.progObject, "pos");
        var colorLocation = gl.getAttribLocation(app.progObject, "color");
    
    
    
        // Activer le buffer. Toute operation sur buffer
        // sera appliquer a posBuffer (il est actif!).
        gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
        gl.enableVertexAttribArray(posLocation);
        gl.vertexAttribPointer(posLocation, 2, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
    
    
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(colorLocation);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    }
    
    function render() {
        var gl = app.gl;
    
        gl.clear(gl.COLOR_BUFFER_BIT)
    
    
        // Dessiner le buffer.
        gl.drawArrays(gl.TRIANGLES, 0, 3 * nbTriangles);
    }
    
    function init() {
        [app.can, app.gl] = getContextGL('can');
        if (app.can == null || app.gl == null) {
            alert("Can't init canvas or context");
            return;
        }
    
        app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight);
    
        var rect = app.can.getBoundingClientRect();
        app.scaleX = app.can.width / rect.width;
        app.scaleY = app.can.height / rect.height;
    
        initGL();
        initScene();
        render();
    }
    div 
    {
    }
    
    #main-div
    {
    display:inline-block;
    }
    
    #viewport, #manager
    {
        float: left;
        margin: auto;
    }
    
    .color
    {
        width:100px;
        height:50px;
    }
    
    .blue{
        background:#0f0;
    }
    
    #viewport
    {
        width: 600px;
        height:700px;
    }
    
    #can
    {
        width: 600px;
        height: 500px;
        border:1px solid orange;
    }
    
    #manager
    {
        width: 200px;
        height:300px;
        padding: 0 0 0 5px;
    
    }
    
    #obj-list
    {
        width: 200px;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Colored Quad</title>
        <link rel="stylesheet" type="text/css" href="style.css">
        <script src="colored_quad.js"></script> 
    
        <script id="vs" type="x-shader/x-vertex">
      precision mediump float;
        attribute vec2 pos;
        attribute vec4 color;
        varying vec4 fcolor;
    
      void main() 
        {
            vec4 pt = vec4(pos, 0.0, 1.0);
            gl_Position = pt;
            fcolor=color;
      }
     </script>
    
        <script id="fs" type="x-shader/x-fragment">
      precision mediump float;
      varying vec4 fcolor;
      void main() 
        {
            vec4 color= fcolor;
        gl_FragColor = color;
      }
      </script>
    
    </head>
    
    <body onload="init();">
    
        <div id="main-div">
    
                <div id="viewport">
                    <canvas id="can" >Your browser doesn't seem to support canvas!</canvas>
                </div>
    
        </div>
    
    </body>
    </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-27
      • 1970-01-01
      • 2014-06-27
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2011-12-18
      相关资源
      最近更新 更多