Stop folder boundaries flickering on the city floor
Ground and folder pavements were boxes a few centimetres apart (and nested folders beyond depth four shared one height), well below depth buffer precision from the helicopter, so their tops z-fought. The floor is now a separate layer painted first in nesting order with depth testing off, drawing only top faces, so deeper folders cover their parents cleanly at any distance; buildings and everything else are drawn afterwards with normal depth testing.
This commit is contained in:
+22
-5
@@ -107,6 +107,9 @@ void main(){
|
|||||||
outColor = vec4(vColor.rgb * pow(1.0 - vUnit.z, 1.6) * .55, 0.0);
|
outColor = vec4(vColor.rgb * pow(1.0 - vUnit.z, 1.6) * .55, 0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// The floor is painted without depth testing, so only its top faces may draw (sides and bottoms would
|
||||||
|
// paint over them).
|
||||||
|
if((vKind.x == 1 || vKind.x == 2) && vFace != 0) discard;
|
||||||
if(vKind.x == 2){ outColor = vec4(fog(vec3(.035, .032, .028)), uAlpha); return; } // asphalt
|
if(vKind.x == 2){ outColor = vec4(fog(vec3(.035, .032, .028)), uAlpha); return; } // asphalt
|
||||||
if(vKind.x == 4){
|
if(vKind.x == 4){
|
||||||
// City wall: concrete courses and panel joints in metres, lit coping along the top.
|
// City wall: concrete courses and panel joints in metres, lit coping along the top.
|
||||||
@@ -437,7 +440,7 @@ export class LandscapeRenderer {
|
|||||||
this.codeTexture = gl.createTexture(); this.codeOn = false;
|
this.codeTexture = gl.createTexture(); this.codeOn = false;
|
||||||
this.anisotropy = gl.getExtension('EXT_texture_filter_anisotropic');
|
this.anisotropy = gl.getExtension('EXT_texture_filter_anisotropic');
|
||||||
this.cube = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.cube); gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
this.cube = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.cube); gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||||
this.landscape = this.boxLayer(); this.cityLayer = this.boxLayer();
|
this.landscape = this.boxLayer(); this.cityLayer = this.boxLayer(); this.cityFloor = this.boxLayer();
|
||||||
this.signProgram = program(gl, SIGN_VS, SIGN_FS); this.signUniforms = uniformsOf(gl, this.signProgram);
|
this.signProgram = program(gl, SIGN_VS, SIGN_FS); this.signUniforms = uniformsOf(gl, this.signProgram);
|
||||||
this.corners = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.corners); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]), gl.STATIC_DRAW);
|
this.corners = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.corners); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]), gl.STATIC_DRAW);
|
||||||
this.signLayer = this.quadLayer(); this.facadeLayer = this.quadLayer(); this.posterLayer = this.quadLayer(); this.posterTexture = this.texture();
|
this.signLayer = this.quadLayer(); this.facadeLayer = this.quadLayer(); this.posterLayer = this.quadLayer(); this.posterTexture = this.texture();
|
||||||
@@ -637,11 +640,19 @@ export class LandscapeRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// City instances: [{x,y,w,h,height,color,atlas:[u,v,du,dv],kind,id}] in metres.
|
// City instances: [{x,y,w,h,height,color,atlas:[u,v,du,dv],kind,id}] in metres.
|
||||||
|
// The floor (ground and folder pavements, in nesting order) is its own layer: its surfaces are
|
||||||
|
// centimetres apart, far below depth-buffer precision from the air, so it is painted in order
|
||||||
|
// without depth testing instead of z-fighting (see render()).
|
||||||
setCity(instances, bounds) {
|
setCity(instances, bounds) {
|
||||||
const packed = new Float32Array(instances.length * FLOATS_PER_INSTANCE);
|
const pack = list => {
|
||||||
instances.forEach((b, i) => packed.set([b.x, b.y, b.w, b.h, ...b.color, b.height, ...(b.atlas || [0, 0, 0, 0]), b.kind, b.lit || 0, b.id || 0, 0], i * FLOATS_PER_INSTANCE));
|
const packed = new Float32Array(list.length * FLOATS_PER_INSTANCE);
|
||||||
|
list.forEach((b, i) => packed.set([b.x, b.y, b.w, b.h, ...b.color, b.height, ...(b.atlas || [0, 0, 0, 0]), b.kind, b.lit || 0, b.id || 0, 0], i * FLOATS_PER_INSTANCE));
|
||||||
|
return packed;
|
||||||
|
};
|
||||||
|
const floor = instances.filter(b => b.kind === KIND.ground || b.kind === KIND.block);
|
||||||
this.cityInstances = instances; this.cityBounds = bounds;
|
this.cityInstances = instances; this.cityBounds = bounds;
|
||||||
this.upload(this.cityLayer, packed);
|
this.upload(this.cityFloor, pack(floor));
|
||||||
|
this.upload(this.cityLayer, pack(instances.filter(b => b.kind !== KIND.ground && b.kind !== KIND.block)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Highlights one landscape tile and one city building by file id (0 clears).
|
// Highlights one landscape tile and one city building by file id (0 clears).
|
||||||
@@ -740,7 +751,13 @@ export class LandscapeRenderer {
|
|||||||
gl.uniform1f(u.uAlpha, alpha);
|
gl.uniform1f(u.uAlpha, alpha);
|
||||||
gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this.codeTexture); gl.uniform1i(u.uCode, 0);
|
gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this.codeTexture); gl.uniform1i(u.uCode, 0);
|
||||||
gl.uniform1f(u.uCodeOn, this.codeOn && this.mode !== '2d' ? 1 : 0);
|
gl.uniform1f(u.uCodeOn, this.codeOn && this.mode !== '2d' ? 1 : 0);
|
||||||
if (city) { gl.uniform1f(u.uFogDensity, fog); gl.uniform3f(u.uFogColor, ...fogColor); }
|
if (city) {
|
||||||
|
gl.uniform1f(u.uFogDensity, fog); gl.uniform3f(u.uFogColor, ...fogColor);
|
||||||
|
// Floor first, painter's order, no depth: later (deeper) folders simply cover their parents.
|
||||||
|
gl.disable(gl.DEPTH_TEST); gl.bindVertexArray(this.cityFloor.vao);
|
||||||
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 36, this.cityFloor.count);
|
||||||
|
gl.enable(gl.DEPTH_TEST); gl.bindVertexArray(layer.vao);
|
||||||
|
}
|
||||||
gl.drawArraysInstanced(gl.TRIANGLES, 0, 36, layer.count);
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 36, layer.count);
|
||||||
if (this.mode === 'city') {
|
if (this.mode === 'city') {
|
||||||
// Light effects add colour and never occlude: additive blending without depth writes.
|
// Light effects add colour and never occlude: additive blending without depth writes.
|
||||||
|
|||||||
Reference in New Issue
Block a user