Skip to content

Instantly share code, notes, and snippets.

@diska
Created August 20, 2018 08:04
Show Gist options
  • Save diska/a6871a5255cb4767f15d69534870e331 to your computer and use it in GitHub Desktop.
Save diska/a6871a5255cb4767f15d69534870e331 to your computer and use it in GitHub Desktop.
三葉レイ動画の22:01時点のコードのGLSL化。
<meta charset="utf-8"><br/>
<canvas id="CNVS"></canvas><hr/>
<script>
const vsrc=`attribute vec4 p;void main(){gl_PointSize=64.;gl_Position=p;}`;
const fsrc=`precision mediump float;
struct Ray{ vec3 o, d;};
struct Sph{ vec3 o; float r;};
const float width=120., height=80.;
float intersect(Sph sph, Ray ray, float tmin, float tmax){
vec3 op=sph.o-ray.o;
float bo=dot(op, ray.d);
float det=bo*bo-dot(op,op)+sph.r*sph.r;
if(det<0.){return -1.;}
float t1=bo-sqrt(det);
if(tmin<t1&&t1<tmax){return t1;}
float t2=bo+sqrt(det);
if(tmin<t2&&t2<tmax){return t2;}
return -1.;
}
vec3 tonemap(vec3 c){
float r=pow(c.r, 1./2.2);
float g=pow(c.g, 1./2.2);
float b=pow(c.b, 1./2.2);
return vec3(r,g,b);
}
void getSphs1(out Sph[2] sphs){// "2 spheres" scene
sphs[0].o=vec3( .5,0,0), sphs[0].r=1.;
sphs[1].o=vec3(-.5,0,0), sphs[1].r=1.;
}
void getSphs2(out Sph[8] sphs){// Cornell Box scene
const float bnum=1e5;
sphs[0].o=vec3( bnum+1., 40.8, 81.6), sphs[0].r=bnum;
sphs[1].o=vec3(-bnum+99., 40.8, 81.6), sphs[1].r=bnum;
// sphs[0].o=vec3( .5,0,0), sphs[0].r=1.;
// sphs[1].o=vec3(-.5,0,0), sphs[1].r=1.;
sphs[2].o=vec3(50., 40.8, bnum), sphs[2].r=bnum;
sphs[3].o=vec3(50., bnum, 81.6), sphs[3].r=bnum;
sphs[4].o=vec3(50., -bnum+81.6, 81.6), sphs[4].r=bnum;
sphs[5].o=vec3(27., 16.5, 47.), sphs[5].r=16.5;
sphs[6].o=vec3(73., 16.5, 78.), sphs[6].r=16.5;
sphs[7].o=vec3(50., 681.6-.27, 81.6), sphs[7].r=600.;
}
void main(){
const float PI=3.141592;
float fov=30.*PI/180., aspect=width/height;
// camera parameters for "2 spheres" scene
// vec3 eye=vec3(5,5,5), center=vec3(0,0,0);
// camera parameters for Cornell Box scene
vec3 eye=vec3(50.,52.,295.6), center=eye+vec3(0.,-0.042612,-1.);
vec3 up=vec3(0,1,0);
// basis vectors for camera coordinates
vec3 wE=normalize(eye-center);
vec3 uE=normalize(cross(up, wE));
vec3 vE=cross(wE, uE);
//
float tf=tan(fov*.5);
vec2 rp=vec2(2.*gl_FragCoord.x/width-1., 2.*gl_FragCoord.y/height-1.);
vec3 wo=normalize(vec3(aspect*tf*rp.x, tf*rp.y, -1));
Ray ray;
// ray.o=vec3(vec2(rp), 5); ray.d=vec3(0,0,-1);
ray.o=eye;
ray.d=uE*wo.x+vE*wo.y+wE*wo.z;
//
vec3 color=vec3(1,0,1);
Sph sph;
// Sph sphs[2]; getSphs1(sphs);
Sph sphs[8]; getSphs2(sphs);
float h, minh=-1., tmax=1000.;
for(int i=0; i<8; i++){
h=intersect(sphs[i], ray, 0., tmax);
if(h<0.){continue;}
sph=sphs[i];
minh=h;
tmax=h;
}
vec3 p, n;
if(minh>0.){
p=ray.o+ray.d*minh;
n=(p-sph.o)/sph.r;
}
if(minh>0.){
gl_FragColor=vec4(color,1);
gl_FragColor=vec4(tonemap(abs(n)),1);
}else{
gl_FragColor=vec4(0,0,0,1);
}
}`;
function draw(){
const width=120, height=80; // Image size
CNVS.width=width, CNVS.height=height;
var cx=CNVS.getContext("webgl");
var vs=cx.createShader(cx.VERTEX_SHADER);cx.shaderSource(vs,vsrc);
var fs=cx.createShader(cx.FRAGMENT_SHADER);cx.shaderSource(fs,fsrc);
var pg=cx.createProgram();cx.attachShader(pg,vs);cx.attachShader(pg,fs);
cx.compileShader(vs);cx.compileShader(fs);cx.linkProgram(pg);
console.log(`vs:${cx.getShaderInfoLog(vs)}\nfs:${cx.getShaderInfoLog(fs)}\n`);
console.log(`pg:${cx.getProgramInfoLog(pg)}\n`);
cx.enableVertexAttribArray(0);
cx.useProgram(pg);
var abuf=cx.createBuffer(cx.ARRAY_BUFFER);
var data=new Float32Array([-1,-1, 1,-1, -1,1, 1,1])
cx.bindBuffer(cx.ARRAY_BUFFER,abuf);
cx.bufferData(cx.ARRAY_BUFFER, data, cx.STATIC_DRAW);
cx.vertexAttribPointer(0, 2,cx.FLOAT, false, 0,0);
cx.bindBuffer(cx.ARRAY_BUFFER,null);
cx.drawArrays(cx.TRIANGLE_STRIP,0,4);
}; draw();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment