Showing Depth in Three.js Point Cloud

那年仲夏 提交于 2020-06-23 12:14:03

问题


I have a 3D scan of a rock that I have represented as a point cloud using Three.js, and I wanted to more explicitly show the features of the rock, perhaps using lighting to show depths with Three. Viewing the rock from the top, I see this: When looking closely from the side, you can see rigid features that I would like to show more closely:

I am unsure in how to approach this, and was hoping for some help in showing these rock features within this visualization. For context, this is my current shader setup:

vertexShader: `
    precision mediump float;
    varying vec3 vColor;
    attribute float alpha;
    varying float vAlpha;
    
    void main() {
        vAlpha = alpha;
        vColor = color;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

        gl_PointSize = 2.0;

        gl_Position = projectionMatrix * mvPosition;
    }
`

fragmentShader: `
    #ifdef GL_OES_standard_derivatives
    #extension GL_OES_standard_derivatives : enable
    #endif
    precision mediump float;
    varying vec3 vColor;
    varying float vAlpha;

    
    void main() {
        float r = 0.0, delta = 0.0, alpha = 1.0;
        vec2 cxy = 2.0 * gl_PointCoord.xy - 1.0;
        r = dot(cxy, cxy);

        //#ifdef GL_OES_standard_derivatives
        delta = fwidth(r);
        alpha = vAlpha - smoothstep(vAlpha - delta, vAlpha + delta, r);
        //#endif
        if (r > 1.0) {
            discard;
        }
        gl_FragColor = vec4(vColor, alpha);
    }
    //varying vec3 vColor;
    //varying float vAlpha;
    //void main() {
        //gl_FragColor = vec4( vColor, vAlpha );
    //}
`

I am creating my point cloud using THREE.Points, with a BufferGeometry geometry and ShaderMaterial material.

Is there a way to go about this more explicitly showing my point cloud depths?

Thank you!


回答1:


The depth of the current fragment is stored in the .z component of gl_FragCoord. The depth is stored in range [0.0, 1.0] (except this range is changed by glDepthRangef):

With that information you can set the alpha channel of the point, with decreasing opacity, by its depth:

float depth = gl_FragCoord.z;
gl_FragColor = vec4(vColor, 1.0 - depth);

Since the depth at perspective projection is not linear (see How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?), it would be nice to have a value in rage [0.0, 1.0], which linearly represents the depth of the point between the near and the far plane.
THis can be done by the function LinearizeDepth in the following example:

uniform vec2 u_depthRange;

float LinearizeDepth(float depth, float near, float far)
{
  float z = depth * 2.0 - 1.0; // Back to NDC 
  return (2.0 * near * far / (far + near - z * (far - near)) - near) / (far-near);
}

void main()
{
    // [...]

   float lineardepth = LinearizeDepth(gl_FragCoord.z, u_depthRange[0], u_depthRange[1]);
   gl_FragColor = vec4(vColor, 1.0 - lineardepth);
}

To make the example tun, the depth range has to be set to the uniform u_depthRange. The near plane of the PerspectiveCamera is stored in the .x component and the far plane in .y component:

var near = 1, far = 10
camera = new THREE.PerspectiveCamera(fov, width / height, near, far);
var uniforms = {
      // [...]
      u_depthRange: {type: 'v2', value: {x:near, y: far}} 
};

var material = new THREE.ShaderMaterial({  
      uniforms: uniforms,
      // [...]
});

Note, for a "good" effect, the near and the far plane of the camera, have to be as close to the geometry as possible!



来源:https://stackoverflow.com/questions/59539047/showing-depth-in-three-js-point-cloud

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!