//Marble Race in Truchet City precision highp float; uniform vec2 resolution; uniform vec2 mouse; uniform float time; uniform sampler2D backbuffer; out vec4 outColor; #define pi acos(-1.) const float tau=2.*pi; #define rot(spin)mat2(cos(spin),sin(spin),-sin(spin),cos(spin)) const bool ONGRID = false; const bool ONRACEORDER = false; const bool ONDRAWCENTER=false; const float COURCEID = 217.; const float onBoardCameraProb=.3; const bool onBoardCamera=false; const bool backCamera=false; const int RACERNUM = 8; // LAPDATA const float ALLLAP = 50.; const float BEFORELAP = 5.; const float STARTLAP = 1.; const float AFTERLAP = 5.; const float ENDLAP = 5.; const float RACELAP = ALLLAP - BEFORELAP - AFTERLAP - ENDLAP; // スタート時の逆流を防ぐ応急処理 float extraMileage = 1.75; float progress; float beforeProgress; float startProgress; float finishProgress; const float marbleSize = .008; const float roadWidth = .1; const float cityHeight = 0.05; const float cityScale = 32.; #define STARTPOSITION vec2(0.,0.) #define INITIALPOS vec2(0.,.5)+STARTPOSITION #define INITIALDIR vec2(1.,0.) const float fogDensity=1.5; const float fogDistance=0.1; const vec3 fogColor=vec3(.34,.37,.4); const float windowSize=.3/cityScale; const float windowDivergence=.2/cityScale; const vec3 windowColor=vec3(.1,.2,.5); const float streetDistance=.015; const vec3 streetColor=vec3(4.,8.,10.); const float beaconProb=.003; const float beaconFreq=.6; const vec3 beaconColor=vec3(1.5,.2,0.); const vec3 beaconGreenColor=vec3(.2,1.5,0.); const vec3 roadGlow=vec3(1,.3,.2)*2E-5; vec4 RACERNUMCOLOR[8]=vec4[]( vec4(1.,0.,0.,1.),// Red vec4(0.,1.,0.,1.),// Green vec4(0.,0.,1.,1.),// Blue vec4(1.,1.,0.,1.),// Yellow vec4(1.,0.,1.,1.),// Magenta vec4(0.,1.,1.,1.),// Cyan vec4(.5,.5,.5,1.),// Gray vec4(1.,1.,1.,1.)// White ); // _ __ ___ (_)___ ___ // | '_ \ / _ \| / __|/ _ \ // | | | | (_) | \__ \ __/ // |_| |_|\___/|_|___/\___| float hash1(vec2 p2){ p2=fract(p2*vec2(5.3983,5.4427)); p2+=dot(p2.yx,p2.xy+vec2(21.5351,14.3137)); return fract(p2.x*p2.y*95.4337); } float hash1(vec2 p2,float p){ vec3 p3=fract(vec3(5.3983*p2.x,5.4427*p2.y,6.9371*p)); p3+=dot(p3,p3.yzx+19.19); return fract((p3.x+p3.y)*p3.z); } vec2 hash2(vec2 p2){ vec3 p3=fract(vec3(5.3983*p2.x,5.4427*p2.y,6.9371*p2.x)); p3+=dot(p3,p3.yzx+19.19); return fract((p3.xx+p3.yz)*p3.zy); } vec2 hash2(vec2 p2,float p){ vec3 p3=fract(vec3(5.3983*p2.x,5.4427*p2.y,6.9371*p)); p3+=dot(p3,p3.yzx+19.19); return fract((p3.xx+p3.yz)*p3.zy); } vec3 hash3(vec2 p2){ vec3 p3=fract(vec3(p2.xyx)*vec3(5.3983,5.4427,6.9371)); p3+=dot(p3,p3.yxz+19.19); return fract((p3.xxy+p3.yzz)*p3.zyx); } float noise1(vec2 p){ vec2 i=floor(p); vec2 f=fract(p); vec2 u=f*f*(3.-2.*f); return mix(mix(hash1(i+vec2(0.,0.)), hash1(i+vec2(1.,0.)),u.x), mix(hash1(i+vec2(0.,1.)), hash1(i+vec2(1.,1.)),u.x),u.y); } float Hash21(vec2 p){ p=fract(p*vec2(234.24,234.535)); p+=dot(p,p+34.23+COURCEID); return fract(p.x*p.y); } // Simplex 2D noise vec3 permute(vec3 x){return mod(((x*34.)+1.)*x,289.);} float snoise(vec2 v){ const vec4 C=vec4(.211324865405187,.366025403784439, -.577350269189626,.024390243902439); vec2 i=floor(v+dot(v,C.yy)); vec2 x0=v-i+dot(i,C.xx); vec2 i1; i1=(x0.x>x0.y)?vec2(1.,0.):vec2(0.,1.); vec4 x12=x0.xyxy+C.xxzz; x12.xy-=i1; i=mod(i,289.); vec3 p=permute(permute(i.y+vec3(0.,i1.y,1.)) +i.x+vec3(0.,i1.x,1.)); vec3 m=max(.5-vec3(dot(x0,x0),dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)),0.); m=m*m; m=m*m; vec3 x=2.*fract(p*C.www)-1.; vec3 h=abs(x)-.5; vec3 ox=floor(x+.5); vec3 a0=x-ox; m*=1.79284291400159-.85373472095314*(a0*a0+h*h); vec3 g; g.x=a0.x*x0.x+h.x*x0.y; g.yz=a0.yz*x12.xz+h.yz*x12.yw; return 130.*dot(m,g); } // _____ _ // | ___|__ _ __ | |_ // | |_ / _ \| '_ \| __| // | _| (_) | | | | |_ // |_| \___/|_| |_|\__| // kinankomoti font_logging https://www.shadertoy.com/view/mdVSWz #define FontWidth 8 #define FontHeight 8 #define LineMaxLength 40 ivec2 font_data[94]=ivec2[]( //0 ivec2(0x00000000,0x00000000),//space //1~10 ivec2(0x7e91897e,0x00000000),//0 ivec2(0x01ff4121,0x00000000),//1 ivec2(0x71898543,0x00000000),//2 ivec2(0x6e919142,0x00000000),//3 ivec2(0x08ff4838,0x00000000),//4 ivec2(0x8e9191f2,0x00000000),//5 ivec2(0x0e91916e,0x00000000),//6 ivec2(0xc0b08f80,0x00000000),//7 ivec2(0x6e91916e,0x00000000),//8 ivec2(0x6e919162,0x00000000),//9 //11~36 ivec2(0x1e11110e,0x00000001),//a ivec2(0x0e11117f,0x00000000),//b ivec2(0x0a11110e,0x00000000),//c ivec2(0x7f11110e,0x00000000),//d ivec2(0x0815150e,0x00000000),//e ivec2(0x48483f08,0x00000000),//f ivec2(0x3e494930,0x00000000),//g ivec2(0x0708087f,0x00000000),//h ivec2(0x012f0900,0x00000000),//i ivec2(0x5e111102,0x00000000),//j ivec2(0x000b047f,0x00000000),//k ivec2(0x017f4100,0x00000000),//l ivec2(0x0807080f,0x00000007),//m ivec2(0x0708080f,0x00000000),//n ivec2(0x06090906,0x00000000),//o ivec2(0x1824243f,0x00000000),//p ivec2(0x3f242418,0x00000000),//q ivec2(0x0010081f,0x00000000),//r ivec2(0x0012150d,0x00000000),//s ivec2(0x11113e10,0x00000000),//t ivec2(0x0f01010e,0x00000000),//u ivec2(0x000e010e,0x00000000),//v ivec2(0x010e010e,0x0000000f),//w ivec2(0x0a040a11,0x00000011),//x ivec2(0x3e090930,0x00000000),//y ivec2(0x00191513,0x00000000),//z //36~63 ivec2(0x7f88887f,0x00000000),//A ivec2(0x6e9191ff,0x00000000),//B ivec2(0x4281817e,0x00000000),//C ivec2(0x7e8181ff,0x00000000),//D ivec2(0x919191ff,0x00000000),//E ivec2(0x909090ff,0x00000000),//F ivec2(0x4685817e,0x00000000),//G ivec2(0xff1010ff,0x00000000),//H ivec2(0x0081ff81,0x00000000),//I ivec2(0x80fe8182,0x00000000),//J ivec2(0x413608ff,0x00000000),//K ivec2(0x010101ff,0x00000000),//L ivec2(0x601060ff,0x000000ff),//M ivec2(0x0c1060ff,0x000000ff),//N ivec2(0x7e81817e,0x00000000),//O ivec2(0x609090ff,0x00000000),//P ivec2(0x7f83817e,0x00000001),//Q ivec2(0x619698ff,0x00000000),//R ivec2(0x4e919162,0x00000000),//S ivec2(0x80ff8080,0x00000080),//T ivec2(0xfe0101fe,0x00000000),//U ivec2(0x0e010ef0,0x000000f0),//V ivec2(0x031c03fc,0x000000fc),//W ivec2(0x340834c3,0x000000c3),//X ivec2(0x300f30c0,0x000000c0),//Y ivec2(0xe1918d83,0x00000081),//Z //63~ ivec2(0x00007d00,0x00000000),//! ivec2(0x60006000,0x00000000),//" ivec2(0x3f123f12,0x00000012),//# ivec2(0x52ff5224,0x0000000c),//$ ivec2(0x33086661,0x00000043),//% ivec2(0x374d5926,0x00000001),//& ivec2(0x00006000,0x00000000),//' ivec2(0x0081423c,0x00000000),//( ivec2(0x003c4281,0x00000000),//) ivec2(0x00143814,0x00000000),//* ivec2(0x00103810,0x00000000),//+ ivec2(0x00020100,0x00000000),//, ivec2(0x08080808,0x00000000),//- ivec2(0x00000100,0x00000000),//. ivec2(0x30080601,0x00000040),/// ivec2(0x00240000,0x00000000),//: ivec2(0x00240200,0x00000000),//; ivec2(0x41221408,0x00000000),//< ivec2(0x00141414,0x00000000),//= ivec2(0x08142241,0x00000000),//> ivec2(0xa999423c,0x0000007c),//@ ivec2(0x008181ff,0x00000000),//[ ivec2(0x06083040,0x00000001),//\ ivec2(0x00000000,0x00000000),//] 何故か表示されない ivec2(0x00ff8181,0x00000000),//] ivec2(0x20402010,0x00000010),//^ ivec2(0x01010101,0x00000000),//_ ivec2(0x40408080,0x00000000),//` ivec2(0x41413608,0x00000000),//{ ivec2(0x00ff0000,0x00000000),//| ivec2(0x08364141,0x00000000),//} ivec2(0x08101008,0x00000010)//~ ); vec3 font(vec2 uv,int id){ vec2 uv1=uv; uv=uv*8.; ivec2 texel=ivec2(uv); int bit_offset=texel.x*FontWidth+texel.y; int s,t; s=font_data[id].x; t=font_data[id].y; int tex=0; if(bit_offset<=31){ s=s>>bit_offset; s=s&0x00000001; tex=s; } else{ t=t>>(bit_offset-32); t=t&0x00000001; tex=t; } tex=(abs(uv1.x-.5)<.5&&abs(uv1.y-.5)<.5)?tex:0; return vec3(tex); } // _ __ // ___ __| |/ _| // / __|/ _` | |_ // \__ \ (_| | _| // |___/\__,_|_| bool drawCircle(vec2 uv,vec2 pos){ float posPoint=.075-length(pos-uv); return ceil(posPoint)==1.; } float calculateGridLine(vec2 uv,float grid_size,float line_width){ // グリッドの線を計算 float line_x=step(grid_size-line_width,mod(uv.x-line_width/2.,grid_size)); float line_y=step(grid_size-line_width,mod(uv.y-line_width/2.,grid_size)); float line=line_x+line_y; return line; } float sdSphere(vec3 p,float r) { return length(p)-r; } // ____ _____ _ _ // / ___| ____| | | | // | | | _| | | | | // | |___| |___| |___| |___ // \____|_____|_____|_____| // inspired by 2d truchet traveler abje https://www.shadertoy.com/view/4tfcDl int getcell(vec2 pos){ return int(floor(Hash21(mod(pos,vec2(64.)))*3.)); } float passedCellNum(float mileage){ // mileage=mod(mileage,128.); return floor(mileage); } struct TruchetData{ vec2 pos; vec2 dir; vec2 floorpos; }; TruchetData allSkippedData[128]; int lastSkippedDataIndex; #define EXTRACELL 5. void setSkipTruchetData(vec2 pos,vec2 dir, vec2 floorpos, float mileage){ for(float i=0.;i.5&&maxT0.)m=mouse.xy/resolution.xy; m*=tau*vec2(1.,.25); float cameraDist=2.; vec3 mouseFix=vec3( cameraDist*sin(m.x)*sin(m.y), cameraDist*cos(m.y), cameraDist*cos(m.x)*sin(m.y)); // 固定カメラ bool isKoteiCamera=backCamera&&!onBoardCamera; if(!isFinished&&!isStarting&&isKoteiCamera){ int index=int(passedCellNum(allRacers[racerNum].mileage)); TruchetData data=allSkippedData[index+1]; center=vec3(data.pos.x,.1,data.pos.y); mouseFix=vec3( roadWidth*sin(m.x)*sin(m.y), roadWidth*cos(m.y), roadWidth*cos(m.x)*sin(m.y)); vec3 ro = center+mouseFix; vec3 target =vec3(allRacers[racerNum].pos.x,marbleSize,allRacers[racerNum].pos.y); vec3 forward = normalize(target-ro); return Camera(ro,createRd(gl_FragCoord.xy,forward)); } vec3 ro=center+mouseFix; if(isStarting){ int index=int(passedCellNum(0.)); TruchetData data=allSkippedData[index]; center=vec3(data.pos.x,.0,data.pos.y); ro = center + vec3(data.dir.x,0.3,data.dir.y) + mouseFix*0.05; } // rdの定義 vec3 forward=normalize(center-ro); vec3 rd=createRd(gl_FragCoord.xy,forward); return Camera(ro,rd); } // __ __ _ ___ _ _ // | \/ | / \ |_ _| \ | | // | |\/| | / _ \ | || \| | // | | | |/ ___ \ | || |\ | // |_| |_/_/ \_\___|_| \_| void main() { vec2 floorpos=STARTPOSITION; vec2 initialPos=INITIALPOS; vec2 dir=INITIALDIR;// 初期の方向 以降最初はx=1の方向に進む前提のコード // ■ 時間の設定 float gameSpeed = time * 0.75; float time = fract(gameSpeed / (ALLLAP)) * (ALLLAP); float raceTime = BEFORELAP < time ? time - BEFORELAP: 0.; progress = raceTime / RACELAP; beforeProgress = clamp(time/(BEFORELAP),0.,1.); startProgress = clamp((raceTime/STARTLAP),0.,1.); finishProgress = clamp((time-(ALLLAP-AFTERLAP-ENDLAP))/AFTERLAP,0.,1.); // ■ トルシェのデータの生成 setSkipTruchetData(initialPos,dir,floorpos,time); // ■ レーサーの生成 for(int i=0;i