WebGL-如何获取纹理的法线数据以进行post-边缘检测处理
WebGL-How to get the normals data of the texture for post-processing of edge detection
在寻找WebGL边缘检测方法的时候,
我看到Unity有一个解决方案。使用 Camera-DepthNormalTexture.shader 将深度和法线数据写入纹理。
我会用Roberts算子来计算得到的数据是否是边,
但是 WebGL 我只能在帧缓冲区中获取 depthTexture,
无法像 unity 一样获得 depthNormalTexture,
我尝试用 WebGL 编写测试,
只使用framebuffer中获取的depthtexture,
但只检测具有巨大深度差异的边缘,
并且无法检测到纯色模型的所有边缘。
我想知道是否有其他方法可以解决此类问题。
(solid color)WebGL test rendering pic
我提前设置好顶点的法线数据
使用gman的回答中提供的着色器,在新的渲染中获取framebuffer中法线数据的纹理。结果好像画了边,但是深度好像不对
framebuffer = gl.createFramebuffer();
// rgb texture
gl.bindTexture(state.gl.TEXTURE_2D, texture);
// ... texImage2D texParameteri set up
// depth texture
gl.bindTexture(state.gl.TEXTURE_2D, depthTexture);
// ... texImage2D texParameteri set up
// Create a with normals data FBO
normalFramebuffer = gl.createFramebuffer();
gl.bindTexture(gl.TEXTURE_2D, normalTexture);
// ... texImage2D texParameteri set up
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
obj.render('rgbaData shader');
gl.bindFramebuffer(gl.FRAMEBUFFER, normalFramebuffer);
obj.render('normalsData shader');
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.useProgram('my edge detection shader');
gl.uniform1i(texture, 0);
gl.uniform1i(depthTexture, 1);
gl.uniform1i(normalTexture, 2);
我的边缘检测着色器
uniform sampler2D texture;
uniform sampler2D depthTexture;
uniform sampler2D normalTexture;
new render edge pic with depth and normals data
"WebGL’s You can only get depthTexture in framebuffer, you can not get depthNormalTexture [...]"
支持深度纹理WebGL 2.0 or by the extension WEBGL_depth_texture。评估是否支持扩展:
if (!gl.getExtension("WEBGL_depth_texture"))
alert('"WEBGL_depth_texture" not supported');
Unity 即使在 WebGL 中也会生成带有法线的纹理,因此这不是 WebGL 的限制。如果你想要一个带有法线的纹理,那么渲染一个带有法线的纹理。
假设你有带法线的几何数据,那么你会使用类似于
的顶点着色器
attribute vec4 position;
attribute vec3 normal;
uniform mat4 projection;
uniform mat4 modelView;
uniform mat4 normalMatrix;
varying vec3 v_normal;
void main() {
gl_Position = projection * modelView * position;
v_normal = mat3(normalMatrix) * normal;
}
和像
这样的片段着色器
precision mediump float;
varying vec3 v_normal;
void main() {
gl_FragColor = vec4(normalize(v_normal) * 0.5 + 0.5, gl_FragCoord.z);
}
和render your shapes to a texture via a framebuffer。然后你有一个带有法线和深度的纹理,你可以将它传递给你的检查边缘着色器
您可以阅读更多关于法线着色器的信息here
在寻找WebGL边缘检测方法的时候,
我看到Unity有一个解决方案。使用 Camera-DepthNormalTexture.shader 将深度和法线数据写入纹理。
我会用Roberts算子来计算得到的数据是否是边,
但是 WebGL 我只能在帧缓冲区中获取 depthTexture,
无法像 unity 一样获得 depthNormalTexture,
我尝试用 WebGL 编写测试,
只使用framebuffer中获取的depthtexture,
但只检测具有巨大深度差异的边缘,
并且无法检测到纯色模型的所有边缘。
我想知道是否有其他方法可以解决此类问题。
(solid color)WebGL test rendering pic
我提前设置好顶点的法线数据
使用gman的回答中提供的着色器,在新的渲染中获取framebuffer中法线数据的纹理。结果好像画了边,但是深度好像不对
framebuffer = gl.createFramebuffer();
// rgb texture
gl.bindTexture(state.gl.TEXTURE_2D, texture);
// ... texImage2D texParameteri set up
// depth texture
gl.bindTexture(state.gl.TEXTURE_2D, depthTexture);
// ... texImage2D texParameteri set up
// Create a with normals data FBO
normalFramebuffer = gl.createFramebuffer();
gl.bindTexture(gl.TEXTURE_2D, normalTexture);
// ... texImage2D texParameteri set up
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
obj.render('rgbaData shader');
gl.bindFramebuffer(gl.FRAMEBUFFER, normalFramebuffer);
obj.render('normalsData shader');
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.useProgram('my edge detection shader');
gl.uniform1i(texture, 0);
gl.uniform1i(depthTexture, 1);
gl.uniform1i(normalTexture, 2);
我的边缘检测着色器
uniform sampler2D texture;
uniform sampler2D depthTexture;
uniform sampler2D normalTexture;
new render edge pic with depth and normals data
"WebGL’s You can only get depthTexture in framebuffer, you can not get depthNormalTexture [...]"
支持深度纹理WebGL 2.0 or by the extension WEBGL_depth_texture。评估是否支持扩展:
if (!gl.getExtension("WEBGL_depth_texture"))
alert('"WEBGL_depth_texture" not supported');
Unity 即使在 WebGL 中也会生成带有法线的纹理,因此这不是 WebGL 的限制。如果你想要一个带有法线的纹理,那么渲染一个带有法线的纹理。
假设你有带法线的几何数据,那么你会使用类似于
的顶点着色器attribute vec4 position;
attribute vec3 normal;
uniform mat4 projection;
uniform mat4 modelView;
uniform mat4 normalMatrix;
varying vec3 v_normal;
void main() {
gl_Position = projection * modelView * position;
v_normal = mat3(normalMatrix) * normal;
}
和像
这样的片段着色器precision mediump float;
varying vec3 v_normal;
void main() {
gl_FragColor = vec4(normalize(v_normal) * 0.5 + 0.5, gl_FragCoord.z);
}
和render your shapes to a texture via a framebuffer。然后你有一个带有法线和深度的纹理,你可以将它传递给你的检查边缘着色器
您可以阅读更多关于法线着色器的信息here