Effective way to animate grass in canvas

I play with the 2d context capabilities of the canvas element to try to create relatively realistic 3d scenes, and I'm currently trying to create equal 3d 'ish' grass depending on the script:

http://jsfiddle.net/PlacidCow/j6h7sajz/

My question is, what is the most effective way to revitalize grass, to act on wind / physics, etc.

Currently, I just turned to the screen - I tried to save the dimensions of each blade in a large array, which then takes age to loop into the animation (therefore, it is laggy and meaningless). Is there an effective way to draw on a blade? Or do people recommend animating on a block (but then how to fix it, since cleaning the patch will ruin the blades in front)? repeating the blades so they animated the animation?

Take a look online (maybe I don’t have enough Google skills), but I either can’t find anything, neither cagey webgl demographic examples, nor C examples, etc., but this is using shaders that are not available for the 2nd canvas .

c = document.getElementsByTagName('canvas')[0];
ctx = c.getContext('2d');

var v = {
    w: c.clientWidth,
    h: c.clientHeight
};
c.width = v.w;
c.height = v.h;

var base = {
    c: [
        [-1, -1, 0],
        [-1, -1, -1],
        [1, -1, -1],
        [1, -1, 0]
    ],
    f: 'brown',
    d: -3
};

draw(base.c, base.f, base.d);

for (var j=1; j<120; j++) {
    for (var k=1; k<200; k++) {
        var z = -1 + 2*j/199;
        var x = -1 + (2*Math.random())/1.01;
        var y = 0.06+Math.random()*0.04;
        var fl = Math.pow(-1, (Math.random()*1000)|0) * Math.random()/20;
        var blade = {
c: [
    [x, -1, z-Math.random()/1000],
    [x+0.002+fl, -1+y, z-Math.random()/1000],
    [x+0.007+fl, -1+y, z-Math.random()/1000],
    [x+0.02, -1, z-Math.random()/1000]
],
f: 'green',
d: 2
        };
        draw(blade.c, blade.f, blade.d);
    }
}

function draw(cds, fill, d) {
    var v = {
        w: c.clientWidth,
        h: c.clientHeight
    };

    ctx.beginPath();

    ctx.moveTo(((cds[0][0] * (1 / (1 - cds[0][2])) + 1) * v.w / 2)|0, ((v.h - (cds[0][1] + 1) * v.h / 2) * (1 / (1 - cds[0][2])))|0);

    for (var i = 1; i < cds.length; i++) {
        ctx.lineTo(((cds[i][0] * (1 / (1 - cds[i][2])) + 1) * v.w / 2)|0, ((v.h - (cds[i][1] + 1) * v.h / 2) * (1 / (1 - cds[i][2])))|0);
}
        ctx.lineTo(((cds[0][0] * (1 / (1 - cds[0][2])) + 1) * v.w / 2)|0, ((v.h - (cds[0][1]+1) * v.h / 2) * (1 / (1 - cds[0][2])))|0);

    if (Math.abs(d) == 1) {
        grd = ctx.createLinearGradient((200-200*d/Math.abs(d))/2, 0, (200+200*d/Math.abs(d))/2,0);
    } else if (Math.abs(d) == 2) {
        grd = ctx.createLinearGradient(0,((v.h - (cds[1][1] + 1) * v.h / 2) * (1 / (1 - cds[1][2])))|0,0,((v.h - (cds[0][1] + 1) * v.h / 2) * (1 / (1 - cds[0][2])))|0+v.h/100);
    } else if (Math.abs(d) == 3) {
        grd = ctx.createLinearGradient(0,(200-200*d/Math.abs(d))/2, 0, (200+200*d/Math.abs(d))/2);
    }
    grd.addColorStop(0, fill);
    grd.addColorStop(1, '#000');

    ctx.fillStyle = grd;
    ctx.fill();
}
+4
source share
1 answer

I would do so to pre-create all the shapes that are possible for each blade of grass. I am not familiar with the mathematics behind grass bending, but it suggests that each form of grass can be described by two variables: bentX and bentZ. Therefore, I would divide the drawing process into 2: generate image frames for grass and rendering.

Pseudocode for frame generation:

var frames = [];
for (var i = min possible of bentX, l = max possible of bentX; i<=l; i += precision for bentX)
    for (var j = ... bentZ .... )
         frames[i][j] = image of grass at (i,j);

Then for rendering:

for each grassObj:
    bentX, bentZ = mathCalcs(grassObj);
    bentX, bentZ = clampToValidValue(bendX, bentZ); 
    frames[bendX][bentZ].draw();
0
source

All Articles