Search code examples
glslshader

GLSL Line Pattern — Changing Colors


I am trying to change the colours at the pen below to black and white. I am having trouble finding the right values. Can someone help me in finding the solution?

CodePen Link

Here is the part of the html that I believe should be changed (I might be wrong though):

float noiseHue = noise(vec3(randIndexHue, randIndexHue, time));
float hue = mix(0.111, 0.138, randIndexHue + (noiseHue * 0.5));
vec4 grain = addGrain(ouv, time, 0.15);
vec3 color = HSLToRGB(vec3(hue, 1.0, 0.5));
vec3 bgColor = HSLToRGB(vec3(0.772, mix(0.75, 1.0, mouseDistance), mix(0.1, 0.25, mouseDistance)));
float val = dline * (mouseDistance * 0.5 + 0.5);

Solution

  • Black is RGB(0, 0, 0) and white is RGB(1, 1, 1). All you have to do is to set color = vec3(1.0) and bgColor = vec3(0.0) (instead of HSLToRGB):

    vec3 color = vec3(1.0);
    vec3 bgColor = vec3(0.0);
    
    float val = dline * (mouseDistance * 0.5 + 0.5);
    vec3 albedo = mix(bgColor, color, val);
    gl_FragColor = vec4(albedo, 1.0) + grain;
    

    See the example:

    //Create var for the contenair, the webGL 3D scene, uniforms to bind into shader and timer
    
    var container;
    var camera, scene, renderer;
    var uniforms;
    var startTime;
    
    
    var cols = 50.;
    var rows  = 50.0;
    
    init(); //init scene
    animate(); //updateScene
    
    function init() {
    	//get contenaire
    	container = document.getElementById('container');
    	
    	//Create THREE.JS scene and timer
    	startTime = Date.now();
    	camera = new THREE.Camera();
    	camera.position.z = 1;
    	scene = new THREE.Scene();
    	
    	//create a simple plance
    	var geometry = new THREE.PlaneBufferGeometry(16, 9);
    	
    	//create uniform table which provide all our GLSL binding
    	uniforms = {
    		time: { type: "f", value: 1.0 },
    		resolution: { type: "v2", value: new THREE.Vector2() },
    		colsrows: {type: "v2", value: new THREE.Vector2()},
    		mouse: {type: "v2", value: new THREE.Vector2()}
    	};
    	
    	//create THREE.JS material
    	var material = new THREE.ShaderMaterial( {
    	//set shaders and uniforms into material
    		uniforms: uniforms,
    		vertexShader: document.getElementById('vertexShader').textContent,
    		fragmentShader: document.getElementById('fragmentShader').textContent
    	} );
    
    	//create mesh, add it to the scene
    	var mesh = new THREE.Mesh(geometry, material);
    	scene.add(mesh);
    	
    	//create renderer and add it to the DOM
    	renderer = new THREE.WebGLRenderer();
    	container.appendChild(renderer.domElement);
    	
    	//check window for resize This will give us the proper resolution values to bind
    	onWindowResize();
    	window.addEventListener('resize', onWindowResize, false);
    	
    }
    
    function onWindowResize(event) {
    	container.style.height = window.innerHeight+"px";
    	container.style.width = window.innerWidth+"px";
    	
    	canvasWidth = container.offsetWidth;
    	canvasHeight = container.offsetHeight;
    	//send new size value to the shader and resize the window
    	uniforms.resolution.value.x = canvasWidth;
    	uniforms.resolution.value.y = canvasHeight;
    	
    	//var res = canvasWidth / cols;
    	//rows = canvasHeight / res;
    	uniforms.colsrows.value.x = cols;
    	uniforms.colsrows.value.y = rows;//rows;
    	
    	renderer.setSize(canvasWidth, canvasHeight);
    }
    
    function animate() {
    	render();
    	requestAnimationFrame(animate);
    }
    
    function render() {
    	var currentTime = Date.now();
    	var elaspedSeconds =  (currentTime - startTime) / 1000.0;
    	var maxTime = 4.0;
    	var normTime = (elaspedSeconds % maxTime) / maxTime;
    	uniforms.time.value = elaspedSeconds * 1.0;
    
    	renderer.render(scene, camera);
    }
    
    
    function move(ev){
     	mx = ev.clientX
      	my = ev.clientY;
    	// console.log(mx+" , "+my);
    	
    	uniforms.mouse.value.x = mx;
    	uniforms.mouse.value.y = my;
    }
    
    document.addEventListener('mousemove', move)
    html, body {
      margin: 0;
      height: 100%;
      background : #1a1a1a;
    }
    
    canvas {
      display: block;
      cursor: none;
    }
    
    #container{
    	background : black;
    	color : white;
      	margin: auto;
    	width : 500px;
    	height : 500px;
    }
    <script src="https://threejs.org/build/three.min.js"></script>
    <!--script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script-->
    
    <div id="container"></div>	
    
    <!-- GLSL SCRIPT -->
    <!-- vertex shader -->
    <script id="vertexShader" type="x-shader/x-vertex">
    	void main() {
    		gl_Position = vec4(position, 1.0);
    	}
    </script>
    
    <!-- fragment shader -->
    <script id="fragmentShader" type="x-shader/x-fragment">
    		#define TWO_PI 6.28318530718
    		#define EPSILON 0.000011
    		uniform vec2 resolution;
    		uniform float time;
    		uniform vec2 colsrows;
    		uniform vec2 mouse;
    	
    		float HueToRGB(float f1, float f2, float hue)
    		{
    			if (hue < 0.0)
    				hue += 1.0;
    			else if (hue > 1.0)
    				hue -= 1.0;
    			float res;
    			if ((6.0 * hue) < 1.0)
    				res = f1 + (f2 - f1) * 6.0 * hue;
    			else if ((2.0 * hue) < 1.0)
    				res = f2;
    			else if ((3.0 * hue) < 2.0)
    				res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
    			else
    				res = f1;
    			return res;
    		}
    
    
    		vec3 HSLToRGB(vec3 hsl)
    		{
    			vec3 rgb;
    
    			if (hsl.y == 0.0)
    				rgb = vec3(hsl.z); // Luminance
    			else
    			{
    				float f2;
    
    				if (hsl.z < 0.5)
    					f2 = hsl.z * (1.0 + hsl.y);
    				else
    					f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);
    
    				float f1 = 2.0 * hsl.z - f2;
    
    				rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));
    				rgb.g = HueToRGB(f1, f2, hsl.x);
    				rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));
    			}
    
    			return rgb;
    		}
    	
    		mat2 rotate2d(float _angle){
    			return mat2(cos(_angle),-sin(_angle),
    						sin(_angle),cos(_angle));
    		}
    		
    		vec2 rotateFrom(vec2 uv, vec2 center, float angle){
    			vec2 uv_ = uv - center;
    			uv_ =  rotate2d(angle) * uv_;
    			uv_ = uv_ + center;
    
    			return uv_;
    		}
    		
    		float random(float value){
    			return fract(sin(value) * 43758.5453123);
    		}
    		
    		float random(vec2 tex){
    			return fract(sin(dot(tex.xy, vec2(12.9898, 78.233))) * 43758.5453123);
    		}
    		
    		vec2 random2D(vec2 uv){
    			uv = vec2(dot(uv, vec2(127.1, 311.7)), dot(uv, vec2(269.5, 183.3)));
    			//return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
    			return fract(sin(uv) * 43758.5453123); //return without offset on x, y
    		}
    
    		vec3 random3D(vec3 uv){
    			uv = vec3(dot(uv, vec3(127.1, 311.7, 120.9898)), dot(uv, vec3(269.5, 183.3, 150.457)), dot(uv, vec3(380.5, 182.3, 170.457)));
    			return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
    		}
    	
    		float cubicCurve(float value){
    			return value * value * (3.0 - 2.0 * value); // custom cubic curve
    		}
    
    		vec2 cubicCurve(vec2 value){
    			return value * value * (3.0 - 2.0 * value); // custom cubic curve
    		}
    
    		vec3 cubicCurve(vec3 value){
    			return value * value * (3.0 - 2.0 * value); // custom cubic curve
    		}
    
    		float noise(vec2 uv){
    			vec2 iuv = floor(uv);
    			vec2 fuv = fract(uv);
    			vec2 suv = cubicCurve(fuv);
    
    			float dotAA_ = dot(random2D(iuv + vec2(0.0)), fuv - vec2(0.0));
    			float dotBB_ = dot(random2D(iuv + vec2(1.0, 0.0)), fuv - vec2(1.0, 0.0));
    			float dotCC_ = dot(random2D(iuv + vec2(0.0, 1.0)), fuv - vec2(0.0, 1.0));
    			float dotDD_ = dot(random2D(iuv + vec2(1.0, 1.0)), fuv - vec2(1.0, 1.0));
    
    			return mix(
    				mix(dotAA_, dotBB_,	suv.x),
    				mix(dotCC_, dotDD_, suv.x),
    				suv.y);
    		}
    
    		float noise(vec3 uv){
    			vec3 iuv = floor(uv);
    			vec3 fuv = fract(uv);
    			vec3 suv = cubicCurve(fuv);
    
    			float dotAA_ = dot(random3D(iuv + vec3(0.0)), fuv - vec3(0.0));
    			float dotBB_ = dot(random3D(iuv + vec3(1.0, 0.0, 0.0)), fuv - vec3(1.0, 0.0, 0.0));
    			float dotCC_ = dot(random3D(iuv + vec3(0.0, 1.0, 0.0)), fuv - vec3(0.0, 1.0, 0.0));
    			float dotDD_ = dot(random3D(iuv + vec3(1.0, 1.0, 0.0)), fuv - vec3(1.0, 1.0, 0.0));
    
    			float dotEE_ = dot(random3D(iuv + vec3(0.0, 0.0, 1.0)), fuv - vec3(0.0, 0.0, 1.0));
    			float dotFF_ = dot(random3D(iuv + vec3(1.0, 0.0, 1.0)), fuv - vec3(1.0, 0.0, 1.0));
    			float dotGG_ = dot(random3D(iuv + vec3(0.0, 1.0, 1.0)), fuv - vec3(0.0, 1.0, 1.0));
    			float dotHH_ = dot(random3D(iuv + vec3(1.0, 1.0, 1.0)), fuv - vec3(1.0, 1.0, 1.0));
    
    			float passH0 = mix(
    				mix(dotAA_, dotBB_,	suv.x),
    				mix(dotCC_, dotDD_, suv.x),
    				suv.y);
    
    			float passH1 = mix(
    				mix(dotEE_, dotFF_,	suv.x),
    				mix(dotGG_, dotHH_, suv.x),
    				suv.y);
    
    			return mix(passH0, passH1, suv.z);
    		}
    	
    		float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
    		{
    			//from https://www.shadertoy.com/view/MtlSDr
    			vec2 l = p2 - p1;
    			float L = length(l);
    			float L2 = L*L;
    
    			float d1 = length(uv - p1);
    			float d2 = length(uv - p2);
    			float d  = min(d1, d2);
    			float ds = dot(uv - p1, l);
    			if (ds >= 0.0 && ds <= L2)
    			{
    				vec2 n = vec2(-l.y, l.x) / L;
    				d = min(d, abs(dot(uv - p1, n)));
    			}
    
    			return 1.0 - smoothstep(0.0, 0.01, d - r);
    		}
    	
    		vec2 fishey(vec2 uv, vec2 center, float ratio, float dist){
    			  vec2 puv = uv + vec2(1.0);
    			 //center coords
    			  vec2 m = vec2(center.x, center.y/ratio) + vec2(1.0);
    			  //vector from center to current fragment
    			  vec2 d = puv - m;
    			  // distance of pixel from center
    			  float r = sqrt(dot(d, d)); 
    			  //amount of effect
    			  float power = ( TWO_PI / (2.0 * sqrt(dot(m, m)))) * mix(0.1, 0.4, pow(dist, 0.75));
    			  //radius of 1:1 effect
    			  float bind;
    			  if (power > 0.0) bind = sqrt(dot(m, m));//stick to corners
    			  //else {if (ratio < 1.0) bind = m.x; else bind = m.y;}//stick to borders
    
    			  //Weird formulas
    			  vec2 nuv;
    			  if (power > 0.0)//fisheye
    				nuv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
    			  else if (power < 0.0)//antifisheye
    			   nuv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
    			  else 
    				nuv = puv;//no effect for power = 1.0
    
    			return nuv - vec2(1.0);
    		}
    	
    		vec4 addGrain(vec2 uv, float time, float grainIntensity){
        		float grain = random(fract(uv * time)) * grainIntensity;
        		return vec4(vec3(grain), 1.0);
    		}
    		
    		void main(){
    			vec2 ouv = gl_FragCoord.xy / resolution.xy;
    			vec2 uv = ouv;
    			
    			float ratio = resolution.x / resolution.y;
    			vec2 nmouse = vec2(mouse.x, mouse.y) / resolution.xy;
    			nmouse.y = 1.0 - nmouse.y;
    			float maxDist = 0.35;
    			float blurEdge = maxDist * 0.5;
    			float blurEdge2 = maxDist * 1.0;
    			vec2 mouseToUV = (uv - nmouse) / vec2(1.0, ratio);
    			float mouseDistance = 1.0 - smoothstep(maxDist - blurEdge, maxDist, length(mouseToUV));
    			float mouseDistance2 = 1.0 - smoothstep(maxDist - blurEdge2, maxDist, length(mouseToUV));
    			
    			
    			uv = fishey(uv, nmouse, ratio,  mouseDistance2);
    			uv = rotateFrom(uv, vec2(0.5), time * 0.1);
    			//animate y
    			//wave
    			uv.y /= ratio;
    			vec2 basedUV = uv + vec2(1.0);
    			float complexityX = 10.0;
    			float complexityY = 10.0;
    			float maxAmp = mix(0.05, 0.75, mouseDistance);
    			float amp = 0.01 * mouseDistance + noise(vec3(basedUV.x * complexityX, basedUV.y * complexityY, time * 0.1)) * maxAmp;
    			float theta = time + mouseDistance + basedUV.y * (TWO_PI);
    			uv.x = fract(uv.x + sin(theta) * amp);
    			//divide into cols rows
    			vec2 nuv = uv * colsrows;
    			vec2 fuv = fract(nuv);
    			vec2 iuv = floor(nuv);
    			
    			float minSpeed = 1.0;
    			float maxSpeed = 5.0;
    			float speed = minSpeed + random(floor(uv.x * colsrows.x)) * (maxSpeed - minSpeed);
    			fuv.y = fract(fuv.y + time * speed);
    			
    			//draw dash line
    			float minWeight = 0.005 + random(vec2(iuv.x, 0.0)) * 0.05;
    			float strokeWeight = mix(minWeight, minWeight * 5.0, mouseDistance);
    			float dlineWidth = mix(1.0, 0.25 - strokeWeight, mouseDistance);//0.5 - strokeWeight;
    			float dline = drawLine(fuv, vec2(0.5, 0.5 - dlineWidth * 0.5), vec2(0.5, 0.5 + dlineWidth * 0.5), strokeWeight);
    			
    			float randIndexHue = random(vec2(iuv.x + floor(time), 0.0));
    			float noiseHue = noise(vec3(randIndexHue, randIndexHue, time));
    			float hue = mix(0.111, 0.138, randIndexHue + (noiseHue * 0.5));
    			vec4 grain = addGrain(ouv, time, 0.15);
    			//vec3 color = HSLToRGB(vec3(hue, 1.0, 0.5));
    			//vec3 bgColor = HSLToRGB(vec3(0.772, mix(0.75, 1.0, mouseDistance), mix(0.1, 0.25, mouseDistance)));
          vec3 color = vec3(1.0);
    			vec3 bgColor = vec3(0.0);
    			float val = dline * (mouseDistance * 0.5 + 0.5);
    			
    			vec3 albedo = mix(bgColor, color, val);
    			
    			gl_FragColor = vec4(albedo, 1.0) + grain;
    		}
    </script>