2014-11-20 2 views
4

Я играю с возможностями 2d-контекста элемента canvas, чтобы попытаться создать относительно реалистичные 3d-сцены, и в настоящее время я пытаюсь создать равнину 3d 'ish' grass в соответствии с скрипку:Эффективный способ анимации травы в холсте

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

Мой вопрос, что является наиболее эффективным способом, чтобы оживить траву взять в действии ветра/физики и т.д.?

В настоящее время я только что нарисован на экране - я попытался сохранить размеры каждого лезвия в большом массиве, который затем принимает возраст, чтобы переходить в анимированный (следовательно, лагги и бессмыслен). Есть ли эффективный способ рисования на клинок? Или люди рекомендуют анимировать на блок (но тогда как исправить, так как очистка патча испортит лезвия впереди)? повторяя лезвия, чтобы они оживили анимацию?

Посмотрел онлайн (может быть, мне не хватает навыков работы с Google), но я либо ничего не нахожу, демонстрации cagey webgl или примеры для C и т. Д., Но это использование шейдеров, которые недоступны для 2-го холста.

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(); 
} 
+0

ли один из них эффект, который вы ищете? http://stackoverflow.com/questions/17171010/grass-like-smoothing-animation-on-beziercurve/17325855#17325855 – markE

+0

Я уже прочитал этот пост, и есть несколько опрятных способов изменить лезвия (все прочитает снова в случай, когда я пропустил ответ) - то, что я сейчас задаю, - это эффективный способ потенциально повлиять на все (на скрипке 200x200 = 40000) лезвия сразу из-за ветра говорят - или, по крайней мере, обмануть впечатление –

+0

Самый эффективный способ 2d, вероятно, создает кадры изображения для каждой травинки и воспроизводит их. Вы можете создавать несколько наборов и использовать другую отправную точку, чтобы создать иллюзию, что все они уникальны. –

ответ

0

Что бы я сделал, это предварительно сформировать все формы, которые возможны для каждой лопасти травы. Я не знаком с математикой за изгибом травы, но позволяет предположить, что каждая форма травы может быть описана двумя переменными: bentX и bentZ. Поэтому я бы разбил процесс рисования на 2: сгенерировал рамки изображений для травы и рендеринга.

Псевдо код для формирования кадра:

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); 

Тогда для рендеринга:

for each grassObj: 
    bentX, bentZ = mathCalcs(grassObj); 
    bentX, bentZ = clampToValidValue(bendX, bentZ); 
    frames[bendX][bentZ].draw(); 
Смежные вопросы