hwijun
hwijun

Reputation: 1

How can I delete a specific object in Webgl (Without library)

I'm studying webgl. Now I spray the food to a random location on the canvas, and when the mouse pointer and the food collide, I try to delete the food.

(The collision implementation of the mouse cursor is another issue, but it is not necessary now.)

However, no matter how many times I looked for it, I could not find a way to erase a specific object even if I explained how to draw it. Is there a way to delete only certain objects from canvas without a library?

The full text of my code is as follows.

var gl;
var points;



window.onload = function init()
{
    var canvas = document.getElementById( "gl-canvas" );
    
    gl = WebGLUtils.setupWebGL( canvas );
    if ( !gl ) { alert( "WebGL isn't available" ); }

    
    // Four Vertices
    
    var vertices = [
        vec2( -0.5, -0.5 ),
        vec2(  -0.5,  0.5 ),
        vec2(  0.5, 0.5 ),
        vec2( 0.5, -0.5)
    ];

    //
    //  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 );
    
    // Load the data into the GPU
    
    var bufferId = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );
    //gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

    // Associate out shader variables with our data buffer
    
    
    
    var foodX, foodY;
    var foodSize = 20;
    var foodNumber = 50;

    
    var vPosition = gl.getAttribLocation( program, "vPosition" );
    // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
    var size = 2;          // 2 components per iteration
    var type = gl.FLOAT;   // the data is 32bit floats
    var normalize = false; // don't normalize the data
    var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
    var offset = 0;        // start at the beginning of the buffer
    gl.vertexAttribPointer( vPosition, size, type, normalize, stride, offset);
    gl.enableVertexAttribArray( vPosition );

    // we added a uniform called vResolution. 
    var vResolution = gl.getUniformLocation(program, "vResolution");
    var fColor = gl.getUniformLocation(program, "fColor");
    
    // set the resolution
    gl.uniform2f(vResolution, gl.canvas.width, gl.canvas.height);

    // draw 50 random rectangles in random colors
    while (foodNumber > 0) {
        // Setup a random rectangle
        // This will write to positionBuffer because
        // its the last thing we bound on the ARRAY_BUFFER
        // bind point

        
        
        //food 좌표는 canvas width와 height 사이에 있도록 하며, canvas 밖으로 빠져나가지 않도록 조절한다.
        foodX = randomInt(canvas.width - foodSize);
        foodY = randomInt(canvas.height-foodSize);
        

        setRectangle(gl, foodX, foodY, foodSize, foodSize);
        foodNumber = foodNumber - 1;

        
        // Set a random color.
        gl.uniform4f(fColor, Math.random(), Math.random(), Math.random(), 1);

        // Draw the rectangle.
        var primitiveType = gl.TRIANGLES;
        var offset = 0;
        var count = 6;
        gl.drawArrays(primitiveType, offset, count);
    }

};



// Returns a random integer from 0 to range - 1.
function randomInt(range) {
  return Math.floor(Math.random() * range);
}

// Fills the buffer with the values that define a rectangle.
 
function setRectangle(gl, x, y, width, height) {
  var x1 = x;
  var x2 = x + width;
  var y1 = y;
  var y2 = y + height;
 
  // NOTE: gl.bufferData(gl.ARRAY_BUFFER, ...) will affect
  // whatever buffer is bound to the `ARRAY_BUFFER` bind point
  // but so far we only have one buffer. If we had more than one
  // buffer we'd want to bind that buffer to `ARRAY_BUFFER` first.
 
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
     x1, y1,
     x2, y1,
     x1, y2,
     x1, y2,
     x2, y1,
     x2, y2]), gl.STATIC_DRAW);
}

function pop(bufferName){
    gl.deleteBuffer(bufferName)
}
<!DOCTYPE html>
<html>
<head>
<script id="vertex-shader" type="x-shader/x-vertex">
//attribute vec4 vPosition;
attribute vec2 vPosition;
uniform vec2 vResolution;
void
main()
{
    // convert the position from pixels to 0.0 to 1.0
    vec2 zeroToOne = vPosition / vResolution;

    // convert from 0->1 to 0->2
    vec2 zeroToTwo = zeroToOne * 2.0;

    // convert from 0->2 to -1->+1 (clip space)
    vec2 clipSpace = zeroToTwo - 1.0;

    //gl_Position = vec4(clipSpace, 0.0, 1.0);
    // To get it to be the more traditional top left corner used for 2d graphics APIs we can just flip the clip space y coordinate.
    gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
</script>

<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 fColor;

void
main()
{
    gl_FragColor = fColor;
}
</script>

<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="snakeGame.js"></script>
</head>

<body>


<canvas id="gl-canvas" width="1024" height="800">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>

<script>
var canvas = 
</script>
</body>
</html>

Upvotes: 0

Views: 1300

Answers (1)

user128511
user128511

Reputation:

There is no such thing as "deleting an object" at the webgl. WebGL is just an API that draws pixels into a canvas. "Objects" are a higher level concept that your code deals with.

You generally keep your own list of things to draw (whether that is the same as your list of objects or not is up to you)

Every "frame" you clear the canvas and then draw all things you want to draw

render function:
  clear the canvas
  for each thing to draw
     draw thing

So "deleting" an object is a matter of not drawing it.

See this and this and this

As an example

const thingsToDraw = [
  { color: [1, 0, 0, 1], center: [0.2, 0.3], },
  { color: [0, 1, 0, 1], center: [0.0, 0.1], },
  { color: [0, 0, 1, 1], center: [-0.5, -0.4], },
  { color: [1, 0.5, 0, 1], center: [-0.2, 0.3], },
  { color: [0, 1, 1, 1], center: [0.7, -0.1], },
  { color: [1, 0, 1, 1], center: [-0.5, 0.4], },
];

const gl = document.querySelector('canvas').getContext('webgl');
const prg = twgl.createProgram(gl, [`
uniform vec4 position;
void main() {
  gl_PointSize = 20.0;
  gl_Position = position;
}`,`
precision mediump float;
uniform vec4 color;
void main() {
  gl_FragColor = color;
}
`]);

const positionLoc = gl.getUniformLocation(prg, "position");
const colorLoc = gl.getUniformLocation(prg, "color");


function drawThing(color, position) {
  gl.useProgram(prg);
  gl.uniform4f(positionLoc, ...position, 0, 1);
  gl.uniform4fv(colorLoc, color);
  gl.drawArrays(gl.POINTS, 0, 1);  // draw 1 point
}

function render(time) {
  time *= 0.001;
  gl.clear(gl.COLOR_BUFFER_BIT);
  
  thingsToDraw.forEach((thing, i) => {
    const t = time * 10 + i;
    const position = [
       thing.center[0] + Math.cos(t) * 0.1,
       thing.center[1] + Math.sin(t) * 0.1,
    ];
    drawThing(thing.color, position);
  });
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);

document.querySelector('button').addEventListener('click', () => {
  thingsToDraw.splice(0, 1);
});
canvas { border: 1px solid black; }
<canvas></canvas>
<button type="button">remove first thing</button>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

How you decide to track and organize your "objects" or your "things to draw" is entirely up to you. Many 3D systems use a scene graph and then draw the entire graph every frame so 2 ways of not drawing something is to either remove it from the graph or else add some flag to each node whether or not to draw it.

In other systems the scene graph is separate from the list of things to draw.

For small programs people might just use an array (like the example above)

Upvotes: 2

Related Questions