亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 webgl 中繪制樹的問題

在 webgl 中繪制樹的問題

慕容3067478 2021-11-18 20:21:02
這次又出現了更多錯誤,只不過這次是在 webgl 端而不是 mathy 算法端。我之前的帖子只是關于繪制一個簡單的 2d 遞歸樹。我現在要做的事情是在鼠標單擊的位置繪制一棵樹,如果左鍵單擊,則為紅線,如果右擊則為藍色。我解決了之前的問題,并且能夠讓樹顯示在我之前的程序版本中。但是,現在當我單擊畫布時,樹甚至不會出現。然而,當我控制臺記錄存儲點的數組時,所有的點似乎都在那里。我想我遺漏了一些東西,但我對 webgl 的了解還不夠多,無法知道那可能是什么。我已經制作了一個工作程序,它可以根據鼠標單擊在鼠標位置繪制不同的顏色點,但我仍然沒有足夠的經驗來弄清楚我在該程序中擁有什么使其能夠工作以及為什么這個當前程序無法顯示任何內容。我敢打賭,我在主要功能或點擊功能中遺漏了一些東西,但我發布了所有內容,因為我不是 100% 確定。
查看完整描述

1 回答

?
呼喚遠方

TA貢獻1856條經驗 獲得超11個贊

您發布的代碼僅gl.drawXXX在 main 中調用一次,因此它永遠不會再繪制任何內容。

你已經設置好了,所以當按下鼠標時click將被調用但從click不調用gl.drawXXX

此外,每次click調用時,您都會使用一組新的點創建一個新緩沖區。這不是使用 WebGL 的正常方式。通常的方法是設置你的點一次(每個你想畫的東西一次),然后使用矩陣來改變位置、方向、比例。

我建議你閱讀一些關于 WebGL 的其他教程。一種做你現在正在做的事情,但它會跟進如何改變位置方向比例,然后是如何用矩陣來做以獲得更大的靈活性。它還涵蓋了繪制多個事物

在任何情況下,要按原樣修復您的代碼,您都需要在更改頂點后進行繪制

// Vertex shader program

var VSHADER_SOURCE = 

    'attribute vec4 a_Position;\n' +

    'void main() {\n' +

    '  gl_Position = a_Position;\n' +

    '}\n';


// Fragment shader program

var FSHADER_SOURCE =

    'precision mediump float;\n' +

    'uniform vec4 u_FragColor;\n' +

    'void main() {\n' +

    '  gl_FragColor = u_FragColor;\n' +

    '}\n';


var m = 0;


function main() {

    var canvas = document.getElementById('webgl');

    // Get the rendering context for WebGL

    var uniform1i = 0;


    var gl = canvas.getContext('webgl');

    if (!gl) {

        console.log('Failed to get the rendering context for WebGL');

        return;

    }


    // Initialize shaders

    if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {

        console.log('Failed to intialize shaders.');

        return;

    }


    // // Get the storage location of a_Position

    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

    if (a_Position < 0) {

        console.log('Failed to get the storage location of a_Position');

        return;

    }


    // Get the storage location of u_FragColor

    var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');

    if (!u_FragColor) {

        console.log('Failed to get the storage location of u_FragColor');

        return;

    }


    // Register function (event handler) to be called on a mouse press

    canvas.onmousedown = function (ev) { click(ev, gl, canvas, a_Position, u_FragColor) };


}



function click(ev, gl, canvas, a_Position, u_FragColor) {

    var x = ev.clientX; // x coordinate of a mouse pointer

    var y = ev.clientY; // y coordinate of a mouse pointer

    var rect = ev.target.getBoundingClientRect();


    x = ((x - rect.left) - canvas.width / 2) / (canvas.width / 2);

    y = (canvas.height / 2 - (y - rect.top)) / (canvas.height / 2);


    if (ev.button == 0) {

        var depth = 4;

        gl.uniform4f(u_FragColor, 1.0, 0, 0, 1.0);// Red

        //red tree, 4 steps, length 50, halved each step


        // Write the positions of vertices to a vertex shader

        var n = initVertexBuffers(gl, x, y);

        if (n < 0) {

            console.log('Failed to set the positions of the vertices');

            return;

        }

        m = n;


    }

    if (ev.button == 2) {

        var depth = 6;

        //blue tree, 6 steps, length 40, halved each step

        gl.uniform4f(u_FragColor, 0, 0, 1.0, 1.0);// Blue

        // Write the positions of vertices to a vertex shader

        var n = initVertexBuffers(gl, x, y);

        if (n < 0) {

            console.log('Failed to set the positions of the vertices');

            return;

        }

        m = n;

    }

    

    // Specify the color for clearing <canvas>

    gl.clearColor(1.0, 1.0, 1.0, 1.0);


    // Clear <canvas>

    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.drawArrays(gl.LINES, 0, m);

    

}



function initVertexBuffers(gl, x, y) {

    let start = [];

    let points = createPoints(x, y, 0.4, 4, Math.PI / 2, start);

    console.log(points);

    var vertices = new Float32Array(points);

    let n = points.length / 2; // The number of vertices

    // Create a buffer object

    var vertexBuffer = gl.createBuffer();

    if (!vertexBuffer) {

        console.log('Failed to create the buffer object');

        return -1;

    }


    // Bind the buffer object to target

    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);

    // Write date into the buffer object

    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);


    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

    if (a_Position < 0) {

        console.log('Failed to get the storage location of a_Position');

        return -1;

    }

    // Assign the buffer object to a_Position variable

    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);


    // Enable the assignment to a_Position variable

    gl.enableVertexAttribArray(a_Position);


    return n;

}


//var points = [x, y];

//var angle = 0;

//var prevPoints = [];

//var prevPointIndex = 0;

function createPoints(x, y, length, depth, angle, points) {

    if (depth > 0) {

        //draws line

        let x2 = x + length * Math.cos(angle);

        let y2 = y + length * Math.sin(angle);

        points.push(x, y, x2, y2);


        //draw left branch;

        createPoints(x2, y2, length / 2, depth - 1, angle + Math.PI / 4, points);


        //goes back

        //points.push(x2, y2);


        //draw right branch

        createPoints(x2, y2, length / 2, depth - 1, angle - Math.PI / 4, points);


        //goes back

        //points.push(x2, y2);

        //console.log(points);

        return points;

    }

    return;

}

main();


//----

function initShaders(gl, vSrc, fSrc) {

  const program = twgl.createProgram(gl, [vSrc, fSrc]);

  gl.program = program; // THIS IS EXTREMELY BAD AND WRONG CODE!!!

  gl.useProgram(program); // THIS IS ALSO WRONG!

  return program;

}

canvas { border: 1px solid black; }

<canvas id="webgl"></canvas>

<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

代碼有很多問題

  1. gl.program不是一回事。無論你從中學到什么書或教程,都是一件可怕的、糟糕的和錯誤的事情。WebGL 程序通常有多個著色器程序,因此一個函數initShaders需要返回創建的程序,以便您可以使用不同的頂點著色器源和片段著色器源多次調用它來制作多個程序。它不應該將一個創建的程序破解到它不屬于的 webgl 上下文。

    注意:即使我實現了initShaders因為你沒有提供它從你的代碼中可以清楚地看出它在做什么gl.program = gl.createProgram。那是無意義的代碼。有多個程序是很常見的。

  2. 通話gl.usePrograminitShaders也可以說是錯誤的。(再次清楚,因為它沒有在您的代碼中的任何地方調用您的版本initShaders正在這樣做。同樣,這沒有意義,因為在普通的 WebGL 頁面中,您有多個著色器,因此您需要gl.useProgram多次調用。

  3. 您正在閱讀的教程看起來很舊,因為它為 GLSL 連接字符串。制作 GLSL 的最簡單方法是使用多行模板文字

    var VSHADER_SOURCE = `
        attribute vec4 a_Position;
        void main() {
          gl_Position = a_Position;
        }
    `;

    容易多了

  4. 它正在調用一些函數getWebGLContext。不需要那樣的東西。只需使用canvas.getContext('webgl')

  5. 調用gl.drawArraysm錯了地方。正確的調用方式gl.drawArraysgl.drawArrays(primitiveType, offset, vertexCount)。偏移量幾乎是 0。沒有第四個參數。

請考慮閱讀一些更好的教程,例如上面鏈接的教程。


查看完整回答
反對 回復 2021-11-18
  • 1 回答
  • 0 關注
  • 240 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號