swh:1:snp:e0709176be0f75f889c92d5bf3c708601dd371a5
Raw File
Tip revision: a26bd38e4abcbfd6bf58e9a5fa424d9ceb959960 authored by Sylvain Thery on 02 December 2022, 14:10:09 UTC
update README
Tip revision: a26bd38
micro_patterns.js
"use strict"

var prg_compute_compact = null;
var prg_compute_aniso_compact = null;

var prg_new_noise = null;
var prg_blur = null;
var prg_copy = null;
var prg_glob = null;
var prg_mean = null;
var prg_inputs = null;
var tex_n1 = null;
var tex_n2 = null;
var tex_nvnv = null;
var tex_nv_ani = null;
var tex_cm = null;
var object = null;			
var selected_shader = 0;
var rot_speed = 0;
var filtering_sel=0;
const par_filtering=[gl.NEAREST,gl.LINEAR,gl.NEAREST_MIPMAP_NEAREST,gl.LINEAR_MIPMAP_NEAREST,gl.LINEAR_MIPMAP_LINEAR];


var sc = 4.0;
var tr = [0.0,0.0];
var dtr = [0.0,0.0];
var aniso = 1.0;

var show_inputs=true;

var config = [
	["stone","noise_pierre_1", "noise_pierre_2","cm11"],
	["bark","noise_ecorce_1", "noise_ecorce_2","cm10"],
	["camouflage","noise_1024_2", "noise_1024_4","cm1"],
	["green","noise_1024_4", "noise_1024_2","cm2"],
	["blue","noise_256_2", "noise_256_4","cm5"],
	["lava","noise_1024_2", "noise_1024_4","cm8"],
	["water","n1", "n2","eau_cm"],
	["hexa","n1", "n2","hexa_cm"],
	["phasor_sand","noise_sin_3","noise_cos_3", "colormap_phasor_sand"],
	["phasor_sin","noise_sin_1","noise_cos_1", "colormap_phasor_sin"],
	["phasor_square","noise_sin_1","noise_cos_1", "colormap_phasor_square"],
];

var config_names=[]



var tcolormap = null;
var render_out = 0;

const StorageTexFormat = [gl.RGBA32F, gl.RGBA16F, gl.RGBA8];
var indStorFilter=2;
var indNoiseFilter=2;
var indCMFilter=2;
var NB_CM=7;


var last_time=0;;
var alphaZ=0;

var canvas_ratio = 1.0;

function precompute_blur(cm_tex_img, cm_tex_array)
{
	let widthCM = NB_CM;
	let width = cm_tex_img.width;
	tex_cm.alloc(width,width,widthCM*widthCM,StorageTexFormat[indCMFilter]);
	
	let column = [];
	for(let i=0;i<widthCM;++i)
	{
		column.push(Texture2d());
		column[i].alloc(width,width,gl.RGBA32F);
	}

	let tex_ba = Texture2d();
	tex_ba.alloc(width,width,gl.RGBA32F);
	let tex_bb = Texture2d();
	tex_bb.alloc(width,width,gl.RGBA32F);
	let fbos=[FBO(tex_ba),FBO(tex_bb)];
	let fbo_readers=[FBO_READ(tex_ba),FBO_READ(tex_bb)];

	let tex_buffer = Texture2d();
	tex_buffer.alloc(width,width,StorageTexFormat[indCMFilter]);
	let fbo_buffer=FBO(tex_buffer);
	let fbo_buffer_read = FBO_READ(tex_buffer);

	let in_reader = FBO_READ(cm_tex_img);
	
	in_reader.bind();
	fbos[1].texture(0).bind();
	gl.copyTexSubImage2D(gl.TEXTURE_2D,0,0,0,0,0,width,width);

	gl.disable(gl.DEPTH_TEST);
	push_fbo();
	prg_blur.bind();
	Uniforms.coord = 1;
	let k=0;
	//for(let i=0;i<widthCM-1;++i)
	for(let i=0;i<widthCM;++i)
	{
		let p2i = 1<<(2*i);
		while(k<p2i)
		{
			fbos[k%2].bind();
			Uniforms.TU_input = fbos[(k+1)%2].texture(0).bind(0);
			gl.drawArrays(gl.TRIANGLES,0,3);
			++k;
		}
		fbo_readers[(k-1)%2].bind();
		column[i].bind();
		gl.copyTexSubImage2D(gl.TEXTURE_2D,0,0,0,0,0,width,width);
	}

	// fbos[k%2].bind();
	// prg_mean.bind();
	// Uniforms.coord=1;
	// Uniforms.TU_input = fbos[(k+1)%2].texture(0).bind(0);
	// gl.drawArrays(gl.TRIANGLES,0,3);
	// ++k;

	// fbo_readers[(k-1)%2].bind();
	// column[widthCM-1].bind();
	// gl.copyTexSubImage2D(gl.TEXTURE_2D,0,0,0,0,0,width,width);

	prg_blur.bind();
	Uniforms.coord = 0;
	let id_cm = 0;
	for(let j=0;j<widthCM;++j)
	{
		in_reader = FBO_READ(column[j]);
		in_reader.bind();
		fbos[1].texture(0).bind();
		gl.copyTexSubImage2D(gl.TEXTURE_2D,0,0,0,0,0,width,width);
		k=0;
		// for(let i=0;i<widthCM-1;++i)
		for(let i=0;i<widthCM;++i)
		{
			let p2i = 1<<(2*i);
			while(k<p2i)
			{
				fbos[k%2].bind();
				prg_blur.bind();
				Uniforms.TU_input = fbos[(k+1)%2].texture(0).bind(0);
				gl.drawArrays(gl.TRIANGLES,0,3);
				++k;
			}
			fbo_buffer.bind();
			prg_copy.bind();
			Uniforms.TU_input = fbos[(k-1)%2].texture(0).bind(0);
			gl.drawArrays(gl.TRIANGLES,0,3);
			fbo_buffer_read.bind();
			cm_tex_array.bind();
			gl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY,0,0,0,id_cm++,0,0,width,width);
		}

		// fbos[k%2].bind();
		// prg_mean.bind();
		// Uniforms.coord=0;
		// Uniforms.TU_input = fbos[(k+1)%2].texture(0).bind(0);
		// gl.drawArrays(gl.TRIANGLES,0,3);
		// ++k;
		// fbo_buffer.bind();
		// prg_copy.bind();
		// Uniforms.TU_input = fbos[(k-1)%2].texture(0).bind(0);
		// gl.drawArrays(gl.TRIANGLES,0,3);
		// fbo_buffer_read.bind();
		// cm_tex_array.bind();
		// gl.copyTexSubImage3D(gl.TEXTURE_2D_ARRAY,0,0,0,id_cm++,0,0,width,width);
	}

	pop_fbo();
}



function precompute_compacted(in_n1, in_n2, out_compact)
{	
	let level = 0;
	let lp2 = 1;
	let w = in_n1.width;
	let tex_b = Texture2d();
	tex_b.alloc(w,w,StorageTexFormat[indNoiseFilter]);
	let fbo = FBO(tex_b);
	let fbor = FBO_READ(tex_b);
	push_fbo();
	gl.disable(gl.DEPTH_TEST);
	prg_compute_compact.bind();
	while(w>=1)
	{
		fbo.bind();
		gl.viewport(0,0,w,w);
		Uniforms.l = level;
		Uniforms.lp2 = lp2;
		Uniforms.TU_in1 = in_n1.bind(0);
		Uniforms.TU_in2 = in_n2.bind(1);
		gl.drawArrays(gl.TRIANGLES,0,3);
		out_compact.alloc(w,w,StorageTexFormat[indNoiseFilter],null,level);
		out_compact.bind();
		fbor.bind();
		gl.copyTexSubImage2D(gl.TEXTURE_2D,level,0,0,0,0,w,w);
		w /= 2;
		level++;
		lp2 *= 2;
	}
	pop_fbo();
}
	

function load_config(id)
{
	let proms = [];
	proms.push(tex_n1.load("data/"+config[id][1]+".png",gl.R8));
	proms.push(tex_n2.load("data/"+config[id][2]+".png",gl.R8));
	proms.push(tcolormap.load("data/colormap/"+config[id][3]+".png",gl.RGBA32F));
	Promise.all(proms).then(()=>
		{
			let t0 = performance.now();
			precompute_compacted(tex_n1,tex_n2,tex_nvnv);
			tex_nvnv.simple_params(gl.REPEAT,gl.LINEAR_MIPMAP_LINEAR);
//			gl.flush();
			let t1 = performance.now();
			ewgl.console.info_nl("Precomputed  variance mipmaps in "+(t1-t0)+" ms");
			precompute_blur(tcolormap,tex_cm);
			let t2 = performance.now();
			ewgl.console.info_nl("Precomputed filtering colormap in "+(t2-t1)+" ms");
			update_wgl();
		});
}



function ihm()
{
	UserInterface.begin(false,true); 
	UserInterface.use_field_set("H","Choose noises/colormap");
	UserInterface.add_list_input(config_names, 0, x=>{load_config(parseInt(x)); update_wgl();});
	UserInterface.add_check_box("show",show_inputs, x=>{show_inputs = x; update_wgl();});
	UserInterface.end_use()

	UserInterface.add_slider("scale texture coordinates",1,32,sc,(x) => { sc = parseInt(x); update_wgl(); });
	
	UserInterface.use_field_set("V","Animation")
	UserInterface.add_button("Reset",() => {
		sl_rot.value = 0;
		sl_rot.oninput();
		sl_tx.value = 50;
		sl_tx.oninput();
		sl_ty.value = 50;
		sl_ty.oninput();
	});
	let sl_rot = UserInterface.add_slider("rotation",0,250,rot_speed*50,(x) => {
		 rot_speed = 0.02*x;
		 ewgl.continuous_update = (rot_speed>0) || (dtr[0]>0) || (dtr[1]>0) ;
		 update_wgl(); });

	let sl_tx = UserInterface.add_slider("translation_U",0,100,50,(x) => {
			dtr[0] = (x-50)/2000.0;
			ewgl.continuous_update = (rot_speed>0) || (dtr[0]!==0) || (dtr[1]!==0) ;
			update_wgl(); });
	let sl_ty = UserInterface.add_slider("translation_V",0,100,50,(x) => {
			dtr[1] = (x-50)/2000.0;
			ewgl.continuous_update = (rot_speed>0) || (dtr[0]!==0) || (dtr[1]!==0) ;	
			update_wgl(); });

	UserInterface.end_use();

	UserInterface.add_slider("Aniso",0,4,0, x => { aniso = Math.pow(2,x); update_wgl();},x => Math.pow(2,x));

	UserInterface.add_radio("V","Render",
	["patterns","noise x","noise y "],
	 render_out,(x) => {
		render_out = parseInt(x);
		update_wgl();});

	UserInterface.use_field_set("H","camera")
 	UserInterface.add_button("1",()=>{ ewgl.scene_camera.look(Vec3(0,-1,0.05),Vec3(0,1,-0.125),Vec3(0,0,1));update_wgl();})
	UserInterface.add_button("2",()=>{ ewgl.scene_camera.look(Vec3(0,-1,0.15),Vec3(0,1,-0.25),Vec3(0,0,1));update_wgl();})
	UserInterface.add_button("3",()=>{ ewgl.scene_camera.look(Vec3(0,-1,0.25),Vec3(0,1,-0.5),Vec3(0,0,1));update_wgl();})
	UserInterface.add_button("4",()=>{ ewgl.scene_camera.look(Vec3(0,-1,0.35),Vec3(0,1,-0.75),Vec3(0,0,1));update_wgl();})
	UserInterface.add_button("5",()=>{ ewgl.scene_camera.look(Vec3(0,-0.5,2),Vec3(0,0.1,-5),Vec3(0,0,1));update_wgl();})
	UserInterface.end_use();

	UserInterface.end();
}


function init_wgl()
{
	for (let  co of config)
	{
		config_names.push(co[0]);
	}
	tex_n1 = Texture2d();
	tex_n1.simple_params(gl.NEAREST_MIPMAP_NEAREST);
	tex_n2 = Texture2d();
	tex_n2.simple_params(gl.NEAREST_MIPMAP_NEAREST);
	tex_nvnv = Texture2d();
	tex_cm = Texture2dArray();
	tcolormap = Texture2d();
//	tcolormap.alloc(256,256,gl.RGBA32F);
	pause_wgl();
	Promise.all([ShaderProgramFromFiles("implicit_quad.vert","mipmap_compact.frag","compact"),
				ShaderProgramFromFiles("implicit_quad.vert","gauss_blur.frag","blur"),
				ShaderProgramFromFiles("textured_mesh.vert","micro_patterns.frag","new_noise"),
				ShaderProgramFromFiles("implicit_quad.vert","copy_tex.frag","copy_cm"),
				ShaderProgramFromFiles("implicit_quad.vert","mean.frag","mean_dir"),
				ShaderProgramFromFiles("textured_mesh.vert","dbg_inputs.frag","inputs"),
			]).then(([p0,p1,p2,p3,p4,p5])=>
				{
					prg_compute_compact = p0;
					prg_blur = p1;
					prg_new_noise = p2;
					prg_copy = p3
					prg_mean = p4;
					prg_inputs = p5;
					ihm();
					load_config(0);
					setTimeout( ()=> {ewgl.console.toggle(false);},3000);
				});


	object = Mesh.Grid(2).renderer(0,-1,1,-1);
	ewgl.scene_camera.set_scene_radius(4);

	ewgl.scene_camera.look(Vec3(0,-1,0.25),Vec3(0,1,-0.5),Vec3(0,0,1));

	ewgl.console.set_max_nb_lines(6);

	FileDroppedOnCanevas((files, mx, my)=>{
		let sc = 0.5*Math.min(canvas_ratio,1.0/canvas_ratio);

		let loaded = 0
		let proms = [];
		if (files.length > 1)
		{
			for (let f of files)
			{
				if (f.name.substr(0,8)==="colormap")
				{
					loaded |= 4;
					proms.push(tcolormap.load(f,gl.RGBA32F));
				}
				if (f.name.substr(0,6)==="noiseY")
				{
					loaded |= 2;
					proms.push(tex_n2.load(f,gl.R8));
				}
				if (f.name.substr(0,6)==="noiseX")
				{
					loaded |= 1;
					proms.push(tex_n1.load(f,gl.R8));
				}
			}
		}
		else
		{
			let f = files[0];
			// let sc = 0.5*Math.min(canvas_ratio,1.0/canvas_ratio);
			// let M = Vec2(mx,my);
			// let V = M.sub(Vec2(-sc,0));
			// let d = V.length()/1.2;
			// if (d <sc)
			// {
			// 	loaded |= 4;
			// 	proms.push(tcolormap.load(f,gl.RGBA32F));
			// }
			// V = M.sub(Vec2(sc*0.8,sc*0.8));
			// d = V.length()/0.96;
			// if (d<sc)
			// {
			// 	loaded |= 1;
			// 	proms.push(tex_n1.load(f,gl.R8));
			// }
			// V = M.sub(Vec2(sc*0.8,-sc*0.8));
			// d = V.length()/0.96;
			// if (d<sc)
			// {
			// 	loaded |= 2;
			// 	proms.push(tex_n2.load(f,gl.R8));
			// }
			if (mx<0)
			{
				loaded |= 4;
				proms.push(tcolormap.load(f,gl.RGBA32F));
			}
			else {
				if (my<0)
				{
					loaded |= 2;
					proms.push(tex_n2.load(f,gl.R8));
				}
				else
				{
					loaded |= 1;
					proms.push(tex_n1.load(f,gl.R8));
				}
			}
		}

		Promise.all(proms).then(()=>
		{
			if ((loaded&3) !== 0)
			{
				precompute_compacted(tex_n1,tex_n2,tex_nvnv);
			}
			if ((loaded&4) !== 0)
			{
				precompute_blur(tcolormap,tex_cm);
			}
			update_wgl();
		});
	})

}



function draw_wgl()
{
	let dt = ewgl.current_time - last_time;
	last_time = ewgl.current_time;
	tr[0] += dt * dtr[0];
	tr[1] += dt * dtr[1];
	alphaZ += rot_speed*dt;
	const proj = ewgl.scene_camera.get_projection_matrix();
	const view = ewgl.scene_camera.get_view_matrix();

	gl.enable(gl.DEPTH_TEST);
	gl.clearColor(0.1,0.1,0.2,1);
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

	tex_cm.simple_params(gl.LINEAR);
	tex_nvnv.simple_params(gl.LINEAR_MIPMAP_LINEAR);

	prg_new_noise.bind();
	Uniforms.projectionMatrix = proj;
	Uniforms.TU_noises = tex_nvnv.bind(0);
	Uniforms.TU_cm = tex_cm.bind(1);
	Uniforms.level_max = Math.log2(tex_nvnv.width);
	Uniforms.aniso_level = aniso;
	Uniforms.sc = sc;
	Uniforms.tr = tr;
	Uniforms.NB_CM = NB_CM
	Uniforms.render_out = render_out;

	const vm =view.mult(Matrix.rotateZ(alphaZ).mult(Matrix.scale(2,2,1)));
	Uniforms.viewMatrix = vm;
		object.draw(gl.TRIANGLES);

	if (show_inputs)
	{
		prg_inputs.bind();
		Uniforms.projectionMatrix =  Matrix.ortho2D();
		let sc = 0.5*Math.min(canvas_ratio,1.0/canvas_ratio);
		Uniforms.viewMatrix = Matrix.scale(sc,sc,1).mult(Matrix.translate(-1.0,0,0));
		Uniforms.TU = tcolormap.bind(0);
		Uniforms.channel = -1;
		object.draw(gl.TRIANGLES);
		Uniforms.viewMatrix = Matrix.scale(sc,sc,1).mult(Matrix.translate(1.0,1.0,0).mult(Matrix.scale(0.8,0.8,1)));
		Uniforms.TU = tex_nvnv.bind(0);
		Uniforms.channel = 0;
		object.draw(gl.TRIANGLES);
		Uniforms.viewMatrix = Matrix.scale(sc,sc,1).mult(Matrix.translate(1.0,-1.0,0).mult(Matrix.scale(0.8,0.8,1)));
		Uniforms.TU = tex_nvnv.bind(0);
		Uniforms.channel = 1;
		object.draw(gl.TRIANGLES);

	}

}

function onkeydown_wgl(k)
{
	if (k=='s')
	{
		[tex_n1,tex_n2] = [tex_n2,tex_n1];
		precompute_compacted(tex_n1,tex_n2,tex_nvnv);
		update_wgl();
	}

}

function resize_wgl(w,h)
{
	canvas_ratio = h/w;
}
ewgl.launch_3d();
back to top