我正在做一個光貼圖的瓷磚地圖,我想知道我該如何聲明一個瓷磚貼圖(光柵化在兩個三角形中)作爲第1層,而其他瓷磚貼圖上面有透明的部分來看第一層?如何在WebGL上使用圖層?
0
A
回答
0
WebGL是一個光柵化API。它只是繪製。它沒有「層」的概念。
您可以在每個框架中實現圖層,繪製第一個地圖,然後在第一個地圖上繪製第二個地圖。這與畫布2D API沒有區別。
至於如何使只有2個三角形(或一個偶數)一tilemap的see this article
也有在使用相同的技術this project但它也支持翻轉和旋轉的磚(90度),並有代碼從Tiled加載地圖。對不起,沒有文檔。查看tilemap.js獲取繪製圖層的着色器和代碼,查看從Tiled加載地圖和圖塊的代碼tiledloader.js。
讓我們從基礎開始。首先,如果我們只是抽2個矩形:第二個(藍色)是一個「層」在第一(紅色)
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的沒有什麼不同。
如果我們把靜態tilemap像圖像一樣,除了矩形的內容之外沒有任何變化。
這裏的第一個圖像
而這裏的第二
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中沒有什麼不同。
現在,您需要從tilemap生成這些圖像,而不是靜態加載它們,這是鏈接的代碼和下面的代碼的作用。基於this 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>
相關問題
- 1. openlayers - 如何使用WebGl在openlayers中呈現矢量圖層
- 2. 如何在android應用上創建圖層圖層?
- 3. 如何使用圖層
- 4. 如何使用WebGL的
- 5. 如何在圖像上創建圖層?
- 6. 如何在canvas圖像webgl上應用紋理?
- 7. 如何在Android中使用圖層
- 8. 如何在webgl中使用framebuffer目標?
- 9. 我如何在webgl中使用stride?
- 10. BING地圖層和PINS:如何在POLYGON層上繪製圖釘?
- 11. 如何在網上部署WebGL Unity WebGL版本?
- 12. 在縮放圖層上使用觸摸
- 13. WEBGL - 如何顯示圖像?
- 14. Leaflet:如何在geojson圖層上使用自定義標記?
- 15. 如何在Keras 2.0.0上使用合併圖層(concat函數)?
- 16. 如何使用jquery在mouseover上顯示圖層
- 17. 如何使用tm_text在同一圖層上顯示兩個值?
- 18. 如何在iOS上使用OpenGL ES實現多層次繪圖?
- 19. 如何使用畫布在圖像上繪製疊加層?
- 20. 如何使用WebGl在畫布上呈現二進制數據?
- 21. 如何在webgl上使用`gl.POINTS`繪製單個像素?
- 22. 如何在asp.net mvc視圖中使用unity3d webgl內容?
- 23. 如何使用核心圖形層圖
- 24. 如何在網頁上看到圖層
- 25. 如何在佈局上實現圖層?
- 26. 如何在mapbox上添加圖層?
- 27. 如何在UIButton的底層上繪圖?
- 28. 如何在View上添加圖層?
- 29. 如何在textureCube上實現WebGL模糊
- 30. 如何在使用WebGl渲染器時在Openlayers 3中顯示geojson圖層的特徵的文本標籤?
好
,我試圖瞭解東治的示例代碼是如何工作的,他畫的 「層」 的一個循環(在WebGL的-tilemap.js從第237行到第247行),但我不明白他是如何聲明瓷磚貼圖位於頂部,我認爲它是uniform2f,或者它只是聲明爲同一個頂點和柵格化的ab因爲有相同的座標。我不確定 – AngeLOL
他沒有在頂部宣佈一個。第一個繪製在底部,下一個繪製在上面,下一個繪製在上面。沒有魔法。見答案 – gman