Three.js(GLSL)-画布调整大小

问题描述 投票:0回答:1

当窗口在the CodePen here处调整为较小尺寸时,我试图至少保留一些比例。当前,事实证明,很难在移动设备上看到线路和交互。您对此有解决方案吗?在基于窗口的调整大小上将缩放比例加倍也许是有意义的,但是我对如何实现它有点迷惑。

JS的负责部分:

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);
}

这是笔:

//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://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>
javascript three.js glsl shader
1个回答
1
投票

线的粗细在drawLine中计算,取决于smoothstep的参数:

smoothstep

将参数增加到edge1,以生成“较粗”的行(例如0.1):

float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
   // [...]

   return 1.0 - smoothstep(0.0, 0.01, d - r);
}

您可以为该行添加其他统一变量:

float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
    // [...]

    return 1.0 - smoothstep(0.0, 0.1, d - r);
}
uniform float thickness;

float drawLine(vec2 uv, vec2 p1, vec2 p2, float r)
{
    // [...]

    return 1.0 - smoothstep(0.0, thickness, d - r);
}
© www.soinside.com 2019 - 2024. All rights reserved.