Image Editor - THREEJS

In this example below you will see how to do a Image Editor - THREEJS with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by jsosas, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright jsosas ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Image Editor - THREEJS</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div id="container"></div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenMax.min.js'></script>
<script src='https://threejs.org/examples/js/postprocessing/EffectComposer.js'></script>
<script src='https://threejs.org/examples/js/postprocessing/ShaderPass.js'></script>
<script src='https://threejs.org/examples/js/postprocessing/BloomPass.js'></script>
<script src='https://threejs.org/examples/js/shaders/CopyShader.js'></script>
<script src='https://threejs.org/examples/js/shaders/ConvolutionShader.js'></script>
<script src='https://threejs.org/examples/js/postprocessing/RenderPass.js'></script>
<script src='https://threejs.org/examples/js/postprocessing/ClearPass.js'></script>
<script src='https://threejs.org/examples/js/postprocessing/MaskPass.js'></script>

  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/jsosas/image-editor-threejs-JKAqEK */
body {
  background-color: red;
  margin: 0px;
  overflow: hidden;
}


/*Downloaded from https://www.codeseek.co/jsosas/image-editor-threejs-JKAqEK */
var container;
var scene;
var camera;
var renderer;
var plane;

var myPass, sharpenPass;

var composer;

var width = window.innerWidth || 2;
var height = window.innerHeight || 2;

THREE.MyShader = {
  uniforms : {
    "tDiffuse": 	{ type: "t", value: 0, texture: null },
    "brillo": { type: "f", value: 0.0 }
  },
  
  vertexShader: 
   "varying vec2 vUv;" +
    "void main() {" +
				"vUv = vec2( uv.x, uv.y );" +
				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );" +
    "}"
  ,
		
  fragmentShader:
		"uniform sampler2D tDiffuse;" +
		"uniform float brillo;" +
    "varying vec2 vUv;" +
		
		"void main() {" +
			"vec4 color = texture2D( tDiffuse, vUv );" +
      
      "color.r = color.r + brillo;" +
      "color.g = color.g + brillo;" +
      "color.b = color.b + brillo;" +
  
			"gl_FragColor = color;" +
		"}"
	};

THREE.SharpenShader = {
  uniforms : {
    "tDiffuse": 	{ type: "t", value: 0, texture: null },
    "radius": 	{ type: "v2", value: new THREE.Vector2( 0.0, 0.0 )  },
    "strength": { type: "f", value: 0.0 }
  },
  
  vertexShader: 
   "varying vec2 vUv;" +
    "void main() {" +
				"vUv = vec2( uv.x, uv.y );" +
				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );" +
    "}"
  ,
		
  fragmentShader: [
		"#define ITERATIONS 4.0",
		"uniform sampler2D tDiffuse;",
		"uniform vec2 radius;",
    "uniform float strength;",
		"varying vec2 vUv;",
  
		"float random( vec3 scale, float seed ) { ",
			// use the fragment position for a different seed per-pixel
			"return fract( sin( dot( gl_FragCoord.xyz + seed, scale ) ) * 43758.5453 + seed );",
		"}",

		"void main() {",
      "vec4 original = texture2D(tDiffuse, vUv);",
			"vec4 colorBlurred = vec4( 0.0 );",
			"float total = 0.0;",
			
			// randomize the lookup values to hide the fixed number of samples
			"float offset = random( vec3( 12.9898, 78.233, 151.7182 ), 0.0 );",
			
			"for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {",
    
				"float percent = ( t + offset - 0.5 ) / ITERATIONS;",
				"float weight = 1.0 - abs( percent );",

				"colorBlurred += texture2D( tDiffuse, vUv + radius * percent ) * weight;",
				"total += weight;",
    
			"}",
      
      "colorBlurred = colorBlurred / total;",
    
			"gl_FragColor = mix(colorBlurred, original, 1.0 + strength);",
    
		"}"
    ].join("\n")
};

function calcTextureOffsets(width, height, size){

  var deltaX = 1.0/width,
      deltaY = 1.0/height,
      distance = Math.floor(size/2),
      offsets = [],
      i,j;

  for(i = -distance; i <= distance; i++){
    for(j = -distance; j <= distance; j++){
      offsets.push(new THREE.Vector2(  i*deltaX,  j*deltaY ));
    }
  }
  return offsets;
}

function init() {
  
  // ----------------------------------------------------
  // DOM ELEMENT 
  
  container = document.getElementById( 'container' );
  
  
  // ----------------------------------------------------
  // RENDERER
  
  renderer = new THREE.WebGLRenderer( {
      antialias: false, alpha: true
    });
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( width, height );
  
  container.appendChild( renderer.domElement );
  
  
  
  // ----------------------------------------------------
  // SCENE
  
  scene = new THREE.Scene();
  
  
  // ----------------------------------------------------
  // CAMERAS
  
  camera = new THREE.OrthographicCamera(
     width/-2, width/2, height/2, height/-2, 1, 2000
    );
  
  // 1 ~ 100
  // -180 ~ 180
  
  camera.position.z = 10;
  //camera.rotation.z = 45 * Math.PI / 180;
  camera.zoom = 1;
  camera.updateProjectionMatrix();
//  camera.angle
  
  // PLANO ·····················
  
  var textureLoader = new THREE.TextureLoader();
  textureLoader.setCrossOrigin("Anonymous");
  
  plane = new THREE.Mesh(
    new THREE.PlaneBufferGeometry( 1, 1 ),
    new THREE.MeshBasicMaterial({
      map:  textureLoader.load( "https://threejs.org/examples/textures/cube/SwedishRoyalCastle/pz.jpg"
          ),
      depthTest: false
    })
  );
  
  //plane.position.z = -500;
  // aspectRatio =  imageWidth / imageHeight
  var aspectRatio = 2;
  plane.scale.set( aspectRatio * height, height, 1 );
  
  scene.add( plane );
  
  
  // ----------------------------------------------------
  // POST-PROCESSING
 
  var renderTargetParams = {
    minFilter: THREE.LinearFilter,
    magFilter: THREE.LinearFilter,
    format: THREE.RGBAFormat,
    stencilBuffer: false
  };
  
  composer = new THREE.EffectComposer(
      renderer, new THREE.WebGLRenderTarget( width, height, renderTargetParams )
    );
  
  
  var inputPass = new THREE.RenderPass( scene, camera );
  
  myPass = new THREE.ShaderPass( THREE.MyShader );
  myPass.uniforms["brillo"].value = 0.0;
  
  sharpenPass = new THREE.ShaderPass( THREE.SharpenShader );
  sharpenPass.uniforms["radius"].value = new THREE.Vector2(
    0.5 / (width),
    0.5 / (height)
  );
  sharpenPass.uniforms["strength"].value = 0.0;
  
  var outputPass = new THREE.ShaderPass(THREE.CopyShader);
  outputPass.renderToScreen = true;
  
  composer.addPass(inputPass);
  composer.addPass(myPass);
  composer.addPass(sharpenPass);
  composer.addPass(outputPass);
  
}

function animate() {
  //requestAnimationFrame(animate);
  setTimeout(function(){
    render();
    
    muevePlano();
    
  }, 1000);
}

function muevePlano() {
  var obj = { initX: plane.position.x, brillo: 0.01, enfoque: 0.0};
  
  TweenMax.to(obj, 2, { initX: 100, brillo: 0.1, enfoque: 60.0, yoyo: true, repeat: -1,
    onUpdate: function(){
      //plane.position.x = obj.initX;
      //myPass.uniforms["brillo"].value = obj.brillo;
      sharpenPass.uniforms["strength"].value = obj.enfoque;
      render();
    }
  });
}

function render() {  
  //renderer.render(scene, camera);
  composer.render();
}

init();
animate();

Comments