Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve depth(for picking) bits precision #421

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 33 additions & 16 deletions src/framebuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { vec3 } from "gl-matrix";


export class Framebuffer {
public static glContextStencilBits = 0; //class static variable
public framebuffer: WebGLFramebuffer;
public renderbuffer: WebGLRenderbuffer;
public texture: WebGLTexture;
Expand Down Expand Up @@ -70,10 +71,19 @@ export class Framebuffer {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

if (this._glVersion === 1) {
//8bit precision
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
} else {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT16, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
}
else if(Framebuffer.glContextStencilBits >= 8) {
//If the stencil bit is 8 bits or more, set to record the depth texture with DEPTH24_STENCIL8 if available (24+8 expands to a total of 32 bits to record depth => needs confirmation)
//DEPTH24_STENCIL8 only available at glVersion 2
gl.texImage2D(gl.TEXTURE_2D, 0, gl["DEPTH24_STENCIL8"], width, height, 0, gl.DEPTH_STENCIL, gl["UNSIGNED_INT_24_8"], null);
}
else {
//16bit precision
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT16, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
}
}

Expand Down Expand Up @@ -109,6 +119,23 @@ export class Framebuffer {
return result;
}

public getPixelAsFloat(x: number, y: number): number {
if (!this.isReady)
return null;
var result = new Uint8Array(4);
this.gl.readPixels(x, y, 1, 1, this.gl.RGBA, this.gl.UNSIGNED_BYTE, result);
return this.decodeFloatFromRGBA(result);
}

public decodeFloatFromRGBA(rgba : Uint8Array):number {
const rightVec4 = [1.0, 1/255.0, 1/65025.0, 1/16581375.0];
const dot = (rgba[0] / 255.0) * rightVec4[0]
+ (rgba[1] / 255.0) * rightVec4[1]
+ (rgba[2] / 255.0) * rightVec4[2]
+ (rgba[3] / 255.0) * rightVec4[3];
return dot;
}

public getDepth(x: number, y: number): number {
if (!this.isReady)
return null;
Expand All @@ -135,15 +162,12 @@ export class Framebuffer {
const depths = this.getDepths(points);

return depths.map((depth, i) => {
if (depth === 255) { // infinity (= nothing, no value)
return null;
}

// convert values to clip space where x and y are [-1, 1] and z is [0, 1]
const point = points[i];
const xc = point.x / this.width * 2.0 - 1.0;
const yc = point.y / this.height * 2.0 - 1.0;
const zc = (depth / 255.0 - 0.5) * 2.0;
const zc = (depth-0.5) * 2.0;

return vec3.fromValues(xc, yc, zc);
});
Expand Down Expand Up @@ -177,20 +201,13 @@ export class Framebuffer {
}

const depth = this.getDepth(x, y);
if (depth === 255) { // infinity
return null;
}

// convert values to clip space where x and y are [-1, 1] and z is [0, 1]
const xc = x / this.width * 2.0 - 1.0;
const yc = y / this.height * 2.0 - 1.0;
const zc = (depth / 255.0 - 0.5) * 2.0;

const depthNear = Math.max(depth - 1, 0);
const zcn = (depthNear / 255.0 - 0.5) * 2.0;

const depthFar = Math.min(depth + 1, 255);
const zcf = (depthFar / 255.0 - 0.5) * 2.0;
const zc = 0.5;
const zcn = 0.0;
const zcf = 1.0;

return {
far: vec3.fromValues(xc, yc, zcf),
Expand Down
38 changes: 34 additions & 4 deletions src/shaders/depth-reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,38 @@ export class DepthReader {

//fragment shader
this.fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
let fsCompiled = compile(this.fragmentShader, depth_fragment_shader);

const depth_fragment_shader_ws = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
precision highp int;
#else
precision mediump float;
precision mediump int;
#define highp mediump
#endif

varying vec2 position;
uniform sampler2D texture;

vec4 packDepth(float depth)
{
// See Aras Pranckevičius' post Encoding Floats to RGBA
// http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * depth;
enc = fract(enc);
enc -= enc.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);
return enc;
}

void main() {
float depth = texture2D(texture, position).x;
gl_FragColor = packDepth(texture2D(texture, position).r);
//[original code] gl_FragColor = vec4(depth, depth, depth, 1.0);
}
`;

let fsCompiled = compile(this.fragmentShader, depth_fragment_shader_ws); //change for ws
if (!fsCompiled) {
throw new Error("Failed to compile depth reading fragment shader");
}
Expand Down Expand Up @@ -92,9 +123,8 @@ export class DepthReader {
gl.enableVertexAttribArray(this.vertAttrs);
gl.vertexAttribPointer(this.vertAttrs, 2, gl.FLOAT, false, 0, 0);


gl.clearColor(0, 0, 0, 0); //zero colour for no-values
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

// draw the quad (2 triangles, 6 vertices)
gl.drawArrays(gl.TRIANGLES, 0, 6);
Expand All @@ -112,7 +142,7 @@ export class DepthReader {
this.draw(tex);

// all components should be the same (therefore just using [0])
var depths = points.map(p => fb.getPixel(p.x, p.y)[0]) ;
var depths = points.map(p => fb.getPixelAsFloat(p.x, p.y)) ;

// free resources
fb.delete();
Expand Down
4 changes: 3 additions & 1 deletion src/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ export class Viewer {
WebGLUtils.setupWebGL(this.canvas, (ctx, version) => {
this.gl = ctx;
this.glVersion = version;
}, { preserveDrawingBuffer: true }, (err) => {
}, { preserveDrawingBuffer: true, stencil: true}, (err) => {
this.error(err);
});

Expand All @@ -386,6 +386,8 @@ export class Viewer {
return;
}

let stencilBits = this.gl.getParameter(this.gl.STENCIL_BITS);
Framebuffer.glContextStencilBits = stencilBits;

// keep reference to the function in case it gets into zone. For example Angular uses
// NgZone forked from the root Zone to refresh data content. But we make heavy use of this
Expand Down