使用变化的Webgl将属性传递给片段着色器

时间:2020-08-29 15:18:20

标签: javascript html glsl shader webgl

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

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

// 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>

1 个答案:

答案 0 :(得分:1)

color属性具有浮点类型:

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>

相关问题