提交 bc7c499e 编写于 作者: M Mr.doob 提交者: GitHub

Merge pull request #11932 from Mugen87/sobel

Examples: Added Sobel Edge Detection
......@@ -214,6 +214,7 @@ var files = {
"webgl_postprocessing_crossfade",
"webgl_postprocessing_dof",
"webgl_postprocessing_dof2",
"webgl_postprocessing_edgedetection",
"webgl_postprocessing_glitch",
"webgl_postprocessing_godrays",
"webgl_postprocessing_masking",
......
/**
* @author zz85 / https://github.com/zz85 | https://www.lab4games.net/zz85/blog
*
* Edge Detection Shader using Sobel filter
* Based on http://rastergrid.com/blog/2011/01/frei-chen-edge-detector
*
* aspect: vec2 of (1/width, 1/height)
*/
THREE.EdgeShader2 = {
uniforms: {
"tDiffuse": { value: null },
"aspect": { value: new THREE.Vector2( 512, 512 ) }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform sampler2D tDiffuse;",
"varying vec2 vUv;",
"uniform vec2 aspect;",
"vec2 texel = vec2(1.0 / aspect.x, 1.0 / aspect.y);",
"mat3 G[2];",
"const mat3 g0 = mat3( 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0 );",
"const mat3 g1 = mat3( 1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0 );",
"void main(void)",
"{",
"mat3 I;",
"float cnv[2];",
"vec3 sample;",
"G[0] = g0;",
"G[1] = g1;",
/* fetch the 3x3 neighbourhood and use the RGB vector's length as intensity value */
"for (float i=0.0; i<3.0; i++)",
"for (float j=0.0; j<3.0; j++) {",
"sample = texture2D( tDiffuse, vUv + texel * vec2(i-1.0,j-1.0) ).rgb;",
"I[int(i)][int(j)] = length(sample);",
"}",
/* calculate the convolution values for all the masks */
"for (int i=0; i<2; i++) {",
"float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]);",
"cnv[i] = dp3 * dp3; ",
"}",
"gl_FragColor = vec4(0.5 * sqrt(cnv[0]*cnv[0]+cnv[1]*cnv[1]));",
"} "
].join( "\n" )
};
......@@ -7,7 +7,7 @@
* aspect: vec2 of (1/width, 1/height)
*/
THREE.EdgeShader = {
THREE.FreiChenShader = {
uniforms: {
......
/**
* @author Mugen87 / https://github.com/Mugen87
*
* Sobel Edge Detection (see https://youtu.be/uihBwtPIBxM)
*
* As mentioned in the video the Sobel operator expects a grayscale image as input.
*
*/
THREE.SobelOperatorShader = {
uniforms: {
"tDiffuse": { value: null },
"resolution": { value: new THREE.Vector2() }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform sampler2D tDiffuse;",
"uniform vec2 resolution;",
"varying vec2 vUv;",
"void main() {",
"vec2 texel = vec2( 1.0 / resolution.x, 1.0 / resolution.y );",
// kernel definition (in glsl matrices are filled in column-major order)
"const mat3 Gx = mat3( -1, -2, -1, 0, 0, 0, 1, 2, 1 );", // x direction kernel
"const mat3 Gy = mat3( -1, 0, 1, -2, 0, 2, -1, 0, 1 );", // y direction kernel
// fetch the 3x3 neighbourhood of a fragment
// first column
"float tx0y0 = texture2D( tDiffuse, vUv + texel * vec2( -1, -1 ) ).r;",
"float tx0y1 = texture2D( tDiffuse, vUv + texel * vec2( -1, 0 ) ).r;",
"float tx0y2 = texture2D( tDiffuse, vUv + texel * vec2( -1, 1 ) ).r;",
// second column
"float tx1y0 = texture2D( tDiffuse, vUv + texel * vec2( 0, -1 ) ).r;",
"float tx1y1 = texture2D( tDiffuse, vUv + texel * vec2( 0, 0 ) ).r;",
"float tx1y2 = texture2D( tDiffuse, vUv + texel * vec2( 0, 1 ) ).r;",
// third column
"float tx2y0 = texture2D( tDiffuse, vUv + texel * vec2( 1, -1 ) ).r;",
"float tx2y1 = texture2D( tDiffuse, vUv + texel * vec2( 1, 0 ) ).r;",
"float tx2y2 = texture2D( tDiffuse, vUv + texel * vec2( 1, 1 ) ).r;",
// gradient value in x direction
"float valueGx = Gx[0][0] * tx0y0 + Gx[1][0] * tx1y0 + Gx[2][0] * tx2y0 + ",
"Gx[0][1] * tx0y1 + Gx[1][1] * tx1y1 + Gx[2][1] * tx2y1 + ",
"Gx[0][2] * tx0y2 + Gx[1][2] * tx1y2 + Gx[2][2] * tx2y2; ",
// gradient value in y direction
"float valueGy = Gy[0][0] * tx0y0 + Gy[1][0] * tx1y0 + Gy[2][0] * tx2y0 + ",
"Gy[0][1] * tx0y1 + Gy[1][1] * tx1y1 + Gy[2][1] * tx2y1 + ",
"Gy[0][2] * tx0y2 + Gy[1][2] * tx1y2 + Gy[2][2] * tx2y2; ",
// magnitute of the total gradient
"float G = sqrt( ( valueGx * valueGx ) + ( valueGy * valueGy ) );",
"gl_FragColor = vec4( vec3( G ), 1 );",
"}"
].join( "\n" )
};
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - postprocessing - edge detection (Sobel)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background:#777;
padding:0;
margin:0;
font-weight: bold;
overflow:hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
}
a {
color: #ffffff;
}
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/LuminosityShader.js"></script>
<script src="js/shaders/SobelOperatorShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<div id="info">
<a href="https://threejs.org" target="_blank">three.js</a> - webgl - postprocessing - edge detection (Sobel)
</div>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer, composer;
var effectSobel;
var params = {
enable: true
};
init();
animate();
function init() {
//
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 10, 20 );
camera.lookAt( scene.position );
//
var geometry = new THREE.IcosahedronGeometry( 8 );
var material = new THREE.MeshPhongMaterial( { color: 0xffff00 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
//
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
scene.add( ambientLight );
var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( pointLight );
scene.add( camera );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// postprocessing
composer = new THREE.EffectComposer( renderer );
var renderPass = new THREE.RenderPass( scene, camera );
composer.addPass( renderPass );
// color to grayscale conversion
var effectGrayScale = new THREE.ShaderPass( THREE.LuminosityShader );
composer.addPass( effectGrayScale );
// you might want to use a gaussian blur filter before
// the next pass to improve the result of the Sobel operator
// Sobel operator
effectSobel = new THREE.ShaderPass( THREE.SobelOperatorShader );
effectSobel.renderToScreen = true;
effectSobel.uniforms.resolution.value.x = window.innerWidth;
effectSobel.uniforms.resolution.value.y = window.innerHeight;
composer.addPass( effectSobel );
var controls = new THREE.OrbitControls( camera );
//
var gui = new dat.GUI();
gui.add( params, 'enable' );
gui.open();
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
composer.setSize( window.innerWidth, window.innerHeight );
effectSobel.uniforms.resolution.value.x = window.innerWidth;
effectSobel.uniforms.resolution.value.y = window.innerHeight;
}
function animate() {
requestAnimationFrame( animate );
if ( params.enable === true ) {
composer.render();
} else {
renderer.render( scene, camera );
}
}
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册