我正在尝试在着色器中实现边缘检测,以在 Three.js 中实现非逼真的“轮廓”效果,遵循以下方法:http: //ar3f.in/goochShading.html。我主要对深色轮廓感兴趣,而不是 Gooch 阴影。我了解此代码中采用的方法,即首先使用对象空间法线渲染模型,然后对该图像使用 Canny 边缘检测(经过一些过滤),最后反转以获得轮廓图像。然后将该轮廓图像与场景的常规(“漫反射”)渲染相乘。
然而,在这个例子中,为了实现两种渲染(一种用于边缘,一种用于漫反射图像),作者复制了主要几何图形并在两个不同的场景中创建了两个网格,以便分别应用两种不同的材质(一种用于仅基于法线进行渲染,以及使用 Gooch 着色进行渲染)。这种方法在我的应用程序中并不是很有吸引力,因为几何图形非常大并且动态更新。没关系,我想我只需要使用 aoverrideMaterial
来RenderPass
绘制所有带有 a 的对象NormalShader
(如下)。不幸的是,这不起作用,因为我的一些对象是THREE.Line
s 或其他任何东西并且没有正常属性,产生如下错误:
WebGL: INVALID_OPERATION: vertexAttribPointer: no bound ARRAY_BUFFER three.js:21636
WebGL: INVALID_OPERATION: drawArrays: attribute 1 is enabled but has no buffer bound three.js:21748
WebGL: INVALID_OPERATION: vertexAttribPointer: no bound ARRAY_BUFFER three.js:21636
2[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1 dev.html:1
[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 1
render
我尝试在每次调用之前使用这样的代码隐藏这些对象:
scene.traverse(function(obj) {
if ( !!obj && obj.geometry && obj.geometry.attributes && !obj.geometry.attributes.normal ) {
obj._visible = obj.visible;
obj.visible = false;
}
})
但我不断收到同样的错误,我不知道如何追踪导致它们的对象。
所以这是我的问题:是否有一种好方法可以过滤掉没有特定属性(例如法线)的对象,即使某些对象是Mesh
esGeometry
而不是BufferGeometry
?
谢谢你的帮助!
编辑:我已经删除了关于替代方法的内容,并在这里开始了一个单独的问题:使用自定义着色器渲染“硬”边缘
NormalShader的代码,供参考:
THREE.NormalShader = {
uniforms: {
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"vNormal = normalize(normal);",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"varying vec3 vNormal;",
"void main(void) {",
"gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, 1.0 );",
"}"
].join("\n")
};