aboutsummaryrefslogblamecommitdiff
path: root/xp/cgxp/main2.js
blob: 05b1fdbdbc469824628c115e92667d586450a697 (plain) (tree)























































































































































































































































































                                                                                                                                  
//Copyright Chris Xiong 2018
//License: Expat (MIT)
var cvs,WGL,vpw,vph,hdiv;
var fsh=`
varying lowp vec4 vC;
void main(void)
{
	gl_FragColor=vC;
}`;
var vsh=`
attribute vec3 vp;
attribute vec4 vc;
uniform mat4 mmodelview;
uniform mat4 mprojection;
varying lowp vec4 vC;
void main(void)
{
	gl_Position=mprojection*mmodelview*vec4(vp,1.);
	vC=vc;
}`;
var shp;
var vbufsize=4096;
var vbo,ibo;
var vb=new Float32Array(vbufsize*7);
var ib=new Uint16Array(vbufsize*6/4);
var Mprojection,Mmodelview;
var primc;
var kst=[];
var pos=[15,4,30];
var ofs=[0.9,3.5,20];
var mzw=50,mzh=35,ppx,ppy,ex,ey;
var maz=[];

var Sphere=function()
{
	this.x=10-Math.random()*20;
	this.y=10-Math.random()*20;
	this.timer=0;this.r=0.2;
}
Sphere.prototype.update=function()
{
	var d=Math.sqrt((this.x-pp.x)*(this.x-pp.x)+(this.y-pp.y)*(this.y-pp.y));
	if(d<0.5&&this.timer===0)this.timer=1;
	if(this.timer>0&&state===0)
	{
		++this.timer;health+=0.01;
		this.r+=0.02;if(health>1)health=1;
	}
	if(this.timer>25)this.timer=-1;
}
Sphere.prototype.draw=function(x,y,a)
{
	if(this.timer!==-1)pushSphere(x,y,0,this.r,[0,1,0,a*(0.6-this.timer*0.6/25)]);
}

function createShader(sh,t)
{
	var shader=WGL.createShader(t);
	WGL.shaderSource(shader,sh);
	WGL.compileShader(shader);
	if(!WGL.getShaderParameter(shader,WGL.COMPILE_STATUS))
	{
		alert("shader error..."+WGL.getShaderInfoLog(shader));
		return null;
	}
	return shader;
}
function pushQuad(a)
{
	if(primc>=vbufsize/4)batchGL();
	for(var i=0;i<4;++i)
	for(var j=0;j<7;++j)vb[primc*7*4+i*7+j]=a[i*7+j];
	++primc;
}
function cube(x,y,z,l,r,g,b,a)
{
	var L=x-l/2,R=x+l/2;
	var B=y-l/2,T=y+l/2;
	var N=z-l/2,F=z+l/2;
	pushQuad([
		L,B,N,r,g,b,a,
		L,T,N,r,g,b,a,
		R,T,N,r,g,b,a,
		R,B,N,r,g,b,a
	]);
	pushQuad([
		L,B,F,r,g,b,a,
		L,T,F,r,g,b,a,
		R,T,F,r,g,b,a,
		R,B,F,r,g,b,a
	]);
	pushQuad([
		L,B,N,r,g,b,a,
		L,T,N,r,g,b,a,
		L,T,F,r,g,b,a,
		L,B,F,r,g,b,a
	]);
	pushQuad([
		R,B,N,r,g,b,a,
		R,T,N,r,g,b,a,
		R,T,F,r,g,b,a,
		R,B,F,r,g,b,a
	]);
	pushQuad([
		L,B,N,r,g,b,a,
		R,B,N,r,g,b,a,
		R,B,F,r,g,b,a,
		L,B,F,r,g,b,a
	]);
	pushQuad([
		L,T,N,r,g,b,a,
		R,T,N,r,g,b,a,
		R,T,F,r,g,b,a,
		L,T,F,r,g,b,a
	]);
}
function pushSphere(x,y,z,r,col)
{
	for(var i=0;i<12;++i)
	for(var j=0;j<12;++j)
	{
		var r1=r*Math.sin(i*Math.PI/12);
		var a=new v3d(x+r1*Math.cos(j*Math.PI/12*2),y+r1*Math.sin(j*Math.PI/12*2),z+r*Math.cos(i*Math.PI/12));
		var b=new v3d(x+r1*Math.cos((j+1)*Math.PI/12*2),y+r1*Math.sin((j+1)*Math.PI/12*2),z+r*Math.cos(i*Math.PI/12));
		r1=r*Math.sin((i+1)*Math.PI/12);
		var c=new v3d(x+r1*Math.cos(j*Math.PI/12*2),y+r1*Math.sin(j*Math.PI/12*2),z+r*Math.cos((i+1)*Math.PI/12));
		var d=new v3d(x+r1*Math.cos((j+1)*Math.PI/12*2),y+r1*Math.sin((j+1)*Math.PI/12*2),z+r*Math.cos((i+1)*Math.PI/12));
		pushQuad([
			a.x,a.y,a.z,col[0],col[1],col[2],col[3],
			b.x,b.y,b.z,col[0],col[1],col[2],col[3],
			d.x,d.y,d.z,col[0],col[1],col[2],col[3],
			c.x,c.y,c.z,col[0],col[1],col[2],col[3]
		]);
	}
}
function randint(c)
{return Math.floor(Math.random()*c);}
function genmaze()
{
	for(var i=0;i<mzw;++i)
	{
		maz[i]=[];
		for(var j=0;j<mzh;++j)maz[i][j]=false;
	}
	var dx=[0,0,-1,1],
		dy=[1,-1,0,0];
	var lst=[];
	var cx=randint(mzw),cy=randint(mzh);
	lst.push({x:cx,y:cy,z:cx,w:cy});
	while(lst.length)
	{
		var rm=lst.splice(randint(lst.length),1);
		var x=rm[0].z,y=rm[0].w;
		if(maz[x][y]==false)
		{
			maz[x][y]=maz[rm[0].x][rm[0].y]=true;
			for(var i=0;i<4;++i)
			{
				cx=x+dx[i]*2;cy=y+dy[i]*2;
				if(cx>=0&&cy>=0&&cx<mzw&&cy<mzh&&
				maz[cx][cy]==false)
				lst.push({x:x+dx[i],y:y+dy[i],z:cx,w:cy});
			}
		}
	}
	for(var i=0;i<mzh;++i)maz[0][i]=maz[mzw-1][i]=false;
	for(var i=0;i<mzw;++i)maz[i][0]=maz[i][mzh-1]=false;
	for(var i=0;i<mzh;++i){if(maz[1][i])lst.push({x:1,y:i});if(maz[mzw-2][i])lst.push({x:mzw-2,y:i});}
	for(var i=0;i<mzw;++i){if(maz[i][1])lst.push({x:i,y:1});if(maz[i][mzh-2])lst.push({x:i,y:mzh-2});}
	if(lst.length<2)return genmaze();
	var rm=lst.splice(randint(lst.length),1);
	ppx=rm[0].x,ppy=rm[0].y;
	rm=lst.splice(randint(lst.length),1);
	ex=rm[0].x,ey=rm[0].y;
}
function init()
{
	cvs=document.getElementById("glCvs");
	if(!window.devicePixelRatio)window.devicePixelRatio=1;
	cvs.width=window.innerWidth;
	cvs.height=window.innerHeight;
	cvs.style.width=cvs.width+"px";
	cvs.style.height=cvs.height+"px";
	cvs.width=cvs.width*window.devicePixelRatio;
	cvs.height=cvs.height*window.devicePixelRatio;
	vpw=cvs.width;vph=cvs.height;
	try
	{WGL=cvs.getContext("webgl")||cvs.getContext("experimental-webgl");}
	catch(e){WGL=null;}
	if(!WGL){alert("WebGL is not supported by your browser...");return;}
	
	WGL.clearColor(0.5,0.5,0.5,1.0);
	WGL.clearDepth(1);
	WGL.enable(WGL.DEPTH_TEST);
	WGL.depthFunc(WGL.LESS);
	WGL.enable(WGL.BLEND);
	WGL.blendFunc(WGL.SRC_ALPHA,WGL.ONE_MINUS_SRC_ALPHA);
	WGL.clear(WGL.COLOR_BUFFER_BIT|WGL.DEPTH_BUFFER_BIT);
	WGL.viewport(0,0,cvs.width,cvs.height);
	
	shp=WGL.createProgram();
	var fshs=createShader(fsh,WGL.FRAGMENT_SHADER);
	var vshs=createShader(vsh,WGL.VERTEX_SHADER);
	WGL.attachShader(shp,vshs);WGL.attachShader(shp,fshs);
	WGL.linkProgram(shp);
	if(!WGL.getProgramParameter(shp,WGL.LINK_STATUS))
	{
		alert("shader link error...");
	}
	WGL.useProgram(shp);
	
	vbo=WGL.createBuffer();
	WGL.bindBuffer(WGL.ARRAY_BUFFER,vbo);
	WGL.bufferData(WGL.ARRAY_BUFFER,vb,WGL.STATIC_DRAW);
	var vpp=WGL.getAttribLocation(shp,"vp");
	var vcp=WGL.getAttribLocation(shp,"vc");
	WGL.enableVertexAttribArray(vpp);
	WGL.enableVertexAttribArray(vcp);
	WGL.bindBuffer(WGL.ARRAY_BUFFER,vbo);
	WGL.vertexAttribPointer(vpp,3,WGL.FLOAT,false,7*4,0);
	WGL.vertexAttribPointer(vcp,4,WGL.FLOAT,false,7*4,3*4);
	
	for(var i=0,n=0,p=0;i<vbufsize/4;++i)
	{
		ib[p++]=n;ib[p++]=n+1;
		ib[p++]=n+2;ib[p++]=n+2;
		ib[p++]=n+3;ib[p++]=n;
		n+=4;
	}
	ibo=WGL.createBuffer();
	WGL.bindBuffer(WGL.ELEMENT_ARRAY_BUFFER,ibo);
	WGL.bufferData(WGL.ELEMENT_ARRAY_BUFFER,ib,WGL.STATIC_DRAW);
	
	document.addEventListener('keydown',function(e){kst[e.code]=1;});
	document.addEventListener('keyup',function(e)
	{
		kst[e.code]=0;
		if(e.code=='KeyD'){if(ppx+1<mzw&&maz[ppx+1][ppy])++ppx;}
		if(e.code=='KeyA'){if(ppx-1>=0&&maz[ppx-1][ppy])--ppx;}
		if(e.code=='KeyW'){if(ppy+1<mzh&&maz[ppx][ppy+1])++ppy;}
		if(e.code=='KeyS'){if(ppy-1>=0&&maz[ppx][ppy-1])--ppy;}
	});
	genmaze();
	requestAnimationFrame(mainloop);
}

function mainloop()
{
	const ofx=-9,ofy=-11;
	WGL.clearColor(0.5,0.5,0.5,1.0);
	WGL.clearDepth(1);
	WGL.clear(WGL.COLOR_BUFFER_BIT|WGL.DEPTH_BUFFER_BIT);
	primc=0;
	Mmodelview=buildIdentityMatrix();

	Mmodelview=buildLookAtMatrix(pos,[15,10,0],[0,0,1]);
	for(var i=0;i<mzw;++i)
	for(var j=0;j<mzh;++j)
	if(!maz[i][j])cube(i+ofx,j+ofy,0,1,0.1,0.1,0.1,1);
	
	cube(ppx+ofx,ppy+ofy,0,0.6,0.1,0.8,0.1,1);
	cube(ex+ofx,ey+ofy,0,0.8,0.4,0.9,0.9,1);
	
	batchGL();
	
	requestAnimationFrame(mainloop);
}

function batchGL()
{
	Mprojection=buildProjectionMatrix3D(vpw,vph,60,0.1,100);
	var mpp=WGL.getUniformLocation(shp,"mprojection");
	WGL.uniformMatrix4fv(mpp,false,Mprojection);
	var mvpp=WGL.getUniformLocation(shp,"mmodelview");
	WGL.uniformMatrix4fv(mvpp,false,Mmodelview);
	WGL.bindBuffer(WGL.ARRAY_BUFFER,vbo);
	WGL.bufferData(WGL.ARRAY_BUFFER,vb,WGL.STATIC_DRAW);
	WGL.drawElements(WGL.TRIANGLES,6*primc,WGL.UNSIGNED_SHORT,0);
	primc=0;
}