2

したがって、Threejs と Brandon Jone の tilemap メソッド (ここにあります) を使用してタイルマップを実装するにはTHREE.Plane、各レイヤーにジオメトリを使用し、次のカスタム シェーダーで顔をペイントします。

頂点シェーダー:

var tilemapVS = [
    "varying vec2 pixelCoord;",
    "varying vec2 texCoord;",

    "uniform vec2 mapSize;",
    "uniform vec2 inverseTileTextureSize;",
    "uniform float inverseTileSize;",

    "void main(void) {",
    "    pixelCoord = (uv * mapSize);",
    "    texCoord = pixelCoord * inverseTileTextureSize * inverseTileSize;",
    "    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
    "}"
].join("\n");

フラグメント シェーダー:

var tilemapFS = [
    "varying vec2 pixelCoord;",
    "varying vec2 texCoord;",

    "uniform sampler2D tiles;",
    "uniform sampler2D sprites;",

    "uniform vec2 inverseTileTextureSize;",
    "uniform vec2 inverseSpriteTextureSize;",
    "uniform float tileSize;",
    "uniform int repeatTiles;",

    "void main(void) {",
    "    vec4 tile = texture2D(tiles, texCoord);", //load this pixel of the tilemap
    "    if(tile.x == 1.0 && tile.y == 1.0) { discard; }", //discard if R is 255 and G is 255
    "    vec2 spriteOffset = floor(tile.xy * 256.0) * tileSize;", //generate the offset in the tileset this pixel represents
    "    vec2 spriteCoord = mod(pixelCoord, tileSize);",
    "    vec4 texture = texture2D(sprites, (spriteOffset + spriteCoord) * inverseSpriteTextureSize);",
    "    gl_FragColor = texture;",
    "}"
].join("\n");

各テクスチャは次のようにセットアップされます。

//Setup Tilemap
this.tilemap.magFilter = THREE.NearestFilter;
this.tilemap.minFilter = THREE.NearestMipMapNearestFilter;
//tilemap.flipY = false;
if(this.repeat) {
    this.tilemap.wrapS = this.tilemap.wrapT = THREE.RepeatWrapping;
} else {
    this.tilemap.wrapS = this.tilemap.wrapT = THREE.ClampToEdgeWrapping;
}

//Setup Tileset
this.tileset.wrapS = this.tileset.wrapT = THREE.ClampToEdgeWrapping;
this.tileset.flipY = false;
if(this.filtered) {
    this.tileset.magFilter = THREE.LinearFilter;
    this.tileset.minFilter = THREE.LinearMipMapLinearFilter;
} else {
    this.tileset.magFilter = THREE.NearestFilter;
    this.tileset.minFilter = THREE.NearestMipMapNearestFilter;
}

そして、ユニフォームは次のとおりです。

//setup shader uniforms
this._uniforms = {
    mapSize: { type: 'v2', value: new THREE.Vector2(this.tilemap.image.width * this.tileSize, this.tilemap.image.height * this.tileSize) },
    inverseSpriteTextureSize: { type: 'v2', value: new THREE.Vector2(1/this.tileset.image.width, 1/this.tileset.image.height) },
    tileSize: { type: 'f', value: this.tileSize },
    inverseTileSize: { type: 'f', value: 1/this.tileSize },

    tiles: { type: 't', value: this.tilemap },
    sprites: { type: 't', value: this.tileset },

    inverseTileTextureSize: { type: 'v2', value: new THREE.Vector2(1/this.tilemap.image.width, 1/this.tilemap.image.height) },
    repeatTiles: { type: 'i', value: this.repeat ? 1 : 0 }
};

そして、実際のジオメトリとメッシュ:

//create the shader material
this._material = new THREE.ShaderMaterial({
    uniforms: this._uniforms,
    vertexShader: tilemapVS,
    fragmentShader: tilemapFS,
    transparent: false
});

this._plane = new THREE.PlaneGeometry(
    this.tilemap.image.width * this.tileSize * this.tileScale,
    this.tilemap.image.height * this.tileSize * this.tileScale
);

this._mesh = new THREE.Mesh(this._plane, this._material);
this._mesh.z = this.zIndex;

this.tileSizeです。16_ this.tileScale_ 4私が抱えている問題は、16x16 タイルの端の周りに破れがあることです。

画面のティアリング

奇妙な部分は、常に発生するわけではなく、y 軸に沿って移動するときに散発的にのみ発生することです (ただし、私の Linux ボックスでは、問題はさらに悪化し、x 軸にも影響します)。

頂点シェーダーで配置すると、16x16 のタイルがわずかにずれているようです。しかし、何が原因なのかわかりません。どんな助けでも大歓迎です、ありがとう!

編集

これは引き裂きのより良い画像です。草地でより目立ちます。

画面のティアリング 2

ご覧のとおり、16x16 タイルのエッジに沿っています ( でスケーリングされているため4)。

4

2 に答える 2

4

ミップマップされたテクスチャを使用していて、テクスチャ座標がタイルのエッジで不連続になっています。

"    vec2 spriteOffset = floor(tile.xy * 256.0) * tileSize;", //generate the offset in the tileset this pixel represents
"    vec2 spriteCoord = mod(pixelCoord, tileSize);",
"    vec4 texture = texture2D(sprites, (spriteOffset + spriteCoord) * inverseSpriteTextureSize);",

floor関数とmod関数は、テクスチャ座標が2つのピクセル間で突然ジャンプすることを意味します(意図したとおり、別のタイルを取得します)。

ただし、テクスチャルックアップはピクセル間の座標の変更を使用して使用するミップマップレベルを決定するため、タイルエッジでは、はるかに小さいミップマップを使用するようにジャンプし、残りのピクセルとは異なるミップマップであるため、不連続性があります。

これを回避する最も簡単な方法は、ミップマップを使用しないことです。たとえば、次のいずれかです。

texture.minFilter = THREE.LinearFilter;
texture.minFilter = THREE.NearestFilter;

それ以外の場合、ミップマップが必要な場合は、3番目のパラメーターバイアスをtexture2Dに渡す必要があります。これを一般的に0.0に設定し、タイトルの端にいるときに、この効果を打ち消すためにトラバースするミップマップの数の負の数にこれを設定します。

たとえば、-11.0は、最も低い単一ピクセルのミップマップから2048x2048のフルサイズのテクスチャまでの11のミップマップを取得します。正確な値は、ズーム画像サイズ、テクスチャサイズなどに基づいて計算する必要があります。

于 2012-11-19T05:49:50.577 に答える
0

カメラの位置がスプライトの UV マッピングでエラーを引き起こしているために、これらの問題が発生していると思われます。基本的に、レンダリングするはずのスプライトのスプライト シートから隣接するスプライトを表示しています。

特にこの行: `vec2 spriteOffset = floor(tile.xy * 256.0) * tileSize;"

オフセットの問題を引き起こしている可能性があるようです。スプライトを明るい色でパディングして、それがポップアップするかどうかを確認することで、より良いチェックを行うことができます.

于 2012-11-14T16:05:13.837 に答える