Three.js 使用自定义着色器的NPR边缘检测
我尝试在着色器中实现边缘检测,以在Three.js中实现非照片级真实感的“轮廓”效果,方法如下:。我主要对深色轮廓感兴趣,而不是古奇阴影。我理解这段代码中采用的方法,即首先使用对象空间法线渲染模型,然后对该图像使用Canny边缘检测(经过一些过滤),最后反转以获得轮廓图像。然后,该轮廓图像与场景的常规(“漫反射”)渲染相乘 但是,在本例中,为了实现两种渲染(一种用于边缘,另一种用于漫反射图像),作者复制了主几何体并在两个不同场景中创建了两个网格,以便分别应用两种不同的材质(一种仅基于法线渲染,另一种使用Gooch着色渲染)。这种方法在我的应用程序中并没有太大的吸引力,因为几何体非常大,并且是动态更新的。不管怎样,我想我应该在Three.js 使用自定义着色器的NPR边缘检测,three.js,shader,edge-detection,npr,Three.js,Shader,Edge Detection,Npr,我尝试在着色器中实现边缘检测,以在Three.js中实现非照片级真实感的“轮廓”效果,方法如下:。我主要对深色轮廓感兴趣,而不是古奇阴影。我理解这段代码中采用的方法,即首先使用对象空间法线渲染模型,然后对该图像使用Canny边缘检测(经过一些过滤),最后反转以获得轮廓图像。然后,该轮廓图像与场景的常规(“漫反射”)渲染相乘 但是,在本例中,为了实现两种渲染(一种用于边缘,另一种用于漫反射图像),作者复制了主几何体并在两个不同场景中创建了两个网格,以便分别应用两种不同的材质(一种仅基于法线渲染,另
RenderPass
上使用overrideMatary
来绘制所有具有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;
}
})
但我总是会遇到同样的错误,我不知道如何追踪导致这些错误的对象
因此,我的问题是:是否有一种很好的方法可以过滤掉没有特定属性的对象(例如法线),即使其中一些对象是网格而不是缓冲几何体?
谢谢你的帮助
编辑:我已经删除了关于替代方法的部分,并在这里开始了一个单独的问题:
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")
};