对象的着色器线框

时间:2017-08-28 11:11:26

标签: three.js webgl shader fragment-shader autodesk-viewer

我希望看到没有像

这样的对角线的物体的线框

enter image description here

目前,我根据顶点添加线条,问题是在我遇到其中几个之后我遇到了重大的性能下降。

示例here对我的三版本来说太新了或者没有工作(我在那里评论过它)。

所以我想尝试实现一个着色器。

我尝试使用这个着色器:https://stackoverflow.com/a/31610464/4279201但是它将形状分解为部分并且我得到了WebGL错误。

enter image description here

我是如何使用它的:

const vertexShader = `
varying vec2 vUv;
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`

const fragmentShader = `
#version 150 compatibility                                         
flat in float diffuse;
flat in float specular;
flat in vec3  edge_mask;                                           
in vec2 bary;
uniform float mesh_width = 1.0;
uniform vec3 mesh_color = vec3(0.0, 0.0, 0.0);
uniform bool lighting = true;
out vec4 frag_color ;
float edge_factor(){                                               
  vec3 bary3 = vec3(bary.x, bary.y, 1.0 - bary.x - bary.y);
  vec3 d = fwidth(bary3);
  vec3 a3 = smoothstep(vec3(0.0, 0.0, 0.0), d * mesh_width, bary3);
  a3 = vec3(1.0, 1.0, 1.0) - edge_mask + edge_mask * a3;
  return min(min(a3.x, a3.y), a3.z);
}
void main() {                                                      
  float s = (lighting && gl_FrontFacing) ? 1.0 : -1.0;
  vec4  Kdiff = gl_FrontFacing ?
    gl_FrontMaterial.diffuse : gl_BackMaterial.diffuse;
  float sdiffuse = s * diffuse;
  vec4 result = vec4(0.1, 0.1, 0.1, 1.0);
  if (sdiffuse > 0.0) {
    result += sdiffuse * Kdiff +
      specular * gl_FrontMaterial.specular;
  }
  frag_color = (mesh_width != 0.0) ?
    mix(vec4(mesh_color, 1.0), result, edge_factor()) :
    result;
}`     

...

const uniforms = {
  color: {
    value: new THREE.Vector4(0, 0, 1, 1),
    type: 'v4'
  }
}

const material = new THREE.ShaderMaterial({
  fragmentShader: data.fragmentShader,
  vertexShader: data.vertexShader,
  uniforms
})

this._viewer.impl.matman().addMaterial(
  data.name, material, true)

    const fragList = this._viewer.model.getFragmentList()

this.toArray(fragIds).forEach((fragId) => {

  fragList.setMaterial(fragId, material)
})

为了实现这个着色器,正确的方法是基本检查每两个顶点之间的角度,如果度数为90,则画一条线?

如何从顶点着色器访问形状的所有顶点?

如何告诉片段着色器在两个与上述条件匹配的顶点之间画一条线? (也是为了保留其他所有内容的默认着色)

我使用的是使用Three.js rev 71的Autodesk查看器。

1 个答案:

答案 0 :(得分:3)

// -- Vertex Shader --
precision mediump float;

// Input from buffers
attribute vec3 aPosition;
attribute vec2 aBaryCoord;

// Value interpolated accross pixels and passed to the fragment shader
varying vec2 vBaryCoord;

// Uniforms
uniform mat4 uModelMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uProjMatrix;

void main() {
    vBaryCoord = aBaryCoord;
    gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(aPosition,1.0);
}
// ---------------------

// -- Fragment Shader --
// This shader doesn't perform any lighting
precision mediump float;

varying vec2 vBaryCoord;

uniform vec3 uMeshColour;

float edgeFactor() {
    vec3 d = fwidth(vBaryCoord);
    vec3 a3 = smoothstep(vec3(0.0,0.0,0.0),d * 1.5,vBaryCoord);
    return min(min(a3.x,a3.y),a3.z);
}

void main() {
    gl_FragColor = vec4(uMeshColour,(1.0 - edgeFactor()) * 0.95);
}
// ---------------------

/*
    This code isn't tested so take it with a grain of salt

    Idea taken from
    http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/
*/