对象的着色器线框 [英] Shader wireframe of an object

查看:28
本文介绍了对象的着色器线框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想看到一个没有对角线的对象的线框

目前,我根据顶点添加线,问题是在我有几个之后我遇到了严重的性能下降.

示例

这就是我使用它的方式:

const vertexShader = `不同的 vec2 vUv;无效主(){vUv = uv;gl_Position = 投影矩阵 * 模型视图矩阵 * vec4(position,1.0);}`const fragmentShader = `#version 150 兼容性在浮动漫射中平坦;在浮动镜面中平坦;在 vec3 edge_mask 中平坦;在 vec2 巴里;均匀浮动mesh_width = 1.0;统一 vec3 mesh_color = vec3(0.0, 0.0, 0.0);统一布尔照明 = 真;出 vec4 frag_color ;浮动边缘因素(){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;返回分钟(分钟(a3.x,a3.y),a3.z);}无效主(){float s = (lighting && gl_FrontFacing) ?1.0:-1.0;vec4 Kdiff = gl_FrontFacing ?gl_FrontMaterial.diffuse : gl_BackMaterial.diffuse;浮动 sdiffuse = s * 扩散;vec4 结果 = vec4(0.1, 0.1, 0.1, 1.0);如果 (sdiffuse > 0.0) {结果 += sdiffuse * Kdiff +高光 * gl_FrontMaterial.specular;}frag_color = (mesh_width != 0.0) ?mix(vec4(mesh_color, 1.0), result, edge_factor()) :结果;}`

...

const 制服 = {颜色: {值:新的 THREE.Vector4(0, 0, 1, 1),类型:'v4'}}const 材质 = 新的 THREE.ShaderMaterial({片段着色器:data.fragmentShader,顶点着色器:data.vertexShader,制服})this._viewer.impl.matman().addMaterial(data.name,材料,真实)const fragList = this._viewer.model.getFragmentList()this.toArray(fragIds).forEach((fragId) => {fragList.setMaterial(fragId, material)})

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

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

我如何告诉片段着色器在符合上述条件的两个顶点之间画一条线?(也保留其他所有内容的默认阴影)

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

解决方案

//-- 顶点着色器 --精密中等浮点数;//从缓冲区输入属性 vec3 aPosition;属性 vec2 aBaryCoord;//跨像素内插的值并传递给片段着色器不同的 vec2 vBaryCoord;//制服统一 mat4 uModelMatrix;统一 mat4 uViewMatrix;统一 mat4 uProjMatrix;无效主(){vBaryCoord = aBaryCoord;gl_Position = uProjMatrix * uViewMatrix * uModelMatrix * vec4(aPosition,1.0);}//---------------------//-- 片段着色器 --//这个着色器不执行任何光照精密中等浮点数;不同的 vec2 vBaryCoord;统一 vec3 uMeshColour;浮动边因子(){vec3 d = fwidth(vBaryCoord);vec3 a3 = smoothstep(vec3(0.0,0.0,0.0),d * 1.5,vBaryCoord);返回分钟(分钟(a3.x,a3.y),a3.z);}无效主(){gl_FragColor = vec4(uMeshColour,(1.0 - edgeFactor()) * 0.95);}//---------------------/*此代码未经测试,因此请谨慎对待想法取自http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/*/

I want to see a wireframe of an object without the diagonals like

Currently, I add lines according to the vertices, the problem is after I have several of those I experience a major performance degradation.

The examples here are either too new for my version of Three or don't work (I commented there about it).

So I want to try to implement a shader instead.

I tried to use this shader: https://stackoverflow.com/a/31610464/4279201 but it breaks the shape to parts and I'm getting WebGL errors.

That's how I use it:

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)
})

So to implement this shader, is the right approach would be to basically check the angle between every two vertices, and draw a line if the degree is 90?

How can I have access to all the vertices of the shape from the vertex shader?

And how can I tell the fragment shader to draw a line between two vertices that match the above condition? (also to leave the default shading for everything else as is)

I'm using Autodesk viewer that uses Three.js rev 71.

解决方案

// -- 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/
*/

这篇关于对象的着色器线框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆