Reset Repo structure.
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch index.html",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"file": "${workspaceFolder}/index.html",
|
||||
"runtimeExecutable": "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
|
||||
"runtimeArgs": ["--args", "--allow-file-access-from-files"]
|
||||
},
|
||||
{
|
||||
"name": "windows",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"file": "${workspaceFolder}/index.html",
|
||||
"runtimeExecutable": "C:/Users/sunyi/AppData/Local/Google/Chrome SxS/Application/chrome.exe",
|
||||
"runtimeArgs": ["--args", "--allow-file-access-from-files"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"python.pythonPath": "/usr/local/bin/python"
|
||||
}
|
||||
|
After Width: | Height: | Size: 336 KiB |
|
After Width: | Height: | Size: 803 KiB |
|
After Width: | Height: | Size: 227 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
@@ -0,0 +1,352 @@
|
||||
|
||||
#ifndef _NDEBUG
|
||||
precision highp float;
|
||||
const int ns = 5;
|
||||
const int cns = 5;
|
||||
float noise(vec3 v){return 1.;}
|
||||
#endif
|
||||
#define _DEBUG_BREAK {gl_FragColor=vec4(1,0,0,1); return;}
|
||||
#define REFRACTION (c2 >= 0.? (eta*W + (eta*c1 - sqrt(c2))*N) : ((W + c1*N)/sqrt(1.-c1*c1)))
|
||||
vec3 foregroundColor = vec3(.0841, .5329, .9604);
|
||||
vec3 groundColor = vec3(.2, .3, .5);
|
||||
vec4 groundSpecular = vec4(.71, .71, .71, 10.);
|
||||
uniform float uTime;// TIME, IN SECONDS
|
||||
uniform vec3 Ambient[ns], Diffuse[ns];
|
||||
uniform vec4 Specular[ns];
|
||||
uniform float ks[ns], kr[ns], kf[ns];
|
||||
uniform vec4 Sph[ns];
|
||||
uniform vec3 SphCanvas[ns];
|
||||
uniform vec3 Glow[ns];
|
||||
uniform sampler2D uSampler[ns+3];
|
||||
uniform vec3 V0;
|
||||
uniform bool glassy;
|
||||
uniform int sel;
|
||||
const float kf_air = 1.000293;
|
||||
varying vec3 trPos;
|
||||
varying float id;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
const float pi=3.14159265359;
|
||||
const float _2pi=2.*pi;
|
||||
|
||||
/***********PLEASE DO INCREASE n_ref(RT DEPTH) FOR BETTER RESULTS************/
|
||||
/*---->*/const int n_ref=31; //2^n-1 because each hit now spawn at most 2 rays.
|
||||
/**BUT BE CAUTIOUS IF YOU DON'T HAVE A DECENT GRAPHICS CARD (below GTX 950M)**/
|
||||
|
||||
const int max_stack = (n_ref+1)/4;
|
||||
vec3 scolor = vec3(0,0,0);
|
||||
struct Ray{
|
||||
vec3 V;
|
||||
vec3 W;
|
||||
float kf, cumulativeK, decay;
|
||||
} stack1[max_stack], stack2[max_stack];
|
||||
bool modulo2(int n){
|
||||
return n-2*(n/2) == 1;
|
||||
}
|
||||
vec2 getTextCoord(vec3 tex_sph, float R){
|
||||
float tex_x=atan(tex_sph.z,tex_sph.x)/_2pi + 0.5;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
|
||||
tex_x=fract(tex_x+uTime/20.);
|
||||
return vec2(tex_x,-asin(tex_sph.y/R)/pi + 0.5);
|
||||
}
|
||||
#define clamp1(x) ((x)<0.?0.:((x) > 1. ? 1.:(x)))
|
||||
vec3 vec_clamp01(vec3 x) {
|
||||
return vec3(clamp1(x.x), clamp1(x.y), clamp1(x.z));
|
||||
}
|
||||
void main(){
|
||||
// gl_FragColor=vec4(_glassy,0,0,1); return;
|
||||
vec3 LDir=vec3(.5,.5,.5);
|
||||
vec3 LCol=vec3(1.,1.,1.);
|
||||
float currKf = kf_air;
|
||||
vec3 color=vec3(.2, .3, .5);
|
||||
vec3 V = V0;
|
||||
vec3 W=(trPos-V);
|
||||
float glassyw = 1.;
|
||||
// bool glassy = _glassy > .1;
|
||||
if(glassy)
|
||||
{
|
||||
vec2 noiseTex = (texPos.xy + 1.)/2.;
|
||||
noiseTex = vec2(clamp1(noiseTex.x ), clamp1(noiseTex.y ));
|
||||
vec4 Wnoise = texture2D(uSampler[ns+2], noiseTex);
|
||||
W += (Wnoise.xyz-.5)*.4;
|
||||
glassyw = Wnoise.w;
|
||||
}
|
||||
bool selected = false;
|
||||
float currentK = 1.;
|
||||
float curr_decay = 1.;
|
||||
int curr_ptr = 0, curr_top = 0, next_top = 0;
|
||||
bool final = false, stackswap = false, stop = false;
|
||||
for(int j=0;j<n_ref;j++)
|
||||
{
|
||||
for(int curr = 0; curr < max_stack; ++curr){
|
||||
if(curr == curr_ptr){
|
||||
bool skip = false;
|
||||
if(j > 0){
|
||||
Ray currR;
|
||||
if(stackswap)
|
||||
currR = stack1[curr];
|
||||
else
|
||||
currR = stack2[curr];
|
||||
currKf = currR.kf;
|
||||
currentK = currR.cumulativeK;
|
||||
curr_decay = currR.decay;
|
||||
if(currKf <= 0.001 || currentK <= 0.001)
|
||||
skip = true;
|
||||
|
||||
V = currR.V;
|
||||
W = currR.W;
|
||||
}
|
||||
else
|
||||
W = normalize(W);
|
||||
if(!skip){
|
||||
float tMin=10000.;
|
||||
int iMin = -1;
|
||||
for(int i=0;i<cns;i++){
|
||||
vec3 Vp=V-Sph[i].xyz;
|
||||
float B=dot(W,Vp);
|
||||
float C=dot(Vp,Vp)-Sph[i].w*Sph[i].w;
|
||||
float D=B*B-C;
|
||||
if(D>0.){
|
||||
float t=-B-sqrt(D);
|
||||
if(t >= 0.01 && t < tMin){
|
||||
tMin = t; // This is an optimization, we don't have to do lighting/tex
|
||||
iMin = i; // for objects that are occuluded, which is expensive!
|
||||
}
|
||||
else if (t >= -0.01 && t <0.01){
|
||||
t = -(t + 2.*B);
|
||||
if(t > 0.01 && t < tMin){
|
||||
tMin = t;
|
||||
iMin = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(iMin >= 0){
|
||||
if(j == 0 && iMin == sel)
|
||||
selected = true;
|
||||
vec3 S=V+tMin*W;
|
||||
if(curr_decay > .01)
|
||||
curr_decay = curr_decay/(1.+tMin*tMin);
|
||||
for(int i = 0; i < cns; ++ i)
|
||||
if(i == iMin)
|
||||
{
|
||||
if(j == 0)
|
||||
{
|
||||
float intensity = sqrt(dot(Glow[i], Glow[i]));
|
||||
if(intensity > 1.7)
|
||||
{
|
||||
gl_FragColor = vec4(1.74*normalize(Glow[i]), 1.);
|
||||
if(selected)
|
||||
gl_FragColor = vec4(normalize(Glow[i])+vec3(.5,0.,0.), 1.);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 texture_color;
|
||||
vec3 tex_sph = (S-Sph[i].xyz);
|
||||
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
|
||||
|
||||
vec3 N=normalize(S-Sph[i].xyz);
|
||||
vec3 realLDir=normalize(LDir-S);
|
||||
float c1 =dot(N, W);
|
||||
float eta, nextkf;
|
||||
if(c1<0.){
|
||||
color=(Ambient[i]+Diffuse[i]*max(0.,dot(N,realLDir))*LCol)*texture_color;
|
||||
for(int k = 0; k < cns; ++k){
|
||||
if(Glow[k].x > .01){
|
||||
vec3 lDir = Sph[k].xyz - S;
|
||||
float dist = length(lDir);
|
||||
lDir /= (dist);
|
||||
dist -= Sph[k].w;
|
||||
color += (Glow[k]/(1.+dist*dist))*Diffuse[i]*
|
||||
max(0.,dot(N,lDir));
|
||||
}
|
||||
}
|
||||
if(final) //if it's the last hit
|
||||
{
|
||||
color += Specular[i].xyz*pow(max(0.,
|
||||
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
|
||||
if(curr_decay > .01 && Glow[i].x > .01)
|
||||
{
|
||||
vec3 glow_color = currentK*curr_decay*Glow[i];
|
||||
float l = length(glow_color);
|
||||
if(l >=1.7)
|
||||
glow_color/=l/1.7;
|
||||
scolor += glow_color;
|
||||
}
|
||||
|
||||
scolor += color * currentK;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
c1 = -c1;
|
||||
eta = currKf/kf[i];
|
||||
nextkf = kf[i];
|
||||
}
|
||||
}
|
||||
else{
|
||||
N = -N;
|
||||
eta = currKf/kf_air;
|
||||
nextkf = kf_air;
|
||||
color = Ambient[i];
|
||||
}
|
||||
float c2 = (1.-eta*eta*(1.-c1*c1));
|
||||
float nextks = currentK * ks[i], nextkr = currentK * kr[i];
|
||||
bool refl = nextks > 0.01, refr = nextkr > 0.01;
|
||||
if(refl || refr)
|
||||
for(int k = 0; k < max_stack; ++k)
|
||||
if(k == next_top){
|
||||
if(stackswap){
|
||||
if(refl)
|
||||
{
|
||||
stack2[k] = Ray(S, 2. * c1 * N + W, currKf, nextks, curr_decay); //reflection
|
||||
currentK -= nextks;
|
||||
next_top ++;
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
if(refl)
|
||||
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
else
|
||||
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
currentK -= nextkr;
|
||||
next_top ++;
|
||||
}
|
||||
}else{
|
||||
if(refl)
|
||||
{ //remember, c1 = -NW now
|
||||
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks, curr_decay); //reflection
|
||||
currentK -= nextks;
|
||||
next_top ++;
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
if(refl)
|
||||
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
else
|
||||
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
currentK -= nextkr;
|
||||
next_top ++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
scolor += color * currentK;
|
||||
if(curr_decay > .01 && Glow[i].x > .01)
|
||||
{
|
||||
vec3 glow_color = currentK*curr_decay*Glow[i];
|
||||
float l = length(glow_color);
|
||||
if(l >=1.7)
|
||||
glow_color/=l/1.7;
|
||||
scolor += glow_color;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float t = -(.2+V.y)/W.y;
|
||||
float sx = V.x + t* W.x, sz = V.z + t * W.z;
|
||||
|
||||
if(t >= 0. && abs(sx) < 1.5 && abs(sz) < 3.)
|
||||
{
|
||||
if(curr_decay > .01)
|
||||
curr_decay = curr_decay/(1.+t*t);
|
||||
vec3 S = vec3(sx, -.2, sz);
|
||||
vec3 realLDir=normalize(LDir - S);
|
||||
color=(0.5+0.5*max(0.,realLDir.y)*LCol)*texture2D(uSampler[ns], vec2((sx+1.5)/3., (sz+3.)/6.)).xyz;
|
||||
if(final&&abs(sx)<1.5 && abs(sz+.6)<3.)
|
||||
{
|
||||
color += groundSpecular.xyz* //specular for ground.
|
||||
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
|
||||
for(int k = 0; k < cns; ++k){
|
||||
if(Glow[k].x > .01){
|
||||
vec3 lDir = Sph[k].xyz - S;
|
||||
float dist = length(lDir);
|
||||
lDir /= (dist);
|
||||
dist -= Sph[k].w;
|
||||
color += (Glow[k]/(1.+dist*dist))* //specular for ground.
|
||||
pow(max(0., dot(vec3(-lDir.x, lDir.y,-lDir.z),-W)),groundSpecular.w);
|
||||
}
|
||||
}
|
||||
scolor += currentK * color;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int k = 0; k < max_stack; ++k)
|
||||
if(k == next_top){
|
||||
if(stackswap)
|
||||
stack2[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15, curr_decay); //reflection
|
||||
else
|
||||
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15, curr_decay); //reflection
|
||||
next_top ++;
|
||||
break;
|
||||
}
|
||||
scolor += (currentK*.85)*color;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(j > 0)
|
||||
{
|
||||
scolor += currentK * (pow(max(0.,dot(W, normalize(LDir - V))), 10.) * vec3(3.,3.,3.) + foregroundColor*0.1);
|
||||
for(int k = 0; k < cns; ++k){
|
||||
if(Glow[k].x > .01){
|
||||
vec3 lDir = Sph[k].xyz - V;
|
||||
float dist = length(lDir);
|
||||
lDir /= (dist);
|
||||
dist -= Sph[k].w;
|
||||
color += (Glow[k]/(1.+dist*dist))* //specular for ground.
|
||||
pow(max(0., dot(vec3(-lDir.x, lDir.y,-lDir.z),W)),groundSpecular.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
else scolor = foregroundColor*0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(++curr_ptr >= curr_top){
|
||||
if(next_top <= 0)
|
||||
stop = true;
|
||||
if(next_top * 2 > max_stack)
|
||||
final = true;
|
||||
curr_top = next_top;
|
||||
next_top = 0;
|
||||
curr_ptr = 0;
|
||||
stackswap = !stackswap;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stop)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(glassy)
|
||||
scolor *= glassyw*glassyw;
|
||||
for(int i = 0; i < ns; ++i){
|
||||
if(i == sel)
|
||||
continue;
|
||||
vec2 sx = SphCanvas[i].xy - texPos.xy;
|
||||
float theta = atan(sx.y/sx.x);
|
||||
if(sx.x > 0. && theta < 0.)
|
||||
theta += _2pi;
|
||||
else if(sx.x < 0.)
|
||||
theta += pi;
|
||||
float intensity = sqrt(dot(Glow[i], Glow[i]));
|
||||
vec3 realD = Sph[i].xyz - V0;
|
||||
float realDist = sqrt(dot(realD, realD))-Sph[i].w;
|
||||
intensity/=(1.+realDist*realDist);
|
||||
float dist = dot(sx, sx) - SphCanvas[i].z*SphCanvas[i].z;
|
||||
intensity *= .5;
|
||||
if(dist < intensity && dist > 0.)
|
||||
{
|
||||
vec3 flare = texture2D(uSampler[ns+1], vec2(0.1+0.9*(dist/intensity), theta/float(2*i+7))).xyz;
|
||||
scolor += flare*flare*Glow[i]/(1.+realDist*realDist);
|
||||
}
|
||||
}
|
||||
scolor = vec_clamp01(scolor);
|
||||
if(selected)
|
||||
scolor.x += 0.5;
|
||||
gl_FragColor=vec4(sqrt(scolor),1.);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
attribute float oid;
|
||||
attribute vec3 aPos;
|
||||
attribute vec3 normal;
|
||||
varying vec3 trPos;
|
||||
uniform mat3 transformation;
|
||||
uniform mat4 uMatrix;
|
||||
varying float id;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
//I used mat3 instead of the augmented mat4 matrix because we
|
||||
//are not doing complex projections yet. I implemented simple
|
||||
//perspective projection back in hw2 by changing focal length
|
||||
//and adjusting the size of the projected surface accrodingly.
|
||||
//New surface = distance(surface, old viewpoint)/ distance(surface, new viewpoint) * old surface
|
||||
// = (deltaFl + fl + 1)/(fl + 1) * old surface
|
||||
//This is implemented by vPos = (dFl + fl + 1)/(fl + 1) * vPos;
|
||||
//Because we will multiply the resulting vPos by the transformation matrix
|
||||
//anyway, I smashed the ratio into the matrix into avoid doing this in shaders.
|
||||
void main() {
|
||||
vec4 pos = uMatrix * vec4(aPos, 1.);
|
||||
gl_Position = pos;
|
||||
id = oid;
|
||||
norm = normal;
|
||||
trPos = transformation *vec3(aPos.x, -aPos.y, -1);
|
||||
texPos = vec3(aPos.x, -aPos.y, -1.);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 906 215" style="enable-background:new 0 0 906 215;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#666666;}
|
||||
.st1{fill:#606060;}
|
||||
.st2{fill:#1D1E1D;}
|
||||
.st3{fill:#FFFFFF;}
|
||||
.st4{fill:#FFFFFF;stroke:#FFFFFF;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<rect x="601.61" y="-0.13" class="st0" width="306" height="215"/>
|
||||
<path class="st1" d="M604.9,214.84H-2.43V0.18h662L604.9,214.84z"/>
|
||||
<path class="st2" d="M307.9,0.18l-57.16,214.67h341.99L646.9,0.18H307.9z"/>
|
||||
<path class="st3" d="M323.71,65.38V39.35c0-1.81,0.64-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h24.72v6.93h-21.79
|
||||
c-0.54,0-1,0.2-1.38,0.59s-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.51
|
||||
c0.54,0,1-0.18,1.39-0.55c0.38-0.38,0.57-0.83,0.57-1.37v-7.29h-9.33v-6.93h16.93v16.61c0,1.77-0.64,3.29-1.91,4.56
|
||||
c-1.28,1.27-2.82,1.9-4.62,1.9h-19.48c-1.8,0-3.34-0.63-4.61-1.9C324.35,68.67,323.71,67.15,323.71,65.38"/>
|
||||
<path class="st3" d="M363.69,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st3" d="M396.45,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v16.01"/>
|
||||
<path class="st3" d="M436.14,62.98c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.52c0.54,0,1-0.18,1.39-0.55
|
||||
c0.38-0.38,0.57-0.83,0.57-1.37V41.75c0-0.54-0.19-1.01-0.57-1.41c-0.38-0.4-0.84-0.6-1.39-0.6H438.1c-0.54,0-1,0.2-1.38,0.6
|
||||
c-0.38,0.4-0.57,0.87-0.57,1.41V62.98z M428.65,65.38V39.35c0-1.81,0.63-3.35,1.89-4.62c1.27-1.27,2.78-1.91,4.54-1.91h19.5
|
||||
c1.76,0,3.29,0.64,4.55,1.91c1.27,1.28,1.91,2.82,1.91,4.62v26.03c0,1.79-0.63,3.31-1.89,4.57c-1.27,1.26-2.79,1.89-4.57,1.89h-19.5
|
||||
c-1.79,0-3.3-0.63-4.55-1.89C429.28,68.69,428.65,67.17,428.65,65.38"/>
|
||||
<path class="st3" d="M475.47,49.02h12.73c0.54,0,1-0.19,1.38-0.57c0.39-0.38,0.57-0.84,0.57-1.38v-5.3c0-0.54-0.19-1.01-0.57-1.41
|
||||
c-0.38-0.4-0.84-0.6-1.38-0.6h-12.73V49.02z M467.98,71.84V32.82h23.39c1.8,0,3.34,0.64,4.6,1.91c1.27,1.28,1.9,2.82,1.9,4.62v10.05
|
||||
c0,1.8-0.63,3.35-1.9,4.62c-1.27,1.28-2.8,1.91-4.61,1.91h-0.48l9.55,15.89h-8.16l-9.65-15.89h-7.16v15.89"/>
|
||||
<path class="st3" d="M504.77,65.38V39.35c0-1.81,0.63-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h19.5v6.93h-16.56
|
||||
c-0.54,0-1.01,0.2-1.39,0.59c-0.38,0.39-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.39,0.55h16.56
|
||||
v6.93h-19.5c-1.8,0-3.34-0.63-4.61-1.9C505.4,68.67,504.77,67.15,504.77,65.38"/>
|
||||
<path class="st3" d="M537.34,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st3" d="M573.1,36.84h-0.82V35.3h0.82c1,0,1,0.57,1,0.76C574.1,36.25,574.1,36.84,573.1,36.84 M575.19,36.06
|
||||
c0-1.14-0.8-1.86-2.09-1.86h-1.91v5.18h1.09v-1.44h0.82c0.05,0,0.1,0,0.15,0l1.05,1.45h1.36l-1.29-1.76
|
||||
C574.9,37.29,575.19,36.74,575.19,36.06 M573.21,40.68c-2,0-3.63-1.63-3.63-3.64s1.63-3.63,3.63-3.63s3.63,1.63,3.63,3.63
|
||||
S575.21,40.68,573.21,40.68 M573.21,32.82c-2.33,0-4.23,1.89-4.23,4.23s1.9,4.23,4.23,4.23s4.23-1.9,4.23-4.23
|
||||
S575.54,32.82,573.21,32.82"/>
|
||||
<path class="st3" d="M341.65,118.07h30.51c1.3,0,2.41-0.46,3.32-1.37c0.92-0.91,1.38-2.02,1.38-3.31v-12.72
|
||||
c0-1.29-0.46-2.42-1.38-3.38c-0.91-0.96-2.03-1.44-3.32-1.44h-30.51V118.07z M323.72,172.75v-93.5h56.03
|
||||
c4.33,0,8.01,1.53,11.04,4.59c3.03,3.05,4.55,6.75,4.55,11.08v24.09c0,4.33-1.52,8.02-4.55,11.08c-3.04,3.05-6.72,4.59-11.05,4.59
|
||||
h-1.14l22.89,38.08h-19.54l-23.12-38.08h-17.17v38.08"/>
|
||||
<path class="st3" d="M408.39,95.58V79.25h71.75v16.33h-26.77v77.17h-18.21V95.58"/>
|
||||
<path class="st3" d="M484.82,172.75l30.99-47.19l-29.18-46.45h21.95l18.47,29.52l18.81-29.52h20.15l-29.52,44.44l31.12,49.2h-21.89
|
||||
l-20.35-31.93l-20.55,31.93"/>
|
||||
<path class="st3" d="M221.13,167.89v-1.14h0.73c0.4,0,0.95,0.03,0.95,0.52c0,0.53-0.28,0.62-0.75,0.62H221.13 M221.13,168.7h0.49
|
||||
l1.14,2h1.25l-1.26-2.09c0.65-0.05,1.19-0.36,1.19-1.23c0-1.09-0.75-1.45-2.03-1.45h-1.84v4.77h1.06V168.7 M226.49,168.33
|
||||
c0-2.8-2.17-4.42-4.59-4.42c-2.44,0-4.61,1.62-4.61,4.42c0,2.8,2.18,4.43,4.61,4.43C224.32,172.75,226.49,171.12,226.49,168.33
|
||||
M225.16,168.33c0,2.04-1.5,3.41-3.27,3.41v-0.01c-1.82,0.01-3.29-1.36-3.29-3.39c0-2.04,1.47-3.4,3.29-3.4
|
||||
C223.67,164.93,225.16,166.29,225.16,168.33"/>
|
||||
<path class="st3" d="M110.83,137.83l0,33.49h9.46v-33.49H110.83z M36.43,137.78v33.54h9.54v-25.46l7.39,0c2.45,0,4.2,0.61,5.37,1.87
|
||||
c1.5,1.59,2.11,4.17,2.11,8.87v14.73h9.25v-18.53c0-13.22-8.43-15.01-16.68-15.01H36.43z M126.06,137.83v33.49h15.34
|
||||
c8.17,0,10.84-1.36,13.73-4.41c2.04-2.14,3.36-6.84,3.36-11.97c0-4.71-1.11-8.91-3.06-11.52c-3.5-4.68-8.55-5.59-16.09-5.59H126.06z
|
||||
M135.44,145.12h4.06c5.9,0,9.71,2.65,9.71,9.52c0,6.88-3.81,9.53-9.71,9.53h-4.06V145.12z M97.2,137.83l-7.89,26.54l-7.56-26.54
|
||||
l-10.21,0l10.8,33.49h13.63l10.89-33.49H97.2z M162.88,171.32h9.46v-33.48l-9.46,0V171.32z M189.4,137.84l-13.21,33.46h9.33
|
||||
l2.09-5.91h15.63l1.97,5.91h10.12l-13.3-33.47L189.4,137.84z M195.54,143.95l5.73,15.68h-11.64"/>
|
||||
<path class="st3" d="M61.86,71.16c0,0,12.17-17.96,36.47-19.81v-6.52c-26.91,2.16-50.22,24.96-50.22,24.96s13.2,38.16,50.22,41.65
|
||||
v-6.93C71.16,101.09,61.86,71.16,61.86,71.16"/>
|
||||
<path class="st3" d="M98.33,90.74v6.34c-20.53-3.66-26.23-25-26.23-25s9.86-10.92,26.23-12.69v6.96c-0.01,0-0.02,0-0.03,0
|
||||
c-8.59-1.03-15.3,7-15.3,7S86.75,86.86,98.33,90.74"/>
|
||||
<path class="st3" d="M98.33,32.81v12.02c0.79-0.06,1.58-0.11,2.38-0.14c30.6-1.03,50.54,25.1,50.54,25.1s-22.9,27.84-46.75,27.84
|
||||
c-2.19,0-4.23-0.21-6.16-0.54v7.43c1.64,0.21,3.35,0.33,5.13,0.33c22.2,0,38.25-11.34,53.8-24.75c2.58,2.07,13.13,7.09,15.3,9.28
|
||||
c-14.78,12.38-49.23,22.35-68.75,22.35c-1.88,0-3.69-0.11-5.47-0.29v10.44h84.38V32.81"/>
|
||||
<path class="st3" d="M98.33,59.39v-8.05c0.78-0.05,1.57-0.1,2.38-0.12c22-0.69,36.44,18.91,36.44,18.91s-15.59,21.65-32.31,21.65
|
||||
c-2.41,0-4.56-0.38-6.5-1.04V66.35c8.57,1.04,10.29,4.82,15.44,13.4l11.46-9.66c0,0-8.36-10.96-22.46-10.96
|
||||
C101.23,59.12,99.76,59.23,98.33,59.39"/>
|
||||
<g>
|
||||
<path class="st4" d="M748.65,113.4c0,32.02-19.46,48.99-43.19,48.99c-24.56,0-41.81-19.04-41.81-47.2
|
||||
c0-29.53,18.35-48.85,43.19-48.85C732.22,66.34,748.65,85.8,748.65,113.4z M676.47,114.92c0,19.87,10.76,37.67,29.67,37.67
|
||||
c19.04,0,29.81-17.53,29.81-38.64c0-18.49-9.66-37.81-29.67-37.81C686.41,76.14,676.47,94.49,676.47,114.92z"/>
|
||||
<path class="st4" d="M764.24,67.86h50.09v10.07h-38.09v30.91h35.19v9.94h-35.19v42.09h-12.01V67.86z"/>
|
||||
<path class="st4" d="M831.45,67.86h50.09v10.07h-38.09v30.91h35.19v9.94h-35.19v42.09h-12.01V67.86z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 906 215" style="enable-background:new 0 0 906 215;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#75B943;}
|
||||
.st1{fill:#1D1E1D;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
.st3{fill:#FFFFFF;stroke:#FFFFFF;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<rect x="601.61" y="-0.13" class="st0" width="306" height="215"/>
|
||||
<g id="surface1">
|
||||
<path class="st0" d="M604.9,214.84H-2.43V0.18h662L604.9,214.84z"/>
|
||||
<path class="st1" d="M307.9,0.18l-57.16,214.67h341.99L646.9,0.18H307.9z"/>
|
||||
<path class="st2" d="M323.71,65.38V39.35c0-1.81,0.64-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h24.72v6.93h-21.79
|
||||
c-0.54,0-1,0.2-1.38,0.59s-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.51
|
||||
c0.54,0,1-0.18,1.39-0.55c0.38-0.38,0.57-0.83,0.57-1.37v-7.29h-9.33v-6.93h16.93v16.61c0,1.77-0.64,3.29-1.91,4.56
|
||||
c-1.28,1.27-2.82,1.9-4.62,1.9h-19.48c-1.8,0-3.34-0.63-4.61-1.9C324.35,68.67,323.71,67.15,323.71,65.38"/>
|
||||
<path class="st2" d="M363.69,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st2" d="M396.45,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v16.01"/>
|
||||
<path class="st2" d="M436.14,62.98c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.52c0.54,0,1-0.18,1.39-0.55
|
||||
c0.38-0.38,0.57-0.83,0.57-1.37V41.75c0-0.54-0.19-1.01-0.57-1.41c-0.38-0.4-0.84-0.6-1.39-0.6H438.1c-0.54,0-1,0.2-1.38,0.6
|
||||
c-0.38,0.4-0.57,0.87-0.57,1.41V62.98z M428.65,65.38V39.35c0-1.81,0.63-3.35,1.89-4.62c1.27-1.27,2.78-1.91,4.54-1.91h19.5
|
||||
c1.76,0,3.29,0.64,4.55,1.91c1.27,1.28,1.91,2.82,1.91,4.62v26.03c0,1.79-0.63,3.31-1.89,4.57c-1.27,1.26-2.79,1.89-4.57,1.89
|
||||
h-19.5c-1.79,0-3.3-0.63-4.55-1.89C429.28,68.69,428.65,67.17,428.65,65.38"/>
|
||||
<path class="st2" d="M475.47,49.02h12.73c0.54,0,1-0.19,1.38-0.57c0.39-0.38,0.57-0.84,0.57-1.38v-5.3c0-0.54-0.19-1.01-0.57-1.41
|
||||
c-0.38-0.4-0.84-0.6-1.38-0.6h-12.73V49.02z M467.98,71.84V32.82h23.39c1.8,0,3.34,0.64,4.6,1.91c1.27,1.28,1.9,2.82,1.9,4.62
|
||||
v10.05c0,1.8-0.63,3.35-1.9,4.62c-1.27,1.28-2.8,1.91-4.61,1.91h-0.48l9.55,15.89h-8.16l-9.65-15.89h-7.16v15.89"/>
|
||||
<path class="st2" d="M504.77,65.38V39.35c0-1.81,0.63-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h19.5v6.93h-16.56
|
||||
c-0.54,0-1.01,0.2-1.39,0.59c-0.38,0.39-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.39,0.55h16.56
|
||||
v6.93h-19.5c-1.8,0-3.34-0.63-4.61-1.9C505.4,68.67,504.77,67.15,504.77,65.38"/>
|
||||
<path class="st2" d="M537.34,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st2" d="M573.1,36.84h-0.82V35.3h0.82c1,0,1,0.57,1,0.76C574.1,36.25,574.1,36.84,573.1,36.84 M575.19,36.06
|
||||
c0-1.14-0.8-1.86-2.09-1.86h-1.91v5.18h1.09v-1.44h0.82c0.05,0,0.1,0,0.15,0l1.05,1.45h1.36l-1.29-1.76
|
||||
C574.9,37.29,575.19,36.74,575.19,36.06 M573.21,40.68c-2,0-3.63-1.63-3.63-3.64s1.63-3.63,3.63-3.63s3.63,1.63,3.63,3.63
|
||||
S575.21,40.68,573.21,40.68 M573.21,32.82c-2.33,0-4.23,1.89-4.23,4.23s1.9,4.23,4.23,4.23s4.23-1.9,4.23-4.23
|
||||
S575.54,32.82,573.21,32.82"/>
|
||||
<path class="st2" d="M341.65,118.07h30.51c1.3,0,2.41-0.46,3.32-1.37c0.92-0.91,1.38-2.02,1.38-3.31v-12.72
|
||||
c0-1.29-0.46-2.42-1.38-3.38c-0.91-0.96-2.03-1.44-3.32-1.44h-30.51V118.07z M323.72,172.75v-93.5h56.03
|
||||
c4.33,0,8.01,1.53,11.04,4.59c3.03,3.05,4.55,6.75,4.55,11.08v24.09c0,4.33-1.52,8.02-4.55,11.08c-3.04,3.05-6.72,4.59-11.05,4.59
|
||||
h-1.14l22.89,38.08h-19.54l-23.12-38.08h-17.17v38.08"/>
|
||||
<path class="st2" d="M408.39,95.58V79.25h71.75v16.33h-26.77v77.17h-18.21V95.58"/>
|
||||
<path class="st2" d="M484.82,172.75l30.99-47.19l-29.18-46.45h21.95l18.47,29.52l18.81-29.52h20.15l-29.52,44.44l31.12,49.2h-21.89
|
||||
l-20.35-31.93l-20.55,31.93"/>
|
||||
<path class="st2" d="M221.13,167.89v-1.14h0.73c0.4,0,0.95,0.03,0.95,0.52c0,0.53-0.28,0.62-0.75,0.62H221.13 M221.13,168.7h0.49
|
||||
l1.14,2h1.25l-1.26-2.09c0.65-0.05,1.19-0.36,1.19-1.23c0-1.09-0.75-1.45-2.03-1.45h-1.84v4.77h1.06V168.7 M226.49,168.33
|
||||
c0-2.8-2.17-4.42-4.59-4.42c-2.44,0-4.61,1.62-4.61,4.42c0,2.8,2.18,4.43,4.61,4.43C224.32,172.75,226.49,171.12,226.49,168.33
|
||||
M225.16,168.33c0,2.04-1.5,3.41-3.27,3.41v-0.01c-1.82,0.01-3.29-1.36-3.29-3.39c0-2.04,1.47-3.4,3.29-3.4
|
||||
C223.67,164.93,225.16,166.29,225.16,168.33"/>
|
||||
<path class="st2" d="M110.83,137.83l0,33.49h9.46v-33.49H110.83z M36.43,137.78v33.54h9.54v-25.46l7.39,0
|
||||
c2.45,0,4.2,0.61,5.37,1.87c1.5,1.59,2.11,4.17,2.11,8.87v14.73h9.25v-18.53c0-13.22-8.43-15.01-16.68-15.01H36.43z M126.06,137.83
|
||||
v33.49h15.34c8.17,0,10.84-1.36,13.73-4.41c2.04-2.14,3.36-6.84,3.36-11.97c0-4.71-1.11-8.91-3.06-11.52
|
||||
c-3.5-4.68-8.55-5.59-16.09-5.59H126.06z M135.44,145.12h4.06c5.9,0,9.71,2.65,9.71,9.52c0,6.88-3.81,9.53-9.71,9.53h-4.06V145.12z
|
||||
M97.2,137.83l-7.89,26.54l-7.56-26.54l-10.21,0l10.8,33.49h13.63l10.89-33.49H97.2z M162.88,171.32h9.46v-33.48l-9.46,0V171.32z
|
||||
M189.4,137.84l-13.21,33.46h9.33l2.09-5.91h15.63l1.97,5.91h10.12l-13.3-33.47L189.4,137.84z M195.54,143.95l5.73,15.68h-11.64"/>
|
||||
<path class="st2" d="M61.86,71.16c0,0,12.17-17.96,36.47-19.81v-6.52c-26.91,2.16-50.22,24.96-50.22,24.96s13.2,38.16,50.22,41.65
|
||||
v-6.93C71.16,101.09,61.86,71.16,61.86,71.16"/>
|
||||
<path class="st2" d="M98.33,90.74v6.34c-20.53-3.66-26.23-25-26.23-25s9.86-10.92,26.23-12.69v6.96c-0.01,0-0.02,0-0.03,0
|
||||
c-8.59-1.03-15.3,7-15.3,7S86.75,86.86,98.33,90.74"/>
|
||||
<path class="st2" d="M98.33,32.81v12.02c0.79-0.06,1.58-0.11,2.38-0.14c30.6-1.03,50.54,25.1,50.54,25.1s-22.9,27.84-46.75,27.84
|
||||
c-2.19,0-4.23-0.21-6.16-0.54v7.43c1.64,0.21,3.35,0.33,5.13,0.33c22.2,0,38.25-11.34,53.8-24.75c2.58,2.07,13.13,7.09,15.3,9.28
|
||||
c-14.78,12.38-49.23,22.35-68.75,22.35c-1.88,0-3.69-0.11-5.47-0.29v10.44h84.38V32.81"/>
|
||||
<path class="st2" d="M98.33,59.39v-8.05c0.78-0.05,1.57-0.1,2.38-0.12c22-0.69,36.44,18.91,36.44,18.91s-15.59,21.65-32.31,21.65
|
||||
c-2.41,0-4.56-0.38-6.5-1.04V66.35c8.57,1.04,10.29,4.82,15.44,13.4l11.46-9.66c0,0-8.36-10.96-22.46-10.96
|
||||
C101.23,59.12,99.76,59.23,98.33,59.39"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st3" d="M768.65,113.4c0,32.02-19.46,48.99-43.19,48.99c-24.56,0-41.81-19.04-41.81-47.2
|
||||
c0-29.53,18.35-48.85,43.19-48.85C752.22,66.34,768.65,85.8,768.65,113.4z M696.47,114.92c0,19.87,10.76,37.67,29.67,37.67
|
||||
c19.04,0,29.81-17.53,29.81-38.64c0-18.49-9.66-37.81-29.67-37.81C706.41,76.14,696.47,94.49,696.47,114.92z"/>
|
||||
<path class="st3" d="M784.24,160.87V67.86h13.11l29.81,47.06c6.9,10.9,12.28,20.7,16.7,30.22l0.28-0.14
|
||||
c-1.1-12.42-1.38-23.74-1.38-38.23V67.86h11.32v93.01h-12.14l-29.53-47.2c-6.49-10.35-12.7-20.98-17.39-31.05l-0.41,0.14
|
||||
c0.69,11.73,0.97,22.91,0.97,38.36v39.74H784.24z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 336 KiB |
|
After Width: | Height: | Size: 803 KiB |
|
After Width: | Height: | Size: 227 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
@@ -0,0 +1,352 @@
|
||||
|
||||
#ifndef _NDEBUG
|
||||
precision highp float;
|
||||
const int ns = 5;
|
||||
const int cns = 5;
|
||||
float noise(vec3 v){return 1.;}
|
||||
#endif
|
||||
#define _DEBUG_BREAK {gl_FragColor=vec4(1,0,0,1); return;}
|
||||
#define REFRACTION (c2 >= 0.? (eta*W + (eta*c1 - sqrt(c2))*N) : ((W + c1*N)/sqrt(1.-c1*c1)))
|
||||
vec3 foregroundColor = vec3(.0841, .5329, .9604);
|
||||
vec3 groundColor = vec3(.2, .3, .5);
|
||||
vec4 groundSpecular = vec4(.71, .71, .71, 10.);
|
||||
uniform float uTime;// TIME, IN SECONDS
|
||||
uniform vec3 Ambient[ns], Diffuse[ns];
|
||||
uniform vec4 Specular[ns];
|
||||
uniform float ks[ns], kr[ns], kf[ns];
|
||||
uniform vec4 Sph[ns];
|
||||
uniform vec3 SphCanvas[ns];
|
||||
uniform vec3 Glow[ns];
|
||||
uniform sampler2D uSampler[ns+3];
|
||||
uniform vec3 V0;
|
||||
uniform bool glassy;
|
||||
uniform int sel;
|
||||
const float kf_air = 1.000293;
|
||||
varying vec3 trPos;
|
||||
varying float id;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
const float pi=3.14159265359;
|
||||
const float _2pi=2.*pi;
|
||||
|
||||
/***********PLEASE DO INCREASE n_ref(RT DEPTH) FOR BETTER RESULTS************/
|
||||
/*---->*/const int n_ref=31; //2^n-1 because each hit now spawn at most 2 rays.
|
||||
/**BUT BE CAUTIOUS IF YOU DON'T HAVE A DECENT GRAPHICS CARD (below GTX 950M)**/
|
||||
|
||||
const int max_stack = (n_ref+1)/4;
|
||||
vec3 scolor = vec3(0,0,0);
|
||||
struct Ray{
|
||||
vec3 V;
|
||||
vec3 W;
|
||||
float kf, cumulativeK, decay;
|
||||
} stack1[max_stack], stack2[max_stack];
|
||||
bool modulo2(int n){
|
||||
return n-2*(n/2) == 1;
|
||||
}
|
||||
vec2 getTextCoord(vec3 tex_sph, float R){
|
||||
float tex_x=atan(tex_sph.z,tex_sph.x)/_2pi + 0.5;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
|
||||
tex_x=fract(tex_x+uTime/20.);
|
||||
return vec2(tex_x,-asin(tex_sph.y/R)/pi + 0.5);
|
||||
}
|
||||
#define clamp1(x) ((x)<0.?0.:((x) > 1. ? 1.:(x)))
|
||||
vec3 vec_clamp01(vec3 x) {
|
||||
return vec3(clamp1(x.x), clamp1(x.y), clamp1(x.z));
|
||||
}
|
||||
void main(){
|
||||
// gl_FragColor=vec4(_glassy,0,0,1); return;
|
||||
vec3 LDir=vec3(.5,.5,.5);
|
||||
vec3 LCol=vec3(1.,1.,1.);
|
||||
float currKf = kf_air;
|
||||
vec3 color=vec3(.2, .3, .5);
|
||||
vec3 V = V0;
|
||||
vec3 W=(trPos-V);
|
||||
float glassyw = 1.;
|
||||
// bool glassy = _glassy > .1;
|
||||
if(glassy)
|
||||
{
|
||||
vec2 noiseTex = (texPos.xy + 1.)/2.;
|
||||
noiseTex = vec2(clamp1(noiseTex.x ), clamp1(noiseTex.y ));
|
||||
vec4 Wnoise = texture2D(uSampler[ns+2], noiseTex);
|
||||
W += (Wnoise.xyz-.5)*.4;
|
||||
glassyw = Wnoise.w;
|
||||
}
|
||||
bool selected = false;
|
||||
float currentK = 1.;
|
||||
float curr_decay = 1.;
|
||||
int curr_ptr = 0, curr_top = 0, next_top = 0;
|
||||
bool final = false, stackswap = false, stop = false;
|
||||
for(int j=0;j<n_ref;j++)
|
||||
{
|
||||
for(int curr = 0; curr < max_stack; ++curr){
|
||||
if(curr == curr_ptr){
|
||||
bool skip = false;
|
||||
if(j > 0){
|
||||
Ray currR;
|
||||
if(stackswap)
|
||||
currR = stack1[curr];
|
||||
else
|
||||
currR = stack2[curr];
|
||||
currKf = currR.kf;
|
||||
currentK = currR.cumulativeK;
|
||||
curr_decay = currR.decay;
|
||||
if(currKf <= 0.001 || currentK <= 0.001)
|
||||
skip = true;
|
||||
|
||||
V = currR.V;
|
||||
W = currR.W;
|
||||
}
|
||||
else
|
||||
W = normalize(W);
|
||||
if(!skip){
|
||||
float tMin=10000.;
|
||||
int iMin = -1;
|
||||
for(int i=0;i<cns;i++){
|
||||
vec3 Vp=V-Sph[i].xyz;
|
||||
float B=dot(W,Vp);
|
||||
float C=dot(Vp,Vp)-Sph[i].w*Sph[i].w;
|
||||
float D=B*B-C;
|
||||
if(D>0.){
|
||||
float t=-B-sqrt(D);
|
||||
if(t >= 0.01 && t < tMin){
|
||||
tMin = t; // This is an optimization, we don't have to do lighting/tex
|
||||
iMin = i; // for objects that are occuluded, which is expensive!
|
||||
}
|
||||
else if (t >= -0.01 && t <0.01){
|
||||
t = -(t + 2.*B);
|
||||
if(t > 0.01 && t < tMin){
|
||||
tMin = t;
|
||||
iMin = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(iMin >= 0){
|
||||
if(j == 0 && iMin == sel)
|
||||
selected = true;
|
||||
vec3 S=V+tMin*W;
|
||||
if(curr_decay > .01)
|
||||
curr_decay = curr_decay/(1.+tMin*tMin);
|
||||
for(int i = 0; i < cns; ++ i)
|
||||
if(i == iMin)
|
||||
{
|
||||
if(j == 0)
|
||||
{
|
||||
float intensity = sqrt(dot(Glow[i], Glow[i]));
|
||||
if(intensity > 1.7)
|
||||
{
|
||||
gl_FragColor = vec4(1.74*normalize(Glow[i]), 1.);
|
||||
if(selected)
|
||||
gl_FragColor = vec4(normalize(Glow[i])+vec3(.5,0.,0.), 1.);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 texture_color;
|
||||
vec3 tex_sph = (S-Sph[i].xyz);
|
||||
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
|
||||
|
||||
vec3 N=normalize(S-Sph[i].xyz);
|
||||
vec3 realLDir=normalize(LDir-S);
|
||||
float c1 =dot(N, W);
|
||||
float eta, nextkf;
|
||||
if(c1<0.){
|
||||
color=(Ambient[i]+Diffuse[i]*max(0.,dot(N,realLDir))*LCol)*texture_color;
|
||||
for(int k = 0; k < cns; ++k){
|
||||
if(Glow[k].x > .01){
|
||||
vec3 lDir = Sph[k].xyz - S;
|
||||
float dist = length(lDir);
|
||||
lDir /= (dist);
|
||||
dist -= Sph[k].w;
|
||||
color += (Glow[k]/(1.+dist*dist))*Diffuse[i]*
|
||||
max(0.,dot(N,lDir));
|
||||
}
|
||||
}
|
||||
if(final) //if it's the last hit
|
||||
{
|
||||
color += Specular[i].xyz*pow(max(0.,
|
||||
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
|
||||
if(curr_decay > .01 && Glow[i].x > .01)
|
||||
{
|
||||
vec3 glow_color = currentK*curr_decay*Glow[i];
|
||||
float l = length(glow_color);
|
||||
if(l >=1.7)
|
||||
glow_color/=l/1.7;
|
||||
scolor += glow_color;
|
||||
}
|
||||
|
||||
scolor += color * currentK;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
c1 = -c1;
|
||||
eta = currKf/kf[i];
|
||||
nextkf = kf[i];
|
||||
}
|
||||
}
|
||||
else{
|
||||
N = -N;
|
||||
eta = currKf/kf_air;
|
||||
nextkf = kf_air;
|
||||
color = Ambient[i];
|
||||
}
|
||||
float c2 = (1.-eta*eta*(1.-c1*c1));
|
||||
float nextks = currentK * ks[i], nextkr = currentK * kr[i];
|
||||
bool refl = nextks > 0.01, refr = nextkr > 0.01;
|
||||
if(refl || refr)
|
||||
for(int k = 0; k < max_stack; ++k)
|
||||
if(k == next_top){
|
||||
if(stackswap){
|
||||
if(refl)
|
||||
{
|
||||
stack2[k] = Ray(S, 2. * c1 * N + W, currKf, nextks, curr_decay); //reflection
|
||||
currentK -= nextks;
|
||||
next_top ++;
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
if(refl)
|
||||
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
else
|
||||
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
currentK -= nextkr;
|
||||
next_top ++;
|
||||
}
|
||||
}else{
|
||||
if(refl)
|
||||
{ //remember, c1 = -NW now
|
||||
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks, curr_decay); //reflection
|
||||
currentK -= nextks;
|
||||
next_top ++;
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
if(refl)
|
||||
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
else
|
||||
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
currentK -= nextkr;
|
||||
next_top ++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
scolor += color * currentK;
|
||||
if(curr_decay > .01 && Glow[i].x > .01)
|
||||
{
|
||||
vec3 glow_color = currentK*curr_decay*Glow[i];
|
||||
float l = length(glow_color);
|
||||
if(l >=1.7)
|
||||
glow_color/=l/1.7;
|
||||
scolor += glow_color;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float t = -(.2+V.y)/W.y;
|
||||
float sx = V.x + t* W.x, sz = V.z + t * W.z;
|
||||
|
||||
if(t >= 0. && abs(sx) < 1.5 && abs(sz) < 3.)
|
||||
{
|
||||
if(curr_decay > .01)
|
||||
curr_decay = curr_decay/(1.+t*t);
|
||||
vec3 S = vec3(sx, -.2, sz);
|
||||
vec3 realLDir=normalize(LDir - S);
|
||||
color=(0.5+0.5*max(0.,realLDir.y)*LCol)*texture2D(uSampler[ns], vec2((sx+1.5)/3., (sz+3.)/6.)).xyz;
|
||||
if(final&&abs(sx)<1.5 && abs(sz+.6)<3.)
|
||||
{
|
||||
color += groundSpecular.xyz* //specular for ground.
|
||||
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
|
||||
for(int k = 0; k < cns; ++k){
|
||||
if(Glow[k].x > .01){
|
||||
vec3 lDir = Sph[k].xyz - S;
|
||||
float dist = length(lDir);
|
||||
lDir /= (dist);
|
||||
dist -= Sph[k].w;
|
||||
color += (Glow[k]/(1.+dist*dist))* //specular for ground.
|
||||
pow(max(0., dot(vec3(-lDir.x, lDir.y,-lDir.z),-W)),groundSpecular.w);
|
||||
}
|
||||
}
|
||||
scolor += currentK * color;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int k = 0; k < max_stack; ++k)
|
||||
if(k == next_top){
|
||||
if(stackswap)
|
||||
stack2[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15, curr_decay); //reflection
|
||||
else
|
||||
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15, curr_decay); //reflection
|
||||
next_top ++;
|
||||
break;
|
||||
}
|
||||
scolor += (currentK*.85)*color;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(j > 0)
|
||||
{
|
||||
scolor += currentK * (pow(max(0.,dot(W, normalize(LDir - V))), 10.) * vec3(3.,3.,3.) + foregroundColor*0.1);
|
||||
for(int k = 0; k < cns; ++k){
|
||||
if(Glow[k].x > .01){
|
||||
vec3 lDir = Sph[k].xyz - V;
|
||||
float dist = length(lDir);
|
||||
lDir /= (dist);
|
||||
dist -= Sph[k].w;
|
||||
color += (Glow[k]/(1.+dist*dist))* //specular for ground.
|
||||
pow(max(0., dot(vec3(-lDir.x, lDir.y,-lDir.z),W)),groundSpecular.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
else scolor = foregroundColor*0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(++curr_ptr >= curr_top){
|
||||
if(next_top <= 0)
|
||||
stop = true;
|
||||
if(next_top * 2 > max_stack)
|
||||
final = true;
|
||||
curr_top = next_top;
|
||||
next_top = 0;
|
||||
curr_ptr = 0;
|
||||
stackswap = !stackswap;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stop)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(glassy)
|
||||
scolor *= glassyw*glassyw;
|
||||
for(int i = 0; i < ns; ++i){
|
||||
if(i == sel)
|
||||
continue;
|
||||
vec2 sx = SphCanvas[i].xy - texPos.xy;
|
||||
float theta = atan(sx.y/sx.x);
|
||||
if(sx.x > 0. && theta < 0.)
|
||||
theta += _2pi;
|
||||
else if(sx.x < 0.)
|
||||
theta += pi;
|
||||
float intensity = sqrt(dot(Glow[i], Glow[i]));
|
||||
vec3 realD = Sph[i].xyz - V0;
|
||||
float realDist = sqrt(dot(realD, realD))-Sph[i].w;
|
||||
intensity/=(1.+realDist*realDist);
|
||||
float dist = dot(sx, sx) - SphCanvas[i].z*SphCanvas[i].z;
|
||||
intensity *= .5;
|
||||
if(dist < intensity && dist > 0.)
|
||||
{
|
||||
vec3 flare = texture2D(uSampler[ns+1], vec2(0.1+0.9*(dist/intensity), theta/float(2*i+7))).xyz;
|
||||
scolor += flare*flare*Glow[i]/(1.+realDist*realDist);
|
||||
}
|
||||
}
|
||||
scolor = vec_clamp01(scolor);
|
||||
if(selected)
|
||||
scolor.x += 0.5;
|
||||
gl_FragColor=vec4(sqrt(scolor),1.);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
attribute float oid;
|
||||
attribute vec3 aPos;
|
||||
attribute vec3 normal;
|
||||
varying vec3 trPos;
|
||||
uniform mat3 transformation;
|
||||
uniform mat4 uMatrix;
|
||||
varying float id;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
//I used mat3 instead of the augmented mat4 matrix because we
|
||||
//are not doing complex projections yet. I implemented simple
|
||||
//perspective projection back in hw2 by changing focal length
|
||||
//and adjusting the size of the projected surface accrodingly.
|
||||
//New surface = distance(surface, old viewpoint)/ distance(surface, new viewpoint) * old surface
|
||||
// = (deltaFl + fl + 1)/(fl + 1) * old surface
|
||||
//This is implemented by vPos = (dFl + fl + 1)/(fl + 1) * vPos;
|
||||
//Because we will multiply the resulting vPos by the transformation matrix
|
||||
//anyway, I smashed the ratio into the matrix into avoid doing this in shaders.
|
||||
void main() {
|
||||
vec4 pos = uMatrix * vec4(aPos, 1.);
|
||||
gl_Position = pos;
|
||||
id = oid;
|
||||
norm = normal;
|
||||
trPos = transformation *vec3(aPos.x, -aPos.y, -1);
|
||||
texPos = vec3(aPos.x, -aPos.y, -1.);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 906 215" style="enable-background:new 0 0 906 215;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#666666;}
|
||||
.st1{fill:#606060;}
|
||||
.st2{fill:#1D1E1D;}
|
||||
.st3{fill:#FFFFFF;}
|
||||
.st4{fill:#FFFFFF;stroke:#FFFFFF;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<rect x="601.61" y="-0.13" class="st0" width="306" height="215"/>
|
||||
<path class="st1" d="M604.9,214.84H-2.43V0.18h662L604.9,214.84z"/>
|
||||
<path class="st2" d="M307.9,0.18l-57.16,214.67h341.99L646.9,0.18H307.9z"/>
|
||||
<path class="st3" d="M323.71,65.38V39.35c0-1.81,0.64-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h24.72v6.93h-21.79
|
||||
c-0.54,0-1,0.2-1.38,0.59s-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.51
|
||||
c0.54,0,1-0.18,1.39-0.55c0.38-0.38,0.57-0.83,0.57-1.37v-7.29h-9.33v-6.93h16.93v16.61c0,1.77-0.64,3.29-1.91,4.56
|
||||
c-1.28,1.27-2.82,1.9-4.62,1.9h-19.48c-1.8,0-3.34-0.63-4.61-1.9C324.35,68.67,323.71,67.15,323.71,65.38"/>
|
||||
<path class="st3" d="M363.69,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st3" d="M396.45,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v16.01"/>
|
||||
<path class="st3" d="M436.14,62.98c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.52c0.54,0,1-0.18,1.39-0.55
|
||||
c0.38-0.38,0.57-0.83,0.57-1.37V41.75c0-0.54-0.19-1.01-0.57-1.41c-0.38-0.4-0.84-0.6-1.39-0.6H438.1c-0.54,0-1,0.2-1.38,0.6
|
||||
c-0.38,0.4-0.57,0.87-0.57,1.41V62.98z M428.65,65.38V39.35c0-1.81,0.63-3.35,1.89-4.62c1.27-1.27,2.78-1.91,4.54-1.91h19.5
|
||||
c1.76,0,3.29,0.64,4.55,1.91c1.27,1.28,1.91,2.82,1.91,4.62v26.03c0,1.79-0.63,3.31-1.89,4.57c-1.27,1.26-2.79,1.89-4.57,1.89h-19.5
|
||||
c-1.79,0-3.3-0.63-4.55-1.89C429.28,68.69,428.65,67.17,428.65,65.38"/>
|
||||
<path class="st3" d="M475.47,49.02h12.73c0.54,0,1-0.19,1.38-0.57c0.39-0.38,0.57-0.84,0.57-1.38v-5.3c0-0.54-0.19-1.01-0.57-1.41
|
||||
c-0.38-0.4-0.84-0.6-1.38-0.6h-12.73V49.02z M467.98,71.84V32.82h23.39c1.8,0,3.34,0.64,4.6,1.91c1.27,1.28,1.9,2.82,1.9,4.62v10.05
|
||||
c0,1.8-0.63,3.35-1.9,4.62c-1.27,1.28-2.8,1.91-4.61,1.91h-0.48l9.55,15.89h-8.16l-9.65-15.89h-7.16v15.89"/>
|
||||
<path class="st3" d="M504.77,65.38V39.35c0-1.81,0.63-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h19.5v6.93h-16.56
|
||||
c-0.54,0-1.01,0.2-1.39,0.59c-0.38,0.39-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.39,0.55h16.56
|
||||
v6.93h-19.5c-1.8,0-3.34-0.63-4.61-1.9C505.4,68.67,504.77,67.15,504.77,65.38"/>
|
||||
<path class="st3" d="M537.34,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st3" d="M573.1,36.84h-0.82V35.3h0.82c1,0,1,0.57,1,0.76C574.1,36.25,574.1,36.84,573.1,36.84 M575.19,36.06
|
||||
c0-1.14-0.8-1.86-2.09-1.86h-1.91v5.18h1.09v-1.44h0.82c0.05,0,0.1,0,0.15,0l1.05,1.45h1.36l-1.29-1.76
|
||||
C574.9,37.29,575.19,36.74,575.19,36.06 M573.21,40.68c-2,0-3.63-1.63-3.63-3.64s1.63-3.63,3.63-3.63s3.63,1.63,3.63,3.63
|
||||
S575.21,40.68,573.21,40.68 M573.21,32.82c-2.33,0-4.23,1.89-4.23,4.23s1.9,4.23,4.23,4.23s4.23-1.9,4.23-4.23
|
||||
S575.54,32.82,573.21,32.82"/>
|
||||
<path class="st3" d="M341.65,118.07h30.51c1.3,0,2.41-0.46,3.32-1.37c0.92-0.91,1.38-2.02,1.38-3.31v-12.72
|
||||
c0-1.29-0.46-2.42-1.38-3.38c-0.91-0.96-2.03-1.44-3.32-1.44h-30.51V118.07z M323.72,172.75v-93.5h56.03
|
||||
c4.33,0,8.01,1.53,11.04,4.59c3.03,3.05,4.55,6.75,4.55,11.08v24.09c0,4.33-1.52,8.02-4.55,11.08c-3.04,3.05-6.72,4.59-11.05,4.59
|
||||
h-1.14l22.89,38.08h-19.54l-23.12-38.08h-17.17v38.08"/>
|
||||
<path class="st3" d="M408.39,95.58V79.25h71.75v16.33h-26.77v77.17h-18.21V95.58"/>
|
||||
<path class="st3" d="M484.82,172.75l30.99-47.19l-29.18-46.45h21.95l18.47,29.52l18.81-29.52h20.15l-29.52,44.44l31.12,49.2h-21.89
|
||||
l-20.35-31.93l-20.55,31.93"/>
|
||||
<path class="st3" d="M221.13,167.89v-1.14h0.73c0.4,0,0.95,0.03,0.95,0.52c0,0.53-0.28,0.62-0.75,0.62H221.13 M221.13,168.7h0.49
|
||||
l1.14,2h1.25l-1.26-2.09c0.65-0.05,1.19-0.36,1.19-1.23c0-1.09-0.75-1.45-2.03-1.45h-1.84v4.77h1.06V168.7 M226.49,168.33
|
||||
c0-2.8-2.17-4.42-4.59-4.42c-2.44,0-4.61,1.62-4.61,4.42c0,2.8,2.18,4.43,4.61,4.43C224.32,172.75,226.49,171.12,226.49,168.33
|
||||
M225.16,168.33c0,2.04-1.5,3.41-3.27,3.41v-0.01c-1.82,0.01-3.29-1.36-3.29-3.39c0-2.04,1.47-3.4,3.29-3.4
|
||||
C223.67,164.93,225.16,166.29,225.16,168.33"/>
|
||||
<path class="st3" d="M110.83,137.83l0,33.49h9.46v-33.49H110.83z M36.43,137.78v33.54h9.54v-25.46l7.39,0c2.45,0,4.2,0.61,5.37,1.87
|
||||
c1.5,1.59,2.11,4.17,2.11,8.87v14.73h9.25v-18.53c0-13.22-8.43-15.01-16.68-15.01H36.43z M126.06,137.83v33.49h15.34
|
||||
c8.17,0,10.84-1.36,13.73-4.41c2.04-2.14,3.36-6.84,3.36-11.97c0-4.71-1.11-8.91-3.06-11.52c-3.5-4.68-8.55-5.59-16.09-5.59H126.06z
|
||||
M135.44,145.12h4.06c5.9,0,9.71,2.65,9.71,9.52c0,6.88-3.81,9.53-9.71,9.53h-4.06V145.12z M97.2,137.83l-7.89,26.54l-7.56-26.54
|
||||
l-10.21,0l10.8,33.49h13.63l10.89-33.49H97.2z M162.88,171.32h9.46v-33.48l-9.46,0V171.32z M189.4,137.84l-13.21,33.46h9.33
|
||||
l2.09-5.91h15.63l1.97,5.91h10.12l-13.3-33.47L189.4,137.84z M195.54,143.95l5.73,15.68h-11.64"/>
|
||||
<path class="st3" d="M61.86,71.16c0,0,12.17-17.96,36.47-19.81v-6.52c-26.91,2.16-50.22,24.96-50.22,24.96s13.2,38.16,50.22,41.65
|
||||
v-6.93C71.16,101.09,61.86,71.16,61.86,71.16"/>
|
||||
<path class="st3" d="M98.33,90.74v6.34c-20.53-3.66-26.23-25-26.23-25s9.86-10.92,26.23-12.69v6.96c-0.01,0-0.02,0-0.03,0
|
||||
c-8.59-1.03-15.3,7-15.3,7S86.75,86.86,98.33,90.74"/>
|
||||
<path class="st3" d="M98.33,32.81v12.02c0.79-0.06,1.58-0.11,2.38-0.14c30.6-1.03,50.54,25.1,50.54,25.1s-22.9,27.84-46.75,27.84
|
||||
c-2.19,0-4.23-0.21-6.16-0.54v7.43c1.64,0.21,3.35,0.33,5.13,0.33c22.2,0,38.25-11.34,53.8-24.75c2.58,2.07,13.13,7.09,15.3,9.28
|
||||
c-14.78,12.38-49.23,22.35-68.75,22.35c-1.88,0-3.69-0.11-5.47-0.29v10.44h84.38V32.81"/>
|
||||
<path class="st3" d="M98.33,59.39v-8.05c0.78-0.05,1.57-0.1,2.38-0.12c22-0.69,36.44,18.91,36.44,18.91s-15.59,21.65-32.31,21.65
|
||||
c-2.41,0-4.56-0.38-6.5-1.04V66.35c8.57,1.04,10.29,4.82,15.44,13.4l11.46-9.66c0,0-8.36-10.96-22.46-10.96
|
||||
C101.23,59.12,99.76,59.23,98.33,59.39"/>
|
||||
<g>
|
||||
<path class="st4" d="M748.65,113.4c0,32.02-19.46,48.99-43.19,48.99c-24.56,0-41.81-19.04-41.81-47.2
|
||||
c0-29.53,18.35-48.85,43.19-48.85C732.22,66.34,748.65,85.8,748.65,113.4z M676.47,114.92c0,19.87,10.76,37.67,29.67,37.67
|
||||
c19.04,0,29.81-17.53,29.81-38.64c0-18.49-9.66-37.81-29.67-37.81C686.41,76.14,676.47,94.49,676.47,114.92z"/>
|
||||
<path class="st4" d="M764.24,67.86h50.09v10.07h-38.09v30.91h35.19v9.94h-35.19v42.09h-12.01V67.86z"/>
|
||||
<path class="st4" d="M831.45,67.86h50.09v10.07h-38.09v30.91h35.19v9.94h-35.19v42.09h-12.01V67.86z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 906 215" style="enable-background:new 0 0 906 215;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#75B943;}
|
||||
.st1{fill:#1D1E1D;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
.st3{fill:#FFFFFF;stroke:#FFFFFF;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<rect x="601.61" y="-0.13" class="st0" width="306" height="215"/>
|
||||
<g id="surface1">
|
||||
<path class="st0" d="M604.9,214.84H-2.43V0.18h662L604.9,214.84z"/>
|
||||
<path class="st1" d="M307.9,0.18l-57.16,214.67h341.99L646.9,0.18H307.9z"/>
|
||||
<path class="st2" d="M323.71,65.38V39.35c0-1.81,0.64-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h24.72v6.93h-21.79
|
||||
c-0.54,0-1,0.2-1.38,0.59s-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.51
|
||||
c0.54,0,1-0.18,1.39-0.55c0.38-0.38,0.57-0.83,0.57-1.37v-7.29h-9.33v-6.93h16.93v16.61c0,1.77-0.64,3.29-1.91,4.56
|
||||
c-1.28,1.27-2.82,1.9-4.62,1.9h-19.48c-1.8,0-3.34-0.63-4.61-1.9C324.35,68.67,323.71,67.15,323.71,65.38"/>
|
||||
<path class="st2" d="M363.69,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st2" d="M396.45,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v16.01"/>
|
||||
<path class="st2" d="M436.14,62.98c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.38,0.55h13.52c0.54,0,1-0.18,1.39-0.55
|
||||
c0.38-0.38,0.57-0.83,0.57-1.37V41.75c0-0.54-0.19-1.01-0.57-1.41c-0.38-0.4-0.84-0.6-1.39-0.6H438.1c-0.54,0-1,0.2-1.38,0.6
|
||||
c-0.38,0.4-0.57,0.87-0.57,1.41V62.98z M428.65,65.38V39.35c0-1.81,0.63-3.35,1.89-4.62c1.27-1.27,2.78-1.91,4.54-1.91h19.5
|
||||
c1.76,0,3.29,0.64,4.55,1.91c1.27,1.28,1.91,2.82,1.91,4.62v26.03c0,1.79-0.63,3.31-1.89,4.57c-1.27,1.26-2.79,1.89-4.57,1.89
|
||||
h-19.5c-1.79,0-3.3-0.63-4.55-1.89C429.28,68.69,428.65,67.17,428.65,65.38"/>
|
||||
<path class="st2" d="M475.47,49.02h12.73c0.54,0,1-0.19,1.38-0.57c0.39-0.38,0.57-0.84,0.57-1.38v-5.3c0-0.54-0.19-1.01-0.57-1.41
|
||||
c-0.38-0.4-0.84-0.6-1.38-0.6h-12.73V49.02z M467.98,71.84V32.82h23.39c1.8,0,3.34,0.64,4.6,1.91c1.27,1.28,1.9,2.82,1.9,4.62
|
||||
v10.05c0,1.8-0.63,3.35-1.9,4.62c-1.27,1.28-2.8,1.91-4.61,1.91h-0.48l9.55,15.89h-8.16l-9.65-15.89h-7.16v15.89"/>
|
||||
<path class="st2" d="M504.77,65.38V39.35c0-1.81,0.63-3.35,1.9-4.62c1.27-1.27,2.8-1.91,4.61-1.91h19.5v6.93h-16.56
|
||||
c-0.54,0-1.01,0.2-1.39,0.59c-0.38,0.39-0.57,0.85-0.57,1.37v21.29c0,0.54,0.19,1,0.57,1.37c0.38,0.37,0.84,0.55,1.39,0.55h16.56
|
||||
v6.93h-19.5c-1.8,0-3.34-0.63-4.61-1.9C505.4,68.67,504.77,67.15,504.77,65.38"/>
|
||||
<path class="st2" d="M537.34,71.84V32.81h27.34v6.93h-19.75v9.16h15.86v6.93h-15.86v9.08h19.75v6.93"/>
|
||||
<path class="st2" d="M573.1,36.84h-0.82V35.3h0.82c1,0,1,0.57,1,0.76C574.1,36.25,574.1,36.84,573.1,36.84 M575.19,36.06
|
||||
c0-1.14-0.8-1.86-2.09-1.86h-1.91v5.18h1.09v-1.44h0.82c0.05,0,0.1,0,0.15,0l1.05,1.45h1.36l-1.29-1.76
|
||||
C574.9,37.29,575.19,36.74,575.19,36.06 M573.21,40.68c-2,0-3.63-1.63-3.63-3.64s1.63-3.63,3.63-3.63s3.63,1.63,3.63,3.63
|
||||
S575.21,40.68,573.21,40.68 M573.21,32.82c-2.33,0-4.23,1.89-4.23,4.23s1.9,4.23,4.23,4.23s4.23-1.9,4.23-4.23
|
||||
S575.54,32.82,573.21,32.82"/>
|
||||
<path class="st2" d="M341.65,118.07h30.51c1.3,0,2.41-0.46,3.32-1.37c0.92-0.91,1.38-2.02,1.38-3.31v-12.72
|
||||
c0-1.29-0.46-2.42-1.38-3.38c-0.91-0.96-2.03-1.44-3.32-1.44h-30.51V118.07z M323.72,172.75v-93.5h56.03
|
||||
c4.33,0,8.01,1.53,11.04,4.59c3.03,3.05,4.55,6.75,4.55,11.08v24.09c0,4.33-1.52,8.02-4.55,11.08c-3.04,3.05-6.72,4.59-11.05,4.59
|
||||
h-1.14l22.89,38.08h-19.54l-23.12-38.08h-17.17v38.08"/>
|
||||
<path class="st2" d="M408.39,95.58V79.25h71.75v16.33h-26.77v77.17h-18.21V95.58"/>
|
||||
<path class="st2" d="M484.82,172.75l30.99-47.19l-29.18-46.45h21.95l18.47,29.52l18.81-29.52h20.15l-29.52,44.44l31.12,49.2h-21.89
|
||||
l-20.35-31.93l-20.55,31.93"/>
|
||||
<path class="st2" d="M221.13,167.89v-1.14h0.73c0.4,0,0.95,0.03,0.95,0.52c0,0.53-0.28,0.62-0.75,0.62H221.13 M221.13,168.7h0.49
|
||||
l1.14,2h1.25l-1.26-2.09c0.65-0.05,1.19-0.36,1.19-1.23c0-1.09-0.75-1.45-2.03-1.45h-1.84v4.77h1.06V168.7 M226.49,168.33
|
||||
c0-2.8-2.17-4.42-4.59-4.42c-2.44,0-4.61,1.62-4.61,4.42c0,2.8,2.18,4.43,4.61,4.43C224.32,172.75,226.49,171.12,226.49,168.33
|
||||
M225.16,168.33c0,2.04-1.5,3.41-3.27,3.41v-0.01c-1.82,0.01-3.29-1.36-3.29-3.39c0-2.04,1.47-3.4,3.29-3.4
|
||||
C223.67,164.93,225.16,166.29,225.16,168.33"/>
|
||||
<path class="st2" d="M110.83,137.83l0,33.49h9.46v-33.49H110.83z M36.43,137.78v33.54h9.54v-25.46l7.39,0
|
||||
c2.45,0,4.2,0.61,5.37,1.87c1.5,1.59,2.11,4.17,2.11,8.87v14.73h9.25v-18.53c0-13.22-8.43-15.01-16.68-15.01H36.43z M126.06,137.83
|
||||
v33.49h15.34c8.17,0,10.84-1.36,13.73-4.41c2.04-2.14,3.36-6.84,3.36-11.97c0-4.71-1.11-8.91-3.06-11.52
|
||||
c-3.5-4.68-8.55-5.59-16.09-5.59H126.06z M135.44,145.12h4.06c5.9,0,9.71,2.65,9.71,9.52c0,6.88-3.81,9.53-9.71,9.53h-4.06V145.12z
|
||||
M97.2,137.83l-7.89,26.54l-7.56-26.54l-10.21,0l10.8,33.49h13.63l10.89-33.49H97.2z M162.88,171.32h9.46v-33.48l-9.46,0V171.32z
|
||||
M189.4,137.84l-13.21,33.46h9.33l2.09-5.91h15.63l1.97,5.91h10.12l-13.3-33.47L189.4,137.84z M195.54,143.95l5.73,15.68h-11.64"/>
|
||||
<path class="st2" d="M61.86,71.16c0,0,12.17-17.96,36.47-19.81v-6.52c-26.91,2.16-50.22,24.96-50.22,24.96s13.2,38.16,50.22,41.65
|
||||
v-6.93C71.16,101.09,61.86,71.16,61.86,71.16"/>
|
||||
<path class="st2" d="M98.33,90.74v6.34c-20.53-3.66-26.23-25-26.23-25s9.86-10.92,26.23-12.69v6.96c-0.01,0-0.02,0-0.03,0
|
||||
c-8.59-1.03-15.3,7-15.3,7S86.75,86.86,98.33,90.74"/>
|
||||
<path class="st2" d="M98.33,32.81v12.02c0.79-0.06,1.58-0.11,2.38-0.14c30.6-1.03,50.54,25.1,50.54,25.1s-22.9,27.84-46.75,27.84
|
||||
c-2.19,0-4.23-0.21-6.16-0.54v7.43c1.64,0.21,3.35,0.33,5.13,0.33c22.2,0,38.25-11.34,53.8-24.75c2.58,2.07,13.13,7.09,15.3,9.28
|
||||
c-14.78,12.38-49.23,22.35-68.75,22.35c-1.88,0-3.69-0.11-5.47-0.29v10.44h84.38V32.81"/>
|
||||
<path class="st2" d="M98.33,59.39v-8.05c0.78-0.05,1.57-0.1,2.38-0.12c22-0.69,36.44,18.91,36.44,18.91s-15.59,21.65-32.31,21.65
|
||||
c-2.41,0-4.56-0.38-6.5-1.04V66.35c8.57,1.04,10.29,4.82,15.44,13.4l11.46-9.66c0,0-8.36-10.96-22.46-10.96
|
||||
C101.23,59.12,99.76,59.23,98.33,59.39"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st3" d="M768.65,113.4c0,32.02-19.46,48.99-43.19,48.99c-24.56,0-41.81-19.04-41.81-47.2
|
||||
c0-29.53,18.35-48.85,43.19-48.85C752.22,66.34,768.65,85.8,768.65,113.4z M696.47,114.92c0,19.87,10.76,37.67,29.67,37.67
|
||||
c19.04,0,29.81-17.53,29.81-38.64c0-18.49-9.66-37.81-29.67-37.81C706.41,76.14,696.47,94.49,696.47,114.92z"/>
|
||||
<path class="st3" d="M784.24,160.87V67.86h13.11l29.81,47.06c6.9,10.9,12.28,20.7,16.7,30.22l0.28-0.14
|
||||
c-1.1-12.42-1.38-23.74-1.38-38.23V67.86h11.32v93.01h-12.14l-29.53-47.2c-6.49-10.35-12.7-20.98-17.39-31.05l-0.41,0.14
|
||||
c0.69,11.73,0.97,22.91,0.97,38.36v39.74H784.24z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,201 @@
|
||||
|
||||
function implicitSurfaceTriangleMesh(implicitFunction, n, args, id = 8) {
|
||||
|
||||
// HERE IS WHERE MOST OF THE WORK HAPPENS
|
||||
|
||||
let marchingTetrahedra = function(V, ni, nj) {
|
||||
|
||||
// CONVENIENCE FUNCTIONS TO COMPUTE (i,j,k) FROM VOLUME INDEX n
|
||||
|
||||
function n2i(n) { return n % ni; }
|
||||
function n2j(n) { return (n / dj >>> 0) % nj; }
|
||||
function n2k(n) { return n / dk >>> 0 ; }
|
||||
|
||||
// ADD A VERTEX, AND RETURN A UNIQUE ID FOR THAT VERTEX
|
||||
|
||||
function E(a, b) {
|
||||
if (a > b) { let tmp = a; a = b; b = tmp; }
|
||||
let ai = n2i(a), aj = n2j(a), ak = n2k(a),
|
||||
bi = n2i(b), bj = n2j(b), bk = n2k(b);
|
||||
let m = (n << 6) + (ai & bi ? 1 << 6 : ai | bi << 3)
|
||||
+ (aj & bj ? dj << 6 : aj << 1 | bj << 4)
|
||||
+ (ak & bk ? dk << 6 : ak << 2 | bk << 5);
|
||||
|
||||
// ADD TO VERTEX ARRAY ONLY THE FIRST TIME THE VERTEX IS ENCOUNTERED
|
||||
|
||||
if (vertexID[m] === undefined) {
|
||||
vertexID[m] = P.length / 3;
|
||||
let t = -V[n+a] / (V[n+b] - V[n+a]),
|
||||
c = function(i,a,b) { return (i + (1-t)*a + t*b) / ni * 2 - 1; };
|
||||
P.push( c(i,ai,bi), c(j,aj,bj), c(k,ak,bk) );
|
||||
}
|
||||
|
||||
return vertexID[m];
|
||||
}
|
||||
|
||||
// CASE WHERE WE ADD ONE TRIANGLE IN A TETRAHEDRON
|
||||
|
||||
function tri(a, b, c, d) {
|
||||
T.push(E(a,b), E(a,c), E(a,d));
|
||||
}
|
||||
|
||||
// CASE WHERE WE ADD TWO TRIANGLES IN A TETRAHEDRON
|
||||
|
||||
function quad(a, b, c, d) {
|
||||
let ac = E(a,c), bc = E(b,c), ad = E(a,d), bd = E(b,d);
|
||||
T.push(bc, ac, ad);
|
||||
T.push(ad, bd, bc);
|
||||
}
|
||||
|
||||
// DECLARE VARIABLES
|
||||
|
||||
let nk = V.length / (ni * nj), di = 1, dj = ni, dk = ni * nj;
|
||||
let dij = di + dj, dik = di + dk, djk = dj + dk, dijk = di + dj + dk;
|
||||
let P = [], T = [], vertexID = [], i, j, k, m = 0, n, S = [0,di,dij,dijk];
|
||||
let lo = new Array(nj * nk),
|
||||
hi = new Array(nj * nk);
|
||||
|
||||
// THE SIX POSSIBLE INTERMEDIATE PATHS THROUGH A TETRAHEDRON
|
||||
|
||||
let S1 = [di , dj , dk , di , dj , dk ];
|
||||
let S2 = [dij, djk, dik, dik, dij, djk];
|
||||
|
||||
// THERE ARE 16 CASES TO CONSIDER
|
||||
|
||||
let cases = [ [0 ], [1, 0,1,2,3], [1, 1,2,0,3], [2, 0,1,2,3],
|
||||
[1, 2,3,0,1], [2, 0,2,3,1], [2, 1,2,0,3], [1, 3,1,2,0],
|
||||
[1, 3,0,2,1], [2, 0,3,1,2], [2, 1,3,2,0], [1, 2,1,0,3],
|
||||
[2, 2,3,0,1], [1, 1,3,0,2], [1, 0,3,2,1], [0 ], ];
|
||||
|
||||
// FOR EACH (Y,Z), DON'T DO ANY WORK OUTSIDE OF X RANGE WHERE SURFACE MIGHT BE
|
||||
|
||||
for (k = 0 ; k < nk ; k++)
|
||||
for (j = 0 ; j < nj ; j++, m++) {
|
||||
let n0 = m * ni, n1 = n0 + ni - 1;
|
||||
for (n = n0 ; n <= n1 && V[n] > 0 ; n++) ;
|
||||
lo[m] = Math.max(0, n-1 - n0);
|
||||
for (n = n1 ; n >= n0 && V[n] > 0 ; --n) ;
|
||||
hi[m] = Math.min(ni-1, n+1 - n0);
|
||||
}
|
||||
|
||||
// FOR ALL Y AND Z IN THE VOLUME
|
||||
|
||||
for (k = 0 ; k < nk - 1 ; k++) {
|
||||
let i0, i1, m = k * nj, n1, s0, s1;
|
||||
for (j = 0 ; j < nj - 1 ; j++, m++) {
|
||||
i0 = Math.min(lo[m], lo[m+1], lo[m+ni], lo[m+1+ni]);
|
||||
i1 = Math.max(hi[m], hi[m+1], hi[m+ni], hi[m+1+ni]);
|
||||
|
||||
// GO THROUGH RANGE OF X WHERE THE SURFACE MIGHT BE (IE: WITH ANY POSITIVE VALUES)
|
||||
|
||||
if (i0 <= i1) {
|
||||
n = m * ni + i0;
|
||||
n1 = m * ni + i1;
|
||||
s0 = (V[n]>0) + (V[n+dj]>0) + (V[n+dk]>0) + (V[n+djk]>0);
|
||||
for (i = i0 ; n <= n1 ; i++, n++, s0 = s1) {
|
||||
|
||||
// FOR EACH CUBE
|
||||
|
||||
s1 = (V[n+di]>0) + (V[n+dij]>0) + (V[n+dik]>0) + (V[n+dijk]>0);
|
||||
if (s0 + s1 & 7) {
|
||||
let C14 = (V[n] > 0) | (V[n+dijk] > 0) << 3;
|
||||
|
||||
// CYCLE THROUGH THE SIX TETRAHEDRA THAT TILE THE CUBE
|
||||
|
||||
for (let p = 0 ; p < 6 ; p++) {
|
||||
let C = cases [ C14 | (V[n+S1[p]] > 0) << 1 | (V[n+S2[p]] > 0) << 2 ];
|
||||
|
||||
// FOR EACH TETRAHEDRON, OUTPUT EITHER ZERO, ONE OR TWO TRIANGLES
|
||||
|
||||
if (C[0]) { // C[0] == number of triangles to be created.
|
||||
S[1] = S1[p]; // assign 2nd and 3rd corners of simplex.
|
||||
S[2] = S2[p];
|
||||
(C[0]==1 ? tri : quad)(S[C[1]], S[C[2]], S[C[3]], S[C[4]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MAKE SURE ALL TRIANGLE VERTICES ARE LISTED IN COUNTERCLOCKWISE ORDER
|
||||
|
||||
for (let m = 0 ; m < T.length ; m += 3) {
|
||||
let a = 3 * T[m], b = 3 * T[m+1], c = 3 * T[m+2],
|
||||
n = Math.floor(ni*(P[a ]+1)/2) +
|
||||
Math.floor(ni*(P[a+1]+1)/2) * dj +
|
||||
Math.floor(ni*(P[a+2]+1)/2) * dk,
|
||||
u = cross([P[b] - P[a], P[b+1] - P[a+1], P[b+2] - P[a+2]],
|
||||
[P[c] - P[b], P[c+1] - P[b+1], P[c+2] - P[b+2]]),
|
||||
v = [ V[n+1] - V[n], V[n+dj] - V[n], V[n+dk] - V[n] ];
|
||||
if (dot(u, v) < 0) { let tmp = T[m]; T[m] = T[m + 2]; T[m + 2] = tmp; }
|
||||
}
|
||||
|
||||
// RETURN POINTS AND TRIANGLES
|
||||
|
||||
return [P, T];
|
||||
}
|
||||
|
||||
// SAMPLE THE VOLUME
|
||||
|
||||
let F = i => (i - n/2) / (n/2);
|
||||
let volume = [];
|
||||
|
||||
for (let k = 0 ; k < n ; k++)
|
||||
for (let j = 0 ; j < n ; j++)
|
||||
for (let i = 0 ; i < n ; i++)
|
||||
volume.push(implicitFunction(F(i), F(j), F(k), args));
|
||||
|
||||
// FIND ALL VERTICES AND TRIANGLES IN THE VOLUME
|
||||
|
||||
let VT = marchingTetrahedra(volume, n, n);
|
||||
let V = VT[0];
|
||||
let T = VT[1];
|
||||
|
||||
// COMPUTE SURFACE NORMALS
|
||||
|
||||
let N = new Array(V.length);
|
||||
for (let i = 0 ; i < V.length ; i += 3) {
|
||||
let x = V[i], y = V[i+1], z = V[i+2], e = .001,
|
||||
f0 = implicitFunction(x ,y ,z , args),
|
||||
fx = implicitFunction(x+e,y ,z , args),
|
||||
fy = implicitFunction(x ,y+e,z , args),
|
||||
fz = implicitFunction(x ,y ,z+e, args),
|
||||
normal = normalize([f0-fx,f0-fy,f0-fz]);
|
||||
for (let j = 0 ; j < 3 ; j++)
|
||||
N[i+j] = normal[j];
|
||||
}
|
||||
|
||||
// CONSTRUCT AND RETURN THE TRIANGLES MESH
|
||||
|
||||
let mesh = [];
|
||||
for (let i = 0; i < T.length; i += 3) {
|
||||
let a = 3 * T[i ],
|
||||
b = 3 * T[i + 1],
|
||||
c = 3 * T[i + 2];
|
||||
mesh.push( id, V[a],V[a+1],V[a+2] , N[a],N[a+1],N[a+2] ,
|
||||
id, V[b],V[b+1],V[b+2] , N[b],N[b+1],N[b+2] ,
|
||||
id, V[c],V[c+1],V[c+2] , N[c],N[c+1],N[c+2] );
|
||||
}
|
||||
return new Float32Array(mesh);
|
||||
}
|
||||
|
||||
let blob = (center, radius, x, y, z) => {
|
||||
x -= center[0];
|
||||
y -= center[1];
|
||||
z -= center[2];
|
||||
return Math.max(0, 1 - .16 * (x*x + y*y + z*z) / (radius * radius));
|
||||
}
|
||||
|
||||
var implicitFunction = (x,y,z,args) => {
|
||||
let ret = -.5;
|
||||
let x4 = _x => _x*_x*_x*_x;
|
||||
args.forEach((paras, _)=>{
|
||||
const center = paras[0],
|
||||
radius = paras[1];
|
||||
ret += x4(blob(center, radius, x, y, z));
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,793 @@
|
||||
//Header file, contains global variable definitions,
|
||||
// asynchronized shader loading and utility functions
|
||||
|
||||
var mousedx = 0,
|
||||
mousedy = 0,
|
||||
mousedz = 0;
|
||||
let seldx = 0,
|
||||
seldy = 0,
|
||||
seldz = 0;
|
||||
var enableSelection = false;
|
||||
var cx = 1,
|
||||
cy = 1,
|
||||
sx = 0,
|
||||
sy = 0,
|
||||
shaders = [];
|
||||
var mouselastX, mouselastY
|
||||
;
|
||||
var fl = 3;
|
||||
let start;
|
||||
var vs, fs;
|
||||
var bezierMat = [-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0],
|
||||
hermiteMat = [2, -3, 0, 1, -2, 3, 0, 0, 1, -2, 1, 0, 1, -1, 0, 0],
|
||||
catmullRomMat = [-.5, 1, -.5, 0, 1.5, -2.5, 0, 1, -1.5, 2, .5, 0, .5, -.5, 0, 0];
|
||||
var starColors = [0.9921, 0.5378, 0.7109,
|
||||
0.65, 0.56, 0.992,
|
||||
0.992, 0.7994, 0.2402,
|
||||
0.1760, 0.5094, 0.5378,
|
||||
.1164, .1274, .2289,
|
||||
.9784, .71, .4482,
|
||||
],
|
||||
n_shapes = starColors.length / 3;
|
||||
var editor = undefined
|
||||
var cos = Math.cos,
|
||||
sin = Math.sin,
|
||||
tan = Math.tan,
|
||||
acos = Math.acos,
|
||||
asin = Math.asin,
|
||||
atan = Math.atan,
|
||||
sqrt = Math.sqrt,
|
||||
pi = Math.PI,
|
||||
abs = Math.abs,
|
||||
pow = Math.pow,
|
||||
log = Math.log;
|
||||
var positionsupdated = true;
|
||||
var paths = [],
|
||||
origpath = [],
|
||||
path_misc = [];
|
||||
var canvas_controls = [];
|
||||
let vsfetch = new XMLHttpRequest();
|
||||
vsfetch.open('GET', './shader.vert');
|
||||
vsfetch.onloadend = function () {
|
||||
vs = vsfetch.responseText;
|
||||
};
|
||||
vsfetch.send();
|
||||
//* LOADING FRAGMENT SHADER
|
||||
let fsfetch = new XMLHttpRequest();
|
||||
fsfetch.open('GET', './shader.frag');
|
||||
fsfetch.onloadend = function () {
|
||||
fs = (fsfetch.responseText);
|
||||
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
|
||||
if (editor != undefined)
|
||||
editor.getSession().setValue(fs);
|
||||
};
|
||||
fsfetch.send();
|
||||
let pathFetch = new XMLHttpRequest();
|
||||
pathFetch.open('GET', './paths.txt');
|
||||
pathFetch.onloadend = function () {
|
||||
let text = pathFetch.responseText;
|
||||
let currX = 0,
|
||||
currY = 0,
|
||||
maxX = -10000,
|
||||
maxY = -10000,
|
||||
minX = 10000,
|
||||
minY = 10000;
|
||||
var currShape = [],
|
||||
currCurve = [];
|
||||
let i = 0;
|
||||
let postProcess = () => {
|
||||
if (currShape.length) {
|
||||
let spanX = maxX - minX;
|
||||
let spanY = maxY - minY;
|
||||
let span = Math.max(spanX, spanY);
|
||||
let l_total = 0;
|
||||
for (var k = 0; k < currShape.length; ++k) {
|
||||
let funcs = [];
|
||||
const curve = currShape[k];
|
||||
for (let j = 0; j < curve.length; j += 2) {
|
||||
curve[j] = (curve[j] - minX) / span - spanX / (span * 2);
|
||||
curve[j + 1] = (curve[j + 1] - minY) / span - spanY / (span * 2);
|
||||
origpath.push(1, curve[j], curve[j + 1], 0, 0, 0, 1);
|
||||
if (j % 6 == 0 && j > 5) {
|
||||
let X = [],
|
||||
Y = [];
|
||||
for (let k = j - 6; k <= j + 1; k += 2) {
|
||||
X.push(curve[k]);
|
||||
Y.push(curve[k + 1]);
|
||||
}
|
||||
let l = (vec_len(minus([X[3], Y[3]], [X[0], Y[0]])) +
|
||||
vec_len(minus([X[3], Y[3]], [X[2], Y[2]])) +
|
||||
vec_len(minus([X[2], Y[2]], [X[1], Y[1]])) +
|
||||
vec_len(minus([X[1], Y[1]], [X[0], Y[0]]))) / 2.;
|
||||
l_total += l;
|
||||
funcs.push([matrix_multiply(bezierMat, X),
|
||||
matrix_multiply(bezierMat, Y), l
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
paths.push(funcs);
|
||||
path_misc.push([l_total, spanX / (2 * span), spanY / (2 * span)]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
let read_num = () => {
|
||||
let num = 0,
|
||||
sign = 1,
|
||||
accepted = 0;
|
||||
|
||||
while (i < text.length && (text[i] < '0' || text[i] > '9') && text[i] != '-') ++i;
|
||||
if (text[i] == '-') {
|
||||
sign = -1;
|
||||
++i;
|
||||
}
|
||||
while (i < text.length && text[i] >= '0' && text[i] <= '9') {
|
||||
let n = text[i++] - '0';
|
||||
accepted *= 10;
|
||||
accepted += n;
|
||||
}
|
||||
|
||||
num += accepted;
|
||||
if (text[i] == '.') {
|
||||
i++;
|
||||
let multiplier = 0.1;
|
||||
accepted = 0;
|
||||
while (i < text.length && text[i] >= '0' && text[i] <= '9') {
|
||||
let n = text[i++] - '0';
|
||||
accepted += n * multiplier;
|
||||
multiplier /= 10;
|
||||
}
|
||||
num += accepted;
|
||||
}
|
||||
return num * sign;
|
||||
}
|
||||
let cRevs = [],
|
||||
c_idx = 0,
|
||||
prevX = 0,
|
||||
prevY = 0,
|
||||
getC = () => {
|
||||
return cRevs[c_idx--];
|
||||
}
|
||||
let get_next = (delta = false) => {
|
||||
if (delta) {
|
||||
currX = prevX + read_num();
|
||||
currY = prevY + read_num();
|
||||
} else {
|
||||
currX = read_num();
|
||||
currY = read_num();
|
||||
}
|
||||
maxX = currX > maxX ? currX : maxX;
|
||||
maxY = currY > maxY ? currY : maxY;
|
||||
minX = currX < minX ? currX : minX;
|
||||
minY = currY < minY ? currY : minY;
|
||||
|
||||
currCurve.push(currX);
|
||||
currCurve.push(currY);
|
||||
}
|
||||
while (i < text.length) {
|
||||
if (text[i] == 'z') {
|
||||
currCurve.length && currShape.push(currCurve);
|
||||
currCurve = [];
|
||||
++i
|
||||
} else if (text[i] == 'N') {
|
||||
postProcess();
|
||||
currShape = [];
|
||||
maxX = -1000, maxY = -1000, minX = 1000, minY = 1000;
|
||||
++i;
|
||||
} else if (text[i] == 'c') {
|
||||
|
||||
prevX = currX;
|
||||
prevY = currY;
|
||||
|
||||
for (let j = 0; j < 3; ++j) {
|
||||
get_next(true);
|
||||
}
|
||||
} else if (text[i] == 'C') {
|
||||
for (let j = 0; j < 3; ++j) {
|
||||
get_next();
|
||||
}
|
||||
} else if (text[i] == 'M') {
|
||||
get_next();
|
||||
} else ++i;
|
||||
}
|
||||
};
|
||||
pathFetch.send();
|
||||
let rtx_VFetch = new XMLHttpRequest(), rtxvshader_txt;
|
||||
rtx_VFetch.open('GET', './RTX.vert');
|
||||
rtx_VFetch.onloadend = function() {
|
||||
rtxvshader_txt = rtx_VFetch.responseText;
|
||||
};
|
||||
rtx_VFetch.send();
|
||||
let rtx_FFetch = new XMLHttpRequest();
|
||||
rtx_FFetch.open('GET', './RTX.frag');
|
||||
rtx_FFetch.onloadend = function () {
|
||||
let rtxfs_text = rtx_FFetch.responseText;
|
||||
|
||||
let interval = setInterval(()=>{
|
||||
if(buildShaders && rtxvshader_txt && canvas1.gl)
|
||||
{
|
||||
gl.shaders[1] = buildShaders(rtxvshader_txt, rtxfs_text);
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
rtx_FFetch.send()
|
||||
let vec_len = v => {
|
||||
let len = 0;
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
len += v[i] * v[i];
|
||||
return sqrt(len);
|
||||
}
|
||||
let matrix_inverse = src => {
|
||||
let dst = [],
|
||||
det = 0,
|
||||
cofactor = (c, r) => {
|
||||
let s = (i, j) => src[c + i & 3 | (r + j & 3) << 2];
|
||||
return (c + r & 1 ? -1 : 1) * ((s(1, 1) * (s(2, 2) * s(3, 3) - s(3, 2) * s(2, 3))) -
|
||||
(s(2, 1) * (s(1, 2) * s(3, 3) - s(3, 2) * s(1, 3))) +
|
||||
(s(3, 1) * (s(1, 2) * s(2, 3) - s(2, 2) * s(1, 3))));
|
||||
}
|
||||
for (let n = 0; n < 16; n++) dst.push(cofactor(n >> 2, n & 3));
|
||||
for (let n = 0; n < 4; n++) det += src[n] * dst[n << 2];
|
||||
for (let n = 0; n < 16; n++) dst[n] /= det;
|
||||
return dst;
|
||||
}
|
||||
|
||||
// I HAVE IMPLEMENTED THESE FUNCTIONS FOR YOU
|
||||
let matrix_identity = () => {
|
||||
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
||||
}
|
||||
let matrix_translate = (x, y, z) => {
|
||||
let m = matrix_identity();
|
||||
m[12] = x;
|
||||
m[13] = y;
|
||||
m[14] = z;
|
||||
return m;
|
||||
}
|
||||
let matrix_perspective = (m) => {
|
||||
let ret = []
|
||||
for (let i = 0; i < 16; i++)
|
||||
ret[i] = m[i];
|
||||
for (let i = 2; i < 15; i += 4) {
|
||||
ret[i] = -ret[i];
|
||||
ret[i + 1] += ret[i] / fl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// YOU NEED TO PROPERLY IMPLEMENT THE FOLLOWING FIVE FUNCTIONS:
|
||||
let matrix_rotateX = theta => {
|
||||
let m = matrix_identity();
|
||||
m[5] = cos(theta);
|
||||
m[6] = sin(theta);
|
||||
m[9] = -sin(theta);
|
||||
m[10] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
|
||||
let matrix_rotateY = theta => {
|
||||
let m = matrix_identity();
|
||||
m[0] = cos(theta);
|
||||
m[2] = -sin(theta);
|
||||
m[8] = sin(theta);
|
||||
m[10] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
let matrix_rotateZ = theta => {
|
||||
let m = matrix_identity();
|
||||
m[0] = cos(theta);
|
||||
m[1] = sin(theta);
|
||||
m[4] = -sin(theta);
|
||||
m[5] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
let matrix_scale = (x, y, z) => {
|
||||
if (y === undefined)
|
||||
y = z = x;
|
||||
let m = matrix_identity();
|
||||
m[0] = x;
|
||||
m[5] = y;
|
||||
m[10] = z;
|
||||
return m;
|
||||
}
|
||||
let matrix_multiply = (a, b, m = 4, n = 4) => { //dim=mn*nm=mm
|
||||
let res = [];
|
||||
if (b.length < m * n) { //mat-vec multiply (i did this for my convenience)
|
||||
for (let i = 0; i < m; ++i) {
|
||||
res[i] = 0;
|
||||
for (let j = 0; j < n; ++j)
|
||||
res[i] += b[j] * a[m * j + i];
|
||||
}
|
||||
return res;
|
||||
} //otherwise mm multiply
|
||||
for (let i = 0; i < m; ++i)
|
||||
for (let j = 0; j < m; ++j) {
|
||||
var t = 0;
|
||||
for (let k = 0; k < n; ++k)
|
||||
t += a[k * m + j] * b[i * n + k];
|
||||
res.push(t);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
let const_multiply = (c, a, add = 0) => {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = (a[i] + add)* c;
|
||||
return m;
|
||||
}
|
||||
|
||||
function dot(a, b) {
|
||||
b=b?b:a;
|
||||
let m = 0;
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m += a[i] * b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function cross(a, b){
|
||||
let m = [];
|
||||
m[0] = a[1]*b[2] - a[2]*b[1];
|
||||
m[1] = a[2]*b[0] - a[0]*b[2];
|
||||
m[2] = a[0]*b[1] - a[1]*b[0];
|
||||
return m;
|
||||
}
|
||||
|
||||
function plus(a, b) {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = a[i] + b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function minus(a, b) {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = a[i] - b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function normalize(v) {
|
||||
let res = [];
|
||||
sum = 0;
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
sum += v[i] * v[i];
|
||||
sum = sqrt(sum);
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
res[i] = v[i] / sum;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
let Matrix = function () {
|
||||
let top = 0,
|
||||
m = [matrix_identity()];
|
||||
this.identity = () => m[top] = matrix_identity();
|
||||
this.translate = (x, y, z) => m[top] = matrix_multiply(m[top], matrix_translate(x, y, z));
|
||||
this.rotateX = theta => m[top] = matrix_multiply(m[top], matrix_rotateX(theta));
|
||||
this.rotateY = theta => m[top] = matrix_multiply(m[top], matrix_rotateY(theta));
|
||||
this.rotateZ = theta => m[top] = matrix_multiply(m[top], matrix_rotateZ(theta));
|
||||
this.scale = (x, y, z) => m[top] = matrix_multiply(m[top], matrix_scale(x, y, z));
|
||||
this.apply = (m1) => m[top] = matrix_multiply(m[top], m1);
|
||||
this.applyl = (m1) => m[top] = matrix_multiply(m1, m[top]);
|
||||
this.value = () => m[top];
|
||||
this.save = () => {
|
||||
m[top + 1] = m[top].slice();
|
||||
top++;
|
||||
}
|
||||
this.restore = () => --top;
|
||||
}
|
||||
function hitTest_sphere(ray, sphere, r) {
|
||||
let B = dot(ray, sphere);
|
||||
let C = dot(sphere, sphere) - r*r;
|
||||
let D = B * B - C;
|
||||
if (D > 0.) {
|
||||
//console.log(D);
|
||||
//let t = -B - sqrt(D);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
function hitTest_square(pt, invMatrix, shape){
|
||||
pt.push(1);
|
||||
const V = dot_xyz(matrix_multiply(invMatrix, [0,0,fl,1])),
|
||||
pos = dot_xyz(matrix_multiply(invMatrix, pt)),
|
||||
W = minus(pos, V),
|
||||
A = shape.slice(1,4),
|
||||
B = shape.slice(8,11),
|
||||
C = shape.slice(15,18),
|
||||
AB = minus(B, A),
|
||||
AC = minus(C, A),
|
||||
AB_AC = cross(AB, AC),
|
||||
VA = minus(V, A),
|
||||
t = - dot(AB_AC, VA)/dot(W, AB_AC),
|
||||
P = plus(V, const_multiply(t, W)),
|
||||
AP = minus(P, A),
|
||||
d_AP_AC = dot(AP, AC),
|
||||
d_AP_AB = dot(AP, AB);
|
||||
if(0 <d_AP_AC && d_AP_AC < dot(AC, AC) && 0 < d_AP_AB && d_AP_AB< dot(AB, AB))
|
||||
return P;
|
||||
else return -1;
|
||||
}
|
||||
let dot_xyz = (v) => {
|
||||
let ret = [];
|
||||
if(v[3])
|
||||
for(let i = 0; i < 3; ++i)
|
||||
ret[i] = v[i]/v[3];
|
||||
else ret = v.slice(0,3);
|
||||
return ret;
|
||||
}
|
||||
let Button = function (onclick = () => {}, shape = [], outlineTy = 'sphere') {
|
||||
this.shape = shape;
|
||||
this.enabled = true;
|
||||
this.outlineTy = outlineTy;
|
||||
this.onClick = onclick;
|
||||
this.updateMatrix = (m) => {this.matrix = matrix_perspective(m); this.invMatrix = matrix_inverse(m);};
|
||||
this.updateMatrix(matrix_identity());
|
||||
this.hovering = false;
|
||||
this.activated = false;
|
||||
this.getShape = () => this.shape;
|
||||
this.draw = () => {setUniform('Matrix4fv', 'uMatrix', false, this.matrix);
|
||||
setUniform('Matrix4fv', 'invMatrix', false, this.invMatrix); drawMesh(this.shape);}
|
||||
this.resetShape = (_sh) => {
|
||||
if(this.shape) delete this.shape;
|
||||
this.shape = new Float32Array(_sh);
|
||||
let maxV = new Array(3).fill(-Infinity), minV = new Array(3).fill(Infinity);
|
||||
for(let i = 0; i < _sh.length; i += 7){
|
||||
const v = [_sh[i + 1], _sh[i + 2], _sh[i + 3]];
|
||||
v.forEach((c, j) => {
|
||||
maxV[j] = maxV[j] > c ? maxV[j] : c;
|
||||
minV[j] = minV[j] < c ? minV[j] : c;
|
||||
})
|
||||
}
|
||||
//build outline
|
||||
switch(this.outlineTy){
|
||||
case 'sphere':
|
||||
this.origin = const_multiply(.5, plus(maxV, minV));
|
||||
//this.origin.push(1);
|
||||
this.radius = 0.6*vec_len(minus(maxV, minV))/2.;
|
||||
break;
|
||||
case 'square':
|
||||
break;
|
||||
case 'circle':
|
||||
break;
|
||||
}
|
||||
switch(this.outlineTy){
|
||||
case 'sphere':
|
||||
this.hitTest = (pt) => {
|
||||
pt.push(1);
|
||||
const V = dot_xyz(matrix_multiply(this.invMatrix, [0,0,fl,1])),
|
||||
pos = dot_xyz(matrix_multiply(this.invMatrix, pt));
|
||||
let W = normalize((minus(pos, V)));
|
||||
let Vp = minus(V, this.origin);
|
||||
return hitTest_sphere(W, Vp, this.radius);
|
||||
}
|
||||
break;
|
||||
case 'square':
|
||||
this.hitTest = (pt) => {
|
||||
this.P = hitTest_square(pt, this.invMatrix, this.shape);
|
||||
return this.P;
|
||||
}
|
||||
break;
|
||||
case 'circle':
|
||||
break;
|
||||
}
|
||||
};
|
||||
if(!shape || shape.length != 0)
|
||||
this.resetShape(shape);
|
||||
canvas_controls.push(this);
|
||||
}
|
||||
let setM = (m) => {
|
||||
let mm = matrix_perspective(m);
|
||||
setUniform('Matrix4fv', 'uMatrix', false, mm);
|
||||
setUniform('Matrix4fv', 'invMatrix', false, matrix_inverse(mm));
|
||||
}
|
||||
//------ CREATING MESH SHAPES
|
||||
|
||||
// CREATE A MESH FROM A PARAMETRIC FUNCTION
|
||||
|
||||
let createMesh = (nu, nv, f, data, oid = 0) => {
|
||||
let tmp = [];
|
||||
for (let v = 0; v < 1; v += 1 / nv) {
|
||||
for (let u = 0; u <= 1; u += 1 / nu) {
|
||||
tmp = tmp.concat(f(u, v, oid, data));
|
||||
tmp = tmp.concat(f(u, v + 1 / nv, oid, data));
|
||||
}
|
||||
tmp = tmp.concat(f(1, v, oid, data));
|
||||
tmp = tmp.concat(f(0, v + 1 / nv, oid, data));
|
||||
}
|
||||
return new Float32Array(tmp);
|
||||
}
|
||||
//Create a Mesh from Splines
|
||||
let createMeshFromSpline = (idx,
|
||||
nu, nv, oid = 16, additional_offset = 0, f = () => {}) => {
|
||||
let S = paths[idx],
|
||||
meta = path_misc[idx];
|
||||
const n_min = 2;
|
||||
let ds = meta[0] / nv,
|
||||
curr_s = 0,
|
||||
curr_d = S[0][2] / Math.ceil(S[0][2] / ds),
|
||||
i = 0,
|
||||
s = 0;
|
||||
let tmp = [],
|
||||
ret = undefined;
|
||||
while (s < meta[0] - 1 / 100000) {
|
||||
|
||||
for (let u = 0; u <= 1; u += 1 / nu) {
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], u, curr_s, idx, oid, additional_offset));
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], u, curr_s + curr_d, idx, oid, additional_offset));
|
||||
}
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], 0, curr_s, idx, oid, additional_offset));
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], 1, curr_s + curr_d, idx, oid, additional_offset));
|
||||
if (ret = f(i, tmp, oid)) {
|
||||
oid = ret;
|
||||
}
|
||||
curr_s += curr_d;
|
||||
if (curr_s >= 1) {
|
||||
s += S[i][2];
|
||||
++i;
|
||||
if (i >= S.length)
|
||||
break;
|
||||
let curr_n = Math.ceil(S[i][2] / ds);
|
||||
curr_n = curr_n < n_min ? n_min : curr_n;
|
||||
curr_d = 1 / curr_n;
|
||||
curr_s = 0;
|
||||
}
|
||||
}
|
||||
return new Float32Array(tmp);
|
||||
}
|
||||
// GLUE TWO MESHES TOGETHER INTO A SINGLE MESH
|
||||
|
||||
let glueMeshes = (a, b) => {
|
||||
let c = [];
|
||||
for (let i = 0; i < a.length; i++)
|
||||
c.push(a[i]); // a
|
||||
for (let i = 0; i < VERTEX_SIZE; i++)
|
||||
c.push(a[a.length - VERTEX_SIZE + i]); // + last vertex of a
|
||||
for (let i = 0; i < VERTEX_SIZE; i++)
|
||||
c.push(b[i]); // + first vertex of b
|
||||
for (let i = 0; i < b.length; i++)
|
||||
c.push(b[i]); // + b
|
||||
return new Float32Array(c);
|
||||
}
|
||||
|
||||
|
||||
let uvToSphere = (u, v, i) => {
|
||||
let theta = 2 * Math.PI * u;
|
||||
let phi = Math.PI * (v - .5);
|
||||
let x = Math.cos(theta) * Math.cos(phi);
|
||||
let y = Math.sin(theta) * Math.cos(phi);
|
||||
let z = Math.sin(phi);
|
||||
return [i, x, y, z].concat(normalize([x, y, z]));
|
||||
}
|
||||
|
||||
let uvToTube = (u, v, i) => {
|
||||
let theta = 2 * Math.PI * u;
|
||||
let x = Math.cos(theta);
|
||||
let y = Math.sin(theta);
|
||||
let z = 2 * v - 1;
|
||||
return [i, x, y, z].concat(normalize([x, y, 0]));
|
||||
}
|
||||
|
||||
let uvToDisk = (u, v, i, dz) => {
|
||||
if (dz === undefined)
|
||||
dz = 0;
|
||||
let theta = 2 * Math.PI * u;
|
||||
let x = Math.cos(theta) * v;
|
||||
let y = Math.sin(theta) * v;
|
||||
let z = dz;
|
||||
return [i, x, y, z].concat([0, 0, Math.sign(z)]);
|
||||
}
|
||||
let uvToTorus = (u, v, i, r) => {
|
||||
let theta = 2 * pi;
|
||||
let phi = theta * v;
|
||||
theta *= u;
|
||||
let x = 1 + r * cos(phi);
|
||||
let y = sin(theta) * x;
|
||||
x *= cos(theta);
|
||||
let z = r * sin(phi);
|
||||
let tx = -sin(theta),
|
||||
ty = cos(theta),
|
||||
tsx = sin(phi),
|
||||
tsy = tsx * tx,
|
||||
tsz = cos(phi);
|
||||
tsx *= -ty;
|
||||
return [i, x, y, z].concat(normalize([ty * tsz * 0.5, -tx * tsz, tx * tsy - ty * tsx]));
|
||||
}
|
||||
|
||||
let createCube = (w, h, l, id) => {
|
||||
let mesh = [];
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, -1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, -1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, 0, 1, 0]);
|
||||
return new Float32Array(mesh);
|
||||
}
|
||||
|
||||
function updatePositions() {
|
||||
let m = matrix_rotateY(-mousedx);
|
||||
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||||
setUniform('3f', 'V0', m[8] * (fl + mousedz), m[9] * (fl + mousedz), m[10] * (fl + mousedz));
|
||||
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||||
setUniform('Matrix3fv', 'transformation', false, [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]]);
|
||||
invTr = matrix_inverse(m);
|
||||
|
||||
positionsupdated = false;
|
||||
}
|
||||
function controls_hitTest(pos, clicked = false){
|
||||
// let iMin = -1, tMin = 10000.;
|
||||
if(channel_disp == 5)
|
||||
return;
|
||||
canvas_controls.forEach((c, i) => {
|
||||
if(c.enabled && c.hitTest && (c.hover||clicked) ){
|
||||
let t = c.hitTest(pos);
|
||||
if(t != -1){
|
||||
if(clicked)
|
||||
c.onClick();
|
||||
else
|
||||
c.hover(true);
|
||||
}
|
||||
else
|
||||
if(c.hovering)
|
||||
c.hover(false);
|
||||
}
|
||||
});
|
||||
//ground
|
||||
if(ground_m && ground){
|
||||
let invG = matrix_inverse(ground_m);
|
||||
let P = hitTest_square(pos, invG, ground);
|
||||
console.log(P);
|
||||
//let Vp = minus(matrix_multiply(invG,[0,0,fl, 1]).slice(0,3), this.origin);
|
||||
if(P!=-1)
|
||||
if(near_magician){
|
||||
if(slider.dragging === true){
|
||||
slider_dl += 10 * (P[0] - slider.lastPos);
|
||||
if(slider_dl < 0) slider_dl = 0;
|
||||
else if (slider_dl > 9) slider_dl = 9;
|
||||
slider.lastPos = P[0];
|
||||
// onUpdate
|
||||
let id = 1 + .45*slider_dl/9;
|
||||
changeID(id, cylinderMesh);
|
||||
} else if(clicked) {
|
||||
const PO = minus([slider_dl/10-.25, .7], [P[0], P[1]]);
|
||||
const rr = PO[0]*PO[0] + PO[1] * PO[1];
|
||||
if(rr < .003){
|
||||
slider.dragging = true;
|
||||
slider.lastPos = P[0];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(clicked || running<=0)
|
||||
{
|
||||
direction_l = [P[0] - delta_l[0]/10, P[1] - delta_l[1]/10];
|
||||
if(P[1] < 0.00000000000001)
|
||||
P[1] = 0.0000000000000001;
|
||||
figure_rot = atan(direction_l[0]/direction_l[1]);
|
||||
if(direction_l[1] < 0){
|
||||
figure_rot = pi + figure_rot;
|
||||
}
|
||||
}
|
||||
//if(figure_rot < 0) figure_rot += pi;
|
||||
//updateStatus([figure_rot, direction_l[0]/direction_l[1]]);
|
||||
if(clicked)
|
||||
{
|
||||
dir_sdl = vec_len(direction_l)*10;
|
||||
direction_l = normalize(direction_l);
|
||||
rebuild = true;
|
||||
running = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//return iMin;
|
||||
}
|
||||
function hitTest(pos) {
|
||||
|
||||
let m = matrix_rotateY(-mousedx);
|
||||
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||||
|
||||
|
||||
let V = [m[8] * (fl + mousedz), m[9] * (fl + mousedz), m[10] * (fl + mousedz)];
|
||||
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||||
|
||||
let trPos = matrix_multiply([m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]], [pos[0], pos[1], -1], 3, 3);
|
||||
|
||||
let W = normalize(minus(trPos, V));
|
||||
let tMin = 10000.;
|
||||
let iMin = -1;
|
||||
for (let i = 0; i < cns; i++) {
|
||||
let Vp = minus(V, matrix_multiply(SphTr[i], Sph[i]));
|
||||
let B = dot(W, Vp);
|
||||
let C = dot(Vp, Vp) - Sph[i][4] * Sph[i][4];
|
||||
let D = B * B - C;
|
||||
if (D > 0.) {
|
||||
let t = -B - sqrt(D);
|
||||
if (t > 0.0 && t < tMin) {
|
||||
tMin = t; // This is an optimization, we don't have to do lighting/tex
|
||||
iMin = i; // for objects that are occuluded, which is expensive!
|
||||
}
|
||||
}
|
||||
}
|
||||
return iMin;
|
||||
}
|
||||
let matrix_transform = (m, p) => {
|
||||
let x = p[0],
|
||||
y = p[1],
|
||||
z = p[2],
|
||||
w = p[3] === undefined ? 1 : p[3];
|
||||
let q = [m[0] * x + m[4] * y + m[8] * z + m[12] * w,
|
||||
m[1] * x + m[5] * y + m[9] * z + m[13] * w,
|
||||
m[2] * x + m[6] * y + m[10] * z + m[14] * w,
|
||||
m[3] * x + m[7] * y + m[11] * z + m[15] * w
|
||||
];
|
||||
return p[3] === undefined ? [q[0] / q[3], q[1] / q[3], q[2] / q[3]] : q;
|
||||
}
|
||||
let evalSpline = (h, t) => {
|
||||
// t *= (h.length - 2) / 2;
|
||||
// let n = 2 * Math.floor(t);
|
||||
// t = t % 1;
|
||||
// let C = matrix_transform(type, [h[n+0],h[n+2],h[n+1],h[n+3]]);
|
||||
// return t*t*t*C[0] + t*t*C[1] + t*C[2] + C[3];
|
||||
return t * t * t * h[0] + t * t * h[1] + t * h[2] + h[3];
|
||||
}
|
||||
let getSurface = (S0, S1, u, v, offsetidx, id = 15, additional_offset = 0) => {
|
||||
const epsilon = .001;
|
||||
let z0 = evalSpline(S0, v),
|
||||
z1 = evalSpline(S0, v + epsilon),
|
||||
|
||||
r0 = evalSpline(S1, v) - path_misc[offsetidx][1] + additional_offset,
|
||||
r1 = evalSpline(S1, v + epsilon),
|
||||
|
||||
tilt = Math.atan2(r0 - r1, z1 - z0);
|
||||
|
||||
let xx = cos(2 * pi * u),
|
||||
yy = sin(2 * pi * u);
|
||||
let x = r0 * xx, // POSITION
|
||||
y = r0 * yy,
|
||||
z = z0,
|
||||
nx = cos(tilt), // NORMAL
|
||||
ny = nx * yy,
|
||||
nz = sin(tilt);
|
||||
nx *= xx;
|
||||
return [id, x, y, z, nx, ny, nz];
|
||||
}
|
||||
let concat = (a, b) => b.forEach(e => a.push(e));
|
||||
@@ -0,0 +1,327 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// THIS IS THE SUPPORT LIBRARY. YOU PROBABLY DON'T WANT TO CHANGE ANYTHING HERE JUST YET.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let fragmentShaderHeader = ['' // WHATEVER CODE WE WANT TO PREDEFINE FOR FRAGMENT SHADERS
|
||||
, 'precision highp float;', 'float noise(vec3 point) { float r = 0.; for (int i=0;i<16;i++) {', ' vec3 D, p = point + mod(vec3(i,i/4,i/8) , vec3(4.0,2.0,2.0)) +', ' 1.7*sin(vec3(i,5*i,8*i)), C=floor(p), P=p-C-.5, A=abs(P);', ' C += mod(C.x+C.y+C.z,2.) * step(max(A.yzx,A.zxy),A) * sign(P);', ' D=34.*sin(987.*float(i)+876.*C+76.*C.yzx+765.*C.zxy);P=p-C-.5;', ' r+=sin(6.3*dot(P,fract(D)-.5))*pow(max(0.,1.-2.*dot(P,P)),4.);', '} return .5 * sin(r); }','\n#define _NDEBUG\n'
|
||||
].join('\n');
|
||||
var ns = 6,
|
||||
cns = 6;
|
||||
fragmentShaderHeader += 'const int ns = ' + ns + ';\n';
|
||||
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
|
||||
var status = 'The TV is a touch screen!';
|
||||
let nfsh = fragmentShaderHeader.split('\n').length + 1; // NUMBER OF LINES OF CODE IN fragmentShaderHeader
|
||||
|
||||
let isFirefox = navigator.userAgent.indexOf('Firefox') > 0;
|
||||
|
||||
function getBlob(data) {
|
||||
let bytes = new Array(data.length);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
bytes[i] = data.charCodeAt(i);
|
||||
}
|
||||
return new Blob([new Uint8Array(bytes)]);
|
||||
}
|
||||
let stack = function (){
|
||||
this.storage = ['Ready.'];
|
||||
this.len = 1;
|
||||
this.pop = ()=>{return this.storage[--this.len-1];}
|
||||
this.push = (o)=>{this.storage[this.len++] = o;}
|
||||
this.update = (o)=>{this.storage[this.len-1] = o;}
|
||||
this.top = () => {return this.storage[this.len - 1];}
|
||||
this.clear = () => this.len = 1;
|
||||
}
|
||||
let status_history = new stack();
|
||||
function updateStatus(val){
|
||||
status_history.update(status);
|
||||
status = val;
|
||||
errorMessage.innerHTML = val;
|
||||
}
|
||||
function pushStatus(val){
|
||||
status_history.push(status);
|
||||
status = val;
|
||||
errorMessage.innerHTML = val;
|
||||
}
|
||||
function restoreStatus(val){
|
||||
status = status_history.pop();
|
||||
errorMessage.innerHTML = status;
|
||||
}
|
||||
function resetStatus() {
|
||||
status_history.clear();
|
||||
updateStatus('Ready.');
|
||||
}
|
||||
var texture = [],
|
||||
gl, program;
|
||||
let textures = [];
|
||||
let lock = false;
|
||||
|
||||
function loadTexture(gl, url, i) {
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 1;
|
||||
const height = 1;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
if (texture[i] == null) {
|
||||
texture[i] = gl.createTexture();
|
||||
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
|
||||
gl.activeTexture(gl.TEXTURE0 + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
}
|
||||
const image = new Image();
|
||||
image.onload = function () {
|
||||
gl.activeTexture(gl.TEXTURE0 + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
srcFormat, srcType, image);
|
||||
|
||||
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
};
|
||||
image.src = url;
|
||||
}
|
||||
function initTextures(gl, program){
|
||||
for (let i = 0; i < ns; ++i) {
|
||||
loadTexture( gl, './' + (i + 1) + '.jpg', i); //Texture loading.
|
||||
textures[i] = i;
|
||||
}
|
||||
textures[ns] = ns;
|
||||
initVideoTexture(gl, ns + 0);
|
||||
textures[ns + 1] = ns + 1;
|
||||
loadTexture(gl, './starburst.png', ns + 1);
|
||||
createNoiseTexture();
|
||||
textures[ns+2] = ns+2;
|
||||
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
|
||||
}
|
||||
function initVideoTexture(gl, i) {
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 1;
|
||||
const height = 1;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
if (texture[i] == null) {
|
||||
texture[i] = gl.createTexture();
|
||||
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
|
||||
gl.activeTexture(gl.TEXTURE + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
}
|
||||
function updateVideoTexture(gl, v_control, i){
|
||||
//return;
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
srcFormat, srcType, v_control);
|
||||
}
|
||||
function createNoiseTexture(){
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 100;
|
||||
const height = 100;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
texture[ns+2] = gl.createTexture();
|
||||
let random_list = [];
|
||||
let get_random = ()=>Math.pow(Math.random(), .1);
|
||||
let get_random2 = ()=>{
|
||||
let r = Math.random();
|
||||
if (r < .5) r = .5*Math.pow(2*r,.1);
|
||||
else r = .5 + .5*Math.pow(r,10);
|
||||
return r;};
|
||||
for(let i = 0; i < 40000; ++i){
|
||||
if(i%4 == 3)
|
||||
random_list.push(255*get_random());
|
||||
else
|
||||
random_list.push(255*get_random2());
|
||||
}
|
||||
const pixel = new Uint8Array(random_list);
|
||||
gl.activeTexture(gl.TEXTURE0+ns+2);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[ns+2]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
function isPowerOf2(value) {
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
function buildShaders(vertexShader, fragmentShader){
|
||||
let curr_program = canvas1.gl.createProgram();
|
||||
let compile_shaders = (type, src) => {
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
gl.attachShader(curr_program, shader);
|
||||
};
|
||||
compile_shaders(gl.VERTEX_SHADER, vertexShader);
|
||||
compile_shaders(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShaderDefs + fragmentShader);
|
||||
gl.linkProgram(curr_program);
|
||||
|
||||
return curr_program;
|
||||
}
|
||||
function gl_start(canvas, vertexShader, fragmentShader) { // START WEBGL RUNNING IN A CANVAS
|
||||
console.log('glstart');
|
||||
setTimeout(function () {
|
||||
try {
|
||||
canvas.gl = canvas.getContext('experimental-webgl'); // Make sure WebGl is supported. IT WOULD BE GREAT TO USE WEBGL2 INSTEAD.
|
||||
} catch (e) {
|
||||
throw 'Sorry, your browser does not support WebGL.';
|
||||
}
|
||||
|
||||
|
||||
canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders:
|
||||
gl = this.gl;
|
||||
program = gl.createProgram(); // Create the WebGL program.
|
||||
|
||||
function addshader(type, src) { // Create and attach a WebGL shader.
|
||||
function spacer(color, width, height) {
|
||||
return '<table bgcolor=' + color +
|
||||
' width=' + width +
|
||||
' height=' + height + '><tr><td> </td></tr></table>';
|
||||
}
|
||||
errorMessage.innerHTML = status;
|
||||
// errorMarker.innerHTML = spacer('white', 1, 1) + '<font size=1 color=white>\u25B6</font>';
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
let msg = gl.getShaderInfoLog(shader);
|
||||
console.log('Cannot compile shader:\n\n' + msg);
|
||||
|
||||
let a = msg.substring(6, msg.length);
|
||||
let line = 0;
|
||||
if (a.substring(0, 3) == ' 0:') {
|
||||
a = a.substring(3, a.length);
|
||||
line = parseInt(a) - nfsh;
|
||||
|
||||
editor.session.setAnnotations([{
|
||||
row: line,
|
||||
column: 0,
|
||||
text: msg,
|
||||
type: "error"
|
||||
}]);
|
||||
}
|
||||
let j = a.indexOf(':');
|
||||
a = 'line ' + (line + 1) + a.substring(j, a.length);
|
||||
if ((j = a.indexOf('\n')) > 0)
|
||||
a = a.substring(0, j);
|
||||
errorMessage.innerHTML = a;
|
||||
} else
|
||||
editor.session.clearAnnotations();
|
||||
gl.attachShader(program, shader);
|
||||
};
|
||||
|
||||
addshader(gl.VERTEX_SHADER, vertexShader); // Add the vertex and fragment shaders.
|
||||
addshader(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShaderDefs + fragmentShader);
|
||||
|
||||
gl.linkProgram(program); // Link the program, report any errors.
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
|
||||
console.log('Could not link the shader program!');
|
||||
gl.useProgram(program);
|
||||
gl.program = program;
|
||||
if(!gl.shaders)
|
||||
gl.shaders = [program];
|
||||
else gl.shaders[0] = program;
|
||||
initTextures(gl, program);
|
||||
positionsupdated = true;
|
||||
let attribs = [
|
||||
.05, .05, .1, .5, .5, 1., 1., .5, .5, 20., 5,0,0, 0.,.0, 1.3,
|
||||
.1, .05, .05, 1., .5, .5, 1., .5, .5, 10., .1,8,0, .3, 1., 1.3,
|
||||
.1, .05, .05, .71, .71, .71, .71, .71, .71, 10., .1,0,9, 0.3, .0, 1.5,
|
||||
.1, .1, .1, .71, .71, .71, .71, .71, .71, 10., 2,2,0, 0.05, 0., 1.,
|
||||
.0, .0, .0, .0, .0, .0, .0, .0, .0, 40., 4,4,4, 0., .85, 1.5
|
||||
]
|
||||
var offset = 0;
|
||||
for (let i = 0; i < ns; i++) {
|
||||
setUniform('3fv', 'Ambient[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('3fv', 'Diffuse[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('4fv', 'Specular[' + i + ']', attribs.slice(offset, offset += 4));
|
||||
setUniform('3fv', 'Glow[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('1fv', 'ks[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
setUniform('1fv', 'kr[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
setUniform('1fv', 'kf[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
}
|
||||
offset = 0;
|
||||
for (let i = 0; i < n_shapes; i++) {
|
||||
setUniform('3fv', 'starColors[' + i + ']', starColors.slice(offset, offset += 3));
|
||||
}
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // Create a square as a triangle strip
|
||||
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( // consisting of two triangles.
|
||||
// [-1, 1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0]), gl.STATIC_DRAW);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.depthFunc(gl.LEQUAL);
|
||||
gl.clearDepth(-1);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
let oid = gl.getAttribLocation(program, 'oid'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(oid);
|
||||
gl.vertexAttribPointer(oid, 1, gl.FLOAT, false, 4 * 7, 0);
|
||||
|
||||
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(aPos);
|
||||
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 4 * 7, 4);
|
||||
|
||||
let normal = gl.getAttribLocation(program, 'normal'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(normal);
|
||||
gl.vertexAttribPointer(normal, 3, gl.FLOAT, false, 4 * 7, 4 * 4);
|
||||
}
|
||||
|
||||
canvas.setShaders(vertexShader, fragmentShader); // Initialize everything,
|
||||
setInterval(function () { // Start the animation loop.
|
||||
gl = canvas.gl;
|
||||
if (gl.startTime === undefined) // First time through,
|
||||
gl.startTime = Date.now(); // record the start time.
|
||||
animate(gl);
|
||||
//gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // Render the square.
|
||||
}, 30);
|
||||
|
||||
}, 100); // Wait 100 milliseconds after page has loaded before starting WebGL.
|
||||
}
|
||||
|
||||
// THE animate() CALLBACK FUNCTION CAN BE REDEFINED IN index.html.
|
||||
|
||||
function animate() {}
|
||||
|
||||
function setUniform(type, name, a, b, c, d, e, f) {
|
||||
if (gl) {
|
||||
let loc = gl.getUniformLocation(gl.program, name);
|
||||
(gl['uniform' + type])(loc, a, b, c, d, e, f);
|
||||
}
|
||||
}
|
||||
|
||||
//let VERTEX_SIZE = 3;
|
||||
|
||||
|
||||
let VERTEX_SIZE = 7;
|
||||
|
||||
|
||||
var drawMesh = (mesh, func = gl.TRIANGLE_STRIP) => {
|
||||
gl.bufferData(gl.ARRAY_BUFFER, mesh, gl.STATIC_DRAW);
|
||||
gl.drawArrays(func, 0, mesh.length / VERTEX_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<video src="pjsk.mp4" id="pjsk" hidden="true" muted="muted" loop="true" style="position:fixed; left:0; top:0;max-width:100%;min-width:100%;min-height: 100%;z-index: -100;"></video>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js" crossorigin="anonymous"></script>
|
||||
<script src=libX.header.js></script>
|
||||
<script src=libX.js></script>
|
||||
<style>
|
||||
.ace_gutter-layer {
|
||||
/* original width is 48px */
|
||||
width: 25px !important;
|
||||
}
|
||||
|
||||
.ace_gutter-layer > * {
|
||||
/* 48 - 32 = 16 */
|
||||
margin-left: 0;
|
||||
}
|
||||
.ace_gutter-cell {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 3px !important;
|
||||
}
|
||||
.code{
|
||||
font-family: "monaco, menlo, ubuntu mono, consolas, source-code-pro" ;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<!!-------- VERTEX SHADER: YOU PROBABLY DON'T WANT TO CHANGE THIS RIGHT NOW -------->
|
||||
|
||||
|
||||
|
||||
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
|
||||
<!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag!! LOADED IN lib2.js -------->
|
||||
|
||||
<font size=7 color=#909090>
|
||||
|
||||
Final Project
|
||||
|
||||
<img id="rtx" style="float:right;" src="./RTXon.svg" type="image/svg+xml"
|
||||
alt="Turn Ray Tracing On/OFF" title="Turn Ray Tracing On/OFF" height=60px /img>
|
||||
<div id="fps" style="font-size:25;float:right;margin-right:18px;"></div>
|
||||
<TABLE cellspacing=0 cellpadding=0 style="width:50%"><TR>
|
||||
<td><font color=red size=5><div id=errorMessage></div></font></td>
|
||||
</TR><TR>
|
||||
<table cellspacing=0>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<div id="ace" style="opacity:90%;width:500px;height:600px;"hidden=true></div>
|
||||
<div id = 'usage' style="opacity:90%;width:500px;height:600px;">
|
||||
<font color=#000000>
|
||||
<i style="font-size:28px;">What's new: </i>
|
||||
<ul style="font-size:24px;">
|
||||
<p>
|
||||
In the final project I implemented Flares and glowing object for ray tracing. The technical
|
||||
details can be found in <a href="http://resources.mpi-inf.mpg.de/lensflareRendering/">this paper</a> from
|
||||
SIGGRAPH 2011.<br>
|
||||
I also implemented a glassy filter by randomly bending the rays shot from the screen. The idea was from my
|
||||
failed attempt to create flares which I thought was caused by diffusion of lights caused by fogs on my glasses.
|
||||
But this actually resembles the images we saw through a <a href="https://www.google.com.hk/search?q=bumpy+glass">bumpy glass</a>.
|
||||
Because the light rays was randomly bent by refractions through it.<br>
|
||||
Also, as usual, I integrated my homework compilation, since I put extra work into every single homeworks and I'm proud to show
|
||||
them in my final project.<br>
|
||||
You may browse the source <a href="./fs">here</a>.<br>
|
||||
</p>
|
||||
</ul>
|
||||
<p style="font-size:24px;">
|
||||
</div>
|
||||
</td><td valign=top style="background-color:azure;opacity: 100%;">
|
||||
<body bgcolor=white text=black link=black alink=blue vlink=blue>
|
||||
<center>
|
||||
<!!--- SUPER SAMPLING THE W/H PARAMS FOR CANVAS ARE RENDER SIZE, IN THE CSS IS ACTUAL(DISPLAY) SIZE.--->
|
||||
<canvas id='canvas1' style=" background-color:#FFF7F8;opacity: 100%;overflow: hidden !important; width: 600px !important; height:600px !important;" width=1199 height=1199></canvas>
|
||||
</center>
|
||||
</body>
|
||||
<div id="controls">
|
||||
<input type="number" id="ins" style="display:none;margin-left:0px;font-size:24px;width:35px;height:45px" value="5" max="5" min = "1">
|
||||
<button id="bns" style="display:none;margin-left:0px;font-size:24px;width:105px;height:45px">Spheres</button>
|
||||
<input type="number" id="insamp" style="margin-left:2px;font-size:24px;width:60px;height:45px" value="2" max="10" min = "0.1" step="0.2">
|
||||
<button id="bnsamp" style="margin-left:0px;font-size:24px;width:190px;height:45px">Super Sampling</button>
|
||||
<button id="bnfs" style="margin-left:2px;font-size:24px;width:180px;height:45px">Fullscreen</button>
|
||||
<button id="clrsel" style="display:none;margin-left:0px;font-size:24px;width:180px;height:45px">Clear Selection</button>
|
||||
<button id="reset" style="margin-left:0px;font-size:24px;width:100px;height:45px">Reset</button>
|
||||
<button id="mov" style="margin-left:0px;font-size:24px;width:180px;height:45px">Move Lighting</button>
|
||||
<button id="pause" style="margin-left:0px;font-size:24px;width:250px;height:45px">HW Compilation!</button>
|
||||
<button id="glsy" style="margin-left:0px;font-size:24px;width:200px;height:45px">Glassy</button>
|
||||
<div style='font-size:25px;'>
|
||||
|
||||
<!-- <font color=#000000>
|
||||
|
||||
<i style="font-size:28px;">What's new: </i>
|
||||
<p style="font-size:24px;">
|
||||
</p> -->
|
||||
<div id="howitworks">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div></td>
|
||||
</tr></table>
|
||||
</TR></TABLE>
|
||||
|
||||
|
||||
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
|
||||
|
||||
<script src="libX.ext.js"></script>
|
||||
|
||||
<script>
|
||||
setInterval(() => {
|
||||
if(window.vs != null && window.fs != null&& canvas1.setShaders === undefined)
|
||||
gl_start(canvas1, vs, fs);
|
||||
}, 200);
|
||||
</script>
|
||||
@@ -0,0 +1,104 @@
|
||||
M11.02,39.45c-2.67-2.97-5.37-5.93-8.01-8.94c-2.42-2.76-2.92-5.66-1.11-8.78c0.81-1.39,1.97-2.41,3.65-2.76c3.9-0.82,7.78-1.71,11.67-2.56c0.86-0.19,1.5-0.51,1.99-1.38c1.9-3.42,3.92-6.76,5.89-10.14c2.6-4.46,9.11-4.47,11.71-0.04
|
||||
c1.98,3.37,3.99,6.72,5.89,10.14c0.48,0.86,1.08,1.23,1.96,1.42c3.94,0.85,7.88,1.68,11.81,2.6c2.44,0.57,3.73,2.34,4.36,4.65c0.77,2.82-0.27,5.08-2.16,7.14c-2.52,2.74-4.97,5.53-7.44,8.32c-0.18,0.2-0.41,0.49-0.38,0.72c0.18,1.94,0.41,3.87,0.63,5.8
|
||||
c0.12,1.04,0.33,2.07,0.36,3.11c0.05,1.93,0.55,3.8,0.17,5.81c-0.65,3.42-4.81,6.08-8.02,4.95c-1.83-0.64-3.65-1.36-5.44-2.11
|
||||
c-2.24-0.94-4.48-1.89-6.67-2.95c-0.75-0.36-1.36-0.27-2.02,0.03c-2.75,1.22-5.47,2.48-8.24,3.66c-1.3,0.56-2.64,1.08-4.01,1.43
|
||||
c-2.45,0.63-4.53-0.26-6.14-2.08c-1.65-1.86-2.05-4.09-1.55-6.54c0.26-1.25,0.25-2.55,0.37-3.83
|
||||
C10.52,44.62,10.77,42.12,11.02,39.45z M56.81,25.75c0.02-1.65-1.04-2.64-2.79-3.01c-4.04-0.84-8.06-1.74-12.1-2.57
|
||||
c-0.91-0.19-1.58-0.65-2.04-1.42c-0.98-1.64-1.93-3.29-2.89-4.93c-1.32-2.26-2.6-4.55-3.98-6.77c-1.12-1.79-2.96-1.74-4.13,0.04
|
||||
c-0.65,0.99-1.23,2.04-1.83,3.07c-1.66,2.84-3.32,5.68-4.97,8.52c-0.48,0.83-1.17,1.32-2.14,1.5c-1.82,0.34-3.62,0.74-5.42,1.14
|
||||
c-2.45,0.54-4.92,1.04-7.34,1.68C5,23.57,4.46,25.5,5.92,27.15c1.64,1.85,3.31,3.69,4.95,5.54c1.33,1.5,2.68,2.97,3.92,4.54
|
||||
c0.38,0.48,0.61,1.21,0.61,1.82c0.01,1.33-0.17,2.65-0.29,3.98c-0.09,0.99-0.19,1.98-0.3,2.97c-0.26,2.26-0.58,4.51-0.77,6.78
|
||||
c-0.05,0.52,0.18,1.14,0.48,1.59c0.8,1.19,1.9,1.37,3.54,0.65c3.75-1.66,7.49-3.32,11.22-5.02c1.06-0.48,2.04-0.61,3.13-0.1
|
||||
c1.94,0.92,3.9,1.78,5.86,2.65c2.05,0.91,4.11,1.78,6.15,2.69c0.93,0.42,1.77,0.3,2.52-0.37c0.76-0.68,1.19-1.49,0.83-2.55
|
||||
c-0.08-0.22-0.12-0.46-0.14-0.7c-0.21-2.51-0.38-5.02-0.61-7.53c-0.12-1.32-0.38-2.63-0.51-3.95c-0.11-1.09-0.17-2.16,0.7-3.09
|
||||
c1.83-1.95,3.6-3.95,5.37-5.94c1.23-1.39,2.46-2.79,3.64-4.22C56.54,26.51,56.69,25.99,56.81,25.75z
|
||||
N
|
||||
M66.36,818.02c-106.2-110.9-61-662.8-36.4-813.56c71.19,1.55,58.77-12.26,72.22,57.92c12.21-15.09,10.15-62.97,37.19-55.8
|
||||
c-11.66,49.82-40.93,95.92-1.62,142.63c15.22,3.36,56.55-137.38,59.66-136.45c2.49,0.74-22.25,91.36-42.07,162.69
|
||||
c8.65,35.12,58.93,87.86,92.29,98.19c14.23-79.7,33.22-361.27,73.99-244.33c41.13-55.27-7.85,38.44-11.46,55.28
|
||||
c-18.92,98.99-27.77,241.63,53.45,119.52c20.21-34.31,20.1-114.01,53.68-126.53c3.84-12.82,10.48-73.87,24.02-73.1
|
||||
c12.83-0.56,65.91-1.83,35.15,7.41c-61.79-15.5-48.75,200.28-45.07,243.92c2.25,20.42,27.14,13.8,38.12,25.45
|
||||
c6.03,4.39,36.44,27.66,18.27,21.91c-40.8-27.63-66.71-54.35-46.2,16.36c-19.89-38.23,1.59-50.13-50.98-60.73
|
||||
c8.31-2.96,35.82,10.04,30.87-4.68c-5.47-26.59-6.9-54.75-14.96-80.46c-22.25,80.4-137.99,191.25-134.59,255.33
|
||||
c28.43-24.91,73.72-62.68,120.64-46.55c78.08,7.49,7.79-16.2-21.17-22.89c25.68-8.32,88.81,23.09,96.53,50.48
|
||||
c-14.88-13.87-8.97-8.07-4.72,6.57c-20.12-14.39-11.58-35.73-44.46-26.75c28.79,18.11,36.81,27.82,49.27,59.28
|
||||
c-15.78,0.19,5.06,35.44-28.02-9.3c-39.56-53.22-130.39-50.05-158.76,12.21c-0.57,107.56,60.34,213.63,68.06,323.78
|
||||
c1.71,10.93,25.65,17.02,33.27,28.59c-11.57-2.96-19.66-12.97-31.03-16.47c-1.22,193.89-65.94,75.43,75.87,233.86
|
||||
c-37.15-15.29-59.1-63.14-92.21-88.24c-15.18-7.04-28.22,43.71-46.26,43.68c57.38-81.24-1.81-123.16,10.19-218.4
|
||||
c8.56,76.16-24.52,144.42-59.52,208.52c-8.14,12.44,0.12,54.47-13.87,54.44c9.71-16.15,13.17-61.15-18.44-81.22
|
||||
C166.51,916.66,113.43,878.18,66.36,818.02z M925.87,407.64c-54.74-44.89,19.53-197.95-29.21-257.87
|
||||
c-7.8,0.23,0.01,139.34-12.78,138.06c-0.76-11.74,2.94-57.56-13.24-57.45c-12.13,43.49-18.05,56.87-20.76,56.35
|
||||
c-3.44-0.66-1.37-22.36-9.37-26.3c-1.4-0.69-3.39-0.47-6.27,1.08c-37.75,31.13-5.8-23.15-21.95-34.81
|
||||
c-10.77-4.3-7.19,51.51-13.81,37.09c-6.3-84.43-23.11-192.91-70.65-258.62c15.21,86.12,50.46,187.09,38.31,278.79
|
||||
c-21.94-86.63-52.72-175.52-70.62-266.49c2.29-9.8-18.19-21-13.94-4.4c30.28,57.1,21.26,334.09,14.6,185.12
|
||||
c-1.5-9.87,2.15-67.2-7.12-67.14c-2.9,30.13-5.79,60.27-8.69,90.4c-32.81-59.32-16.97-176.63-52.31-212.83
|
||||
c11.12,94.4-6.13,188.39-24.34,280.85c3.07-43.88,20.04-96.61,8.43-137.16c-6.3,14.9-20.93,66.96-26.59,61.57
|
||||
c-8.59-0.89-9.05-48.09-14.45-48.15c-3.39-0.04-6.04,18.34-7.95,31.07c-7.59,50.46-15.93,93.98-17.18,93.85
|
||||
c8.57-40.75,5.67-198.5-18.91-251.56c4.95,62.89-1.02,125.94-10.23,188.11c3.54-69.31,13.94-164.75-15.9-222.74
|
||||
c32.11,126.08-28.75,489.29,30.52,197.35c28.79,98.72-65.28,261.35,58.73,108.86c-37.19,187.32,36.13-32.28,47.76-103.08
|
||||
c8.96,94.67-2.01-42.55,6.66-79.88c30.75,97.92,53.06,199.4-5.06,292.92C737.6,336.4,694.28,5.48,752.2,275.59
|
||||
c12.58,35.83-30.59,24.88-39.09,50.66c61.29-24.55,38.95-35.44,52.83,53.39c0.4,3.52-0.24,7.19-4.7,7.28
|
||||
c-25.86,1.03-45.18,18.23-57.25,38.9c13.43-3.39,50.98-46.17,61.23-33.44c-21.97,29.52-78.97,40.99-72.67,90.22
|
||||
c3.55-15.72,78.25-89.59,75.21-54.58c-1.37,4.97-0.6,13.02-7.63,13.72c-61.1,2.32-80.25,119.34-40.63,125.28
|
||||
c-13.21-11.3-15.2-27.18-9.08-34.25c7.41-8.57,27.36-4.95,29.07,0.51c0.78,2.5-2.15,5.13-0.96,7.46c0.58,1.13,2.72,1.77,8.48,1.56
|
||||
c38.89-7.77,7.11,28.36-12.62,33.66c17.65,7.15,41.53-6.09,43.26-25.21c-13.61-10.4-3.01-29.64,12.23-22.19
|
||||
c39.17-39.2-23.35-78.46-17.83-98.65c2.53-4.97,11.94-9.86,47.83-3.67c17.2,5.95,27.38,81.41,34.69,33.83
|
||||
c26.79,65.65,1.08,95.95-22.65,157.49c-19.8,84.29-61.4,159.4-148.77,185.06c-117.87,55.02-132.92,97.58-258.09,25.2
|
||||
c46.48,32.06,76.67,55,136.6,42.95c-16.18,37.26-58.98,60.98-65.42,102.39c20.1-25.76,40.19-51.51,60.29-77.27
|
||||
c-8.67,85.19,10.27,58.11-48.65,125.91c90.48-25.72,17.5-180.83,122.56-177.14c18.96,52.7-4.18,120.02,8.63,173.54
|
||||
c2.68-39.19,12.24-88.12,46.19-106.21c456.17,81.79,348.93-736.88,256.65-896.72c22.97,42.24,68.59,278.45,36,201.55
|
||||
c-3.91-9.81-16.93-10.42-12.04,2.06c-3.92,64.31,14.29,179.15-11.75,192.94z M348.31,563.23c5.68,9.7,20.47-3.9,12.83-8.26c-3.76-6.73-7.6-13.49-12.17-19.69
|
||||
c-8.79-11.93,9.75-6.48,8.3-13.53c21.55,9.97,28.08,14.2,46.14-5.3c-0.61,18.31-0.16,38.03-18.36,50.23
|
||||
c18.72,10.53,30.46-6.95,33.62-24.89c-25.93,2.12,1.38-48.33,8.9-22.45c7.53-11.49,6.87-26.71,9.65-39.21
|
||||
C420.8,350.18,268.58,459.17,348.31,563.23z M517.13,804.37c-10.18-5.07-29.37-7.14-13.37-22.49
|
||||
c18.15-20.96,102.96-23.38,73.03,12.59c29.3-17.57-7.7-35.22-30.46-31.69C518.69,758.1,459.7,799.43,517.13,804.37z
|
||||
N
|
||||
M106.8,0c-3.3,4.6-6.3,9.4-8.8,14.5c-2.8-5-5.7-9.8-8.8-14.5C52.9,32.5,56.8,74.2,98,99.6c0,0,0,0,0,0c0,0,0,0,0,0C139.5,74,142.9,32.2,106.8,0z M5.4,60.7c3.7,4.5,7.4,8.8,11,12.8c-5.4,1-10.9,2.3-16.5,3.9 c19.6,44.6,60.5,53.8,97.4,22.5c0,0,0,0,0,0c0,0,0,0,0,0C85.9,52.4,47.2,36.3,5.4,60.7z M31.2,174.9c5.3-1.5,10.5-3.8,15.6-6.6c-0.8,5.7-1.2,11.3-1.4,16.8c48.5-4.9,69.9-40.9,51.5-85.7c0,0,0,0-0.1,0c0,0,0,0,0,0C48.2,95.8,20.9,127.6,31.2,174.9zM148.3,186.1c-0.4-5.5-0.9-11.1-1.4-16.8c5.1,2.4,10.3,4.6,15.6,6.6c10.4-47.6-17.3-79.1-65.6-75.5c0,0,0,0,0,0c0,0-0.1,0-0.1,0C78.3,145.5,100.1,181.3,148.3,186.1z M195.1,76.9c-5.9-1.5-11.5-2.9-16.5-3.9c3.9-4,7.6-8.3,11-12.8c-42.1-24.6-80.6-8-92.1,39.1c0,0,0,0,0,0c0,0,0,0,0,0C134.9,130.9,175.6,121.2,195.1,76.9z
|
||||
N
|
||||
M35.2,14.9c-2.4,0-4.8,1-6.5,2.7c-1.7-1.7-4.1-2.7-6.5-2.7c-5.6,0.2-10,5-9.8,10.6c0,9.7,13.1,17.8,14.6,18.6c1,0.6,2.3,0.6,3.3,0C31.8,43.2,45,35.2,45,25.5C45.2,19.8,40.8,15.1,35.2,14.9z
|
||||
N
|
||||
M140 20C73 20 20 74 20 140c0 135 136 170 228 303 c88-132 229-173 229-303 c0-66-54-120-120-120c-48 0-90 28-109 69c-19-41-60-69-108-69z
|
||||
N
|
||||
M96,2.86c-2.05,4.41-4.22,9.48-6.33,15.17
|
||||
c-1.08,2.92-3,8.28-4.95,15.1c-3.16,11.03-4.62,19.6-5.81,26.71c-2.49,14.88-3.28,26.75-3.45,30.36c-0.02,0.43-0.08,1.78-0.2,3.64
|
||||
c-0.36,5.44-0.87,9.65-1.16,11.83c0,0-0.56,4.27-1.3,8.34c-0.19,1.07-0.4,2.13-0.4,2.13c-0.02,0.09-0.03,0.16-0.03,0.17
|
||||
c-0.05,0.25-5.9,30.37-5.91,40.92c0,0.85,0.03,3.62-1.34,4.24c-0.46,0.21-0.96,0.13-1.34,0.01c-7.07,0.06-12.87,0.76-16.99,1.42
|
||||
c0,0-13,2.1-30.7,9.21c-3.62,1.46-7.03,3-7.34,3.14c-2.48,1.13-4.67,2.19-6.52,3.12c1.83-0.17,4-0.52,6.39-1.21
|
||||
c1.84-0.53,3.45-1.16,4.82-1.78c0,0,10.45-3.6,19.4-5.26c5.58-1.03,6.34-0.55,17.45-1.7c6.41-0.66,11.59-1.36,14.88-1.84
|
||||
c7.74-1.12,10.4-0.32,11,1.04c0.13,0.29,0.13,0.55,0.11,0.94c-0.24,5.58-3.01,9.41-2.26,13.44c0.04,0.22,0.07,0.33,0.33,1.59
|
||||
c0.13,0.62,0.56,2.75,0.85,4.34c0.4,2.22,0.41,2.72,0.72,4.65c0.6,3.67,0.9,5.5,1.48,6.82c1.14,2.59,2.86,4.11,4.88,5.88
|
||||
c2.01,1.76,3.74,2.73,6.91,4.49c2.61,1.45,4.85,2.52,6.44,3.23z
|
||||
N
|
||||
M12.43,1.78c0.4,0.5,0.94,1.28,1.36,2.32
|
||||
c0.67,1.66,0.67,3.07,0.67,4.45c0,0.92,0.04,4.84,0,6.15c-0.19,6.59,0.61,7.24,0,11.71c-0.34,2.51-0.83,4.02-1.19,4.96
|
||||
c-0.18,0.48-0.94,2.43-2.52,4.74c-0.44,0.64-1.1,1.54-3.04,3.63c-3.35,3.61-5.27,4.39-5.19,5.19c0.13,1.28,5.07,2.54,25.78,2.55z
|
||||
N
|
||||
M105,654.21c-7.27-2.1-16.75-4.87-27.83-8.17
|
||||
c-40.23-11.98-49.04-15.35-58.28-22.6c-5.71-4.47-14.05-12.37-21.32-25.91C2.14,588.3,8.74,575.32,17.11,560
|
||||
c13.51-24.74,22.16-40.57,35.49-58.91c7.85-10.79,19.4-25.32,35.36-41.18c0.72-5.12,1.23-9.06,1.53-11.49
|
||||
c0.57-4.57,0.8-6.77,2.34-9.27c1.46-2.37,3.38-3.84,4.75-4.7c0.63-143.54,1.26-287.08,1.89-430.62z
|
||||
N
|
||||
M204.68,0.14c-1.76,0.11-4.62,0.27-8.17,0.38
|
||||
c-6.7,0.21-8.06-0.01-10.6,0.77c-3.92,1.2-3.97,2.71-8.07,4.59c-2.36,1.08-3.84,1.26-12.22,2.17c-5.45,0.59-10.87,1.53-16.34,1.91
|
||||
c-5.84,0.41-9.63,0.36-12,3.2c-1.04,1.25-1.47,2.63-1.66,3.56c-3.32,18.64-2.48,32.37-1.02,41.62c0.57,3.57,3.63,21.7,0.89,34.76
|
||||
c-0.17,0.79-0.64,2.93-1.15,5.97c-0.28,1.67-1.58,9.69-1.66,17.62c-0.05,5.4,1.24,12.84,3.83,27.7c0.5,2.88,1.27,7.13,2.17,13.28
|
||||
c0.59,4.02,1.01,7.31,1.28,9.45c-0.52,3.62-0.43,6.53-0.26,8.55c0.29,3.26,0.86,4.56,0.13,6.77c-0.77,2.31-1.92,2.45-2.43,4.85
|
||||
c-0.48,2.29,0.42,2.86-0.15,4.95c-0.41,1.49-1.13,2.2-2.79,4.24c-1.48,1.82-2.74,3.8-4.21,5.62c-4.31,5.35-8.49,10.81-12.89,16.09
|
||||
c-5.78,6.93-6.86,8.58-17.49,21.96c-18.52,23.3-21.63,26.32-32.55,40.21c-24.98,31.79-37.81,53.07-40.72,57.96
|
||||
c0,0-7.82,13.11-17.62,36.64c-2.39,5.73-5.45,13.54-6.38,24.13c-0.58,6.56-0.34,12.62,0,12.64c0.41,0.02,0.43-8.67,2.7-18.95
|
||||
c1.86-8.39,4.48-14.51,8.17-22.47c8.35-18.03,12.53-27.04,19.74-39.15c9.69-16.26,19.31-28.61,38.55-53.32
|
||||
c5.65-7.26,4.63-5.77,17.11-21.45c13.19-16.57,27.11-32.56,39.85-49.48c0.35-0.47,1.41-1.88,3.13-3.42c0,0,2.37-2.12,5.36-3.58
|
||||
c6.09-2.99,20.05-2.23,25.95-2c7.4,0.28,14.81-0.1,22.22-0.1c8.52,0,15.39-0.01,19.63-0.01z
|
||||
N
|
||||
M0.94,0.6c2.08,18.15,2.97,32.18,3.39,41.88
|
||||
c0,0,0.86,19.42,2.87,34.97c1.76,13.6,2.61,14.56,5.45,32.49c1.14,7.2,1.2,8.27,5.73,44.13c3.64,28.81,4.03,31.51,4.32,38.54
|
||||
c0.2,4.94,0.57,17.17-0.63,32.88c-0.89,11.66-2.25,19.73-3,24.73c-3.72,24.69-3.65,45.64-3.59,66.15
|
||||
c0.04,13.85,0.17,33.71,3.42,59.26c2.56,20.15,6,35.46,6.44,62.42c0.01,0.88,0.13,1.85,0.2,3.47c0.31,6.41-0.11,11.45-0.35,14.17
|
||||
c-3.35,37.28-5.52,47.52-5.52,47.52c-1.06,4.71-2.95,10.98-0.08,13.41c1.1,0.94,2.42,0.94,9.8,0.98c3.87,0.02,7.02,0.04,8.28,0.05z
|
||||
N
|
||||
M9.22,0C6.92,4.49,4,11.35,2.55,20.09
|
||||
c-1.21,7.29-0.82,12.5-0.33,20.94C3.3,59.23,3.79,73.41,3.9,76.76c0.65,20.48-0.9,19.3,0.05,35.96c0.7,12.33,2.2,24.62,2.98,30.95
|
||||
c1.78,14.5,2.82,18.69,2.45,27.6c-0.42,10.1-1.94,8.9-2.49,20.33c-0.54,11.15,0.83,13.91,0.19,27.57c-0.35,7.5-0.78,6.96-0.98,13.91
|
||||
c-0.12,4.35-0.01,6.38,0.61,21.61c0.24,5.92,0.64,10.99,0.78,17.78c0.12,6.38,0.06,11.89,0.02,14.77
|
||||
c-0.07,5.78-0.11,8.68-0.27,11.31c-0.96,16.14-5.06,22.75-1.69,25.57c0.93,0.78,1.57,0.55,8.39,0.78c4.83,0.16,8.78,0.42,11.44,0.61z
|
||||
N
|
||||
@@ -0,0 +1,25 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
import math
|
||||
mat = cv2.imread('starburst.png')
|
||||
mat2 = np.zeros((900, 1273, 3))
|
||||
print(mat.shape)
|
||||
rad = 0
|
||||
for i in range(0, 900):
|
||||
dt = 0
|
||||
s = math.sin(rad)
|
||||
c = math.cos(rad)
|
||||
for j in range(0, 1273):
|
||||
# if(dt*c > 913 or dt*c < -913 or dt * s > 900 or dt*s < -900):
|
||||
# break
|
||||
x = 900+int(dt*s)
|
||||
x = x if x < 1800 else 1799
|
||||
y = 913+int(dt*c)
|
||||
y = y if y < 1826 else 1799
|
||||
|
||||
mat2[i][j] = mat[900+int(dt*s)][913+int(dt*c)]
|
||||
dt += 1
|
||||
rad += .007
|
||||
cv2.imwrite('starburst3.png',mat2)
|
||||
cv2.imshow('a', mat2)
|
||||
cv2.waitKey(0)
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
vec3 foregroundColor = vec3(.0841, .5329, .9604);
|
||||
uniform vec3 starColors[10];
|
||||
uniform vec3 V0;
|
||||
uniform sampler2D uSampler[ns + 1]; //ns + vs
|
||||
varying vec3 norm;
|
||||
varying float id;
|
||||
varying vec3 glpos;
|
||||
varying vec3 texPos;
|
||||
vec3 LDir=vec3(.5,.5,.5);
|
||||
void main(){
|
||||
vec3 color =foregroundColor.xyz;
|
||||
float sp = 0.4, df = 0.4, amb = 0.4, ex=5., alpha = 1.;
|
||||
vec3 l = vec3(1,1,1);
|
||||
float alp = 2.*abs(.49999 - fract(id+.00001));
|
||||
if(id < -2.5){gl_FragColor = vec4(texture2D(uSampler[ns + 0], (1.+texPos.xy)/2.).xyz, 1.); return;} //pjsk
|
||||
else if(id <-1.5) {color = vec3(.05,.05,.05);sp = 1.; df=.4; amb = .3, ex = 5.;}
|
||||
else if(id <-.5) {color = vec3(0.,1.,0.2034);}
|
||||
else if(id < 1.5) {color = vec3(1.0000, 0.3570, 0.3570);sp = 1.; df=.2; amb = .7, ex = 20.;}
|
||||
else if (id < 2.5) color = vec3(1.,.16,.36);
|
||||
else if (id < 3.5) {color = vec3(1.0000, 0.7725, 0.7725);sp = .5; df=.8; amb = .05;}
|
||||
else if (id < 4.5) {color = vec3(0.9612,0.3057,0.3369);sp = .5; df=.5; amb = .5; ex=20.;}
|
||||
else if (id < 6.5) {}
|
||||
else if (id < 7.5) {color = starColors[0]; sp = 0.3, df = 0.3, amb = 0.8, ex=5.;}
|
||||
else if (id < 8.5) {color = starColors[1]; sp = 0.05, df = 0.1, amb = 0.8, ex=10.,l = color;alp*=1.1;}
|
||||
else if (id < 9.5) {color = starColors[2]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 10.5) {color = starColors[3]; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 12.5) {color = starColors[4]; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 13.5) {color = starColors[4]*2.; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 14.5) {
|
||||
color = .4*foregroundColor + .8*starColors[4]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;
|
||||
if(texPos.y > .3)
|
||||
color = vec3(1.,1.,1.);
|
||||
}
|
||||
else if (id < 15.5) {color = .3*vec3(0.9612,0.3057,0.3369)+.8*starColors[4]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 16.5) {gl_FragColor=vec4(1.,1.,1., alp);return;}
|
||||
else if (id < 17.5) {color = vec3(.35,.35,.35);sp = .3; df=.6; amb = .1, ex = 1.;}
|
||||
else if (id < 18.5) {
|
||||
color = vec3(.6,.29,.12);sp = .1; df=.2; amb = .7, ex = 1.;
|
||||
vec3 P = vec3(sin(texPos.y*1.), sin(texPos.x*1.5+1.), cos(texPos.z*1.));
|
||||
// APPLY PROCEDURAL NOISE TEXTURE.
|
||||
float cloud = min(0.99, max(0., 1. * noise(.8 * P)));
|
||||
color = (1.-cloud)*color + starColors[5] * cloud*3.;
|
||||
}
|
||||
|
||||
if(id < 0. &&id > -1.5){
|
||||
vec3 P = vec3(sin(glpos.y*1.), sin(glpos.x*1.5+1.), cos(glpos.z*1.));
|
||||
// APPLY PROCEDURAL NOISE TEXTURE.
|
||||
float cloud = min(0.99, max(0., 1. * noise(1. * P)));
|
||||
color = (1.-cloud)*color + starColors[5] * cloud*3.;
|
||||
}
|
||||
vec3 V = V0;
|
||||
vec3 W=normalize(glpos-V);
|
||||
vec3 realLDir=normalize(LDir - glpos);
|
||||
|
||||
color = color*(amb+ df*max(0.,dot(norm,realLDir)))
|
||||
+ sp*pow(max(0., dot(2.*dot(norm, realLDir)*norm-realLDir, -W)),ex)*l;
|
||||
gl_FragColor=vec4(sqrt(color), alp);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
uniform mat4 uMatrix;
|
||||
uniform mat4 invMatrix;
|
||||
uniform mat3 transformation;
|
||||
attribute float oid;
|
||||
attribute vec3 aPos;
|
||||
attribute vec3 normal;
|
||||
varying float id;
|
||||
varying vec3 glpos;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
void main() {
|
||||
vec4 pos = uMatrix * vec4(aPos, 1.);
|
||||
texPos = aPos;
|
||||
gl_Position = pos ;
|
||||
glpos = pos.xyz;
|
||||
id = oid;
|
||||
norm = normalize(vec4(normal,0.)*invMatrix).xyz;
|
||||
}
|
||||
|
After Width: | Height: | Size: 734 KiB |
@@ -0,0 +1,201 @@
|
||||
|
||||
function implicitSurfaceTriangleMesh(implicitFunction, n, args, id = 8) {
|
||||
|
||||
// HERE IS WHERE MOST OF THE WORK HAPPENS
|
||||
|
||||
let marchingTetrahedra = function(V, ni, nj) {
|
||||
|
||||
// CONVENIENCE FUNCTIONS TO COMPUTE (i,j,k) FROM VOLUME INDEX n
|
||||
|
||||
function n2i(n) { return n % ni; }
|
||||
function n2j(n) { return (n / dj >>> 0) % nj; }
|
||||
function n2k(n) { return n / dk >>> 0 ; }
|
||||
|
||||
// ADD A VERTEX, AND RETURN A UNIQUE ID FOR THAT VERTEX
|
||||
|
||||
function E(a, b) {
|
||||
if (a > b) { let tmp = a; a = b; b = tmp; }
|
||||
let ai = n2i(a), aj = n2j(a), ak = n2k(a),
|
||||
bi = n2i(b), bj = n2j(b), bk = n2k(b);
|
||||
let m = (n << 6) + (ai & bi ? 1 << 6 : ai | bi << 3)
|
||||
+ (aj & bj ? dj << 6 : aj << 1 | bj << 4)
|
||||
+ (ak & bk ? dk << 6 : ak << 2 | bk << 5);
|
||||
|
||||
// ADD TO VERTEX ARRAY ONLY THE FIRST TIME THE VERTEX IS ENCOUNTERED
|
||||
|
||||
if (vertexID[m] === undefined) {
|
||||
vertexID[m] = P.length / 3;
|
||||
let t = -V[n+a] / (V[n+b] - V[n+a]),
|
||||
c = function(i,a,b) { return (i + (1-t)*a + t*b) / ni * 2 - 1; };
|
||||
P.push( c(i,ai,bi), c(j,aj,bj), c(k,ak,bk) );
|
||||
}
|
||||
|
||||
return vertexID[m];
|
||||
}
|
||||
|
||||
// CASE WHERE WE ADD ONE TRIANGLE IN A TETRAHEDRON
|
||||
|
||||
function tri(a, b, c, d) {
|
||||
T.push(E(a,b), E(a,c), E(a,d));
|
||||
}
|
||||
|
||||
// CASE WHERE WE ADD TWO TRIANGLES IN A TETRAHEDRON
|
||||
|
||||
function quad(a, b, c, d) {
|
||||
let ac = E(a,c), bc = E(b,c), ad = E(a,d), bd = E(b,d);
|
||||
T.push(bc, ac, ad);
|
||||
T.push(ad, bd, bc);
|
||||
}
|
||||
|
||||
// DECLARE VARIABLES
|
||||
|
||||
let nk = V.length / (ni * nj), di = 1, dj = ni, dk = ni * nj;
|
||||
let dij = di + dj, dik = di + dk, djk = dj + dk, dijk = di + dj + dk;
|
||||
let P = [], T = [], vertexID = [], i, j, k, m = 0, n, S = [0,di,dij,dijk];
|
||||
let lo = new Array(nj * nk),
|
||||
hi = new Array(nj * nk);
|
||||
|
||||
// THE SIX POSSIBLE INTERMEDIATE PATHS THROUGH A TETRAHEDRON
|
||||
|
||||
let S1 = [di , dj , dk , di , dj , dk ];
|
||||
let S2 = [dij, djk, dik, dik, dij, djk];
|
||||
|
||||
// THERE ARE 16 CASES TO CONSIDER
|
||||
|
||||
let cases = [ [0 ], [1, 0,1,2,3], [1, 1,2,0,3], [2, 0,1,2,3],
|
||||
[1, 2,3,0,1], [2, 0,2,3,1], [2, 1,2,0,3], [1, 3,1,2,0],
|
||||
[1, 3,0,2,1], [2, 0,3,1,2], [2, 1,3,2,0], [1, 2,1,0,3],
|
||||
[2, 2,3,0,1], [1, 1,3,0,2], [1, 0,3,2,1], [0 ], ];
|
||||
|
||||
// FOR EACH (Y,Z), DON'T DO ANY WORK OUTSIDE OF X RANGE WHERE SURFACE MIGHT BE
|
||||
|
||||
for (k = 0 ; k < nk ; k++)
|
||||
for (j = 0 ; j < nj ; j++, m++) {
|
||||
let n0 = m * ni, n1 = n0 + ni - 1;
|
||||
for (n = n0 ; n <= n1 && V[n] > 0 ; n++) ;
|
||||
lo[m] = Math.max(0, n-1 - n0);
|
||||
for (n = n1 ; n >= n0 && V[n] > 0 ; --n) ;
|
||||
hi[m] = Math.min(ni-1, n+1 - n0);
|
||||
}
|
||||
|
||||
// FOR ALL Y AND Z IN THE VOLUME
|
||||
|
||||
for (k = 0 ; k < nk - 1 ; k++) {
|
||||
let i0, i1, m = k * nj, n1, s0, s1;
|
||||
for (j = 0 ; j < nj - 1 ; j++, m++) {
|
||||
i0 = Math.min(lo[m], lo[m+1], lo[m+ni], lo[m+1+ni]);
|
||||
i1 = Math.max(hi[m], hi[m+1], hi[m+ni], hi[m+1+ni]);
|
||||
|
||||
// GO THROUGH RANGE OF X WHERE THE SURFACE MIGHT BE (IE: WITH ANY POSITIVE VALUES)
|
||||
|
||||
if (i0 <= i1) {
|
||||
n = m * ni + i0;
|
||||
n1 = m * ni + i1;
|
||||
s0 = (V[n]>0) + (V[n+dj]>0) + (V[n+dk]>0) + (V[n+djk]>0);
|
||||
for (i = i0 ; n <= n1 ; i++, n++, s0 = s1) {
|
||||
|
||||
// FOR EACH CUBE
|
||||
|
||||
s1 = (V[n+di]>0) + (V[n+dij]>0) + (V[n+dik]>0) + (V[n+dijk]>0);
|
||||
if (s0 + s1 & 7) {
|
||||
let C14 = (V[n] > 0) | (V[n+dijk] > 0) << 3;
|
||||
|
||||
// CYCLE THROUGH THE SIX TETRAHEDRA THAT TILE THE CUBE
|
||||
|
||||
for (let p = 0 ; p < 6 ; p++) {
|
||||
let C = cases [ C14 | (V[n+S1[p]] > 0) << 1 | (V[n+S2[p]] > 0) << 2 ];
|
||||
|
||||
// FOR EACH TETRAHEDRON, OUTPUT EITHER ZERO, ONE OR TWO TRIANGLES
|
||||
|
||||
if (C[0]) { // C[0] == number of triangles to be created.
|
||||
S[1] = S1[p]; // assign 2nd and 3rd corners of simplex.
|
||||
S[2] = S2[p];
|
||||
(C[0]==1 ? tri : quad)(S[C[1]], S[C[2]], S[C[3]], S[C[4]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MAKE SURE ALL TRIANGLE VERTICES ARE LISTED IN COUNTERCLOCKWISE ORDER
|
||||
|
||||
for (let m = 0 ; m < T.length ; m += 3) {
|
||||
let a = 3 * T[m], b = 3 * T[m+1], c = 3 * T[m+2],
|
||||
n = Math.floor(ni*(P[a ]+1)/2) +
|
||||
Math.floor(ni*(P[a+1]+1)/2) * dj +
|
||||
Math.floor(ni*(P[a+2]+1)/2) * dk,
|
||||
u = cross([P[b] - P[a], P[b+1] - P[a+1], P[b+2] - P[a+2]],
|
||||
[P[c] - P[b], P[c+1] - P[b+1], P[c+2] - P[b+2]]),
|
||||
v = [ V[n+1] - V[n], V[n+dj] - V[n], V[n+dk] - V[n] ];
|
||||
if (dot(u, v) < 0) { let tmp = T[m]; T[m] = T[m + 2]; T[m + 2] = tmp; }
|
||||
}
|
||||
|
||||
// RETURN POINTS AND TRIANGLES
|
||||
|
||||
return [P, T];
|
||||
}
|
||||
|
||||
// SAMPLE THE VOLUME
|
||||
|
||||
let F = i => (i - n/2) / (n/2);
|
||||
let volume = [];
|
||||
|
||||
for (let k = 0 ; k < n ; k++)
|
||||
for (let j = 0 ; j < n ; j++)
|
||||
for (let i = 0 ; i < n ; i++)
|
||||
volume.push(implicitFunction(F(i), F(j), F(k), args));
|
||||
|
||||
// FIND ALL VERTICES AND TRIANGLES IN THE VOLUME
|
||||
|
||||
let VT = marchingTetrahedra(volume, n, n);
|
||||
let V = VT[0];
|
||||
let T = VT[1];
|
||||
|
||||
// COMPUTE SURFACE NORMALS
|
||||
|
||||
let N = new Array(V.length);
|
||||
for (let i = 0 ; i < V.length ; i += 3) {
|
||||
let x = V[i], y = V[i+1], z = V[i+2], e = .001,
|
||||
f0 = implicitFunction(x ,y ,z , args),
|
||||
fx = implicitFunction(x+e,y ,z , args),
|
||||
fy = implicitFunction(x ,y+e,z , args),
|
||||
fz = implicitFunction(x ,y ,z+e, args),
|
||||
normal = normalize([f0-fx,f0-fy,f0-fz]);
|
||||
for (let j = 0 ; j < 3 ; j++)
|
||||
N[i+j] = normal[j];
|
||||
}
|
||||
|
||||
// CONSTRUCT AND RETURN THE TRIANGLES MESH
|
||||
|
||||
let mesh = [];
|
||||
for (let i = 0; i < T.length; i += 3) {
|
||||
let a = 3 * T[i ],
|
||||
b = 3 * T[i + 1],
|
||||
c = 3 * T[i + 2];
|
||||
mesh.push( id, V[a],V[a+1],V[a+2] , N[a],N[a+1],N[a+2] ,
|
||||
id, V[b],V[b+1],V[b+2] , N[b],N[b+1],N[b+2] ,
|
||||
id, V[c],V[c+1],V[c+2] , N[c],N[c+1],N[c+2] );
|
||||
}
|
||||
return new Float32Array(mesh);
|
||||
}
|
||||
|
||||
let blob = (center, radius, x, y, z) => {
|
||||
x -= center[0];
|
||||
y -= center[1];
|
||||
z -= center[2];
|
||||
return Math.max(0, 1 - .16 * (x*x + y*y + z*z) / (radius * radius));
|
||||
}
|
||||
|
||||
var implicitFunction = (x,y,z,args) => {
|
||||
let ret = -.5;
|
||||
let x4 = _x => _x*_x*_x*_x;
|
||||
args.forEach((paras, _)=>{
|
||||
const center = paras[0],
|
||||
radius = paras[1];
|
||||
ret += x4(blob(center, radius, x, y, z));
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<video src="pjsk.mp4" id="pjsk" hidden="true" muted="muted" loop="true" style="position:fixed; left:0; top:0;max-width:100%;min-width:100%;min-height: 100%;z-index: -100;"></video>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js" crossorigin="anonymous"></script>
|
||||
<script src=libX.header.js></script>
|
||||
<script src=libX.js></script>
|
||||
<style>
|
||||
.ace_gutter-layer {
|
||||
/* original width is 48px */
|
||||
width: 25px !important;
|
||||
}
|
||||
|
||||
.ace_gutter-layer > * {
|
||||
/* 48 - 32 = 16 */
|
||||
margin-left: 0;
|
||||
}
|
||||
.ace_gutter-cell {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 3px !important;
|
||||
}
|
||||
.code{
|
||||
font-family: "monaco, menlo, ubuntu mono, consolas, source-code-pro" ;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<!!-------- VERTEX SHADER: YOU PROBABLY DON'T WANT TO CHANGE THIS RIGHT NOW -------->
|
||||
|
||||
|
||||
|
||||
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
|
||||
<!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag!! LOADED IN lib2.js -------->
|
||||
|
||||
<font size=7 color=#909090>
|
||||
|
||||
Final Project
|
||||
|
||||
<img id="rtx" style="float:right;" src="./RTXon.svg" type="image/svg+xml"
|
||||
alt="Turn Ray Tracing On/OFF" title="Turn Ray Tracing On/OFF" height=60px /img>
|
||||
<div id="fps" style="font-size:25;float:right;margin-right:18px;"></div>
|
||||
<TABLE cellspacing=0 cellpadding=0 style="width:50%"><TR>
|
||||
<td><font color=red size=5><div id=errorMessage></div></font></td>
|
||||
</TR><TR>
|
||||
<table cellspacing=0>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<div id="ace" style="opacity:90%;width:500px;height:600px;"hidden=true></div>
|
||||
<div id = 'usage' style="opacity:90%;width:500px;height:600px;">
|
||||
<font color=#000000>
|
||||
<i style="font-size:28px;">What's new: </i>
|
||||
<ul style="font-size:24px;">
|
||||
<p>
|
||||
In the final project I implemented Flares and glowing object for ray tracing. The technical
|
||||
details can be found in <a href="http://resources.mpi-inf.mpg.de/lensflareRendering/">this paper</a> from
|
||||
SIGGRAPH 2011.<br>
|
||||
I also implemented a glassy filter by randomly bending the rays shot from the screen. The idea was from my
|
||||
failed attempt to create flares which I thought was caused by diffusion of lights caused by fogs on my glasses.
|
||||
But this actually resembles the images we saw through a <a href="https://www.google.com.hk/search?q=bumpy+glass">bumpy glass</a>.
|
||||
Because the light rays was randomly bent by refractions through it.<br>
|
||||
Also, as usual, I integrated my homework compilation, since I put extra work into every single homeworks and I'm proud to show
|
||||
them in my final project.<br>
|
||||
You may browse the source <a href="./fs">here</a>.<br>
|
||||
</p>
|
||||
</ul>
|
||||
<p style="font-size:24px;">
|
||||
</div>
|
||||
</td><td valign=top style="background-color:azure;opacity: 100%;">
|
||||
<body bgcolor=white text=black link=black alink=blue vlink=blue>
|
||||
<center>
|
||||
<!!--- SUPER SAMPLING THE W/H PARAMS FOR CANVAS ARE RENDER SIZE, IN THE CSS IS ACTUAL(DISPLAY) SIZE.--->
|
||||
<canvas id='canvas1' style=" background-color:#FFF7F8;opacity: 100%;overflow: hidden !important; width: 600px !important; height:600px !important;" width=1199 height=1199></canvas>
|
||||
</center>
|
||||
</body>
|
||||
<div id="controls">
|
||||
<input type="number" id="ins" style="display:none;margin-left:0px;font-size:24px;width:35px;height:45px" value="5" max="5" min = "1">
|
||||
<button id="bns" style="display:none;margin-left:0px;font-size:24px;width:105px;height:45px">Spheres</button>
|
||||
<input type="number" id="insamp" style="margin-left:2px;font-size:24px;width:60px;height:45px" value="2" max="10" min = "0.1" step="0.2">
|
||||
<button id="bnsamp" style="margin-left:0px;font-size:24px;width:190px;height:45px">Super Sampling</button>
|
||||
<button id="bnfs" style="margin-left:2px;font-size:24px;width:180px;height:45px">Fullscreen</button>
|
||||
<button id="clrsel" style="display:none;margin-left:0px;font-size:24px;width:180px;height:45px">Clear Selection</button>
|
||||
<button id="reset" style="margin-left:0px;font-size:24px;width:100px;height:45px">Reset</button>
|
||||
<button id="mov" style="margin-left:0px;font-size:24px;width:180px;height:45px">Move Lighting</button>
|
||||
<button id="pause" style="margin-left:0px;font-size:24px;width:250px;height:45px">HW Compilation!</button>
|
||||
<button id="glsy" style="margin-left:0px;font-size:24px;width:200px;height:45px">Glassy</button>
|
||||
<div style='font-size:25px;'>
|
||||
|
||||
<!-- <font color=#000000>
|
||||
|
||||
<i style="font-size:28px;">What's new: </i>
|
||||
<p style="font-size:24px;">
|
||||
</p> -->
|
||||
<div id="howitworks">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div></td>
|
||||
</tr></table>
|
||||
</TR></TABLE>
|
||||
|
||||
|
||||
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
|
||||
|
||||
<script src="libX.ext.js"></script>
|
||||
|
||||
<script>
|
||||
setInterval(() => {
|
||||
if(window.vs != null && window.fs != null&& canvas1.setShaders === undefined)
|
||||
gl_start(canvas1, vs, fs);
|
||||
}, 200);
|
||||
</script>
|
||||
@@ -0,0 +1,98 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js" crossorigin="anonymous"></script>
|
||||
<script src=lib10.header.js></script>
|
||||
<script src=animation.js></script>
|
||||
<script src=implicitSurface.js></script>
|
||||
<script src=lib10.js></script>
|
||||
<style>
|
||||
.ace_gutter-layer {
|
||||
/* original width is 48px */
|
||||
width: 25px !important;
|
||||
}
|
||||
|
||||
.ace_gutter-layer > * {
|
||||
/* 48 - 32 = 16 */
|
||||
margin-left: 0;
|
||||
}
|
||||
.ace_gutter-cell {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 3px !important;
|
||||
}
|
||||
.code{
|
||||
font-family: "monaco, menlo, ubuntu mono, consolas, source-code-pro" ;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<!!-------- VERTEX SHADER: YOU PROBABLY DON'T WANT TO CHANGE THIS RIGHT NOW -------->
|
||||
|
||||
|
||||
|
||||
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
|
||||
<!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag!! LOADED IN lib2.js -------->
|
||||
|
||||
<font size=7 color=#909090>
|
||||
|
||||
Pikachu
|
||||
|
||||
<div id="fps" style="font-size:25;float:right;margin-right:18px;"></div>
|
||||
<TABLE cellspacing=0 cellpadding=0 style="width:50%"><TR>
|
||||
<td><font color=red size=5><div id=errorMessage></div></font></td>
|
||||
</TR><TR>
|
||||
<table cellspacing=0>
|
||||
<tr>
|
||||
<td valign=top>
|
||||
<div id="ace" style="opacity:90%;width:300px;height:700px;"hidden=true></div>
|
||||
<div id = 'usage' style="opacity:90%;width:300px;height:700px;">
|
||||
<font color=#000000>
|
||||
<i style="font-size:28px;">What's new: </i>
|
||||
<ul style="font-size:24px;">
|
||||
|
||||
</ul>
|
||||
<p style="font-size:24px;">
|
||||
</div>
|
||||
</td><td valign=top style="background-color:azure;opacity: 100%;">
|
||||
<body bgcolor=white text=black link=black alink=blue vlink=blue>
|
||||
<center>
|
||||
<!!--- SUPER SAMPLING THE W/H PARAMS FOR CANVAS ARE RENDER SIZE, IN THE CSS IS ACTUAL(DISPLAY) SIZE.--->
|
||||
<canvas id='canvas1' style=" background-color:#333333;opacity: 100%;overflow: hidden !important; width: 600px !important; height:600px !important;" width=1199 height=1199></canvas>
|
||||
</center>
|
||||
</body>
|
||||
<div id="controls">
|
||||
<input type="number" id="ins" style="display:none;margin-left:0px;font-size:24px;width:35px;height:45px" value="5" max="5" min = "1">
|
||||
<button id="bns" style="display:none;margin-left:0px;font-size:24px;width:105px;height:45px">Spheres</button>
|
||||
<input type="number" id="insamp" style="margin-left:2px;font-size:24px;width:60px;height:45px" value="2" max="10" min = "0.1" step="0.2">
|
||||
<button id="bnsamp" style="margin-left:0px;font-size:24px;width:190px;height:45px">Super Sampling</button>
|
||||
<button id="bnfs" style="margin-left:2px;font-size:24px;width:180px;height:45px">Fullscreen</button>
|
||||
<button id="clrsel" style="display:none;margin-left:0px;font-size:24px;width:180px;height:45px">Clear Selection</button>
|
||||
<button id="reset" style="margin-left:0px;font-size:24px;width:100px;height:45px">Reset</button>
|
||||
<button id="mov" style="margin-left:0px;font-size:24px;width:180px;height:45px">Move Lighting</button>
|
||||
<button id="pause" style="margin-left:0px;font-size:24px;width:100px;height:45px">Pause</button>
|
||||
<div style='font-size:25px;'>
|
||||
|
||||
<!-- <font color=#000000>
|
||||
|
||||
<i style="font-size:28px;">What's new: </i>
|
||||
<p style="font-size:24px;">
|
||||
</p> -->
|
||||
<div id="howitworks">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div></td>
|
||||
</tr></table>
|
||||
</TR></TABLE>
|
||||
|
||||
|
||||
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
|
||||
|
||||
<script src="lib10.ext.js"></script>
|
||||
|
||||
<script>
|
||||
setInterval(() => {
|
||||
if(window.vs != null && window.fs != null&& canvas1.setShaders === undefined)
|
||||
gl_start(canvas1, vs, fs);
|
||||
}, 200);
|
||||
</script>
|
||||
@@ -0,0 +1,790 @@
|
||||
//Header file, contains global variable definitions,
|
||||
// asynchronized shader loading and utility functions
|
||||
|
||||
var mousedx = 0,
|
||||
mousedy = 0,
|
||||
mousedz = 0;
|
||||
let seldx = 0,
|
||||
seldy = 0,
|
||||
seldz = 0;
|
||||
var enableSelection = false;
|
||||
var cx = 1,
|
||||
cy = 1,
|
||||
sx = 0,
|
||||
sy = 0,
|
||||
shaders = [];
|
||||
var mouselastX, mouselastY
|
||||
;
|
||||
var fl = 3;
|
||||
let start;
|
||||
var vs, fs;
|
||||
var bezierMat = [-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0],
|
||||
hermiteMat = [2, -3, 0, 1, -2, 3, 0, 0, 1, -2, 1, 0, 1, -1, 0, 0],
|
||||
catmullRomMat = [-.5, 1, -.5, 0, 1.5, -2.5, 0, 1, -1.5, 2, .5, 0, .5, -.5, 0, 0];
|
||||
var starColors = [0.9921, 0.5378, 0.7109,
|
||||
0.65, 0.56, 0.992,
|
||||
0.992, 0.7994, 0.2402,
|
||||
0.1760, 0.5094, 0.5378,
|
||||
.1164, .1274, .2289,
|
||||
.9784, .71, .4482,
|
||||
],
|
||||
n_shapes = starColors.length / 3;
|
||||
var editor = undefined
|
||||
var cos = Math.cos,
|
||||
sin = Math.sin,
|
||||
tan = Math.tan,
|
||||
acos = Math.acos,
|
||||
asin = Math.asin,
|
||||
atan = Math.atan,
|
||||
sqrt = Math.sqrt,
|
||||
pi = Math.PI,
|
||||
abs = Math.abs,
|
||||
pow = Math.pow,
|
||||
log = Math.log;
|
||||
var positionsupdated = true;
|
||||
var paths = [],
|
||||
origpath = [],
|
||||
path_misc = [];
|
||||
var canvas_controls = [];
|
||||
let vsfetch = new XMLHttpRequest();
|
||||
vsfetch.open('GET', './shader.vert');
|
||||
vsfetch.onloadend = function () {
|
||||
vs = vsfetch.responseText;
|
||||
};
|
||||
vsfetch.send();
|
||||
//* LOADING FRAGMENT SHADER
|
||||
let fsfetch = new XMLHttpRequest();
|
||||
fsfetch.open('GET', './shader.frag');
|
||||
fsfetch.onloadend = function () {
|
||||
fs = (fsfetch.responseText);
|
||||
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
|
||||
if (editor != undefined)
|
||||
editor.getSession().setValue(fs);
|
||||
};
|
||||
fsfetch.send();
|
||||
let pathFetch = new XMLHttpRequest();
|
||||
pathFetch.open('GET', './paths.txt');
|
||||
pathFetch.onloadend = function () {
|
||||
let text = pathFetch.responseText;
|
||||
let currX = 0,
|
||||
currY = 0,
|
||||
maxX = -10000,
|
||||
maxY = -10000,
|
||||
minX = 10000,
|
||||
minY = 10000;
|
||||
var currShape = [],
|
||||
currCurve = [];
|
||||
let i = 0;
|
||||
let postProcess = () => {
|
||||
if (currShape.length) {
|
||||
let spanX = maxX - minX;
|
||||
let spanY = maxY - minY;
|
||||
let span = Math.max(spanX, spanY);
|
||||
let l_total = 0;
|
||||
for (var k = 0; k < currShape.length; ++k) {
|
||||
let funcs = [];
|
||||
const curve = currShape[k];
|
||||
for (let j = 0; j < curve.length; j += 2) {
|
||||
curve[j] = (curve[j] - minX) / span - spanX / (span * 2);
|
||||
curve[j + 1] = (curve[j + 1] - minY) / span - spanY / (span * 2);
|
||||
origpath.push(1, curve[j], curve[j + 1], 0, 0, 0, 1);
|
||||
if (j % 6 == 0 && j > 5) {
|
||||
let X = [],
|
||||
Y = [];
|
||||
for (let k = j - 6; k <= j + 1; k += 2) {
|
||||
X.push(curve[k]);
|
||||
Y.push(curve[k + 1]);
|
||||
}
|
||||
let l = (vec_len(minus([X[3], Y[3]], [X[0], Y[0]])) +
|
||||
vec_len(minus([X[3], Y[3]], [X[2], Y[2]])) +
|
||||
vec_len(minus([X[2], Y[2]], [X[1], Y[1]])) +
|
||||
vec_len(minus([X[1], Y[1]], [X[0], Y[0]]))) / 2.;
|
||||
l_total += l;
|
||||
funcs.push([matrix_multiply(bezierMat, X),
|
||||
matrix_multiply(bezierMat, Y), l
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
paths.push(funcs);
|
||||
path_misc.push([l_total, spanX / (2 * span), spanY / (2 * span)]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
let read_num = () => {
|
||||
let num = 0,
|
||||
sign = 1,
|
||||
accepted = 0;
|
||||
|
||||
while (i < text.length && (text[i] < '0' || text[i] > '9') && text[i] != '-') ++i;
|
||||
if (text[i] == '-') {
|
||||
sign = -1;
|
||||
++i;
|
||||
}
|
||||
while (i < text.length && text[i] >= '0' && text[i] <= '9') {
|
||||
let n = text[i++] - '0';
|
||||
accepted *= 10;
|
||||
accepted += n;
|
||||
}
|
||||
|
||||
num += accepted;
|
||||
if (text[i] == '.') {
|
||||
i++;
|
||||
let multiplier = 0.1;
|
||||
accepted = 0;
|
||||
while (i < text.length && text[i] >= '0' && text[i] <= '9') {
|
||||
let n = text[i++] - '0';
|
||||
accepted += n * multiplier;
|
||||
multiplier /= 10;
|
||||
}
|
||||
num += accepted;
|
||||
}
|
||||
return num * sign;
|
||||
}
|
||||
let cRevs = [],
|
||||
c_idx = 0,
|
||||
prevX = 0,
|
||||
prevY = 0,
|
||||
getC = () => {
|
||||
return cRevs[c_idx--];
|
||||
}
|
||||
let get_next = (delta = false) => {
|
||||
if (delta) {
|
||||
currX = prevX + read_num();
|
||||
currY = prevY + read_num();
|
||||
} else {
|
||||
currX = read_num();
|
||||
currY = read_num();
|
||||
}
|
||||
maxX = currX > maxX ? currX : maxX;
|
||||
maxY = currY > maxY ? currY : maxY;
|
||||
minX = currX < minX ? currX : minX;
|
||||
minY = currY < minY ? currY : minY;
|
||||
|
||||
currCurve.push(currX);
|
||||
currCurve.push(currY);
|
||||
}
|
||||
while (i < text.length) {
|
||||
if (text[i] == 'z') {
|
||||
currCurve.length && currShape.push(currCurve);
|
||||
currCurve = [];
|
||||
++i
|
||||
} else if (text[i] == 'N') {
|
||||
postProcess();
|
||||
currShape = [];
|
||||
maxX = -1000, maxY = -1000, minX = 1000, minY = 1000;
|
||||
++i;
|
||||
} else if (text[i] == 'c') {
|
||||
|
||||
prevX = currX;
|
||||
prevY = currY;
|
||||
|
||||
for (let j = 0; j < 3; ++j) {
|
||||
get_next(true);
|
||||
}
|
||||
} else if (text[i] == 'C') {
|
||||
for (let j = 0; j < 3; ++j) {
|
||||
get_next();
|
||||
}
|
||||
} else if (text[i] == 'M') {
|
||||
get_next();
|
||||
} else ++i;
|
||||
}
|
||||
};
|
||||
pathFetch.send();
|
||||
let rtx_VFetch = new XMLHttpRequest(), rtxvshader_txt;
|
||||
rtx_VFetch.open('GET', './RTX.vert');
|
||||
rtx_VFetch.onloadend = function() {
|
||||
rtxvshader_txt = rtx_VFetch.responseText;
|
||||
};
|
||||
rtx_VFetch.send();
|
||||
let rtx_FFetch = new XMLHttpRequest();
|
||||
rtx_FFetch.open('GET', './RTX.frag');
|
||||
rtx_FFetch.onloadend = function () {
|
||||
let rtxfs_text = rtx_FFetch.responseText;
|
||||
|
||||
let interval = setInterval(()=>{
|
||||
if(buildShaders && rtxvshader_txt && canvas1.gl)
|
||||
{
|
||||
gl.shaders[1] = buildShaders(rtxvshader_txt, rtxfs_text);
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
rtx_FFetch.send()
|
||||
let vec_len = v => {
|
||||
let len = 0;
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
len += v[i] * v[i];
|
||||
return sqrt(len);
|
||||
}
|
||||
let matrix_inverse = src => {
|
||||
let dst = [],
|
||||
det = 0,
|
||||
cofactor = (c, r) => {
|
||||
let s = (i, j) => src[c + i & 3 | (r + j & 3) << 2];
|
||||
return (c + r & 1 ? -1 : 1) * ((s(1, 1) * (s(2, 2) * s(3, 3) - s(3, 2) * s(2, 3))) -
|
||||
(s(2, 1) * (s(1, 2) * s(3, 3) - s(3, 2) * s(1, 3))) +
|
||||
(s(3, 1) * (s(1, 2) * s(2, 3) - s(2, 2) * s(1, 3))));
|
||||
}
|
||||
for (let n = 0; n < 16; n++) dst.push(cofactor(n >> 2, n & 3));
|
||||
for (let n = 0; n < 4; n++) det += src[n] * dst[n << 2];
|
||||
for (let n = 0; n < 16; n++) dst[n] /= det;
|
||||
return dst;
|
||||
}
|
||||
|
||||
// I HAVE IMPLEMENTED THESE FUNCTIONS FOR YOU
|
||||
let matrix_identity = () => {
|
||||
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
||||
}
|
||||
let matrix_translate = (x, y, z) => {
|
||||
let m = matrix_identity();
|
||||
m[12] = x;
|
||||
m[13] = y;
|
||||
m[14] = z;
|
||||
return m;
|
||||
}
|
||||
let matrix_perspective = (m) => {
|
||||
let ret = []
|
||||
for (let i = 0; i < 16; i++)
|
||||
ret[i] = m[i];
|
||||
for (let i = 2; i < 15; i += 4) {
|
||||
ret[i] = -ret[i];
|
||||
ret[i + 1] += ret[i] / fl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// YOU NEED TO PROPERLY IMPLEMENT THE FOLLOWING FIVE FUNCTIONS:
|
||||
let matrix_rotateX = theta => {
|
||||
let m = matrix_identity();
|
||||
m[5] = cos(theta);
|
||||
m[6] = sin(theta);
|
||||
m[9] = -sin(theta);
|
||||
m[10] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
|
||||
let matrix_rotateY = theta => {
|
||||
let m = matrix_identity();
|
||||
m[0] = cos(theta);
|
||||
m[2] = -sin(theta);
|
||||
m[8] = sin(theta);
|
||||
m[10] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
let matrix_rotateZ = theta => {
|
||||
let m = matrix_identity();
|
||||
m[0] = cos(theta);
|
||||
m[1] = sin(theta);
|
||||
m[4] = -sin(theta);
|
||||
m[5] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
let matrix_scale = (x, y, z) => {
|
||||
if (y === undefined)
|
||||
y = z = x;
|
||||
let m = matrix_identity();
|
||||
m[0] = x;
|
||||
m[5] = y;
|
||||
m[10] = z;
|
||||
return m;
|
||||
}
|
||||
let matrix_multiply = (a, b, m = 4, n = 4) => { //dim=mn*nm=mm
|
||||
let res = [];
|
||||
if (b.length < m * n) { //mat-vec multiply (i did this for my convenience)
|
||||
for (let i = 0; i < m; ++i) {
|
||||
res[i] = 0;
|
||||
for (let j = 0; j < n; ++j)
|
||||
res[i] += b[j] * a[m * j + i];
|
||||
}
|
||||
return res;
|
||||
} //otherwise mm multiply
|
||||
for (let i = 0; i < m; ++i)
|
||||
for (let j = 0; j < m; ++j) {
|
||||
var t = 0;
|
||||
for (let k = 0; k < n; ++k)
|
||||
t += a[k * m + j] * b[i * n + k];
|
||||
res.push(t);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
let const_multiply = (c, a, add = 0) => {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = (a[i] + add)* c;
|
||||
return m;
|
||||
}
|
||||
|
||||
function dot(a, b) {
|
||||
b=b?b:a;
|
||||
let m = 0;
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m += a[i] * b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function cross(a, b){
|
||||
let m = [];
|
||||
m[0] = a[1]*b[2] - a[2]*b[1];
|
||||
m[1] = a[2]*b[0] - a[0]*b[2];
|
||||
m[2] = a[0]*b[1] - a[1]*b[0];
|
||||
return m;
|
||||
}
|
||||
|
||||
function plus(a, b) {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = a[i] + b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function minus(a, b) {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = a[i] - b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function normalize(v) {
|
||||
let res = [];
|
||||
sum = 0;
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
sum += v[i] * v[i];
|
||||
sum = sqrt(sum);
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
res[i] = v[i] / sum;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
let Matrix = function () {
|
||||
let top = 0,
|
||||
m = [matrix_identity()];
|
||||
this.identity = () => m[top] = matrix_identity();
|
||||
this.translate = (x, y, z) => m[top] = matrix_multiply(m[top], matrix_translate(x, y, z));
|
||||
this.rotateX = theta => m[top] = matrix_multiply(m[top], matrix_rotateX(theta));
|
||||
this.rotateY = theta => m[top] = matrix_multiply(m[top], matrix_rotateY(theta));
|
||||
this.rotateZ = theta => m[top] = matrix_multiply(m[top], matrix_rotateZ(theta));
|
||||
this.scale = (x, y, z) => m[top] = matrix_multiply(m[top], matrix_scale(x, y, z));
|
||||
this.apply = (m1) => m[top] = matrix_multiply(m[top], m1);
|
||||
this.applyl = (m1) => m[top] = matrix_multiply(m1, m[top]);
|
||||
this.value = () => m[top];
|
||||
this.save = () => {
|
||||
m[top + 1] = m[top].slice();
|
||||
top++;
|
||||
}
|
||||
this.restore = () => --top;
|
||||
}
|
||||
function hitTest_sphere(ray, sphere, r) {
|
||||
let B = dot(ray, sphere);
|
||||
let C = dot(sphere, sphere) - r*r;
|
||||
let D = B * B - C;
|
||||
if (D > 0.) {
|
||||
//console.log(D);
|
||||
//let t = -B - sqrt(D);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
function hitTest_square(pt, invMatrix, shape){
|
||||
pt.push(1);
|
||||
const V = dot_xyz(matrix_multiply(invMatrix, [0,0,fl,1])),
|
||||
pos = dot_xyz(matrix_multiply(invMatrix, pt)),
|
||||
W = minus(pos, V),
|
||||
A = shape.slice(1,4),
|
||||
B = shape.slice(8,11),
|
||||
C = shape.slice(15,18),
|
||||
AB = minus(B, A),
|
||||
AC = minus(C, A),
|
||||
AB_AC = cross(AB, AC),
|
||||
VA = minus(V, A),
|
||||
t = - dot(AB_AC, VA)/dot(W, AB_AC),
|
||||
P = plus(V, const_multiply(t, W)),
|
||||
AP = minus(P, A),
|
||||
d_AP_AC = dot(AP, AC),
|
||||
d_AP_AB = dot(AP, AB);
|
||||
if(0 <d_AP_AC && d_AP_AC < dot(AC, AC) && 0 < d_AP_AB && d_AP_AB< dot(AB, AB))
|
||||
return P;
|
||||
else return -1;
|
||||
}
|
||||
let dot_xyz = (v) => {
|
||||
let ret = [];
|
||||
if(v[3])
|
||||
for(let i = 0; i < 3; ++i)
|
||||
ret[i] = v[i]/v[3];
|
||||
else ret = v.slice(0,3);
|
||||
return ret;
|
||||
}
|
||||
let Button = function (onclick = () => {}, shape = [], outlineTy = 'sphere') {
|
||||
this.shape = shape;
|
||||
this.enabled = true;
|
||||
this.outlineTy = outlineTy;
|
||||
this.onClick = onclick;
|
||||
this.updateMatrix = (m) => {this.matrix = matrix_perspective(m); this.invMatrix = matrix_inverse(m);};
|
||||
this.updateMatrix(matrix_identity());
|
||||
this.hovering = false;
|
||||
this.activated = false;
|
||||
this.getShape = () => this.shape;
|
||||
this.draw = () => {setUniform('Matrix4fv', 'uMatrix', false, this.matrix);
|
||||
setUniform('Matrix4fv', 'invMatrix', false, this.invMatrix); drawMesh(this.shape);}
|
||||
this.resetShape = (_sh) => {
|
||||
if(this.shape) delete this.shape;
|
||||
this.shape = new Float32Array(_sh);
|
||||
let maxV = new Array(3).fill(-Infinity), minV = new Array(3).fill(Infinity);
|
||||
for(let i = 0; i < _sh.length; i += 7){
|
||||
const v = [_sh[i + 1], _sh[i + 2], _sh[i + 3]];
|
||||
v.forEach((c, j) => {
|
||||
maxV[j] = maxV[j] > c ? maxV[j] : c;
|
||||
minV[j] = minV[j] < c ? minV[j] : c;
|
||||
})
|
||||
}
|
||||
//build outline
|
||||
switch(this.outlineTy){
|
||||
case 'sphere':
|
||||
this.origin = const_multiply(.5, plus(maxV, minV));
|
||||
//this.origin.push(1);
|
||||
this.radius = 0.6*vec_len(minus(maxV, minV))/2.;
|
||||
break;
|
||||
case 'square':
|
||||
break;
|
||||
case 'circle':
|
||||
break;
|
||||
}
|
||||
switch(this.outlineTy){
|
||||
case 'sphere':
|
||||
this.hitTest = (pt) => {
|
||||
pt.push(1);
|
||||
const V = dot_xyz(matrix_multiply(this.invMatrix, [0,0,fl,1])),
|
||||
pos = dot_xyz(matrix_multiply(this.invMatrix, pt));
|
||||
let W = normalize((minus(pos, V)));
|
||||
let Vp = minus(V, this.origin);
|
||||
return hitTest_sphere(W, Vp, this.radius);
|
||||
}
|
||||
break;
|
||||
case 'square':
|
||||
this.hitTest = (pt) => {
|
||||
this.P = hitTest_square(pt, this.invMatrix, this.shape);
|
||||
return this.P;
|
||||
}
|
||||
break;
|
||||
case 'circle':
|
||||
break;
|
||||
}
|
||||
};
|
||||
if(!shape || shape.length != 0)
|
||||
this.resetShape(shape);
|
||||
canvas_controls.push(this);
|
||||
}
|
||||
let setM = (m) => {
|
||||
let mm = matrix_perspective(m);
|
||||
setUniform('Matrix4fv', 'uMatrix', false, mm);
|
||||
setUniform('Matrix4fv', 'invMatrix', false, matrix_inverse(mm));
|
||||
}
|
||||
//------ CREATING MESH SHAPES
|
||||
|
||||
// CREATE A MESH FROM A PARAMETRIC FUNCTION
|
||||
|
||||
let createMesh = (nu, nv, f, data, oid = 0) => {
|
||||
let tmp = [];
|
||||
for (let v = 0; v < 1; v += 1 / nv) {
|
||||
for (let u = 0; u <= 1; u += 1 / nu) {
|
||||
tmp = tmp.concat(f(u, v, oid, data));
|
||||
tmp = tmp.concat(f(u, v + 1 / nv, oid, data));
|
||||
}
|
||||
tmp = tmp.concat(f(1, v, oid, data));
|
||||
tmp = tmp.concat(f(0, v + 1 / nv, oid, data));
|
||||
}
|
||||
return new Float32Array(tmp);
|
||||
}
|
||||
//Create a Mesh from Splines
|
||||
let createMeshFromSpline = (idx,
|
||||
nu, nv, oid = 16, additional_offset = 0, f = () => {}) => {
|
||||
let S = paths[idx],
|
||||
meta = path_misc[idx];
|
||||
const n_min = 2;
|
||||
let ds = meta[0] / nv,
|
||||
curr_s = 0,
|
||||
curr_d = S[0][2] / Math.ceil(S[0][2] / ds),
|
||||
i = 0,
|
||||
s = 0;
|
||||
let tmp = [],
|
||||
ret = undefined;
|
||||
while (s < meta[0] - 1 / 100000) {
|
||||
|
||||
for (let u = 0; u <= 1; u += 1 / nu) {
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], u, curr_s, idx, oid, additional_offset));
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], u, curr_s + curr_d, idx, oid, additional_offset));
|
||||
}
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], 0, curr_s, idx, oid, additional_offset));
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], 1, curr_s + curr_d, idx, oid, additional_offset));
|
||||
if (ret = f(i, tmp, oid)) {
|
||||
oid = ret;
|
||||
}
|
||||
curr_s += curr_d;
|
||||
if (curr_s >= 1) {
|
||||
s += S[i][2];
|
||||
++i;
|
||||
if (i >= S.length)
|
||||
break;
|
||||
let curr_n = Math.ceil(S[i][2] / ds);
|
||||
curr_n = curr_n < n_min ? n_min : curr_n;
|
||||
curr_d = 1 / curr_n;
|
||||
curr_s = 0;
|
||||
}
|
||||
}
|
||||
return new Float32Array(tmp);
|
||||
}
|
||||
// GLUE TWO MESHES TOGETHER INTO A SINGLE MESH
|
||||
|
||||
let glueMeshes = (a, b) => {
|
||||
let c = [];
|
||||
for (let i = 0; i < a.length; i++)
|
||||
c.push(a[i]); // a
|
||||
for (let i = 0; i < VERTEX_SIZE; i++)
|
||||
c.push(a[a.length - VERTEX_SIZE + i]); // + last vertex of a
|
||||
for (let i = 0; i < VERTEX_SIZE; i++)
|
||||
c.push(b[i]); // + first vertex of b
|
||||
for (let i = 0; i < b.length; i++)
|
||||
c.push(b[i]); // + b
|
||||
return new Float32Array(c);
|
||||
}
|
||||
|
||||
|
||||
let uvToSphere = (u, v, i) => {
|
||||
let theta = 2 * Math.PI * u;
|
||||
let phi = Math.PI * (v - .5);
|
||||
let x = Math.cos(theta) * Math.cos(phi);
|
||||
let y = Math.sin(theta) * Math.cos(phi);
|
||||
let z = Math.sin(phi);
|
||||
return [i, x, y, z].concat(normalize([x, y, z]));
|
||||
}
|
||||
|
||||
let uvToTube = (u, v, i) => {
|
||||
let theta = 2 * Math.PI * u;
|
||||
let x = Math.cos(theta);
|
||||
let y = Math.sin(theta);
|
||||
let z = 2 * v - 1;
|
||||
return [i, x, y, z].concat(normalize([x, y, 0]));
|
||||
}
|
||||
|
||||
let uvToDisk = (u, v, i, dz) => {
|
||||
if (dz === undefined)
|
||||
dz = 0;
|
||||
let theta = 2 * Math.PI * u;
|
||||
let x = Math.cos(theta) * v;
|
||||
let y = Math.sin(theta) * v;
|
||||
let z = dz;
|
||||
return [i, x, y, z].concat([0, 0, Math.sign(z)]);
|
||||
}
|
||||
let uvToTorus = (u, v, i, r) => {
|
||||
let theta = 2 * pi;
|
||||
let phi = theta * v;
|
||||
theta *= u;
|
||||
let x = 1 + r * cos(phi);
|
||||
let y = sin(theta) * x;
|
||||
x *= cos(theta);
|
||||
let z = r * sin(phi);
|
||||
let tx = -sin(theta),
|
||||
ty = cos(theta),
|
||||
tsx = sin(phi),
|
||||
tsy = tsx * tx,
|
||||
tsz = cos(phi);
|
||||
tsx *= -ty;
|
||||
return [i, x, y, z].concat(normalize([ty * tsz * 0.5, -tx * tsz, tx * tsy - ty * tsx]));
|
||||
}
|
||||
|
||||
let createCube = (w, h, l, id) => {
|
||||
let mesh = [];
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, -1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, -1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, 0, 1, 0]);
|
||||
return new Float32Array(mesh);
|
||||
}
|
||||
|
||||
function updatePositions() {
|
||||
let m = matrix_rotateY(-mousedx);
|
||||
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||||
setUniform('3f', 'V0', m[8] * (fl + mousedz), m[9] * (fl + mousedz), m[10] * (fl + mousedz));
|
||||
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||||
setUniform('Matrix3fv', 'transformation', false, [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]]);
|
||||
invTr = matrix_inverse(m);
|
||||
|
||||
positionsupdated = false;
|
||||
}
|
||||
function controls_hitTest(pos, clicked = false){
|
||||
// let iMin = -1, tMin = 10000.;
|
||||
if(channel_disp == 5)
|
||||
return;
|
||||
canvas_controls.forEach((c, i) => {
|
||||
if(c.enabled && c.hitTest && (c.hover||clicked) ){
|
||||
let t = c.hitTest(pos);
|
||||
if(t != -1){
|
||||
if(clicked)
|
||||
c.onClick();
|
||||
else
|
||||
c.hover(true);
|
||||
}
|
||||
else
|
||||
if(c.hovering)
|
||||
c.hover(false);
|
||||
}
|
||||
});
|
||||
//ground
|
||||
if(ground_m && ground){
|
||||
let invG = matrix_inverse(ground_m);
|
||||
let P = hitTest_square(pos, invG, ground);
|
||||
console.log(P);
|
||||
//let Vp = minus(matrix_multiply(invG,[0,0,fl, 1]).slice(0,3), this.origin);
|
||||
if(P!=-1)
|
||||
if(near_magician){
|
||||
if(slider.dragging === true){
|
||||
slider_dl += 10 * (P[0] - slider.lastPos);
|
||||
if(slider_dl < 0) slider_dl = 0;
|
||||
else if (slider_dl > 9) slider_dl = 9;
|
||||
slider.lastPos = P[0];
|
||||
// onUpdate
|
||||
let id = 1 + .45*slider_dl/9;
|
||||
changeID(id, cylinderMesh);
|
||||
} else if(clicked) {
|
||||
const PO = minus([slider_dl/10-.25, .7], [P[0], P[1]]);
|
||||
const rr = PO[0]*PO[0] + PO[1] * PO[1];
|
||||
if(rr < .003){
|
||||
slider.dragging = true;
|
||||
slider.lastPos = P[0];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(clicked || running<=0)
|
||||
{
|
||||
direction_l = [P[0] - delta_l[0]/10, P[1] - delta_l[1]/10];
|
||||
if(P[1] < 0.00000000000001)
|
||||
P[1] = 0.0000000000000001;
|
||||
figure_rot = atan(direction_l[0]/direction_l[1]);
|
||||
if(direction_l[1] < 0){
|
||||
figure_rot = pi + figure_rot;
|
||||
}
|
||||
}
|
||||
//if(figure_rot < 0) figure_rot += pi;
|
||||
//updateStatus([figure_rot, direction_l[0]/direction_l[1]]);
|
||||
if(clicked)
|
||||
{
|
||||
dir_sdl = vec_len(direction_l)*10;
|
||||
direction_l = normalize(direction_l);
|
||||
rebuild = true;
|
||||
running = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//return iMin;
|
||||
}
|
||||
function hitTest(pos) {
|
||||
|
||||
let m = matrix_rotateY(-mousedx);
|
||||
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||||
let V = [m[8] * (fl + mousedz), m[9] * (fl + mousedz), m[10] * (fl + mousedz)];
|
||||
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||||
let trPos = matrix_multiply([m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]], [pos[0], -pos[1], -1], 3, 3);
|
||||
|
||||
let W = normalize(minus(trPos, V));
|
||||
let tMin = 10000.;
|
||||
let iMin = -1;
|
||||
for (let i = 0; i < cns; i++) {
|
||||
let Vp = minus(V, matrix_multiply(SphTr[i], Sph[i]));
|
||||
let B = dot(W, Vp);
|
||||
let C = dot(Vp, Vp) - Sph[i][4] * Sph[i][4];
|
||||
let D = B * B - C;
|
||||
if (D > 0.) {
|
||||
let t = -B - sqrt(D);
|
||||
if (t > 0.0 && t < tMin) {
|
||||
tMin = t; // This is an optimization, we don't have to do lighting/tex
|
||||
iMin = i; // for objects that are occuluded, which is expensive!
|
||||
}
|
||||
}
|
||||
}
|
||||
return iMin;
|
||||
}
|
||||
let matrix_transform = (m, p) => {
|
||||
let x = p[0],
|
||||
y = p[1],
|
||||
z = p[2],
|
||||
w = p[3] === undefined ? 1 : p[3];
|
||||
let q = [m[0] * x + m[4] * y + m[8] * z + m[12] * w,
|
||||
m[1] * x + m[5] * y + m[9] * z + m[13] * w,
|
||||
m[2] * x + m[6] * y + m[10] * z + m[14] * w,
|
||||
m[3] * x + m[7] * y + m[11] * z + m[15] * w
|
||||
];
|
||||
return p[3] === undefined ? [q[0] / q[3], q[1] / q[3], q[2] / q[3]] : q;
|
||||
}
|
||||
let evalSpline = (h, t) => {
|
||||
// t *= (h.length - 2) / 2;
|
||||
// let n = 2 * Math.floor(t);
|
||||
// t = t % 1;
|
||||
// let C = matrix_transform(type, [h[n+0],h[n+2],h[n+1],h[n+3]]);
|
||||
// return t*t*t*C[0] + t*t*C[1] + t*C[2] + C[3];
|
||||
return t * t * t * h[0] + t * t * h[1] + t * h[2] + h[3];
|
||||
}
|
||||
let getSurface = (S0, S1, u, v, offsetidx, id = 15, additional_offset = 0) => {
|
||||
const epsilon = .001;
|
||||
let z0 = evalSpline(S0, v),
|
||||
z1 = evalSpline(S0, v + epsilon),
|
||||
|
||||
r0 = evalSpline(S1, v) - path_misc[offsetidx][1] + additional_offset,
|
||||
r1 = evalSpline(S1, v + epsilon),
|
||||
|
||||
tilt = Math.atan2(r0 - r1, z1 - z0);
|
||||
|
||||
let xx = cos(2 * pi * u),
|
||||
yy = sin(2 * pi * u);
|
||||
let x = r0 * xx, // POSITION
|
||||
y = r0 * yy,
|
||||
z = z0,
|
||||
nx = cos(tilt), // NORMAL
|
||||
ny = nx * yy,
|
||||
nz = sin(tilt);
|
||||
nx *= xx;
|
||||
return [id, x, y, z, nx, ny, nz];
|
||||
}
|
||||
let concat = (a, b) => b.forEach(e => a.push(e));
|
||||
@@ -0,0 +1,327 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// THIS IS THE SUPPORT LIBRARY. YOU PROBABLY DON'T WANT TO CHANGE ANYTHING HERE JUST YET.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let fragmentShaderHeader = ['' // WHATEVER CODE WE WANT TO PREDEFINE FOR FRAGMENT SHADERS
|
||||
, 'precision highp float;', 'float noise(vec3 point) { float r = 0.; for (int i=0;i<16;i++) {', ' vec3 D, p = point + mod(vec3(i,i/4,i/8) , vec3(4.0,2.0,2.0)) +', ' 1.7*sin(vec3(i,5*i,8*i)), C=floor(p), P=p-C-.5, A=abs(P);', ' C += mod(C.x+C.y+C.z,2.) * step(max(A.yzx,A.zxy),A) * sign(P);', ' D=34.*sin(987.*float(i)+876.*C+76.*C.yzx+765.*C.zxy);P=p-C-.5;', ' r+=sin(6.3*dot(P,fract(D)-.5))*pow(max(0.,1.-2.*dot(P,P)),4.);', '} return .5 * sin(r); }','\n#define _NDEBUG\n'
|
||||
].join('\n');
|
||||
var ns = 6,
|
||||
cns = 6;
|
||||
fragmentShaderHeader += 'const int ns = ' + ns + ';\n';
|
||||
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
|
||||
var status = 'The TV is a touch screen!';
|
||||
let nfsh = fragmentShaderHeader.split('\n').length + 1; // NUMBER OF LINES OF CODE IN fragmentShaderHeader
|
||||
|
||||
let isFirefox = navigator.userAgent.indexOf('Firefox') > 0;
|
||||
|
||||
function getBlob(data) {
|
||||
let bytes = new Array(data.length);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
bytes[i] = data.charCodeAt(i);
|
||||
}
|
||||
return new Blob([new Uint8Array(bytes)]);
|
||||
}
|
||||
let stack = function (){
|
||||
this.storage = ['Ready.'];
|
||||
this.len = 1;
|
||||
this.pop = ()=>{return this.storage[--this.len-1];}
|
||||
this.push = (o)=>{this.storage[this.len++] = o;}
|
||||
this.update = (o)=>{this.storage[this.len-1] = o;}
|
||||
this.top = () => {return this.storage[this.len - 1];}
|
||||
this.clear = () => this.len = 1;
|
||||
}
|
||||
let status_history = new stack();
|
||||
function updateStatus(val){
|
||||
status_history.update(status);
|
||||
status = val;
|
||||
errorMessage.innerHTML = val;
|
||||
}
|
||||
function pushStatus(val){
|
||||
status_history.push(status);
|
||||
status = val;
|
||||
errorMessage.innerHTML = val;
|
||||
}
|
||||
function restoreStatus(val){
|
||||
status = status_history.pop();
|
||||
errorMessage.innerHTML = status;
|
||||
}
|
||||
function resetStatus() {
|
||||
status_history.clear();
|
||||
updateStatus('Ready.');
|
||||
}
|
||||
var texture = [],
|
||||
gl, program;
|
||||
let textures = [];
|
||||
let lock = false;
|
||||
|
||||
function loadTexture(gl, url, i) {
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 1;
|
||||
const height = 1;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
if (texture[i] == null) {
|
||||
texture[i] = gl.createTexture();
|
||||
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
|
||||
gl.activeTexture(gl.TEXTURE0 + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
}
|
||||
const image = new Image();
|
||||
image.onload = function () {
|
||||
gl.activeTexture(gl.TEXTURE0 + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
srcFormat, srcType, image);
|
||||
|
||||
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
};
|
||||
image.src = url;
|
||||
}
|
||||
function initTextures(gl, program){
|
||||
for (let i = 0; i < ns; ++i) {
|
||||
loadTexture( gl, './' + (i + 1) + '.jpg', i); //Texture loading.
|
||||
textures[i] = i;
|
||||
}
|
||||
textures[ns] = ns;
|
||||
initVideoTexture(gl, ns + 0);
|
||||
textures[ns + 1] = ns + 1;
|
||||
loadTexture(gl, './starburst.png', ns + 1);
|
||||
createNoiseTexture();
|
||||
textures[ns+2] = ns+2;
|
||||
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
|
||||
}
|
||||
function initVideoTexture(gl, i) {
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 1;
|
||||
const height = 1;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
if (texture[i] == null) {
|
||||
texture[i] = gl.createTexture();
|
||||
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
|
||||
gl.activeTexture(gl.TEXTURE + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
}
|
||||
function updateVideoTexture(gl, v_control, i){
|
||||
//return;
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
srcFormat, srcType, v_control);
|
||||
}
|
||||
function createNoiseTexture(){
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 100;
|
||||
const height = 100;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
texture[ns+2] = gl.createTexture();
|
||||
let random_list = [];
|
||||
let get_random = ()=>Math.pow(Math.random(), .1);
|
||||
let get_random2 = ()=>{
|
||||
let r = Math.random();
|
||||
if (r < .5) r = .5*Math.pow(2*r,.1);
|
||||
else r = .5 + .5*Math.pow(r,10);
|
||||
return r;};
|
||||
for(let i = 0; i < 40000; ++i){
|
||||
if(i%4 == 3)
|
||||
random_list.push(255*get_random());
|
||||
else
|
||||
random_list.push(255*get_random2());
|
||||
}
|
||||
const pixel = new Uint8Array(random_list);
|
||||
gl.activeTexture(gl.TEXTURE0+ns+2);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[ns+2]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
function isPowerOf2(value) {
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
function buildShaders(vertexShader, fragmentShader){
|
||||
let curr_program = canvas1.gl.createProgram();
|
||||
let compile_shaders = (type, src) => {
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
gl.attachShader(curr_program, shader);
|
||||
};
|
||||
compile_shaders(gl.VERTEX_SHADER, vertexShader);
|
||||
compile_shaders(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShaderDefs + fragmentShader);
|
||||
gl.linkProgram(curr_program);
|
||||
|
||||
return curr_program;
|
||||
}
|
||||
function gl_start(canvas, vertexShader, fragmentShader) { // START WEBGL RUNNING IN A CANVAS
|
||||
console.log('glstart');
|
||||
setTimeout(function () {
|
||||
try {
|
||||
canvas.gl = canvas.getContext('experimental-webgl'); // Make sure WebGl is supported. IT WOULD BE GREAT TO USE WEBGL2 INSTEAD.
|
||||
} catch (e) {
|
||||
throw 'Sorry, your browser does not support WebGL.';
|
||||
}
|
||||
|
||||
|
||||
canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders:
|
||||
gl = this.gl;
|
||||
program = gl.createProgram(); // Create the WebGL program.
|
||||
|
||||
function addshader(type, src) { // Create and attach a WebGL shader.
|
||||
function spacer(color, width, height) {
|
||||
return '<table bgcolor=' + color +
|
||||
' width=' + width +
|
||||
' height=' + height + '><tr><td> </td></tr></table>';
|
||||
}
|
||||
errorMessage.innerHTML = status;
|
||||
// errorMarker.innerHTML = spacer('white', 1, 1) + '<font size=1 color=white>\u25B6</font>';
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
let msg = gl.getShaderInfoLog(shader);
|
||||
console.log('Cannot compile shader:\n\n' + msg);
|
||||
|
||||
let a = msg.substring(6, msg.length);
|
||||
let line = 0;
|
||||
if (a.substring(0, 3) == ' 0:') {
|
||||
a = a.substring(3, a.length);
|
||||
line = parseInt(a) - nfsh;
|
||||
|
||||
editor.session.setAnnotations([{
|
||||
row: line,
|
||||
column: 0,
|
||||
text: msg,
|
||||
type: "error"
|
||||
}]);
|
||||
}
|
||||
let j = a.indexOf(':');
|
||||
a = 'line ' + (line + 1) + a.substring(j, a.length);
|
||||
if ((j = a.indexOf('\n')) > 0)
|
||||
a = a.substring(0, j);
|
||||
errorMessage.innerHTML = a;
|
||||
} else
|
||||
editor.session.clearAnnotations();
|
||||
gl.attachShader(program, shader);
|
||||
};
|
||||
|
||||
addshader(gl.VERTEX_SHADER, vertexShader); // Add the vertex and fragment shaders.
|
||||
addshader(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShaderDefs + fragmentShader);
|
||||
|
||||
gl.linkProgram(program); // Link the program, report any errors.
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
|
||||
console.log('Could not link the shader program!');
|
||||
gl.useProgram(program);
|
||||
gl.program = program;
|
||||
if(!gl.shaders)
|
||||
gl.shaders = [program];
|
||||
else gl.shaders[0] = program;
|
||||
initTextures(gl, program);
|
||||
positionsupdated = true;
|
||||
let attribs = [
|
||||
.05, .05, .1, .5, .5, 1., 1., .5, .5, 20., 5,0,0, 0.,.0, 1.3,
|
||||
.1, .05, .05, 1., .5, .5, 1., .5, .5, 10., .1,8,0, .3, 1., 1.3,
|
||||
.1, .05, .05, .71, .71, .71, .71, .71, .71, 10., .1,0,9, 0.3, .0, 1.5,
|
||||
.1, .1, .1, .71, .71, .71, .71, .71, .71, 10., 2,2,0, 0.05, 0., 1.,
|
||||
.0, .0, .0, .0, .0, .0, .0, .0, .0, 40., 4,4,4, 0., .85, 1.5
|
||||
]
|
||||
var offset = 0;
|
||||
for (let i = 0; i < ns; i++) {
|
||||
setUniform('3fv', 'Ambient[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('3fv', 'Diffuse[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('4fv', 'Specular[' + i + ']', attribs.slice(offset, offset += 4));
|
||||
setUniform('3fv', 'Glow[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('1fv', 'ks[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
setUniform('1fv', 'kr[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
setUniform('1fv', 'kf[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
}
|
||||
offset = 0;
|
||||
for (let i = 0; i < n_shapes; i++) {
|
||||
setUniform('3fv', 'starColors[' + i + ']', starColors.slice(offset, offset += 3));
|
||||
}
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // Create a square as a triangle strip
|
||||
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( // consisting of two triangles.
|
||||
// [-1, 1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0]), gl.STATIC_DRAW);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.depthFunc(gl.LEQUAL);
|
||||
gl.clearDepth(-1);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
let oid = gl.getAttribLocation(program, 'oid'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(oid);
|
||||
gl.vertexAttribPointer(oid, 1, gl.FLOAT, false, 4 * 7, 0);
|
||||
|
||||
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(aPos);
|
||||
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 4 * 7, 4);
|
||||
|
||||
let normal = gl.getAttribLocation(program, 'normal'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(normal);
|
||||
gl.vertexAttribPointer(normal, 3, gl.FLOAT, false, 4 * 7, 4 * 4);
|
||||
}
|
||||
|
||||
canvas.setShaders(vertexShader, fragmentShader); // Initialize everything,
|
||||
setInterval(function () { // Start the animation loop.
|
||||
gl = canvas.gl;
|
||||
if (gl.startTime === undefined) // First time through,
|
||||
gl.startTime = Date.now(); // record the start time.
|
||||
animate(gl);
|
||||
//gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // Render the square.
|
||||
}, 30);
|
||||
|
||||
}, 100); // Wait 100 milliseconds after page has loaded before starting WebGL.
|
||||
}
|
||||
|
||||
// THE animate() CALLBACK FUNCTION CAN BE REDEFINED IN index.html.
|
||||
|
||||
function animate() {}
|
||||
|
||||
function setUniform(type, name, a, b, c, d, e, f) {
|
||||
if (gl) {
|
||||
let loc = gl.getUniformLocation(gl.program, name);
|
||||
(gl['uniform' + type])(loc, a, b, c, d, e, f);
|
||||
}
|
||||
}
|
||||
|
||||
//let VERTEX_SIZE = 3;
|
||||
|
||||
|
||||
let VERTEX_SIZE = 7;
|
||||
|
||||
|
||||
var drawMesh = (mesh, func = gl.TRIANGLE_STRIP) => {
|
||||
gl.bufferData(gl.ARRAY_BUFFER, mesh, gl.STATIC_DRAW);
|
||||
gl.drawArrays(func, 0, mesh.length / VERTEX_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,793 @@
|
||||
//Header file, contains global variable definitions,
|
||||
// asynchronized shader loading and utility functions
|
||||
|
||||
var mousedx = 0,
|
||||
mousedy = 0,
|
||||
mousedz = 0;
|
||||
let seldx = 0,
|
||||
seldy = 0,
|
||||
seldz = 0;
|
||||
var enableSelection = false;
|
||||
var cx = 1,
|
||||
cy = 1,
|
||||
sx = 0,
|
||||
sy = 0,
|
||||
shaders = [];
|
||||
var mouselastX, mouselastY
|
||||
;
|
||||
var fl = 3;
|
||||
let start;
|
||||
var vs, fs;
|
||||
var bezierMat = [-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0],
|
||||
hermiteMat = [2, -3, 0, 1, -2, 3, 0, 0, 1, -2, 1, 0, 1, -1, 0, 0],
|
||||
catmullRomMat = [-.5, 1, -.5, 0, 1.5, -2.5, 0, 1, -1.5, 2, .5, 0, .5, -.5, 0, 0];
|
||||
var starColors = [0.9921, 0.5378, 0.7109,
|
||||
0.65, 0.56, 0.992,
|
||||
0.992, 0.7994, 0.2402,
|
||||
0.1760, 0.5094, 0.5378,
|
||||
.1164, .1274, .2289,
|
||||
.9784, .71, .4482,
|
||||
],
|
||||
n_shapes = starColors.length / 3;
|
||||
var editor = undefined
|
||||
var cos = Math.cos,
|
||||
sin = Math.sin,
|
||||
tan = Math.tan,
|
||||
acos = Math.acos,
|
||||
asin = Math.asin,
|
||||
atan = Math.atan,
|
||||
sqrt = Math.sqrt,
|
||||
pi = Math.PI,
|
||||
abs = Math.abs,
|
||||
pow = Math.pow,
|
||||
log = Math.log;
|
||||
var positionsupdated = true;
|
||||
var paths = [],
|
||||
origpath = [],
|
||||
path_misc = [];
|
||||
var canvas_controls = [];
|
||||
let vsfetch = new XMLHttpRequest();
|
||||
vsfetch.open('GET', './shader.vert');
|
||||
vsfetch.onloadend = function () {
|
||||
vs = vsfetch.responseText;
|
||||
};
|
||||
vsfetch.send();
|
||||
//* LOADING FRAGMENT SHADER
|
||||
let fsfetch = new XMLHttpRequest();
|
||||
fsfetch.open('GET', './shader.frag');
|
||||
fsfetch.onloadend = function () {
|
||||
fs = (fsfetch.responseText);
|
||||
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
|
||||
if (editor != undefined)
|
||||
editor.getSession().setValue(fs);
|
||||
};
|
||||
fsfetch.send();
|
||||
let pathFetch = new XMLHttpRequest();
|
||||
pathFetch.open('GET', './paths.txt');
|
||||
pathFetch.onloadend = function () {
|
||||
let text = pathFetch.responseText;
|
||||
let currX = 0,
|
||||
currY = 0,
|
||||
maxX = -10000,
|
||||
maxY = -10000,
|
||||
minX = 10000,
|
||||
minY = 10000;
|
||||
var currShape = [],
|
||||
currCurve = [];
|
||||
let i = 0;
|
||||
let postProcess = () => {
|
||||
if (currShape.length) {
|
||||
let spanX = maxX - minX;
|
||||
let spanY = maxY - minY;
|
||||
let span = Math.max(spanX, spanY);
|
||||
let l_total = 0;
|
||||
for (var k = 0; k < currShape.length; ++k) {
|
||||
let funcs = [];
|
||||
const curve = currShape[k];
|
||||
for (let j = 0; j < curve.length; j += 2) {
|
||||
curve[j] = (curve[j] - minX) / span - spanX / (span * 2);
|
||||
curve[j + 1] = (curve[j + 1] - minY) / span - spanY / (span * 2);
|
||||
origpath.push(1, curve[j], curve[j + 1], 0, 0, 0, 1);
|
||||
if (j % 6 == 0 && j > 5) {
|
||||
let X = [],
|
||||
Y = [];
|
||||
for (let k = j - 6; k <= j + 1; k += 2) {
|
||||
X.push(curve[k]);
|
||||
Y.push(curve[k + 1]);
|
||||
}
|
||||
let l = (vec_len(minus([X[3], Y[3]], [X[0], Y[0]])) +
|
||||
vec_len(minus([X[3], Y[3]], [X[2], Y[2]])) +
|
||||
vec_len(minus([X[2], Y[2]], [X[1], Y[1]])) +
|
||||
vec_len(minus([X[1], Y[1]], [X[0], Y[0]]))) / 2.;
|
||||
l_total += l;
|
||||
funcs.push([matrix_multiply(bezierMat, X),
|
||||
matrix_multiply(bezierMat, Y), l
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
paths.push(funcs);
|
||||
path_misc.push([l_total, spanX / (2 * span), spanY / (2 * span)]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
let read_num = () => {
|
||||
let num = 0,
|
||||
sign = 1,
|
||||
accepted = 0;
|
||||
|
||||
while (i < text.length && (text[i] < '0' || text[i] > '9') && text[i] != '-') ++i;
|
||||
if (text[i] == '-') {
|
||||
sign = -1;
|
||||
++i;
|
||||
}
|
||||
while (i < text.length && text[i] >= '0' && text[i] <= '9') {
|
||||
let n = text[i++] - '0';
|
||||
accepted *= 10;
|
||||
accepted += n;
|
||||
}
|
||||
|
||||
num += accepted;
|
||||
if (text[i] == '.') {
|
||||
i++;
|
||||
let multiplier = 0.1;
|
||||
accepted = 0;
|
||||
while (i < text.length && text[i] >= '0' && text[i] <= '9') {
|
||||
let n = text[i++] - '0';
|
||||
accepted += n * multiplier;
|
||||
multiplier /= 10;
|
||||
}
|
||||
num += accepted;
|
||||
}
|
||||
return num * sign;
|
||||
}
|
||||
let cRevs = [],
|
||||
c_idx = 0,
|
||||
prevX = 0,
|
||||
prevY = 0,
|
||||
getC = () => {
|
||||
return cRevs[c_idx--];
|
||||
}
|
||||
let get_next = (delta = false) => {
|
||||
if (delta) {
|
||||
currX = prevX + read_num();
|
||||
currY = prevY + read_num();
|
||||
} else {
|
||||
currX = read_num();
|
||||
currY = read_num();
|
||||
}
|
||||
maxX = currX > maxX ? currX : maxX;
|
||||
maxY = currY > maxY ? currY : maxY;
|
||||
minX = currX < minX ? currX : minX;
|
||||
minY = currY < minY ? currY : minY;
|
||||
|
||||
currCurve.push(currX);
|
||||
currCurve.push(currY);
|
||||
}
|
||||
while (i < text.length) {
|
||||
if (text[i] == 'z') {
|
||||
currCurve.length && currShape.push(currCurve);
|
||||
currCurve = [];
|
||||
++i
|
||||
} else if (text[i] == 'N') {
|
||||
postProcess();
|
||||
currShape = [];
|
||||
maxX = -1000, maxY = -1000, minX = 1000, minY = 1000;
|
||||
++i;
|
||||
} else if (text[i] == 'c') {
|
||||
|
||||
prevX = currX;
|
||||
prevY = currY;
|
||||
|
||||
for (let j = 0; j < 3; ++j) {
|
||||
get_next(true);
|
||||
}
|
||||
} else if (text[i] == 'C') {
|
||||
for (let j = 0; j < 3; ++j) {
|
||||
get_next();
|
||||
}
|
||||
} else if (text[i] == 'M') {
|
||||
get_next();
|
||||
} else ++i;
|
||||
}
|
||||
};
|
||||
pathFetch.send();
|
||||
let rtx_VFetch = new XMLHttpRequest(), rtxvshader_txt;
|
||||
rtx_VFetch.open('GET', './RTX.vert');
|
||||
rtx_VFetch.onloadend = function() {
|
||||
rtxvshader_txt = rtx_VFetch.responseText;
|
||||
};
|
||||
rtx_VFetch.send();
|
||||
let rtx_FFetch = new XMLHttpRequest();
|
||||
rtx_FFetch.open('GET', './RTX.frag');
|
||||
rtx_FFetch.onloadend = function () {
|
||||
let rtxfs_text = rtx_FFetch.responseText;
|
||||
|
||||
let interval = setInterval(()=>{
|
||||
if(buildShaders && rtxvshader_txt && canvas1.gl)
|
||||
{
|
||||
gl.shaders[1] = buildShaders(rtxvshader_txt, rtxfs_text);
|
||||
clearInterval(interval);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
rtx_FFetch.send()
|
||||
let vec_len = v => {
|
||||
let len = 0;
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
len += v[i] * v[i];
|
||||
return sqrt(len);
|
||||
}
|
||||
let matrix_inverse = src => {
|
||||
let dst = [],
|
||||
det = 0,
|
||||
cofactor = (c, r) => {
|
||||
let s = (i, j) => src[c + i & 3 | (r + j & 3) << 2];
|
||||
return (c + r & 1 ? -1 : 1) * ((s(1, 1) * (s(2, 2) * s(3, 3) - s(3, 2) * s(2, 3))) -
|
||||
(s(2, 1) * (s(1, 2) * s(3, 3) - s(3, 2) * s(1, 3))) +
|
||||
(s(3, 1) * (s(1, 2) * s(2, 3) - s(2, 2) * s(1, 3))));
|
||||
}
|
||||
for (let n = 0; n < 16; n++) dst.push(cofactor(n >> 2, n & 3));
|
||||
for (let n = 0; n < 4; n++) det += src[n] * dst[n << 2];
|
||||
for (let n = 0; n < 16; n++) dst[n] /= det;
|
||||
return dst;
|
||||
}
|
||||
|
||||
// I HAVE IMPLEMENTED THESE FUNCTIONS FOR YOU
|
||||
let matrix_identity = () => {
|
||||
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
||||
}
|
||||
let matrix_translate = (x, y, z) => {
|
||||
let m = matrix_identity();
|
||||
m[12] = x;
|
||||
m[13] = y;
|
||||
m[14] = z;
|
||||
return m;
|
||||
}
|
||||
let matrix_perspective = (m) => {
|
||||
let ret = []
|
||||
for (let i = 0; i < 16; i++)
|
||||
ret[i] = m[i];
|
||||
for (let i = 2; i < 15; i += 4) {
|
||||
ret[i] = -ret[i];
|
||||
ret[i + 1] += ret[i] / fl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
// YOU NEED TO PROPERLY IMPLEMENT THE FOLLOWING FIVE FUNCTIONS:
|
||||
let matrix_rotateX = theta => {
|
||||
let m = matrix_identity();
|
||||
m[5] = cos(theta);
|
||||
m[6] = sin(theta);
|
||||
m[9] = -sin(theta);
|
||||
m[10] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
|
||||
let matrix_rotateY = theta => {
|
||||
let m = matrix_identity();
|
||||
m[0] = cos(theta);
|
||||
m[2] = -sin(theta);
|
||||
m[8] = sin(theta);
|
||||
m[10] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
let matrix_rotateZ = theta => {
|
||||
let m = matrix_identity();
|
||||
m[0] = cos(theta);
|
||||
m[1] = sin(theta);
|
||||
m[4] = -sin(theta);
|
||||
m[5] = cos(theta);
|
||||
return m;
|
||||
}
|
||||
let matrix_scale = (x, y, z) => {
|
||||
if (y === undefined)
|
||||
y = z = x;
|
||||
let m = matrix_identity();
|
||||
m[0] = x;
|
||||
m[5] = y;
|
||||
m[10] = z;
|
||||
return m;
|
||||
}
|
||||
let matrix_multiply = (a, b, m = 4, n = 4) => { //dim=mn*nm=mm
|
||||
let res = [];
|
||||
if (b.length < m * n) { //mat-vec multiply (i did this for my convenience)
|
||||
for (let i = 0; i < m; ++i) {
|
||||
res[i] = 0;
|
||||
for (let j = 0; j < n; ++j)
|
||||
res[i] += b[j] * a[m * j + i];
|
||||
}
|
||||
return res;
|
||||
} //otherwise mm multiply
|
||||
for (let i = 0; i < m; ++i)
|
||||
for (let j = 0; j < m; ++j) {
|
||||
var t = 0;
|
||||
for (let k = 0; k < n; ++k)
|
||||
t += a[k * m + j] * b[i * n + k];
|
||||
res.push(t);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
let const_multiply = (c, a, add = 0) => {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = (a[i] + add)* c;
|
||||
return m;
|
||||
}
|
||||
|
||||
function dot(a, b) {
|
||||
b=b?b:a;
|
||||
let m = 0;
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m += a[i] * b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function cross(a, b){
|
||||
let m = [];
|
||||
m[0] = a[1]*b[2] - a[2]*b[1];
|
||||
m[1] = a[2]*b[0] - a[0]*b[2];
|
||||
m[2] = a[0]*b[1] - a[1]*b[0];
|
||||
return m;
|
||||
}
|
||||
|
||||
function plus(a, b) {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = a[i] + b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function minus(a, b) {
|
||||
let m = [];
|
||||
for (let i = 0; i < a.length; ++i)
|
||||
m[i] = a[i] - b[i];
|
||||
return m;
|
||||
}
|
||||
|
||||
function normalize(v) {
|
||||
let res = [];
|
||||
sum = 0;
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
sum += v[i] * v[i];
|
||||
sum = sqrt(sum);
|
||||
for (let i = 0; i < v.length; ++i)
|
||||
res[i] = v[i] / sum;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
let Matrix = function () {
|
||||
let top = 0,
|
||||
m = [matrix_identity()];
|
||||
this.identity = () => m[top] = matrix_identity();
|
||||
this.translate = (x, y, z) => m[top] = matrix_multiply(m[top], matrix_translate(x, y, z));
|
||||
this.rotateX = theta => m[top] = matrix_multiply(m[top], matrix_rotateX(theta));
|
||||
this.rotateY = theta => m[top] = matrix_multiply(m[top], matrix_rotateY(theta));
|
||||
this.rotateZ = theta => m[top] = matrix_multiply(m[top], matrix_rotateZ(theta));
|
||||
this.scale = (x, y, z) => m[top] = matrix_multiply(m[top], matrix_scale(x, y, z));
|
||||
this.apply = (m1) => m[top] = matrix_multiply(m[top], m1);
|
||||
this.applyl = (m1) => m[top] = matrix_multiply(m1, m[top]);
|
||||
this.value = () => m[top];
|
||||
this.save = () => {
|
||||
m[top + 1] = m[top].slice();
|
||||
top++;
|
||||
}
|
||||
this.restore = () => --top;
|
||||
}
|
||||
function hitTest_sphere(ray, sphere, r) {
|
||||
let B = dot(ray, sphere);
|
||||
let C = dot(sphere, sphere) - r*r;
|
||||
let D = B * B - C;
|
||||
if (D > 0.) {
|
||||
//console.log(D);
|
||||
//let t = -B - sqrt(D);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
function hitTest_square(pt, invMatrix, shape){
|
||||
pt.push(1);
|
||||
const V = dot_xyz(matrix_multiply(invMatrix, [0,0,fl,1])),
|
||||
pos = dot_xyz(matrix_multiply(invMatrix, pt)),
|
||||
W = minus(pos, V),
|
||||
A = shape.slice(1,4),
|
||||
B = shape.slice(8,11),
|
||||
C = shape.slice(15,18),
|
||||
AB = minus(B, A),
|
||||
AC = minus(C, A),
|
||||
AB_AC = cross(AB, AC),
|
||||
VA = minus(V, A),
|
||||
t = - dot(AB_AC, VA)/dot(W, AB_AC),
|
||||
P = plus(V, const_multiply(t, W)),
|
||||
AP = minus(P, A),
|
||||
d_AP_AC = dot(AP, AC),
|
||||
d_AP_AB = dot(AP, AB);
|
||||
if(0 <d_AP_AC && d_AP_AC < dot(AC, AC) && 0 < d_AP_AB && d_AP_AB< dot(AB, AB))
|
||||
return P;
|
||||
else return -1;
|
||||
}
|
||||
let dot_xyz = (v) => {
|
||||
let ret = [];
|
||||
if(v[3])
|
||||
for(let i = 0; i < 3; ++i)
|
||||
ret[i] = v[i]/v[3];
|
||||
else ret = v.slice(0,3);
|
||||
return ret;
|
||||
}
|
||||
let Button = function (onclick = () => {}, shape = [], outlineTy = 'sphere') {
|
||||
this.shape = shape;
|
||||
this.enabled = true;
|
||||
this.outlineTy = outlineTy;
|
||||
this.onClick = onclick;
|
||||
this.updateMatrix = (m) => {this.matrix = matrix_perspective(m); this.invMatrix = matrix_inverse(m);};
|
||||
this.updateMatrix(matrix_identity());
|
||||
this.hovering = false;
|
||||
this.activated = false;
|
||||
this.getShape = () => this.shape;
|
||||
this.draw = () => {setUniform('Matrix4fv', 'uMatrix', false, this.matrix);
|
||||
setUniform('Matrix4fv', 'invMatrix', false, this.invMatrix); drawMesh(this.shape);}
|
||||
this.resetShape = (_sh) => {
|
||||
if(this.shape) delete this.shape;
|
||||
this.shape = new Float32Array(_sh);
|
||||
let maxV = new Array(3).fill(-Infinity), minV = new Array(3).fill(Infinity);
|
||||
for(let i = 0; i < _sh.length; i += 7){
|
||||
const v = [_sh[i + 1], _sh[i + 2], _sh[i + 3]];
|
||||
v.forEach((c, j) => {
|
||||
maxV[j] = maxV[j] > c ? maxV[j] : c;
|
||||
minV[j] = minV[j] < c ? minV[j] : c;
|
||||
})
|
||||
}
|
||||
//build outline
|
||||
switch(this.outlineTy){
|
||||
case 'sphere':
|
||||
this.origin = const_multiply(.5, plus(maxV, minV));
|
||||
//this.origin.push(1);
|
||||
this.radius = 0.6*vec_len(minus(maxV, minV))/2.;
|
||||
break;
|
||||
case 'square':
|
||||
break;
|
||||
case 'circle':
|
||||
break;
|
||||
}
|
||||
switch(this.outlineTy){
|
||||
case 'sphere':
|
||||
this.hitTest = (pt) => {
|
||||
pt.push(1);
|
||||
const V = dot_xyz(matrix_multiply(this.invMatrix, [0,0,fl,1])),
|
||||
pos = dot_xyz(matrix_multiply(this.invMatrix, pt));
|
||||
let W = normalize((minus(pos, V)));
|
||||
let Vp = minus(V, this.origin);
|
||||
return hitTest_sphere(W, Vp, this.radius);
|
||||
}
|
||||
break;
|
||||
case 'square':
|
||||
this.hitTest = (pt) => {
|
||||
this.P = hitTest_square(pt, this.invMatrix, this.shape);
|
||||
return this.P;
|
||||
}
|
||||
break;
|
||||
case 'circle':
|
||||
break;
|
||||
}
|
||||
};
|
||||
if(!shape || shape.length != 0)
|
||||
this.resetShape(shape);
|
||||
canvas_controls.push(this);
|
||||
}
|
||||
let setM = (m) => {
|
||||
let mm = matrix_perspective(m);
|
||||
setUniform('Matrix4fv', 'uMatrix', false, mm);
|
||||
setUniform('Matrix4fv', 'invMatrix', false, matrix_inverse(mm));
|
||||
}
|
||||
//------ CREATING MESH SHAPES
|
||||
|
||||
// CREATE A MESH FROM A PARAMETRIC FUNCTION
|
||||
|
||||
let createMesh = (nu, nv, f, data, oid = 0) => {
|
||||
let tmp = [];
|
||||
for (let v = 0; v < 1; v += 1 / nv) {
|
||||
for (let u = 0; u <= 1; u += 1 / nu) {
|
||||
tmp = tmp.concat(f(u, v, oid, data));
|
||||
tmp = tmp.concat(f(u, v + 1 / nv, oid, data));
|
||||
}
|
||||
tmp = tmp.concat(f(1, v, oid, data));
|
||||
tmp = tmp.concat(f(0, v + 1 / nv, oid, data));
|
||||
}
|
||||
return new Float32Array(tmp);
|
||||
}
|
||||
//Create a Mesh from Splines
|
||||
let createMeshFromSpline = (idx,
|
||||
nu, nv, oid = 16, additional_offset = 0, f = () => {}) => {
|
||||
let S = paths[idx],
|
||||
meta = path_misc[idx];
|
||||
const n_min = 2;
|
||||
let ds = meta[0] / nv,
|
||||
curr_s = 0,
|
||||
curr_d = S[0][2] / Math.ceil(S[0][2] / ds),
|
||||
i = 0,
|
||||
s = 0;
|
||||
let tmp = [],
|
||||
ret = undefined;
|
||||
while (s < meta[0] - 1 / 100000) {
|
||||
|
||||
for (let u = 0; u <= 1; u += 1 / nu) {
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], u, curr_s, idx, oid, additional_offset));
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], u, curr_s + curr_d, idx, oid, additional_offset));
|
||||
}
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], 0, curr_s, idx, oid, additional_offset));
|
||||
tmp = tmp.concat(getSurface(S[i][1], S[i][0], 1, curr_s + curr_d, idx, oid, additional_offset));
|
||||
if (ret = f(i, tmp, oid)) {
|
||||
oid = ret;
|
||||
}
|
||||
curr_s += curr_d;
|
||||
if (curr_s >= 1) {
|
||||
s += S[i][2];
|
||||
++i;
|
||||
if (i >= S.length)
|
||||
break;
|
||||
let curr_n = Math.ceil(S[i][2] / ds);
|
||||
curr_n = curr_n < n_min ? n_min : curr_n;
|
||||
curr_d = 1 / curr_n;
|
||||
curr_s = 0;
|
||||
}
|
||||
}
|
||||
return new Float32Array(tmp);
|
||||
}
|
||||
// GLUE TWO MESHES TOGETHER INTO A SINGLE MESH
|
||||
|
||||
let glueMeshes = (a, b) => {
|
||||
let c = [];
|
||||
for (let i = 0; i < a.length; i++)
|
||||
c.push(a[i]); // a
|
||||
for (let i = 0; i < VERTEX_SIZE; i++)
|
||||
c.push(a[a.length - VERTEX_SIZE + i]); // + last vertex of a
|
||||
for (let i = 0; i < VERTEX_SIZE; i++)
|
||||
c.push(b[i]); // + first vertex of b
|
||||
for (let i = 0; i < b.length; i++)
|
||||
c.push(b[i]); // + b
|
||||
return new Float32Array(c);
|
||||
}
|
||||
|
||||
|
||||
let uvToSphere = (u, v, i) => {
|
||||
let theta = 2 * Math.PI * u;
|
||||
let phi = Math.PI * (v - .5);
|
||||
let x = Math.cos(theta) * Math.cos(phi);
|
||||
let y = Math.sin(theta) * Math.cos(phi);
|
||||
let z = Math.sin(phi);
|
||||
return [i, x, y, z].concat(normalize([x, y, z]));
|
||||
}
|
||||
|
||||
let uvToTube = (u, v, i) => {
|
||||
let theta = 2 * Math.PI * u;
|
||||
let x = Math.cos(theta);
|
||||
let y = Math.sin(theta);
|
||||
let z = 2 * v - 1;
|
||||
return [i, x, y, z].concat(normalize([x, y, 0]));
|
||||
}
|
||||
|
||||
let uvToDisk = (u, v, i, dz) => {
|
||||
if (dz === undefined)
|
||||
dz = 0;
|
||||
let theta = 2 * Math.PI * u;
|
||||
let x = Math.cos(theta) * v;
|
||||
let y = Math.sin(theta) * v;
|
||||
let z = dz;
|
||||
return [i, x, y, z].concat([0, 0, Math.sign(z)]);
|
||||
}
|
||||
let uvToTorus = (u, v, i, r) => {
|
||||
let theta = 2 * pi;
|
||||
let phi = theta * v;
|
||||
theta *= u;
|
||||
let x = 1 + r * cos(phi);
|
||||
let y = sin(theta) * x;
|
||||
x *= cos(theta);
|
||||
let z = r * sin(phi);
|
||||
let tx = -sin(theta),
|
||||
ty = cos(theta),
|
||||
tsx = sin(phi),
|
||||
tsy = tsx * tx,
|
||||
tsz = cos(phi);
|
||||
tsx *= -ty;
|
||||
return [i, x, y, z].concat(normalize([ty * tsz * 0.5, -tx * tsz, tx * tsy - ty * tsx]));
|
||||
}
|
||||
|
||||
let createCube = (w, h, l, id) => {
|
||||
let mesh = [];
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, -1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 0, 1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, -1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, -1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, -1, 0, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
|
||||
mesh = mesh.concat([id, -w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 0, -1]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, -l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 1, 0, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, -h / 2, l / 2, 1, 0, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
|
||||
mesh = mesh.concat([id, w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, w / 2, h / 2, -l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, l / 2, 0, 1, 0]);
|
||||
mesh = mesh.concat([id, -w / 2, h / 2, -l / 2, 0, 1, 0]);
|
||||
return new Float32Array(mesh);
|
||||
}
|
||||
|
||||
function updatePositions() {
|
||||
let m = matrix_rotateY(-mousedx);
|
||||
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||||
setUniform('3f', 'V0', m[8] * (fl + mousedz), m[9] * (fl + mousedz), m[10] * (fl + mousedz));
|
||||
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||||
setUniform('Matrix3fv', 'transformation', false, [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]]);
|
||||
invTr = matrix_inverse(m);
|
||||
|
||||
positionsupdated = false;
|
||||
}
|
||||
function controls_hitTest(pos, clicked = false){
|
||||
// let iMin = -1, tMin = 10000.;
|
||||
if(channel_disp == 5)
|
||||
return;
|
||||
canvas_controls.forEach((c, i) => {
|
||||
if(c.enabled && c.hitTest && (c.hover||clicked) ){
|
||||
let t = c.hitTest(pos);
|
||||
if(t != -1){
|
||||
if(clicked)
|
||||
c.onClick();
|
||||
else
|
||||
c.hover(true);
|
||||
}
|
||||
else
|
||||
if(c.hovering)
|
||||
c.hover(false);
|
||||
}
|
||||
});
|
||||
//ground
|
||||
if(ground_m && ground){
|
||||
let invG = matrix_inverse(ground_m);
|
||||
let P = hitTest_square(pos, invG, ground);
|
||||
console.log(P);
|
||||
//let Vp = minus(matrix_multiply(invG,[0,0,fl, 1]).slice(0,3), this.origin);
|
||||
if(P!=-1)
|
||||
if(near_magician){
|
||||
if(slider.dragging === true){
|
||||
slider_dl += 10 * (P[0] - slider.lastPos);
|
||||
if(slider_dl < 0) slider_dl = 0;
|
||||
else if (slider_dl > 9) slider_dl = 9;
|
||||
slider.lastPos = P[0];
|
||||
// onUpdate
|
||||
let id = 1 + .45*slider_dl/9;
|
||||
changeID(id, cylinderMesh);
|
||||
} else if(clicked) {
|
||||
const PO = minus([slider_dl/10-.25, .7], [P[0], P[1]]);
|
||||
const rr = PO[0]*PO[0] + PO[1] * PO[1];
|
||||
if(rr < .003){
|
||||
slider.dragging = true;
|
||||
slider.lastPos = P[0];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(clicked || running<=0)
|
||||
{
|
||||
direction_l = [P[0] - delta_l[0]/10, P[1] - delta_l[1]/10];
|
||||
if(P[1] < 0.00000000000001)
|
||||
P[1] = 0.0000000000000001;
|
||||
figure_rot = atan(direction_l[0]/direction_l[1]);
|
||||
if(direction_l[1] < 0){
|
||||
figure_rot = pi + figure_rot;
|
||||
}
|
||||
}
|
||||
//if(figure_rot < 0) figure_rot += pi;
|
||||
//updateStatus([figure_rot, direction_l[0]/direction_l[1]]);
|
||||
if(clicked)
|
||||
{
|
||||
dir_sdl = vec_len(direction_l)*10;
|
||||
direction_l = normalize(direction_l);
|
||||
rebuild = true;
|
||||
running = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//return iMin;
|
||||
}
|
||||
function hitTest(pos) {
|
||||
|
||||
let m = matrix_rotateY(-mousedx);
|
||||
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||||
|
||||
|
||||
let V = [m[8] * (fl + mousedz), m[9] * (fl + mousedz), m[10] * (fl + mousedz)];
|
||||
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||||
|
||||
let trPos = matrix_multiply([m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]], [pos[0], pos[1], -1], 3, 3);
|
||||
|
||||
let W = normalize(minus(trPos, V));
|
||||
let tMin = 10000.;
|
||||
let iMin = -1;
|
||||
for (let i = 0; i < cns; i++) {
|
||||
let Vp = minus(V, matrix_multiply(SphTr[i], Sph[i]));
|
||||
let B = dot(W, Vp);
|
||||
let C = dot(Vp, Vp) - Sph[i][4] * Sph[i][4];
|
||||
let D = B * B - C;
|
||||
if (D > 0.) {
|
||||
let t = -B - sqrt(D);
|
||||
if (t > 0.0 && t < tMin) {
|
||||
tMin = t; // This is an optimization, we don't have to do lighting/tex
|
||||
iMin = i; // for objects that are occuluded, which is expensive!
|
||||
}
|
||||
}
|
||||
}
|
||||
return iMin;
|
||||
}
|
||||
let matrix_transform = (m, p) => {
|
||||
let x = p[0],
|
||||
y = p[1],
|
||||
z = p[2],
|
||||
w = p[3] === undefined ? 1 : p[3];
|
||||
let q = [m[0] * x + m[4] * y + m[8] * z + m[12] * w,
|
||||
m[1] * x + m[5] * y + m[9] * z + m[13] * w,
|
||||
m[2] * x + m[6] * y + m[10] * z + m[14] * w,
|
||||
m[3] * x + m[7] * y + m[11] * z + m[15] * w
|
||||
];
|
||||
return p[3] === undefined ? [q[0] / q[3], q[1] / q[3], q[2] / q[3]] : q;
|
||||
}
|
||||
let evalSpline = (h, t) => {
|
||||
// t *= (h.length - 2) / 2;
|
||||
// let n = 2 * Math.floor(t);
|
||||
// t = t % 1;
|
||||
// let C = matrix_transform(type, [h[n+0],h[n+2],h[n+1],h[n+3]]);
|
||||
// return t*t*t*C[0] + t*t*C[1] + t*C[2] + C[3];
|
||||
return t * t * t * h[0] + t * t * h[1] + t * h[2] + h[3];
|
||||
}
|
||||
let getSurface = (S0, S1, u, v, offsetidx, id = 15, additional_offset = 0) => {
|
||||
const epsilon = .001;
|
||||
let z0 = evalSpline(S0, v),
|
||||
z1 = evalSpline(S0, v + epsilon),
|
||||
|
||||
r0 = evalSpline(S1, v) - path_misc[offsetidx][1] + additional_offset,
|
||||
r1 = evalSpline(S1, v + epsilon),
|
||||
|
||||
tilt = Math.atan2(r0 - r1, z1 - z0);
|
||||
|
||||
let xx = cos(2 * pi * u),
|
||||
yy = sin(2 * pi * u);
|
||||
let x = r0 * xx, // POSITION
|
||||
y = r0 * yy,
|
||||
z = z0,
|
||||
nx = cos(tilt), // NORMAL
|
||||
ny = nx * yy,
|
||||
nz = sin(tilt);
|
||||
nx *= xx;
|
||||
return [id, x, y, z, nx, ny, nz];
|
||||
}
|
||||
let concat = (a, b) => b.forEach(e => a.push(e));
|
||||
@@ -0,0 +1,327 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// THIS IS THE SUPPORT LIBRARY. YOU PROBABLY DON'T WANT TO CHANGE ANYTHING HERE JUST YET.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let fragmentShaderHeader = ['' // WHATEVER CODE WE WANT TO PREDEFINE FOR FRAGMENT SHADERS
|
||||
, 'precision highp float;', 'float noise(vec3 point) { float r = 0.; for (int i=0;i<16;i++) {', ' vec3 D, p = point + mod(vec3(i,i/4,i/8) , vec3(4.0,2.0,2.0)) +', ' 1.7*sin(vec3(i,5*i,8*i)), C=floor(p), P=p-C-.5, A=abs(P);', ' C += mod(C.x+C.y+C.z,2.) * step(max(A.yzx,A.zxy),A) * sign(P);', ' D=34.*sin(987.*float(i)+876.*C+76.*C.yzx+765.*C.zxy);P=p-C-.5;', ' r+=sin(6.3*dot(P,fract(D)-.5))*pow(max(0.,1.-2.*dot(P,P)),4.);', '} return .5 * sin(r); }','\n#define _NDEBUG\n'
|
||||
].join('\n');
|
||||
var ns = 6,
|
||||
cns = 6;
|
||||
fragmentShaderHeader += 'const int ns = ' + ns + ';\n';
|
||||
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
|
||||
var status = 'The TV is a touch screen!';
|
||||
let nfsh = fragmentShaderHeader.split('\n').length + 1; // NUMBER OF LINES OF CODE IN fragmentShaderHeader
|
||||
|
||||
let isFirefox = navigator.userAgent.indexOf('Firefox') > 0;
|
||||
|
||||
function getBlob(data) {
|
||||
let bytes = new Array(data.length);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
bytes[i] = data.charCodeAt(i);
|
||||
}
|
||||
return new Blob([new Uint8Array(bytes)]);
|
||||
}
|
||||
let stack = function (){
|
||||
this.storage = ['Ready.'];
|
||||
this.len = 1;
|
||||
this.pop = ()=>{return this.storage[--this.len-1];}
|
||||
this.push = (o)=>{this.storage[this.len++] = o;}
|
||||
this.update = (o)=>{this.storage[this.len-1] = o;}
|
||||
this.top = () => {return this.storage[this.len - 1];}
|
||||
this.clear = () => this.len = 1;
|
||||
}
|
||||
let status_history = new stack();
|
||||
function updateStatus(val){
|
||||
status_history.update(status);
|
||||
status = val;
|
||||
errorMessage.innerHTML = val;
|
||||
}
|
||||
function pushStatus(val){
|
||||
status_history.push(status);
|
||||
status = val;
|
||||
errorMessage.innerHTML = val;
|
||||
}
|
||||
function restoreStatus(val){
|
||||
status = status_history.pop();
|
||||
errorMessage.innerHTML = status;
|
||||
}
|
||||
function resetStatus() {
|
||||
status_history.clear();
|
||||
updateStatus('Ready.');
|
||||
}
|
||||
var texture = [],
|
||||
gl, program;
|
||||
let textures = [];
|
||||
let lock = false;
|
||||
|
||||
function loadTexture(gl, url, i) {
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 1;
|
||||
const height = 1;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
if (texture[i] == null) {
|
||||
texture[i] = gl.createTexture();
|
||||
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
|
||||
gl.activeTexture(gl.TEXTURE0 + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
}
|
||||
const image = new Image();
|
||||
image.onload = function () {
|
||||
gl.activeTexture(gl.TEXTURE0 + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
srcFormat, srcType, image);
|
||||
|
||||
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
};
|
||||
image.src = url;
|
||||
}
|
||||
function initTextures(gl, program){
|
||||
for (let i = 0; i < ns; ++i) {
|
||||
loadTexture( gl, './' + (i + 1) + '.jpg', i); //Texture loading.
|
||||
textures[i] = i;
|
||||
}
|
||||
textures[ns] = ns;
|
||||
initVideoTexture(gl, ns + 0);
|
||||
textures[ns + 1] = ns + 1;
|
||||
loadTexture(gl, './starburst.png', ns + 1);
|
||||
createNoiseTexture();
|
||||
textures[ns+2] = ns+2;
|
||||
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
|
||||
}
|
||||
function initVideoTexture(gl, i) {
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 1;
|
||||
const height = 1;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
if (texture[i] == null) {
|
||||
texture[i] = gl.createTexture();
|
||||
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
|
||||
gl.activeTexture(gl.TEXTURE + i);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
}
|
||||
function updateVideoTexture(gl, v_control, i){
|
||||
//return;
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
srcFormat, srcType, v_control);
|
||||
}
|
||||
function createNoiseTexture(){
|
||||
const level = 0;
|
||||
const internalFormat = gl.RGBA;
|
||||
const width = 100;
|
||||
const height = 100;
|
||||
const border = 0;
|
||||
const srcFormat = gl.RGBA;
|
||||
const srcType = gl.UNSIGNED_BYTE;
|
||||
texture[ns+2] = gl.createTexture();
|
||||
let random_list = [];
|
||||
let get_random = ()=>Math.pow(Math.random(), .1);
|
||||
let get_random2 = ()=>{
|
||||
let r = Math.random();
|
||||
if (r < .5) r = .5*Math.pow(2*r,.1);
|
||||
else r = .5 + .5*Math.pow(r,10);
|
||||
return r;};
|
||||
for(let i = 0; i < 40000; ++i){
|
||||
if(i%4 == 3)
|
||||
random_list.push(255*get_random());
|
||||
else
|
||||
random_list.push(255*get_random2());
|
||||
}
|
||||
const pixel = new Uint8Array(random_list);
|
||||
gl.activeTexture(gl.TEXTURE0+ns+2);
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture[ns+2]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
|
||||
width, height, border, srcFormat, srcType,
|
||||
pixel);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
}
|
||||
function isPowerOf2(value) {
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
function buildShaders(vertexShader, fragmentShader){
|
||||
let curr_program = canvas1.gl.createProgram();
|
||||
let compile_shaders = (type, src) => {
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
gl.attachShader(curr_program, shader);
|
||||
};
|
||||
compile_shaders(gl.VERTEX_SHADER, vertexShader);
|
||||
compile_shaders(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShaderDefs + fragmentShader);
|
||||
gl.linkProgram(curr_program);
|
||||
|
||||
return curr_program;
|
||||
}
|
||||
function gl_start(canvas, vertexShader, fragmentShader) { // START WEBGL RUNNING IN A CANVAS
|
||||
console.log('glstart');
|
||||
setTimeout(function () {
|
||||
try {
|
||||
canvas.gl = canvas.getContext('experimental-webgl'); // Make sure WebGl is supported. IT WOULD BE GREAT TO USE WEBGL2 INSTEAD.
|
||||
} catch (e) {
|
||||
throw 'Sorry, your browser does not support WebGL.';
|
||||
}
|
||||
|
||||
|
||||
canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders:
|
||||
gl = this.gl;
|
||||
program = gl.createProgram(); // Create the WebGL program.
|
||||
|
||||
function addshader(type, src) { // Create and attach a WebGL shader.
|
||||
function spacer(color, width, height) {
|
||||
return '<table bgcolor=' + color +
|
||||
' width=' + width +
|
||||
' height=' + height + '><tr><td> </td></tr></table>';
|
||||
}
|
||||
errorMessage.innerHTML = status;
|
||||
// errorMarker.innerHTML = spacer('white', 1, 1) + '<font size=1 color=white>\u25B6</font>';
|
||||
let shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, src);
|
||||
gl.compileShader(shader);
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
let msg = gl.getShaderInfoLog(shader);
|
||||
console.log('Cannot compile shader:\n\n' + msg);
|
||||
|
||||
let a = msg.substring(6, msg.length);
|
||||
let line = 0;
|
||||
if (a.substring(0, 3) == ' 0:') {
|
||||
a = a.substring(3, a.length);
|
||||
line = parseInt(a) - nfsh;
|
||||
|
||||
editor.session.setAnnotations([{
|
||||
row: line,
|
||||
column: 0,
|
||||
text: msg,
|
||||
type: "error"
|
||||
}]);
|
||||
}
|
||||
let j = a.indexOf(':');
|
||||
a = 'line ' + (line + 1) + a.substring(j, a.length);
|
||||
if ((j = a.indexOf('\n')) > 0)
|
||||
a = a.substring(0, j);
|
||||
errorMessage.innerHTML = a;
|
||||
} else
|
||||
editor.session.clearAnnotations();
|
||||
gl.attachShader(program, shader);
|
||||
};
|
||||
|
||||
addshader(gl.VERTEX_SHADER, vertexShader); // Add the vertex and fragment shaders.
|
||||
addshader(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShaderDefs + fragmentShader);
|
||||
|
||||
gl.linkProgram(program); // Link the program, report any errors.
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
|
||||
console.log('Could not link the shader program!');
|
||||
gl.useProgram(program);
|
||||
gl.program = program;
|
||||
if(!gl.shaders)
|
||||
gl.shaders = [program];
|
||||
else gl.shaders[0] = program;
|
||||
initTextures(gl, program);
|
||||
positionsupdated = true;
|
||||
let attribs = [
|
||||
.05, .05, .1, .5, .5, 1., 1., .5, .5, 20., 5,0,0, 0.,.0, 1.3,
|
||||
.1, .05, .05, 1., .5, .5, 1., .5, .5, 10., .1,8,0, .3, 1., 1.3,
|
||||
.1, .05, .05, .71, .71, .71, .71, .71, .71, 10., .1,0,9, 0.3, .0, 1.5,
|
||||
.1, .1, .1, .71, .71, .71, .71, .71, .71, 10., 2,2,0, 0.05, 0., 1.,
|
||||
.0, .0, .0, .0, .0, .0, .0, .0, .0, 40., 4,4,4, 0., .85, 1.5
|
||||
]
|
||||
var offset = 0;
|
||||
for (let i = 0; i < ns; i++) {
|
||||
setUniform('3fv', 'Ambient[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('3fv', 'Diffuse[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('4fv', 'Specular[' + i + ']', attribs.slice(offset, offset += 4));
|
||||
setUniform('3fv', 'Glow[' + i + ']', attribs.slice(offset, offset += 3));
|
||||
setUniform('1fv', 'ks[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
setUniform('1fv', 'kr[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
setUniform('1fv', 'kf[' + i + ']', attribs.slice(offset, offset += 1));
|
||||
}
|
||||
offset = 0;
|
||||
for (let i = 0; i < n_shapes; i++) {
|
||||
setUniform('3fv', 'starColors[' + i + ']', starColors.slice(offset, offset += 3));
|
||||
}
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // Create a square as a triangle strip
|
||||
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( // consisting of two triangles.
|
||||
// [-1, 1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0]), gl.STATIC_DRAW);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.depthFunc(gl.LEQUAL);
|
||||
gl.clearDepth(-1);
|
||||
gl.enable(gl.BLEND);
|
||||
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
||||
let oid = gl.getAttribLocation(program, 'oid'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(oid);
|
||||
gl.vertexAttribPointer(oid, 1, gl.FLOAT, false, 4 * 7, 0);
|
||||
|
||||
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(aPos);
|
||||
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 4 * 7, 4);
|
||||
|
||||
let normal = gl.getAttribLocation(program, 'normal'); // Set aPos attribute for each vertex.
|
||||
gl.enableVertexAttribArray(normal);
|
||||
gl.vertexAttribPointer(normal, 3, gl.FLOAT, false, 4 * 7, 4 * 4);
|
||||
}
|
||||
|
||||
canvas.setShaders(vertexShader, fragmentShader); // Initialize everything,
|
||||
setInterval(function () { // Start the animation loop.
|
||||
gl = canvas.gl;
|
||||
if (gl.startTime === undefined) // First time through,
|
||||
gl.startTime = Date.now(); // record the start time.
|
||||
animate(gl);
|
||||
//gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // Render the square.
|
||||
}, 30);
|
||||
|
||||
}, 100); // Wait 100 milliseconds after page has loaded before starting WebGL.
|
||||
}
|
||||
|
||||
// THE animate() CALLBACK FUNCTION CAN BE REDEFINED IN index.html.
|
||||
|
||||
function animate() {}
|
||||
|
||||
function setUniform(type, name, a, b, c, d, e, f) {
|
||||
if (gl) {
|
||||
let loc = gl.getUniformLocation(gl.program, name);
|
||||
(gl['uniform' + type])(loc, a, b, c, d, e, f);
|
||||
}
|
||||
}
|
||||
|
||||
//let VERTEX_SIZE = 3;
|
||||
|
||||
|
||||
let VERTEX_SIZE = 7;
|
||||
|
||||
|
||||
var drawMesh = (mesh, func = gl.TRIANGLE_STRIP) => {
|
||||
gl.bufferData(gl.ARRAY_BUFFER, mesh, gl.STATIC_DRAW);
|
||||
gl.drawArrays(func, 0, mesh.length / VERTEX_SIZE);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
vec3 foregroundColor = vec3(.0841, .5329, .9604);
|
||||
uniform vec3 starColors[10];
|
||||
uniform vec3 V0;
|
||||
uniform sampler2D uSampler[ns + 1]; //ns + vs
|
||||
varying vec3 norm;
|
||||
varying float id;
|
||||
varying vec3 glpos;
|
||||
varying vec3 texPos;
|
||||
vec3 LDir=vec3(.5,.5,.5);
|
||||
void main(){
|
||||
vec3 color =foregroundColor.xyz;
|
||||
float sp = 0.4, df = 0.4, amb = 0.4, ex=5., alpha = 1.;
|
||||
vec3 l = vec3(1,1,1);
|
||||
if(id < -2.5){gl_FragColor = vec4(texture2D(uSampler[ns + 0], (1.+texPos.xy)/2.).xyz, 1.); return;} //pjsk
|
||||
else if(id <-1.5) {color = vec3(.05,.05,.05);sp = 1.; df=.4; amb = .3, ex = 5.;}
|
||||
else if(id < 1.5) {color = vec3(1.0000, 0.3570, 0.3570);sp = 1.; df=.2; amb = .7, ex = 20.;}
|
||||
else if (id < 2.5) color = vec3(1.,.16,.36);
|
||||
else if (id < 3.5) {color = vec3(1.0000, 0.7725, 0.7725);sp = .5; df=.8; amb = .05;}
|
||||
else if (id < 4.5) {color = vec3(0.9612,0.3057,0.3369);sp = .5; df=.5; amb = .5; ex=20.;}
|
||||
else if (id < 6.5) {}
|
||||
else if (id < 7.5) {color = starColors[0]; sp = 0.3, df = 0.3, amb = 0.8, ex=5.;}
|
||||
else if (id < 8.5) {color = starColors[1]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 9.5) {color = starColors[2]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 10.5) {color = starColors[3]; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 12.5) {color = starColors[4]; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 13.5) {color = starColors[4]*2.; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 14.5) {color = .4*foregroundColor + .8*starColors[4]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 15.5) {color = .3*vec3(0.9612,0.3057,0.3369)+.8*starColors[4]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 16.5) {float alp = 2.*abs(.49999 - fract(id+.00001));gl_FragColor=vec4(1.,1.,1., alp);return;}
|
||||
|
||||
if(id < 0. &&id > -1.5){
|
||||
vec3 P = vec3(sin(glpos.y*1.), sin(glpos.x*1.5+1.), cos(glpos.z*1.));
|
||||
// APPLY PROCEDURAL NOISE TEXTURE.
|
||||
float cloud = min(0.99, max(0., 1. * noise(1. * P)));
|
||||
color = (1.-cloud)*color + starColors[5] * cloud*3.;
|
||||
}
|
||||
vec3 V = V0;
|
||||
vec3 W=normalize(glpos-V);
|
||||
vec3 realLDir=normalize(LDir - glpos);
|
||||
|
||||
color = color*(amb+ df*max(0.,dot(norm,realLDir)))
|
||||
+ sp*pow(max(0., dot(2.*dot(norm, realLDir)*norm-realLDir, -W)),ex)*l;
|
||||
gl_FragColor=vec4(sqrt(color), alpha);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
uniform mat4 uMatrix;
|
||||
uniform mat4 invMatrix;
|
||||
uniform mat3 transformation;
|
||||
attribute float oid;
|
||||
attribute vec3 aPos;
|
||||
attribute vec3 normal;
|
||||
varying float id;
|
||||
varying vec3 glpos;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
void main() {
|
||||
vec4 pos = uMatrix * vec4(aPos, 1.);
|
||||
texPos = aPos;
|
||||
gl_Position = pos ;
|
||||
glpos = pos.xyz;
|
||||
id = oid;
|
||||
norm = normalize(vec4(normal,0.)*invMatrix).xyz;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
M11.02,39.45c-2.67-2.97-5.37-5.93-8.01-8.94c-2.42-2.76-2.92-5.66-1.11-8.78c0.81-1.39,1.97-2.41,3.65-2.76c3.9-0.82,7.78-1.71,11.67-2.56c0.86-0.19,1.5-0.51,1.99-1.38c1.9-3.42,3.92-6.76,5.89-10.14c2.6-4.46,9.11-4.47,11.71-0.04
|
||||
c1.98,3.37,3.99,6.72,5.89,10.14c0.48,0.86,1.08,1.23,1.96,1.42c3.94,0.85,7.88,1.68,11.81,2.6c2.44,0.57,3.73,2.34,4.36,4.65c0.77,2.82-0.27,5.08-2.16,7.14c-2.52,2.74-4.97,5.53-7.44,8.32c-0.18,0.2-0.41,0.49-0.38,0.72c0.18,1.94,0.41,3.87,0.63,5.8
|
||||
c0.12,1.04,0.33,2.07,0.36,3.11c0.05,1.93,0.55,3.8,0.17,5.81c-0.65,3.42-4.81,6.08-8.02,4.95c-1.83-0.64-3.65-1.36-5.44-2.11
|
||||
c-2.24-0.94-4.48-1.89-6.67-2.95c-0.75-0.36-1.36-0.27-2.02,0.03c-2.75,1.22-5.47,2.48-8.24,3.66c-1.3,0.56-2.64,1.08-4.01,1.43
|
||||
c-2.45,0.63-4.53-0.26-6.14-2.08c-1.65-1.86-2.05-4.09-1.55-6.54c0.26-1.25,0.25-2.55,0.37-3.83
|
||||
C10.52,44.62,10.77,42.12,11.02,39.45z M56.81,25.75c0.02-1.65-1.04-2.64-2.79-3.01c-4.04-0.84-8.06-1.74-12.1-2.57
|
||||
c-0.91-0.19-1.58-0.65-2.04-1.42c-0.98-1.64-1.93-3.29-2.89-4.93c-1.32-2.26-2.6-4.55-3.98-6.77c-1.12-1.79-2.96-1.74-4.13,0.04
|
||||
c-0.65,0.99-1.23,2.04-1.83,3.07c-1.66,2.84-3.32,5.68-4.97,8.52c-0.48,0.83-1.17,1.32-2.14,1.5c-1.82,0.34-3.62,0.74-5.42,1.14
|
||||
c-2.45,0.54-4.92,1.04-7.34,1.68C5,23.57,4.46,25.5,5.92,27.15c1.64,1.85,3.31,3.69,4.95,5.54c1.33,1.5,2.68,2.97,3.92,4.54
|
||||
c0.38,0.48,0.61,1.21,0.61,1.82c0.01,1.33-0.17,2.65-0.29,3.98c-0.09,0.99-0.19,1.98-0.3,2.97c-0.26,2.26-0.58,4.51-0.77,6.78
|
||||
c-0.05,0.52,0.18,1.14,0.48,1.59c0.8,1.19,1.9,1.37,3.54,0.65c3.75-1.66,7.49-3.32,11.22-5.02c1.06-0.48,2.04-0.61,3.13-0.1
|
||||
c1.94,0.92,3.9,1.78,5.86,2.65c2.05,0.91,4.11,1.78,6.15,2.69c0.93,0.42,1.77,0.3,2.52-0.37c0.76-0.68,1.19-1.49,0.83-2.55
|
||||
c-0.08-0.22-0.12-0.46-0.14-0.7c-0.21-2.51-0.38-5.02-0.61-7.53c-0.12-1.32-0.38-2.63-0.51-3.95c-0.11-1.09-0.17-2.16,0.7-3.09
|
||||
c1.83-1.95,3.6-3.95,5.37-5.94c1.23-1.39,2.46-2.79,3.64-4.22C56.54,26.51,56.69,25.99,56.81,25.75z
|
||||
N
|
||||
M66.36,818.02c-106.2-110.9-61-662.8-36.4-813.56c71.19,1.55,58.77-12.26,72.22,57.92c12.21-15.09,10.15-62.97,37.19-55.8
|
||||
c-11.66,49.82-40.93,95.92-1.62,142.63c15.22,3.36,56.55-137.38,59.66-136.45c2.49,0.74-22.25,91.36-42.07,162.69
|
||||
c8.65,35.12,58.93,87.86,92.29,98.19c14.23-79.7,33.22-361.27,73.99-244.33c41.13-55.27-7.85,38.44-11.46,55.28
|
||||
c-18.92,98.99-27.77,241.63,53.45,119.52c20.21-34.31,20.1-114.01,53.68-126.53c3.84-12.82,10.48-73.87,24.02-73.1
|
||||
c12.83-0.56,65.91-1.83,35.15,7.41c-61.79-15.5-48.75,200.28-45.07,243.92c2.25,20.42,27.14,13.8,38.12,25.45
|
||||
c6.03,4.39,36.44,27.66,18.27,21.91c-40.8-27.63-66.71-54.35-46.2,16.36c-19.89-38.23,1.59-50.13-50.98-60.73
|
||||
c8.31-2.96,35.82,10.04,30.87-4.68c-5.47-26.59-6.9-54.75-14.96-80.46c-22.25,80.4-137.99,191.25-134.59,255.33
|
||||
c28.43-24.91,73.72-62.68,120.64-46.55c78.08,7.49,7.79-16.2-21.17-22.89c25.68-8.32,88.81,23.09,96.53,50.48
|
||||
c-14.88-13.87-8.97-8.07-4.72,6.57c-20.12-14.39-11.58-35.73-44.46-26.75c28.79,18.11,36.81,27.82,49.27,59.28
|
||||
c-15.78,0.19,5.06,35.44-28.02-9.3c-39.56-53.22-130.39-50.05-158.76,12.21c-0.57,107.56,60.34,213.63,68.06,323.78
|
||||
c1.71,10.93,25.65,17.02,33.27,28.59c-11.57-2.96-19.66-12.97-31.03-16.47c-1.22,193.89-65.94,75.43,75.87,233.86
|
||||
c-37.15-15.29-59.1-63.14-92.21-88.24c-15.18-7.04-28.22,43.71-46.26,43.68c57.38-81.24-1.81-123.16,10.19-218.4
|
||||
c8.56,76.16-24.52,144.42-59.52,208.52c-8.14,12.44,0.12,54.47-13.87,54.44c9.71-16.15,13.17-61.15-18.44-81.22
|
||||
C166.51,916.66,113.43,878.18,66.36,818.02z M925.87,407.64c-54.74-44.89,19.53-197.95-29.21-257.87
|
||||
c-7.8,0.23,0.01,139.34-12.78,138.06c-0.76-11.74,2.94-57.56-13.24-57.45c-12.13,43.49-18.05,56.87-20.76,56.35
|
||||
c-3.44-0.66-1.37-22.36-9.37-26.3c-1.4-0.69-3.39-0.47-6.27,1.08c-37.75,31.13-5.8-23.15-21.95-34.81
|
||||
c-10.77-4.3-7.19,51.51-13.81,37.09c-6.3-84.43-23.11-192.91-70.65-258.62c15.21,86.12,50.46,187.09,38.31,278.79
|
||||
c-21.94-86.63-52.72-175.52-70.62-266.49c2.29-9.8-18.19-21-13.94-4.4c30.28,57.1,21.26,334.09,14.6,185.12
|
||||
c-1.5-9.87,2.15-67.2-7.12-67.14c-2.9,30.13-5.79,60.27-8.69,90.4c-32.81-59.32-16.97-176.63-52.31-212.83
|
||||
c11.12,94.4-6.13,188.39-24.34,280.85c3.07-43.88,20.04-96.61,8.43-137.16c-6.3,14.9-20.93,66.96-26.59,61.57
|
||||
c-8.59-0.89-9.05-48.09-14.45-48.15c-3.39-0.04-6.04,18.34-7.95,31.07c-7.59,50.46-15.93,93.98-17.18,93.85
|
||||
c8.57-40.75,5.67-198.5-18.91-251.56c4.95,62.89-1.02,125.94-10.23,188.11c3.54-69.31,13.94-164.75-15.9-222.74
|
||||
c32.11,126.08-28.75,489.29,30.52,197.35c28.79,98.72-65.28,261.35,58.73,108.86c-37.19,187.32,36.13-32.28,47.76-103.08
|
||||
c8.96,94.67-2.01-42.55,6.66-79.88c30.75,97.92,53.06,199.4-5.06,292.92C737.6,336.4,694.28,5.48,752.2,275.59
|
||||
c12.58,35.83-30.59,24.88-39.09,50.66c61.29-24.55,38.95-35.44,52.83,53.39c0.4,3.52-0.24,7.19-4.7,7.28
|
||||
c-25.86,1.03-45.18,18.23-57.25,38.9c13.43-3.39,50.98-46.17,61.23-33.44c-21.97,29.52-78.97,40.99-72.67,90.22
|
||||
c3.55-15.72,78.25-89.59,75.21-54.58c-1.37,4.97-0.6,13.02-7.63,13.72c-61.1,2.32-80.25,119.34-40.63,125.28
|
||||
c-13.21-11.3-15.2-27.18-9.08-34.25c7.41-8.57,27.36-4.95,29.07,0.51c0.78,2.5-2.15,5.13-0.96,7.46c0.58,1.13,2.72,1.77,8.48,1.56
|
||||
c38.89-7.77,7.11,28.36-12.62,33.66c17.65,7.15,41.53-6.09,43.26-25.21c-13.61-10.4-3.01-29.64,12.23-22.19
|
||||
c39.17-39.2-23.35-78.46-17.83-98.65c2.53-4.97,11.94-9.86,47.83-3.67c17.2,5.95,27.38,81.41,34.69,33.83
|
||||
c26.79,65.65,1.08,95.95-22.65,157.49c-19.8,84.29-61.4,159.4-148.77,185.06c-117.87,55.02-132.92,97.58-258.09,25.2
|
||||
c46.48,32.06,76.67,55,136.6,42.95c-16.18,37.26-58.98,60.98-65.42,102.39c20.1-25.76,40.19-51.51,60.29-77.27
|
||||
c-8.67,85.19,10.27,58.11-48.65,125.91c90.48-25.72,17.5-180.83,122.56-177.14c18.96,52.7-4.18,120.02,8.63,173.54
|
||||
c2.68-39.19,12.24-88.12,46.19-106.21c456.17,81.79,348.93-736.88,256.65-896.72c22.97,42.24,68.59,278.45,36,201.55
|
||||
c-3.91-9.81-16.93-10.42-12.04,2.06c-3.92,64.31,14.29,179.15-11.75,192.94z M348.31,563.23c5.68,9.7,20.47-3.9,12.83-8.26c-3.76-6.73-7.6-13.49-12.17-19.69
|
||||
c-8.79-11.93,9.75-6.48,8.3-13.53c21.55,9.97,28.08,14.2,46.14-5.3c-0.61,18.31-0.16,38.03-18.36,50.23
|
||||
c18.72,10.53,30.46-6.95,33.62-24.89c-25.93,2.12,1.38-48.33,8.9-22.45c7.53-11.49,6.87-26.71,9.65-39.21
|
||||
C420.8,350.18,268.58,459.17,348.31,563.23z M517.13,804.37c-10.18-5.07-29.37-7.14-13.37-22.49
|
||||
c18.15-20.96,102.96-23.38,73.03,12.59c29.3-17.57-7.7-35.22-30.46-31.69C518.69,758.1,459.7,799.43,517.13,804.37z
|
||||
N
|
||||
M106.8,0c-3.3,4.6-6.3,9.4-8.8,14.5c-2.8-5-5.7-9.8-8.8-14.5C52.9,32.5,56.8,74.2,98,99.6c0,0,0,0,0,0c0,0,0,0,0,0C139.5,74,142.9,32.2,106.8,0z M5.4,60.7c3.7,4.5,7.4,8.8,11,12.8c-5.4,1-10.9,2.3-16.5,3.9 c19.6,44.6,60.5,53.8,97.4,22.5c0,0,0,0,0,0c0,0,0,0,0,0C85.9,52.4,47.2,36.3,5.4,60.7z M31.2,174.9c5.3-1.5,10.5-3.8,15.6-6.6c-0.8,5.7-1.2,11.3-1.4,16.8c48.5-4.9,69.9-40.9,51.5-85.7c0,0,0,0-0.1,0c0,0,0,0,0,0C48.2,95.8,20.9,127.6,31.2,174.9zM148.3,186.1c-0.4-5.5-0.9-11.1-1.4-16.8c5.1,2.4,10.3,4.6,15.6,6.6c10.4-47.6-17.3-79.1-65.6-75.5c0,0,0,0,0,0c0,0-0.1,0-0.1,0C78.3,145.5,100.1,181.3,148.3,186.1z M195.1,76.9c-5.9-1.5-11.5-2.9-16.5-3.9c3.9-4,7.6-8.3,11-12.8c-42.1-24.6-80.6-8-92.1,39.1c0,0,0,0,0,0c0,0,0,0,0,0C134.9,130.9,175.6,121.2,195.1,76.9z
|
||||
N
|
||||
M35.2,14.9c-2.4,0-4.8,1-6.5,2.7c-1.7-1.7-4.1-2.7-6.5-2.7c-5.6,0.2-10,5-9.8,10.6c0,9.7,13.1,17.8,14.6,18.6c1,0.6,2.3,0.6,3.3,0C31.8,43.2,45,35.2,45,25.5C45.2,19.8,40.8,15.1,35.2,14.9z
|
||||
N
|
||||
M140 20C73 20 20 74 20 140c0 135 136 170 228 303 c88-132 229-173 229-303 c0-66-54-120-120-120c-48 0-90 28-109 69c-19-41-60-69-108-69z
|
||||
N
|
||||
M96,2.86c-2.05,4.41-4.22,9.48-6.33,15.17
|
||||
c-1.08,2.92-3,8.28-4.95,15.1c-3.16,11.03-4.62,19.6-5.81,26.71c-2.49,14.88-3.28,26.75-3.45,30.36c-0.02,0.43-0.08,1.78-0.2,3.64
|
||||
c-0.36,5.44-0.87,9.65-1.16,11.83c0,0-0.56,4.27-1.3,8.34c-0.19,1.07-0.4,2.13-0.4,2.13c-0.02,0.09-0.03,0.16-0.03,0.17
|
||||
c-0.05,0.25-5.9,30.37-5.91,40.92c0,0.85,0.03,3.62-1.34,4.24c-0.46,0.21-0.96,0.13-1.34,0.01c-7.07,0.06-12.87,0.76-16.99,1.42
|
||||
c0,0-13,2.1-30.7,9.21c-3.62,1.46-7.03,3-7.34,3.14c-2.48,1.13-4.67,2.19-6.52,3.12c1.83-0.17,4-0.52,6.39-1.21
|
||||
c1.84-0.53,3.45-1.16,4.82-1.78c0,0,10.45-3.6,19.4-5.26c5.58-1.03,6.34-0.55,17.45-1.7c6.41-0.66,11.59-1.36,14.88-1.84
|
||||
c7.74-1.12,10.4-0.32,11,1.04c0.13,0.29,0.13,0.55,0.11,0.94c-0.24,5.58-3.01,9.41-2.26,13.44c0.04,0.22,0.07,0.33,0.33,1.59
|
||||
c0.13,0.62,0.56,2.75,0.85,4.34c0.4,2.22,0.41,2.72,0.72,4.65c0.6,3.67,0.9,5.5,1.48,6.82c1.14,2.59,2.86,4.11,4.88,5.88
|
||||
c2.01,1.76,3.74,2.73,6.91,4.49c2.61,1.45,4.85,2.52,6.44,3.23z
|
||||
N
|
||||
M12.43,1.78c0.4,0.5,0.94,1.28,1.36,2.32
|
||||
c0.67,1.66,0.67,3.07,0.67,4.45c0,0.92,0.04,4.84,0,6.15c-0.19,6.59,0.61,7.24,0,11.71c-0.34,2.51-0.83,4.02-1.19,4.96
|
||||
c-0.18,0.48-0.94,2.43-2.52,4.74c-0.44,0.64-1.1,1.54-3.04,3.63c-3.35,3.61-5.27,4.39-5.19,5.19c0.13,1.28,5.07,2.54,25.78,2.55z
|
||||
N
|
||||
M105,654.21c-7.27-2.1-16.75-4.87-27.83-8.17
|
||||
c-40.23-11.98-49.04-15.35-58.28-22.6c-5.71-4.47-14.05-12.37-21.32-25.91C2.14,588.3,8.74,575.32,17.11,560
|
||||
c13.51-24.74,22.16-40.57,35.49-58.91c7.85-10.79,19.4-25.32,35.36-41.18c0.72-5.12,1.23-9.06,1.53-11.49
|
||||
c0.57-4.57,0.8-6.77,2.34-9.27c1.46-2.37,3.38-3.84,4.75-4.7c0.63-143.54,1.26-287.08,1.89-430.62z
|
||||
N
|
||||
M204.68,0.14c-1.76,0.11-4.62,0.27-8.17,0.38
|
||||
c-6.7,0.21-8.06-0.01-10.6,0.77c-3.92,1.2-3.97,2.71-8.07,4.59c-2.36,1.08-3.84,1.26-12.22,2.17c-5.45,0.59-10.87,1.53-16.34,1.91
|
||||
c-5.84,0.41-9.63,0.36-12,3.2c-1.04,1.25-1.47,2.63-1.66,3.56c-3.32,18.64-2.48,32.37-1.02,41.62c0.57,3.57,3.63,21.7,0.89,34.76
|
||||
c-0.17,0.79-0.64,2.93-1.15,5.97c-0.28,1.67-1.58,9.69-1.66,17.62c-0.05,5.4,1.24,12.84,3.83,27.7c0.5,2.88,1.27,7.13,2.17,13.28
|
||||
c0.59,4.02,1.01,7.31,1.28,9.45c-0.52,3.62-0.43,6.53-0.26,8.55c0.29,3.26,0.86,4.56,0.13,6.77c-0.77,2.31-1.92,2.45-2.43,4.85
|
||||
c-0.48,2.29,0.42,2.86-0.15,4.95c-0.41,1.49-1.13,2.2-2.79,4.24c-1.48,1.82-2.74,3.8-4.21,5.62c-4.31,5.35-8.49,10.81-12.89,16.09
|
||||
c-5.78,6.93-6.86,8.58-17.49,21.96c-18.52,23.3-21.63,26.32-32.55,40.21c-24.98,31.79-37.81,53.07-40.72,57.96
|
||||
c0,0-7.82,13.11-17.62,36.64c-2.39,5.73-5.45,13.54-6.38,24.13c-0.58,6.56-0.34,12.62,0,12.64c0.41,0.02,0.43-8.67,2.7-18.95
|
||||
c1.86-8.39,4.48-14.51,8.17-22.47c8.35-18.03,12.53-27.04,19.74-39.15c9.69-16.26,19.31-28.61,38.55-53.32
|
||||
c5.65-7.26,4.63-5.77,17.11-21.45c13.19-16.57,27.11-32.56,39.85-49.48c0.35-0.47,1.41-1.88,3.13-3.42c0,0,2.37-2.12,5.36-3.58
|
||||
c6.09-2.99,20.05-2.23,25.95-2c7.4,0.28,14.81-0.1,22.22-0.1c8.52,0,15.39-0.01,19.63-0.01z
|
||||
N
|
||||
M0.94,0.6c2.08,18.15,2.97,32.18,3.39,41.88
|
||||
c0,0,0.86,19.42,2.87,34.97c1.76,13.6,2.61,14.56,5.45,32.49c1.14,7.2,1.2,8.27,5.73,44.13c3.64,28.81,4.03,31.51,4.32,38.54
|
||||
c0.2,4.94,0.57,17.17-0.63,32.88c-0.89,11.66-2.25,19.73-3,24.73c-3.72,24.69-3.65,45.64-3.59,66.15
|
||||
c0.04,13.85,0.17,33.71,3.42,59.26c2.56,20.15,6,35.46,6.44,62.42c0.01,0.88,0.13,1.85,0.2,3.47c0.31,6.41-0.11,11.45-0.35,14.17
|
||||
c-3.35,37.28-5.52,47.52-5.52,47.52c-1.06,4.71-2.95,10.98-0.08,13.41c1.1,0.94,2.42,0.94,9.8,0.98c3.87,0.02,7.02,0.04,8.28,0.05z
|
||||
N
|
||||
M9.22,0C6.92,4.49,4,11.35,2.55,20.09
|
||||
c-1.21,7.29-0.82,12.5-0.33,20.94C3.3,59.23,3.79,73.41,3.9,76.76c0.65,20.48-0.9,19.3,0.05,35.96c0.7,12.33,2.2,24.62,2.98,30.95
|
||||
c1.78,14.5,2.82,18.69,2.45,27.6c-0.42,10.1-1.94,8.9-2.49,20.33c-0.54,11.15,0.83,13.91,0.19,27.57c-0.35,7.5-0.78,6.96-0.98,13.91
|
||||
c-0.12,4.35-0.01,6.38,0.61,21.61c0.24,5.92,0.64,10.99,0.78,17.78c0.12,6.38,0.06,11.89,0.02,14.77
|
||||
c-0.07,5.78-0.11,8.68-0.27,11.31c-0.96,16.14-5.06,22.75-1.69,25.57c0.93,0.78,1.57,0.55,8.39,0.78c4.83,0.16,8.78,0.42,11.44,0.61z
|
||||
N
|
||||
@@ -0,0 +1,25 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
import math
|
||||
mat = cv2.imread('starburst.png')
|
||||
mat2 = np.zeros((900, 1273, 3))
|
||||
print(mat.shape)
|
||||
rad = 0
|
||||
for i in range(0, 900):
|
||||
dt = 0
|
||||
s = math.sin(rad)
|
||||
c = math.cos(rad)
|
||||
for j in range(0, 1273):
|
||||
# if(dt*c > 913 or dt*c < -913 or dt * s > 900 or dt*s < -900):
|
||||
# break
|
||||
x = 900+int(dt*s)
|
||||
x = x if x < 1800 else 1799
|
||||
y = 913+int(dt*c)
|
||||
y = y if y < 1826 else 1799
|
||||
|
||||
mat2[i][j] = mat[900+int(dt*s)][913+int(dt*c)]
|
||||
dt += 1
|
||||
rad += .007
|
||||
cv2.imwrite('starburst3.png',mat2)
|
||||
cv2.imshow('a', mat2)
|
||||
cv2.waitKey(0)
|
||||
@@ -0,0 +1,263 @@
|
||||
|
||||
#ifndef _NDEBUG
|
||||
precision highp float;
|
||||
const int ns = 5;
|
||||
const int cns = 5;
|
||||
float noise(vec3 v){return 1.;}
|
||||
#endif
|
||||
#define _DEBUG_BREAK {gl_FragColor=vec4(1,0,0,1); return;}
|
||||
#define REFRACTION (c2 >= 0.? (eta*W + (eta*c1 - sqrt(c2))*N) : ((W + c1*N)/sqrt(1.-c1*c1)))
|
||||
vec3 foregroundColor = vec3(.0841, .5329, .9604);
|
||||
vec3 groundColor = vec3(.2, .3, .5);
|
||||
vec4 groundSpecular = vec4(.71, .71, .71, 10.);
|
||||
uniform float uTime;// TIME, IN SECONDS
|
||||
uniform vec3 Ambient[ns], Diffuse[ns];
|
||||
uniform vec4 Specular[ns];
|
||||
uniform vec3 Glow[ns];
|
||||
uniform float ks[ns], kr[ns], kf[ns];
|
||||
uniform vec4 Sph[ns];
|
||||
uniform sampler2D uSampler[ns+2];
|
||||
uniform vec3 V0;
|
||||
uniform int sel;
|
||||
const float kf_air = 1.000293;
|
||||
varying vec3 trPos;
|
||||
varying vec3 texPos;
|
||||
const float pi=3.14159265359;
|
||||
const float _2pi=2.*pi;
|
||||
|
||||
/***********PLEASE DO INCREASE n_ref(RT DEPTH) FOR BETTER RESULTS************/
|
||||
/*---->*/const int n_ref=15; //2^n-1 because each hit now spawn at most 2 rays.
|
||||
//const int _n_swap = 3; //cosntexpr log(n_ref + 1)
|
||||
/**BUT BE CAUTIOUS IF YOU DON'T HAVE A DECENT GRAPHICS CARD (below GTX 950M)**/
|
||||
|
||||
const int max_stack = (n_ref+1)/4;
|
||||
vec3 scolor = vec3(0,0,0);
|
||||
struct Ray{
|
||||
vec3 V;
|
||||
vec3 W;
|
||||
float kf, cumulativeK, decay;
|
||||
} stack1[max_stack], stack2[max_stack];
|
||||
bool modulo2(int n){
|
||||
return n-2*(n/2) == 1;
|
||||
}
|
||||
vec2 getTextCoord(vec3 tex_sph, float R){
|
||||
float tex_x=atan(tex_sph.z,tex_sph.x)/_2pi + 0.5;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
|
||||
tex_x=fract(tex_x+uTime/20.);
|
||||
return vec2(tex_x,-asin(tex_sph.y/R)/pi + 0.5);
|
||||
}
|
||||
#define clamp1(x) ((x)<0.?1.+(x):((x) > 1. ? (x) - 1.:(x)))
|
||||
void main(){
|
||||
vec3 LDir=vec3(.5,.5,.5);
|
||||
vec3 LCol=vec3(1.,1.,1.);
|
||||
float currKf = kf_air;
|
||||
vec3 color=vec3(.2, .3, .5);
|
||||
vec3 V = V0;
|
||||
vec3 W=(trPos-V);
|
||||
const bool glassy = false;
|
||||
float glassyw = 1.;
|
||||
if(glassy)
|
||||
{
|
||||
vec2 noiseTex = (texPos.xy + 1.)/2.;
|
||||
noiseTex = vec2(clamp1(noiseTex.x ), clamp1(noiseTex.y ));
|
||||
vec4 Wnoise = texture2D(uSampler[ns], noiseTex);
|
||||
W += (Wnoise.xyz-.5)*.4;
|
||||
glassyw = Wnoise.w;
|
||||
}
|
||||
bool selected = false;
|
||||
float currentK = 1.;
|
||||
float curr_decay = 1.;
|
||||
int curr_ptr = 0, curr_top = 0, next_top = 0;
|
||||
bool final = false, stackswap = false, stop = false;
|
||||
for(int j=0;j<n_ref;j++)
|
||||
{
|
||||
for(int curr = 0; curr < max_stack; ++curr){
|
||||
if(curr == curr_ptr){
|
||||
bool skip = false;
|
||||
if(j > 0){
|
||||
Ray currR;
|
||||
if(stackswap)
|
||||
currR = stack1[curr];
|
||||
else
|
||||
currR = stack2[curr];
|
||||
currKf = currR.kf;
|
||||
currentK = currR.cumulativeK;
|
||||
curr_decay = currR.decay;
|
||||
if(currKf <= 0.001 || currentK <= 0.001)
|
||||
skip = true;
|
||||
V = currR.V;
|
||||
W = currR.W;
|
||||
}
|
||||
else
|
||||
W = normalize(W);
|
||||
if(!skip){
|
||||
float tMin=10000.;
|
||||
int iMin = -1;
|
||||
for(int i=0;i<cns;i++){
|
||||
vec3 Vp=V-Sph[i].xyz;
|
||||
float B=dot(W,Vp);
|
||||
float C=dot(Vp,Vp)-Sph[i].w*Sph[i].w;
|
||||
float D=B*B-C;
|
||||
if(D>0.){
|
||||
float t=-B-sqrt(D);
|
||||
if(t >= 0.01 && t < tMin){
|
||||
tMin = t; // This is an optimization, we don't have to do lighting/tex
|
||||
iMin = i; // for objects that are occuluded, which is expensive!
|
||||
}
|
||||
else if (t >= -0.01 && t <0.01){
|
||||
t = -(t + 2.*B);
|
||||
if(t > 0.01 && t < tMin){
|
||||
tMin = t;
|
||||
iMin = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(iMin >= 0){
|
||||
if(j == 0 && iMin == sel)
|
||||
selected = true;
|
||||
vec3 S=V+tMin*W;
|
||||
if(curr_decay > .01)
|
||||
curr_decay = curr_decay/(1.+tMin*tMin);
|
||||
for(int i = 0; i < cns; ++ i)
|
||||
if(i == iMin)
|
||||
{
|
||||
vec3 texture_color;
|
||||
vec3 tex_sph = (S-Sph[i].xyz);
|
||||
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
|
||||
|
||||
vec3 N=normalize(S-Sph[i].xyz);
|
||||
vec3 realLDir=normalize(LDir-S);
|
||||
float c1 =dot(N, W);
|
||||
float eta, nextkf;
|
||||
if(c1<0.){
|
||||
color=(Ambient[i]+Diffuse[i]*max(0.,dot(N,realLDir))*LCol)*texture_color;
|
||||
if(final) //if it's the last hit
|
||||
{
|
||||
color += Specular[i].xyz*pow(max(0.,
|
||||
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
|
||||
if(curr_decay > .01 && Glow[i].x > .01)
|
||||
scolor += currentK*curr_decay*Glow[i];
|
||||
scolor += color * currentK;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
c1 = -c1;
|
||||
eta = currKf/kf[i];
|
||||
nextkf = kf[i];
|
||||
}
|
||||
}
|
||||
else{
|
||||
N = -N;
|
||||
eta = currKf/kf_air;
|
||||
nextkf = kf_air;
|
||||
color = Ambient[i];
|
||||
}
|
||||
float c2 = (1.-eta*eta*(1.-c1*c1));
|
||||
float nextks = currentK * ks[i], nextkr = currentK * kr[i];
|
||||
bool refl = nextks > 0.01, refr = nextkr > 0.01;
|
||||
if(refl || refr)
|
||||
for(int k = 0; k < max_stack; ++k)
|
||||
if(k == next_top){
|
||||
if(stackswap){
|
||||
if(refl)
|
||||
{
|
||||
stack2[k] = Ray(S, 2. * c1 * N + W, currKf, nextks, curr_decay); //reflection
|
||||
currentK -= nextks;
|
||||
next_top ++;
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
if(refl)
|
||||
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
else
|
||||
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
currentK -= nextkr;
|
||||
next_top ++;
|
||||
}
|
||||
}else{
|
||||
if(refl)
|
||||
{ //remember, c1 = -NW now
|
||||
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks, curr_decay); //reflection
|
||||
currentK -= nextks;
|
||||
next_top ++;
|
||||
}
|
||||
if(refr)
|
||||
{
|
||||
if(refl)
|
||||
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
else
|
||||
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr, curr_decay); //refraction
|
||||
currentK -= nextkr;
|
||||
next_top ++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
scolor += color * currentK;
|
||||
if(curr_decay > .01 && Glow[i].x > .01)
|
||||
scolor += currentK*curr_decay*Glow[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float t = -(.2+V.y)/W.y;
|
||||
float sx = V.x + t* W.x, sz = V.z + t * W.z;
|
||||
|
||||
if(t >= 0. && abs(sx) < 1.5 && abs(sz) < 3.)
|
||||
{
|
||||
if(curr_decay > .01)
|
||||
curr_decay = curr_decay/(1.+t*t);
|
||||
vec3 S = vec3(sx, -.2, sz);
|
||||
vec3 realLDir=normalize(LDir - S);
|
||||
color=(0.5+0.5*max(0.,realLDir.y)*LCol)*texture2D(uSampler[4],vec2((sx+1.4)/3., (sz+1.5)/4.)).xyz;
|
||||
if(final&&abs(sx)<1.5 && abs(sz+.6)<3.)
|
||||
{
|
||||
color += groundSpecular.xyz* //specular for ground.
|
||||
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
|
||||
scolor += currentK * color;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int k = 0; k < max_stack; ++k)
|
||||
if(k == next_top){
|
||||
if(stackswap)
|
||||
stack2[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15, curr_decay); //reflection
|
||||
else
|
||||
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15, curr_decay); //reflection
|
||||
next_top ++;
|
||||
break;
|
||||
}
|
||||
scolor += (currentK*.85)*color;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(j > 0)
|
||||
scolor += currentK * (pow(max(0.,dot(W, normalize(LDir - V))), 10.) * vec3(3.,3.,3.) + foregroundColor*0.1);
|
||||
else scolor = foregroundColor*0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(++curr_ptr >= curr_top){
|
||||
if(next_top <= 0)
|
||||
stop = true;
|
||||
if(next_top * 2 > max_stack)
|
||||
final = true;
|
||||
curr_top = next_top;
|
||||
next_top = 0;
|
||||
curr_ptr = 0;
|
||||
stackswap = !stackswap;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(stop)
|
||||
break;
|
||||
}
|
||||
if(selected)
|
||||
scolor.x += 0.5;
|
||||
|
||||
if(glassy)
|
||||
scolor *= glassyw*glassyw;
|
||||
gl_FragColor=vec4(sqrt(scolor),1.);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
vec3 foregroundColor = vec3(.0841, .5329, .9604);
|
||||
uniform vec3 starColors[10];
|
||||
uniform vec3 V0;
|
||||
uniform sampler2D uSampler[ns + 1]; //ns + vs
|
||||
varying vec3 norm;
|
||||
varying float id;
|
||||
varying vec3 glpos;
|
||||
varying vec3 texPos;
|
||||
vec3 LDir=vec3(.5,.5,.5);
|
||||
void main(){
|
||||
vec3 color =foregroundColor.xyz;
|
||||
float sp = 0.4, df = 0.4, amb = 0.4, ex=5., alpha = 1.;
|
||||
vec3 l = vec3(1,1,1);
|
||||
float alp = 2.*abs(.49999 - fract(id+.00001));
|
||||
if(id < -2.5){gl_FragColor = vec4(texture2D(uSampler[ns + 0], (1.+texPos.xy)/2.).xyz, 1.); return;} //pjsk
|
||||
else if(id <-1.5) {color = vec3(.05,.05,.05);sp = 1.; df=.4; amb = .3, ex = 5.;}
|
||||
else if(id <-.5) {color = vec3(0.,1.,0.2034);}
|
||||
else if(id < 1.5) {color = vec3(1.0000, 0.3570, 0.3570);sp = 1.; df=.2; amb = .7, ex = 20.;}
|
||||
else if (id < 2.5) color = vec3(1.,.16,.36);
|
||||
else if (id < 3.5) {color = vec3(1.0000, 0.7725, 0.7725);sp = .5; df=.8; amb = .05;}
|
||||
else if (id < 4.5) {color = vec3(0.9612,0.3057,0.3369);sp = .5; df=.5; amb = .5; ex=20.;}
|
||||
else if (id < 6.5) {}
|
||||
else if (id < 7.5) {color = starColors[0]; sp = 0.3, df = 0.3, amb = 0.8, ex=5.;}
|
||||
else if (id < 8.5) {color = starColors[1]; sp = 0.05, df = 0.1, amb = 0.8, ex=10.,l = color;alp*=1.1;}
|
||||
else if (id < 9.5) {color = starColors[2]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 10.5) {color = starColors[3]; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 12.5) {color = starColors[4]; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 13.5) {color = starColors[4]*2.; sp = 0., df = 0., amb = 1., ex=10.,l = color;}
|
||||
else if (id < 14.5) {
|
||||
color = .4*foregroundColor + .8*starColors[4]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;
|
||||
if(texPos.y > .3)
|
||||
color = vec3(1.,1.,1.);
|
||||
}
|
||||
else if (id < 15.5) {color = .3*vec3(0.9612,0.3057,0.3369)+.8*starColors[4]; sp = 0.5, df = 0.5, amb = 0.8, ex=10.,l = color;}
|
||||
else if (id < 16.5) {gl_FragColor=vec4(1.,1.,1., alp);return;}
|
||||
else if (id < 17.5) {color = vec3(.35,.35,.35);sp = .3; df=.6; amb = .1, ex = 1.;}
|
||||
else if (id < 18.5) {
|
||||
color = vec3(.6,.29,.12);sp = .1; df=.2; amb = .7, ex = 1.;
|
||||
vec3 P = vec3(sin(texPos.y*1.), sin(texPos.x*1.5+1.), cos(texPos.z*1.));
|
||||
// APPLY PROCEDURAL NOISE TEXTURE.
|
||||
float cloud = min(0.99, max(0., 1. * noise(.8 * P)));
|
||||
color = (1.-cloud)*color + starColors[5] * cloud*3.;
|
||||
}
|
||||
|
||||
if(id < 0. &&id > -1.5){
|
||||
vec3 P = vec3(sin(glpos.y*1.), sin(glpos.x*1.5+1.), cos(glpos.z*1.));
|
||||
// APPLY PROCEDURAL NOISE TEXTURE.
|
||||
float cloud = min(0.99, max(0., 1. * noise(1. * P)));
|
||||
color = (1.-cloud)*color + starColors[5] * cloud*3.;
|
||||
}
|
||||
vec3 V = V0;
|
||||
vec3 W=normalize(glpos-V);
|
||||
vec3 realLDir=normalize(LDir - glpos);
|
||||
|
||||
color = color*(amb+ df*max(0.,dot(norm,realLDir)))
|
||||
+ sp*pow(max(0., dot(2.*dot(norm, realLDir)*norm-realLDir, -W)),ex)*l;
|
||||
gl_FragColor=vec4(sqrt(color), alp);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
uniform mat4 uMatrix;
|
||||
uniform mat4 invMatrix;
|
||||
uniform mat3 transformation;
|
||||
attribute float oid;
|
||||
attribute vec3 aPos;
|
||||
attribute vec3 normal;
|
||||
varying float id;
|
||||
varying vec3 glpos;
|
||||
varying vec3 norm;
|
||||
varying vec3 texPos;
|
||||
void main() {
|
||||
vec4 pos = uMatrix * vec4(aPos, 1.);
|
||||
texPos = aPos;
|
||||
gl_Position = pos ;
|
||||
glpos = pos.xyz;
|
||||
id = oid;
|
||||
norm = normalize(vec4(normal,0.)*invMatrix).xyz;
|
||||
}
|
||||
|
After Width: | Height: | Size: 734 KiB |