2017-02-22 19 views

答えて

0

WebGLはラスタライズAPIです。それはただ描くだけです。 「レイヤー」という概念はありません。

フレームごとにレイヤを実現し、最初のタイルマップを描画してから、最初のタイルマップの上に2番目のタイルマップを描画できます。キャンバスの2D APIと変わりはありません。ちょうど2三角形(あるいは1)でタイルマップを描画する方法については

see this article

同じ技術を使用していますthis projectでもありますが、それはまた、裏返しと回転のタイルを(90度)とがありますサポートしていますTiledからマップをロードするコード。申し訳ありませんが、ドキュメントはありません。レイヤを描画するシェーダとコードについてはtilemap.jsを、タイルでマップとタイルをロードするコードについてはtiledloader.jsを参照してください。

基本的なことから始めましょう。私達はちょうど2つの長方形第二1(青)である第一(赤)の上に「層」

const ctx = document.querySelector("canvas").getContext("2d"); 
 
function render(time) { 
 
    time *= 0.001; // seconds 
 
    
 
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
 
    
 
    var t1 = time * -1.1; 
 
    ctx.fillStyle = "red"; 
 
    ctx.fillRect(50 + Math.sin(t1) * 20, 50 + Math.cos(t1) * 20, 128, 64); 
 
    
 
    var t2 = time * 1.3; 
 
    ctx.fillStyle = "blue"; 
 
    ctx.fillRect(75 + Math.sin(t2) * 20, 30 + Math.cos(t2) * 20, 64, 128); 
 

 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<canvas />

を描く最初の場合、これはWebGLの中に何ら変わりないだろう。

矩形の内容を除いて、静的なタイルマップのような画像をそれぞれ変更することができます。ここで

は、第1の画像は

layer2

そして、ここでは、第二

再び

layer2

const ctx = document.querySelector("canvas").getContext("2d"); 
 
const layer1 = new Image(); 
 
layer1.src = "http://i.imgur.com/KTXDmsa.png"; 
 
const layer2 = new Image(); 
 
layer2.src = "http://i.imgur.com/3qVLkO5.png"; 
 

 

 
function render(time) { 
 
    time *= 0.001; // seconds 
 
    
 
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
 
    
 
    var t1 = time * -1.1; 
 
    ctx.drawImage(layer1, 50 + Math.sin(t1) * 20, 50 + Math.cos(t1) * 20); 
 
    
 
    var t2 = time * 1.3; 
 
    ctx.drawImage(layer2, 75 + Math.sin(t2) * 20, 30 + Math.cos(t2) * 20); 
 

 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<canvas />

だのですWebGLでは違いはありません。

これらの画像は、リンクされたコードと以下のコードを静的にロードする代わりに、タイルマップから生成する必要があります。

this tileset

tileset

const m4 = twgl.m4; 
 
const gl = document.querySelector("canvas").getContext("webgl"); 
 

 
// compile & link shaders and lookup locations 
 
const progInfo = twgl.createProgramInfo(gl, ["vs", "fs"]); 
 

 
// make a unit quad 
 
const quadBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl, 1, .5, .5); 
 

 
// load tiles into texture 
 
const tilesAcross = 16; 
 
const tilesDown = 16; 
 
const tileWidth = 32; 
 
const tileHeight = 32; 
 
const tiles = twgl.createTexture(gl, { 
 
    src: "http://i.imgur.com/sz79FPd.png", 
 
    crossOrigin: "", 
 
    minMag: gl.NEAREST, 
 
}); 
 

 
// layer 0 
 
const tilemap0 = createTilemap({ 
 
    width: 8, 
 
    height: 5, 
 
    map: new Uint32Array([ 
 
    t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), 
 
    t(1, 2), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(1, 2),  
 
    t(1, 2), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(1, 2),  
 
    t(1, 2), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(9, 6), t(1, 2),  
 
    t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), t(1, 2), 
 
    ]), 
 
}); 
 

 
// layer 1 
 
const tilemap1 = createTilemap({ 
 
    width: 8, 
 
    height: 5, 
 
    map: new Uint32Array([ 
 
    t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), 
 
    t(0, 0), t(4, 5), t(5, 5), t(6, 5), t(0, 0), t(0, 0), t(0, 0), t(0, 0), 
 
    t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(4, 5), t(5, 5), t(6, 5), 
 
    t(4, 5), t(5, 5), t(6, 5), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), 
 
    t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), t(0, 0), 
 
    ]), 
 
}); 
 

 
function t(x, y, xflip, yflip, xyswap) { 
 
    return x | (y << 8) | 
 
     (((xflip ? 0x80 : 0) | (yflip ? 0x40 : 0) | (xyswap ? 0x20 : 0)) << 24); 
 
} 
 

 
// copy the tilemap into a texture 
 
function createTilemap(tilemap) { 
 
    tilemap.texture = twgl.createTexture(gl, { 
 
    src: new Uint8Array(tilemap.map.buffer), 
 
    width: tilemap.width, 
 
    minMag: gl.NEAREST, 
 
    }); 
 
    return tilemap; 
 
}; 
 

 

 
function drawTilemap(options) { 
 
    const tilemap = options.tilemap; 
 
    
 
    const scaleX = options.scaleX || 1; 
 
    const scaleY = options.scaleY || 1; 
 

 
    const dispScaleX = options.width/gl.canvas.width; 
 
    const dispScaleY = options.height/gl.canvas.height; 
 

 
    let texMat = m4.translation([options.scrollX, options.scrollY, 0]); 
 
    texMat = m4.rotateZ(texMat, options.rotation); 
 
    texMat = m4.scale(texMat, [ 
 
    gl.canvas.width/tileWidth/scaleX * (dispScaleX), 
 
    gl.canvas.height/tileHeight/scaleY * (dispScaleY), 
 
    1, 
 
    ]); 
 
    texMat = m4.translate(texMat, [ 
 
    -options.originX/gl.canvas.width, 
 
    -options.originY/gl.canvas.height, 
 
    0, 
 
    ]); 
 

 
    const matrix = [ 
 
    2 * dispScaleX,0,0,0, 
 
    0,-2 * dispScaleY,0,0, 
 
    0,0,1,0, 
 
    -1 + 2 * (options.x | 0)/gl.canvas.width, 1 - 2 * (options.y | 0)/gl.canvas.height,0,1, 
 
    ]; 
 

 
    gl.useProgram(progInfo.program); 
 
    
 
    // calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer 
 
    twgl.setBuffersAndAttributes(gl, progInfo, quadBufferInfo); 
 
    
 
    // calls gl.uniformXXX and gl.activeTexture, gl.bindTexture 
 
    twgl.setUniforms(progInfo, { 
 
    u_matrix: matrix, 
 
    u_texMatrix: texMat, 
 
    u_tilemap: tilemap.texture, 
 
    u_tiles: tiles, 
 
    u_tilemapSize: [tilemap.width, tilemap.height], 
 
    u_tilesetSize: [tilesAcross, tilesDown], 
 
    }); 
 
    
 
    // calls gl.drawElements 
 
    twgl.drawBufferInfo(gl, quadBufferInfo); 
 
} 
 

 
function render(time) { 
 
    time *= 0.001; 
 
    
 
    // draw layer 0 
 
    drawTilemap({ 
 
    tilemap: tilemap0, 
 
    tiles: tiles, 
 
    // position and width, height on canvas 
 
    x: Math.cos(time * .9) * 20, 
 
    y: Math.sin(time * .9) * 20, 
 
    width: 256, 
 
    height: 160, 
 
    // offset into tilemap (repeats at edges) 
 
    scrollX: 0, 
 
    scrollY: 0, 
 
    // rotation/scale point 
 
    originX: 0, 
 
    originY: 0, 
 
    // rotation in radians 
 
    rotation: 0, 
 
    // scale 
 
    scaleX: 1, 
 
    scaleY: 1, 
 
    }); 
 

 
    // draw layer 1 
 
    drawTilemap({ 
 
    tilemap: tilemap1, 
 
    tiles: tiles, 
 
    x: Math.sin(time) * 20, 
 
    y: Math.cos(time) * 20, 
 
    width: 256, 
 
    height: 160, 
 
    scrollX: 0, 
 
    scrollY: 0, 
 
    originX: 0, 
 
    originY: 0, 
 
    rotation: 0, 
 
    }); 
 

 

 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<canvas /> 
 
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script> 
 
<script id="vs" type="foo"> 
 
attribute vec4 position; 
 
attribute vec4 texcoord; 
 

 
uniform mat4 u_matrix; 
 
uniform mat4 u_texMatrix; 
 

 
varying vec2 v_texcoord; 
 

 
void main() { 
 
    gl_Position = u_matrix * position; 
 
    v_texcoord = (u_texMatrix * texcoord).xy; 
 
} 
 
</script> 
 
<script id="fs" type="foo"> 
 
precision mediump float; 
 

 
uniform sampler2D u_tilemap; 
 
uniform sampler2D u_tiles; 
 
uniform vec2 u_tilemapSize; // tiles across/down map 
 
uniform vec2 u_tilesetSize; // pixels across a single tile 
 

 
varying vec2 v_texcoord; 
 

 
void main() { 
 
    // v_texcoord is in tile units which is based on u_texMatrix from the 
 
    // vertex shader 
 
    
 
    // this is the tile to start at 
 
    vec2 tilemapCoord = floor(v_texcoord); 
 
    
 
    // this is a fractional amount into a tile 
 
    vec2 texcoord = fract(v_texcoord); 
 
    
 
    // computes the UV coord pull the correct value out of tilemap 
 
    vec2 tileFoo = fract((tilemapCoord + vec2(0.5, 0.5))/u_tilemapSize); 
 
    
 
    // get a single tile out of the tilemap and convert from 0 -> 1 to 0 -> 255 
 
    vec4 tile = floor(texture2D(u_tilemap, tileFoo) * 256.0); 
 

 
    // flags for the tile are in w (xflip, yflip, xyswap) 
 
    float flags = tile.w; 
 
    float xflip = step(128.0, flags); 
 
    flags = flags - xflip * 128.0; 
 
    float yflip = step(64.0, flags); 
 
    flags = flags - yflip * 64.0; 
 
    float xySwap = step(32.0, flags); 
 
    
 
    // based on the flags swap the texcoord inside the tile 
 
    if (xflip > 0.0) { 
 
    texcoord = vec2(1.0 - texcoord.x, texcoord.y); 
 
    } 
 
    if (yflip > 0.0) { 
 
    texcoord = vec2(texcoord.x, 1.0 - texcoord.y); 
 
    } 
 
    if (xySwap > 0.0) { 
 
    texcoord = texcoord.yx; 
 
    } 
 

 
    // scale the tex coords for a single tile 
 
    vec2 tileCoord = (tile.xy + texcoord)/u_tilesetSize; 
 
    
 
    // get the color from the tile 
 
    vec4 color = texture2D(u_tiles, tileCoord); 
 
    
 
    // if alpha is below some threshold don't draw at all 
 
    if (color.a <= 0.1) { 
 
    discard; 
 
    } 
 
    gl_FragColor = color; 
 
} 
 
</script>

+0

まあに基づいて、私は東寺の例のコードがどのように機能するかを理解しようとしていた、彼はWebGLの中で(forループで "レイヤー" を描きます237行目から247行目までのtilemap.js)、私はタイルマップが一番上にあると宣言しているのか、uniform2fと宣言されているのか、あるいは単に同じ頂点のように宣言され、ab同じ座標を持つので大事です私は確信していません – AngeLOL

+0

彼は一番上に宣言していません。最初のものは下に描画され、次の描画はその上に描画され、次の描画は描画より上に描画されます。魔法はありません。答えを見る – gman

関連する問題