无库情况下如何删除WebGL中的特定对象(以食物元素为例)
Hey there! Let's clear up a key misunderstanding first: WebGL doesn't work like the DOM where you have "objects" you can delete directly. When you call gl.drawArrays() or similar functions, you're just painting pixels onto the canvas—WebGL doesn't keep track of the rectangles you drew as separate entities. To "remove" a food item, you need to:
- Keep track of all your food data yourself (positions, sizes, colors)
- Re-render the entire scene from scratch every time something changes (like deleting a food)
Here's how to adjust your code to make this work:
Step 1: Maintain a Food Data Array
Instead of drawing all foods immediately on init, store each food's properties in an array. This way, you can easily add/remove items and re-render them.
Step 2: Create a Render Function
Write a function that clears the canvas, then loops through your food array and draws each item one by one.
Step 3: Handle Removal (Collision Trigger)
When your collision detection logic identifies a food to remove, splice it from the array and call the render function again.
Modified Full Code
var gl; var points; var foodArray = []; // Store all food data here var foodSize = 20; var canvas; window.onload = function init() { canvas = document.getElementById("gl-canvas"); gl = WebGLUtils.setupWebGL(canvas); if (!gl) { alert("WebGL isn't available"); } // Configure WebGL gl.viewport(0, 0, canvas.width, canvas.height); gl.clearColor(0.0, 0.0, 0.0, 1.0); // Load shaders and initialize attribute buffers var program = initShaders(gl, "vertex-shader", "fragment-shader"); gl.useProgram(program); // Create buffer once (we'll reuse it for all foods) var bufferId = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, bufferId); // Setup attribute pointers var vPosition = gl.getAttribLocation(program, "vPosition"); var size = 2; var type = gl.FLOAT; var normalize = false; var stride = 0; var offset = 0; gl.vertexAttribPointer(vPosition, size, type, normalize, stride, offset); gl.enableVertexAttribArray(vPosition); // Setup uniforms var vResolution = gl.getUniformLocation(program, "vResolution"); gl.uniform2f(vResolution, gl.canvas.width, gl.canvas.height); window.fColor = gl.getUniformLocation(program, "fColor"); // Generate initial food data generateFood(50); // Initial render render(); // Example: Add a click handler to simulate removal (replace with your collision logic) canvas.addEventListener("click", function(e) { // For demo: Find and remove the clicked food const mouseX = e.offsetX; const mouseY = e.offsetY; const targetIndex = foodArray.findIndex(food => mouseX >= food.x && mouseX <= food.x + foodSize && mouseY >= food.y && mouseY <= food.y + foodSize ); if (targetIndex !== -1) { foodArray.splice(targetIndex, 1); render(); } }); }; // Generate food and add to array function generateFood(count) { for (let i = 0; i < count; i++) { const foodX = randomInt(canvas.width - foodSize); const foodY = randomInt(canvas.height - foodSize); foodArray.push({ x: foodX, y: foodY, color: [Math.random(), Math.random(), Math.random(), 1] }); } } // Render all food from the array function render() { // Clear the entire canvas first gl.clear(gl.COLOR_BUFFER_BIT); // Loop through each food and draw it foodArray.forEach(food => { setRectangle(gl, food.x, food.y, foodSize, foodSize); gl.uniform4fv(fColor, food.color); gl.drawArrays(gl.TRIANGLES, 0, 6); }); } // Helper functions (unchanged except minor tweaks) function randomInt(range) { return Math.floor(Math.random() * range); } function setRectangle(gl, x, y, width, height) { var x1 = x; var x2 = x + width; var y1 = y; var y2 = y + height; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2 ]), gl.STATIC_DRAW); }
Key Changes Explained
foodArray: Stores all food items with their position and color—this is your source of truth for what should be on screen.render(): Clears the canvas every time, then redraws every food in the array. This is how "removal" works: if an item isn't in the array, it won't get drawn.- Click Handler: A working demo of collision detection—when you click a food, it gets removed from the array and the scene re-renders. This uses simple bounding box checks, which you can refine later if needed.
内容的提问来源于stack exchange,提问作者hwijun

