Reset Repo structure.

master
Bill 4 years ago
commit 4c104a8c26

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

@ -0,0 +1,360 @@
<script src=lib1.js></script>
<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>
<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>
<body bgcolor=white text=black link=black alink=blue vlink=blue>
<center>
<canvas id='canvas1' width=600 height=600></canvas>
</center>
</body>
<!!-------- VERTEX SHADER: YOU PROBABLY DON'T WANT TO CHANGE THIS RIGHT NOW -------->
<script id='my_vertex_shader' type='x-shader/x-vertex'>
attribute vec3 aPos;
varying vec3 vPos;
void main() {
gl_Position = vec4(aPos, 1.);
vPos = aPos;
}
</script>
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
<script id='my_fragment_shader' type='x-shader/x-fragment'>
uniform float uTime; // TIME, IN SECONDS
uniform int flags;
varying vec3 vPos; // -1 < vPos.x < +1
// -1 < vPos.y < +1
// vPos.z == 0
uniform sampler2D uSampler;
// YOU MUST DEFINE A main() FUNCTION.
void main() {
////////////////////////////////////////////////
//
// HERE, FOR YOUR HOMEWORK, YOU CAN WRITE ANY
// CODE YOU LIKE
//DEFINE A COLOR FOR THIS FRAGMENT.
// LIGHT DIRECTION AND COLOR
vec3 LDir = vec3(1, 1, 1);
vec3 LCol = vec3(1.,.98,.9);
vec3 VDir = vec3(0., 0., 1.);
float R = 0.5 + 0.3*sin(uTime/10.);
// vPos IS THE 3D LOCATION OF THIS FRAGMENT.
// SURFACE REFLECTANCE PROPERTIES
vec3 diffuse = vec3(.7,.7,.6);
vec3 ambient = vec3(.1,.1,.09);
vec3 specular = vec3(.35,.35,.3);
// CREATE A WACKY BACKGROUND PATTERN.
vec3 color = vec3(.5 + .5 * sin(20. * vPos.x + sin(10. * vPos.y + 5. * uTime)),
.5,
.5 + .5 * sin(20. * vPos.y + sin(10. * vPos.x + 5. * uTime)));
vec3 specularlight; //specular light should disregard object color.
float x = vPos.x;
float y = vPos.y;
// CREATE BOUNCING ANIMATION.
y += .5 - 2. * abs(.5 * sin(uTime));
// FIGURE OUT WHETHER THIS PIXEL IS ON THE SPHERE.
float rr = x * x + y * y;
// IF SO, THEN SHADE THE SPHERE.
if (rr < R*R) {
// COMPUTE THE z AND NORMAL OF THE SPHERE.
float z = R * sqrt(1. - rr/(R*R));
vec3 N = vec3(x,y,z) / R;
// APPLY SHADING AND LIGHTING.
vec3 realVPos = vec3(vPos.x, vPos.y, z);
//*DIRECTIONS ARE NORMALIZED TO GET THE CORRECT PHONG LIGHTING
LDir = normalize(LDir - realVPos);
VDir = normalize(VDir - realVPos);
vec3 lcolor = ambient;
lcolor += diffuse * max(0., dot(N, LDir)) * LCol;
//*SPECULAR LIGHTS ARE ADDED
specularlight = specular *
pow(max(0.,dot(2.*dot(N, LDir) * N - LDir, VDir)),3.) * LCol;
// ROTATE THE TEXTURE OVER TIME.
float angle = 0.4 * uTime;
float px = cos(angle) * N.x + sin(angle) * N.z;
float pz = -sin(angle) * N.x + cos(angle) * N.z;
vec3 P = vec3(px, N.y, pz);
// APPLY PROCEDURAL NOISE TEXTURE.
float cloud = min(0.85, max(-0.05, 2. * noise(1.1 * P)));
//const float rspeed = 10.;
//*CALCULATING THE TEXTURE COORDINATE.
const float pi = 3.14159265359;
float tex_x = acos(abs(x)/sqrt(R*R-y*y));
if(x > 0.)
tex_x = pi - tex_x;
tex_x = R * tex_x;
tex_x *= 1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x = tex_x + float(uTime)*R;
float _2pir = 2. * pi * R;
float quo = float(int(tex_x/_2pir));
tex_x = (tex_x - quo * _2pir) / _2pir;
//*TEXTURE MAPPING
vec3 texture_color;
if(flags /*& 0x1*/ == 0)
texture_color = texture2D(uSampler, vec2(tex_x, ((R - y)/(2.*R)))).xyz;
else
texture_color = vec3(.0841, .5329, .9604);
color = lcolor *
(cloud + texture_color) + specularlight;
}
//*CALCULATING LIGHTING AND SHADOWS FOR THE BACKGROUND
else{
vec3 realVPos = vec3(vPos.x, vPos.y, -1.);
vec3 N = vec3(0., 0., 1.);
vec3 C = vec3(0., vPos.y - y, 0.);
// APPLY SHADING AND LIGHTING.
vec3 lcolor = 6.*ambient;
//*CALCULATING DISTANCE BETWEEN SPHERE CENTER TO THE RAY
//BETWEEN THE POINT TO LIGHT SOURCE
vec3 LV = realVPos - LDir;
vec3 LC = C - LDir;
vec3 VC = C - realVPos;
float lLV = dot(LV, LV);
float lLC = dot(LC, LC);
float lVC = dot(VC, VC);
float RR = R*R;
float d_VCVL = -dot(VC, LV);
float dist = min(lLC, lVC);
if (d_VCVL > 0.)
dist = min(dist, lVC - d_VCVL*d_VCVL/lLV);
//*CALCULATE DISTANCE BETWEEN SPHERE CENTER TO THE RAY BETWEEN POINT TO CAMERA
vec3 EV = realVPos - VDir;
vec3 EC = C - VDir;
float lEV = dot(EV, EV);
float lEC = dot(EC, EC);
float d_VCVE = -dot(VC, EV);
float dist2 = min(lEC, lVC);
if (d_VCVE > 0.)
dist2 = min(dist2, lVC - d_VCVE*d_VCVE/lEV);
//*AMBIENT LIGHT WILL DECAY WHEN BACKGROUND POINT IS CLOSER TO THE SPHERE
//*FIRST THE DISTANCE IS NORMALIZED, THEN I CURVED IT WITH LOGISTIC FUNCTION
float aratio0 = 1./(1.+pow(2.71828,15.*(.2-(sqrt(lVC) - R - .4806)/1.381)));
lcolor *= aratio0;
diffuse *= pow(aratio0, 0.3);
//*TEST IF CAMERA CAN SEE THE POINT
if(dist2 < RR)
{
specular *= 0.;
float d = sqrt(dist2);
float ratio = pow(2., sqrt(dist2)/R) - 1.;
diffuse *= ratio;
}
//*TEST IF THE LIGHT CAN REACH THE BACKGROUND POINT DIRECTLY
if(dist < RR)
{
specular *= 0.;
float ratio = pow(2.7, sqrt(dist)/R) - 1.7;
float aratio = pow(2., sqrt(dist)/R) - 1.;
if(ratio < 0.)
ratio = 0.;
diffuse *= ratio;
lcolor *= aratio;
}
LDir = normalize(LDir - realVPos);
VDir = normalize(VDir - realVPos);
lcolor += 1.2*diffuse * max(0., dot(N, LDir)) * LCol;
specularlight = 0.3*specular *
pow(max(0., dot(2.*dot(N, LDir) * N - LDir, VDir)),32.) * LCol;
color = color * lcolor + specularlight;
}
// APPLY GAMMA CORRECTION AND SET THE PIXEL COLOR.
gl_FragColor = vec4(sqrt(color), 1.0);
}
</script>
<!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW -------->
<script id='my_title' type='text/html'>
The Bouncing Earth
</script>
<!!-------- HERE IS WHERE YOU CAN PROVIDE A LONGER TEXT DESCRIPTION -------->
<script id='my_instructions' type='text/html'><font color=#909090>
<p style="font-size:30px; ">This is a description
of my cool homework
that you are seeing now.</p>
<p>
<i style="font-size:25px;">Here is how it works:</i>
<ul>
<li>First, I added <a href="http://planetpixelemporium.com/download/download.php?earthmap1k.jpg">texture</a> to the sphere. The code to load the texture is from
<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">here</a>. Please wait a sec for the texture to download.</li>
<li>Then, I mapped the 3D sphere surface to the rectangular 2D texture picture. </li>
<li>I also make it look like it's rotating by adding uTime to the offset of the texture and reset the offset to 0 whenever it exceeds
the width of the texture.</li>
<li>I used Perlin Noise to generate fake clouds.</li>
<li> I modified the lighting so that the light source won't move with the sphere and
the lighting will change when the sphere moves. I also added specular lights to make it shinier.</li>
<li> I tried to add some 'soft shadow' to it. I used a mix of methods inspired by Ambient Occlusion and Ray Tracing.<br>
<ul>
<li>The Ambient lights and diffusion lights are reduced with respect to the distance between the background point and the sphere.</li>
<li>The specular light of the background wall is eliminated and the diffusion factor is reduced when the ray shooting from the background point
towards the light source or from the background point towards the camera position intersect with the sphere.</li>
</ul>
<li>I added basic interactions such as press ctrl + 't' key to hide/show texture, click on the above canvas to pause/unpause animations.
Just a proof of concept.</li>
<li>Finally, I made some small changes like changing R over time and refined the UI a little bit. I used
<a href="https://ace.c9.io">Ace</a> for code highlighting and autocompletion on the edit panel.</li>
<li>Comments begin with '//*' are added by me.</li>
<li>Repo on <a href="https://github.com/sunyinqi0508/graphics_hw1">Github</a>.</li>
</li>
</ul>
<p>
</script>
<!!-------- YOU PROBABLY DON'T WANT TO CHANGE ANYTHING BELOW FOR NOW -------->
<script>
// CREATE THE HTML DOCUMENT
let flags = 0x0;
let vs = my_vertex_shader.innerHTML,
fs = my_fragment_shader.innerHTML;
fs = fs.substring(1, fs.length);
document.body.innerHTML = [''
,'<font size=7 color=#909090>' + my_title.innerHTML
,'<TABLE cellspacing=0 cellpadding=0><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="width:800px;height:1780px;"></div>'
,'</td><td valign=top>' + document.body.innerHTML + '<div style=\'font-size:25px\'>' + my_instructions.innerHTML + '</div>' + '</td>'
,'</tr></table>'
,'</TR></TABLE>'
].join('');
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
let text = fs.split('\n'), cols = 0;
for (let i = 0 ; i < text.length ; i++)
cols = Math.max(cols, text[i].length);
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
editor.getSession().setValue(fs);
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
editor.session.on('change', function(delta) {
canvas1.setShaders(vs, editor.getSession().getValue());
});
let lastTime = Date.now();
let animating = true;
let ctrl = false;
canvas1.addEventListener('click',function(ev){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
});
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Control'))
{
ctrl = true;
}
else if(ctrl && e.code == 'KeyT')
{
mask = 0x1;
flags = flags&!mask | (!(flags&mask)*mask);
setUniform('1i', 'flags', flags);
}
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
{
ctrl = false;
}
});
// SET THE CURRENT TIME IN SECONDS BEFORE RENDERING EACH FRAME.
let startTime = Date.now();
function animate(gl) {
if(animating)
setUniform('1f', 'uTime', (Date.now() - startTime) / 1000);
else
setUniform('1f', 'uTime', (lastTime - startTime) / 1000);
}
// START EVERYTHING.
gl_start(canvas1, vs, fs);
</script>

@ -0,0 +1,175 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
let nfsh = fragmentShaderHeader.split('\n').length; // NUMBER OF LINES OF CODE IN fragmentShaderHeader
let isFirefox = navigator.userAgent.indexOf('Firefox') > 0; // IS THIS THE FIREFOX BROWSER?
let errorMsg = '';
//
// Initialize a texture and load an image.
// When the image finished loading copy it into the texture.
//
function loadTexture(gl, url) {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// Because images have to be downloaded over the internet
// they might take a moment until they are ready.
// Until then put a single pixel in the texture so we can
// use it immediately. When the image has finished downloading
// we'll update the texture with the contents of the image.
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;
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
width, height, border, srcFormat, srcType,
pixel);
const image = new Image();
image.onload = function () {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
srcFormat, srcType, image);
// WebGL1 has different requirements for power of 2 images
// vs non power of 2 images so check if the image is a
// power of 2 in both dimensions.
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
// Yes, it's a power of 2. Generate mips.
gl.generateMipmap(gl.TEXTURE_2D);
} else {
// No, it's not a power of 2. Turn off mips and set
// wrapping to clamp to edge
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;
return texture;
}
function isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
function gl_start(canvas, vertexShader, fragmentShader) { // START WEBGL RUNNING IN A CANVAS
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:
let 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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = '<br>';
// 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 + 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;
let texture = loadTexture(gl, './earthmap1k.jpg') //Texture loading.
// Tell WebGL we want to affect texture unit 0
gl.activeTexture(gl.TEXTURE0);
// Bind the texture to texture unit 0
gl.bindTexture(gl.TEXTURE_2D, texture);
// Tell the shader we bound the texture to texture unit 0
gl.uniform1i(gl.getUniformLocation(program, 'uSampler'), 0);
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);
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0);
}
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() { }
let gl;
function setUniform(type, name, a, b, c, d, e, f) {
let loc = gl.getUniformLocation(gl.program, name);
(gl['uniform' + type])(loc, a, b, c, d, e, f);
}

@ -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,4 @@
{
"python.pythonPath": "/usr/local/bin/python",
"svg.preview.background": "black"
}

@ -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,301 @@
let lerp = (a,b,t) => a + t * (b - a); // LINEAR INTERPOLATION
let N = 0; // GREATER N INCREASES "NERVOUSNESS" OF BIG OBJECT
// TIMING TABLE FOR THE ANIMATION SEQUENCE
let timing = [
[0, lerp(1,.5,N)],
[1.8, lerp(2.3,2.1,N)],
[lerp(2,2.5,N), 2.8],
[2.0, 3.2],
[3.4, 3.9],
[4.3, 5.0],
];
// EASE CURVE TO ACCELERATE FROM REST AND THEN DECELERATE TO REST
let sCurve = t => (3 - 2 * t) * t * t;
let jCurve = t => t*t*t*t;
let jCurve3 = t => t*t*t;
// EVALUATE THE TIMING OF ONE ANIMATION PARAMETER FOR THIS FRAME
let evalTiming = n => {
let t0 = timing[n][0];
let t1 = timing[n][1];
if (animationTime < t0)
return 0;
if (animationTime > t1)
return 1;
return sCurve((animationTime - t0) / (t1 - t0));
}
let bounce = t => Math.sin(Math.PI * t);
let wiggle = t => Math.sin(6 * Math.PI * t);
let trees = []
function add_tree(pos) {
trees.append(new Float32Array(pos))
createMesh(32,32,uvToCone,-1, 20);
}
class State {
constructor(idx = 0, step = 1) {
this.leg = true;
this.progress = 0;
this.rh = this.lh = .5 * pi;
this.lf = this.rf = 0;
this.running = 0;
this.direction_l = [0, 0];
this.dir_sdl = 0;
this.delta_l = [0, 0];
this.wiggle_t = 0;
this.punch_t = 1;
this.idx = idx;
if(rebuild[idx] === undefined)
rebuild.push(true);
states[this.idx] = this;
this.fig_rot_t = 0;
this.figure_rot = pi;
this.old_figure_rot = pi;
this.curr_figure_rot = pi;
this.target_figure_rot = pi;
this.delta_height = 0;
this.delta = const_multiply(step, [-.7*pi , 0.5 * pi, 0.44 * pi, 0.55 * pi]);
this.stepSize = step;
this.turnStep = .1;
this.stepLength = this.stepSize*(1.8522);
this.life = 3;
this.damage = .05;
this.dead = false;
this.death_t = 0;
this.hitID = 19;
}
reset(){
this.running = 0;
this.leg = true;
this.progress = 0;
this.delta_height = 0;
this.dir_sdl = 0;
this.rh = this.lh = .5 * pi;
this.lf = this.rf = 0;
this.dead = false;
this.wiggle_t = 0;
this.death_t = 0;
}
initialize() {
this.figure_rot = pi;
this.old_figure_rot = pi;
this.curr_figure_rot = pi;
this.target_figure_rot = pi;
this.reset();
this.wiggle_t = 0;
this.punch_t = 1;
this.fig_rot_t = 0;
this.direction_l = [0, 0];
this.delta_l = [0, 0];
this.life = 3;
this.delta_l = [0,0];
this.direction_l = [0, 0];
this.dir_sdl = 0;
}
set_stepSize(step){
this.delta = const_multiply(step, [-.7*pi , 0.5 * pi, 0.44 * pi, 0.55 * pi]);
this.stepSize = step;
this.stepLength = this.stepSize*(1.8522);
}
hitTest(punchProg){
states.forEach((st, i)=>{
if(i != this.idx){
//1.15=.5*.23*10; .92 = .4*.23*10 .23=figure_scale, 10=overall_scale
const armlength = 1.15*cos(punchProg*pi/4)+.92*cos(-.53*pi*punchProg)
let dir = normalize(this.direction_l);
let punchpos = plus(plus(this.delta_l,
const_multiply(.3, [dir[1],-dir[0]])),
const_multiply(armlength, dir));
if(vec_len(minus(punchpos, st.delta_l)) < .65){
st.hit(this);
}
}
});
}
start_punch(){
if(this.punch_t >= 1){
this.punch_t = 0;
rebuild[this.idx] = true;
}
}
punch(){
if(this.punch_t < 1)
{
rebuild[this.idx] = true;
this.punch_t+=.05;
if(this.punch_t <= .05)
return 1.2;
else
{
let punchProg;
if(this.punch_t <= .4)
punchProg = 1.2*(1-jCurve((this.punch_t- .05)/.35));
else
punchProg = 1-jCurve(2-2*(this.punch_t+.1)/1.1);
if(this.hitTest(punchProg))
this.punch_t = 1;
return punchProg;
}
}
return 1;
}
restoreID(st){
objects[st.idx].forEach(
(obj, i)=>{
changeID(st.orig_objid[i], obj[0]);
}
)
}
defaultHit(){
if(objects[this.idx][0][0][0] != this.hitID){
this.orig_objid = [];
objects[this.idx].forEach(
(obj, i) => {
this.orig_objid[i] = (obj[0])[0];
}
)
objects[this.idx].forEach(
(obj, i) => {
changeID(this.hitID, obj[0]);
}
)
setTimeout(this.restoreID, 100, this);
}
if(this.dead&&this.wiggle_t<=0){
rebuild[this.idx] = true;
this.wiggle_t = 2.5;
}
else if(this.life > 0)
{
this.life -= this.damage;
}
else {
this.death();
}
}
defaultDeath(){
this.dead = true;
this.death_t = 1;
rebuild[this.idx] = true;
}
hit(hitter){this.defaultHit(hitter);}
death() {if(!this.dead){this.defaultDeath();}}
animated_turn(){
if(this.target_figure_rot != this.figure_rot)
{
this.fig_rot_t = 1;
this.figure_rot %= 2*pi;
if(this.figure_rot < 0) this.figure_rot += 2*pi;
this.curr_figure_rot %= 2*pi;
if(this.curr_figure_rot < 0) this.curr_figure_rot += 2*pi;
if((this.curr_figure_rot - this.figure_rot) > pi)
this.curr_figure_rot -= 2*pi;
else if (this.curr_figure_rot - this.figure_rot < -pi)
this.figure_rot -= 2*pi;
this.old_figure_rot = this.curr_figure_rot;
this.target_figure_rot = this.figure_rot;
}
if(this.fig_rot_t > 0)
{
this.fig_rot_t-=this.turnStep;
this.curr_figure_rot = lerp(
this.old_figure_rot, this.figure_rot, sCurve(1-this.fig_rot_t));
}
}
turn(pt, animated = true){
this.direction_l = [pt[0] - this.delta_l[0]/10, pt[1] - this.delta_l[1]/10];
if(this.direction_l[1] == 0)
this.direction_l[1] = 0.0000000000000001;
this.figure_rot = atan(this.direction_l[0]/this.direction_l[1]);
if(this.direction_l[1] < 0)
this.figure_rot = pi + this.figure_rot;
if(!animated)
{
this.curr_figure_rot = this.target_figure_rot = this.figure_rot;
this.fig_rot_t = 0;
}
}
walk(){
this.dir_sdl = vec_len(this.direction_l)*10;
this.direction_l = normalize(this.direction_l);
rebuild[this.idx] = true;
this.running = 1;
}
next() {
//return this.presentation();
if (this.running <= 0)
{
this.reset();
return {
rh: .5 * pi,
lh: .5 * pi,
rf: 0,
lf: 0,
dh: 0,
dl: 0
}
}
this.running--;
const steps = 28;
let dl = 0;
if (this.progress >= steps / 2) {
this.progress = 0;
this.leg = !this.leg;
}
let delta = deepcopy(this.delta);
for (let i = 0; i < 4; ++i) delta[i] /= steps;
if (this.leg) {
if (this.progress < steps / 4) {
this.lh += delta[0];
this.rh += delta[3];
this.lf += delta[1];
this.rf += delta[2];
} else {
this.lh -= delta[0];
this.rh -= delta[3];
this.lf -= delta[1];
this.rf -= delta[2];
}
} else {
if (this.progress < steps / 4) {
this.lh += delta[3];
this.rh += delta[0];
this.lf += delta[2];
this.rf += delta[1];
} else {
this.lh -= delta[3];
this.rh -= delta[0];
this.lf -= delta[2];
this.rf -= delta[1];
}
}
let delta_h = Math.max((1 - cos(abs(this.lh - pi / 2))) * .5 + (1 - cos(abs(this.lf))) * .6, (1 - cos(abs(this.rh - pi / 2))) * .5 + (1 - cos(abs(this.rf))) * .6);
this.progress++;
return {
lh: this.lh,
lf: this.lf,
rh: this.rh,
rf: this.rf,
dh: delta_h,
dl: this.stepLength / steps
};
}
presentation(){
return {lh:.4*pi, lf:pi/6,rh:.7*pi, rf:pi/8, dh:0, dl: 0};
}
};
function update_tree(idx){
//scale, add leaves, add branch
}

@ -0,0 +1,105 @@
//------ CREATING MESH SHAPES
// CREATE A MESH FROM A PARAMETRIC FUNCTION
let createMesh = (nu, nv, f, data) => {
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,data));
tmp = tmp.concat(f(u,v+1/nv,data));
}
tmp = tmp.concat(f(1,v,data));
tmp = tmp.concat(f(0,v+1/nv,data));
}
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 createSquareMesh = (i, z) => {
let m = [], n = 6, j = z < 0 ? (i + 2) % 3 : (i + 1) % 3,
k = z < 0 ? (i + 1) % 3 : (i + 2) % 3;
m[i] = m[1*n+i] = m[2*n+i] = m[3*n+i] = z;
m[j] = m[2*n+j] = m[2*n+k] = m[3*n+k] = -1;
m[k] = m[1*n+j] = m[1*n+k] = m[3*n+j] = 1;
m[3+i] = m[1*n+3+i] = m[2*n+3+i] = m[3*n+3+i] = z < 0 ? -1 : 1;
m[3+j] = m[1*n+3+j] = m[2*n+3+j] = m[3*n+3+j] = 0;
m[3+k] = m[1*n+3+k] = m[2*n+3+k] = m[3*n+3+k] = 0;
return new Float32Array(m);
}
let squareMesh = createSquareMesh(2, 0);
let cubeMesh = glueMeshes(
glueMeshes(glueMeshes(createSquareMesh(0,-1),createSquareMesh(0,1)),
glueMeshes(createSquareMesh(1,-1),createSquareMesh(1,1))),
glueMeshes(createSquareMesh(2,-1),createSquareMesh(2,1)) );
let uvToTorus = (u,v,r) => {
let theta = 2 * Math.PI * u;
let phi = 2 * Math.PI * v;
let x = Math.cos(theta) * (1 + r * Math.cos(phi));
let y = Math.sin(theta) * (1 + r * Math.cos(phi));
let z = r * Math.sin(phi);
let nx = Math.cos(theta) * Math.cos(phi);
let ny = Math.sin(theta) * Math.cos(phi);
let nz = Math.sin(phi);
return [x,y,z, nx,ny,nz];
}
let uvToSphere = (u,v) => {
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 [x,y,z, x,y,z];
}
let uvToTube = (u,v) => {
let theta = 2 * Math.PI * u;
let x = Math.cos(theta);
let y = Math.sin(theta);
let z = 2 * v - 1;
return [x,y,z, x,y,0];
}
let uvToDisk = (u,v,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 [x,y,z, 0,0,dz ? Math.sign(dz) : 1];
}
let torusMesh = createMesh(32, 16, uvToTorus, .5);
let sphereMesh = createMesh(32, 16, uvToSphere);
let tubeMesh = createMesh(32, 2, uvToTube);
let diskMesh = createMesh(32, 2, uvToDisk);
let diskNMesh = createMesh(32, 2, uvToDisk, -1);
let diskPMesh = createMesh(32, 2, uvToDisk, 1);
let cylinderMesh = glueMeshes(glueMeshes(tubeMesh, diskPMesh), diskNMesh);

@ -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,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>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,809 @@
//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 = [];
var states = [];
function deepcopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
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 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;
}
let scale = (v, s) => [ s * v[0] , s * v[1] , s * v[2] ];
let norm = v => Math.sqrt(dot(v,v));
// 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 uvToCone = (u, v, i) => {
let theta = 2 * Math.PI * u;
let x = Math.cos(theta)*(1-v);
let y = Math.sin(theta)*(1-v);
let z = 2 * v - 1;
return [i, x, y, z].concat(normalize([x, y, 0]));
}
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]]);
positionsupdated = false;
}
function controls_hitTest(pos, clicked = false){
// let iMin = -1, tMin = 10000.;
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);
//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 (!state.dead){
if(clicked || state.running<=0)
{
state.turn(P, clicked);
}
//if(state.figure_rot < 0) state.figure_rot += pi;
//updateStatus([state.figure_rot, state.direction_l[0]/state.direction_l[1]]);
if(clicked)
{
state.walk();
}
}
}
//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));
let transform_mesh = (m,arr) => {
for(let i = 0; i < arr.length; i+=7){
const mod = dot_xyz(
matrix_multiply(m, [arr[i+1], arr[i+2], arr[i+3], 1]));
const mod_nor = normalize(dot_xyz(
matrix_multiply(m, [arr[i+4], arr[i+5], arr[i+6], 0])));
arr[i+1] = mod[0];
arr[i+2] = mod[1];
arr[i+3] = mod[2];
arr[i+4] = mod_nor[0];
arr[i+5] = mod_nor[1];
arr[i+6] = mod_nor[2];
}
}
let thicken_contour = (thickness, contour) =>{
let res = [];
let inner_contour = contour.slice();
transform_mesh(matrix_scale(thickness), inner_contour);
for(let i = 0; i < contour.length - 7; i+=7){
for (let j = 0; j < 7; ++ j)
res.push(contour[i + j]);
res.push(contour[0]);
for (let j = 1; j < 7; ++ j)
res.push((inner_contour[i + j]+inner_contour[i+7+j])/2);
}
for (let j = 0; j < 7; ++ j)
res.push(contour[contour.length - 7 + j]);
res.push(contour[0]);
for (let j = 1; j < 7; ++ j)
res.push((inner_contour[contour.length - 7 + j]+inner_contour[j])/2);
for (let j = 0; j < 7; ++ j)
res.push(contour[j]);
return res;
}
let sqlen = (a, b) => { return a*a + b*b; }

@ -0,0 +1,266 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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;', '#define _NDEBUG\n','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); }'
].join('\n');
var ns = 5,
cns = 5;
fragmentShaderHeader += 'const int ns = ' + ns + ';\n';
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
var status = '';
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){
}
function initVideoTexture(gl, i) {
}
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 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>&nbsp;</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., 0., .0, 1.3,
.1, .05, .05, 1., .5, .5, 1., .5, .5, 10., .3, 1., 1.3,
.1, .05, .05, .71, .71, .71, .71, .71, .71, 10., 0.3, .0, 1.5,
.1, .1, .1, .71, .71, .71, .71, .71, .71, 10., 0.05, 0., 1.,
.0, .0, .0, .0, .0, .0, .0, .0, .0, 40., 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('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,107 @@
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
M
M7.97,1.32c-1.2,2.4-2.58,5.53-3.81,9.3c-1.89,5.82-2.51,10.42-2.64,11.39c-0.28,2.2-0.69,6.44,0.73,18.39c0.57,4.79,1.47,11.13,2.94,18.58c0.94,0.01,1.87,0.03,2.81,0.04z
N

@ -0,0 +1,64 @@
#ifndef _NDEBUG
precision highp float;
const int ns = 5;
const int cns = 5;
float noise(vec3 v){return 1.;}
#endif
vec3 foregroundColor = vec3(.0841, .5329, .9604);
uniform vec3 starColors[10];
uniform vec3 V0;
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 <-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.659, 0.0384);sp = .2; df=.4; amb = .7, ex = 1.;l = color = vec3(1.0000, 0.7, 0.04);}
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.;
}
else if (id < 19.5) {color = vec3(.4,.4,.4);sp = .0; df=.0; amb = 1., ex = 1.,alp=1.;}
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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

@ -0,0 +1,2 @@
# graphics_hw2
[link](https://billsun.dev/graphics/hw2)

@ -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,350 @@
<script src=lib2.js></script>
<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>
<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>
<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="overflow: auto; width: 600px; height:600px;" width=1200 height=1200></canvas>
</center>
</body>
<!!-------- VERTEX SHADER: YOU PROBABLY DON'T WANT TO CHANGE THIS RIGHT NOW -------->
<script id='my_vertex_shader' type='x-shader/x-vertex'>
attribute vec3 aPos;
varying vec3 vPos;
void main() {
gl_Position = vec4(aPos, 1.);
vPos = aPos;
}
</script>
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
<!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag!! LOADED IN lib2.js -------->
<!--script src="shader.frag" id='my_fragment_shader' type='x-shader/x-fragment'> </script>
<!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW -------->
<script id='my_title' type='text/html'>
Solar RTX
</script>
<!!-------- HERE IS WHERE YOU CAN PROVIDE A LONGER TEXT DESCRIPTION -------->
<script id='my_instructions' type='text/html'><font color=#909090>
<p style="font-size:30px; ">In this homework, I implemented Global illumination w/
Realtime Recursive Ray Tracing!
<p>
<i style="font-size:25px;">Usage: </i>
<ul>
<li>Ctrl+Alt/Option+T: Toggle Texture.</li>
<li>Ctrl+S: Download fragment shader.</li>
<li>Ctrl+Alt/Option+R: Toggle Recursive Ray Tracing.</li>
<li>Ctrl+Alt/Option+N: Reset ViewPoint.</li>
<li>Ctrl+Alt/Option+P: Toggle Pause/Resume.</li>
<li style="color:red;">Please unfocus the Editing area (click somewhere else on the page) to use hotkeys.</li>
<li>Double Click on canvas (WITHOUT key modifiers): Toggle Pause/Resume.</li>
<li>MOUSE DRAG, SCROLL/WHEEL ZOOM: Changing Viewing point.</li>
<li>Use Chromium based browser for better performance.</li>
</ul>
<i style="font-size:25px;">How it works:</i>
<ul>
<li>First, I started with what I've already done in <a href="https://billsun.dev/graphics/hw1">homework 1</a>. Which already included complete Phong shading with
Specular light and much more (spherical texture mapping, simple interactions, improved UI/shader editor).
</li>
<li> I then merged the code from hw2 and added texture to each sphere.</li>
<li> I modified the ray tracing algorithm so that when hitting an object, instead of just returning color calculated from
Phong model:<br>
<ul>
<li>It recursively bounces and/or refract(NOT IMPLEMENTED YET) itself spawning new rays.</li>
<li>The color of this pixel equals to Ambient + Diffuse + ks*color[Reflected] + kt*color[Refracted].
(<a href="https://www.cs.drexel.edu/~david/Classes/Papers/p343-whitted.pdf">Turner Whitted Model</a>)</li>
<li>The tracing will stop when a ray was not hitting any object or was reflected/refracted n_ref times. </li>
<li>The color/intensity of the final lights are computed via specular component from the Phong model.</li>
<li>You may increase n_ref for more iterations, but please proceed with caution, because it may halt the computer.
</li>
</ul>
<li>I added more interactions, you can now change the viewpoint by
holding shift and alt key while dragging on canvas to rotate,
or holding shift and alt while scrolling on canvas to change focal length.
This is implemented by applying a transformation matrix to the viewpoint and projection surface.
</li>
<li>Finally, I used super sampling via doubling the render dimensions of the canvas to reduce aliasing. SEE comments on index.html</li>
<li>Repo on <a href="https://github.com/sunyinqi0508/graphics_hw1">Github</a>.</li>
</li>
</ul>
<p>
</script>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script>
// CREATE THE HTML DOCUMENT
let flags = 0x0;
let vs = my_vertex_shader.innerHTML;
//* LOADING FRAGMENT SHADER
var client = new XMLHttpRequest();
client.open('GET', './shader.frag');
client.onloadend = function() {
fs = (client.responseText);
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
gl_start(canvas1, vs, fs);
editor.getSession().setValue(fs);
editor.session.on('change', function(delta) {
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
});
}
client.send();
document.body.innerHTML = [''
,'<font size=7 color=#909090>' + my_title.innerHTML
,'<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><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="width:800px;height:2200px;"></div>'
,'</td><td valign=top>' + document.body.innerHTML
,'<input type="number" id="ins" style="margin-left:3px;font-size:24px;width:100px;height:45px" value="4">'
,'<button id="bns" style="margin-left:5px;font-size:24px;width:150px;height:45px">Set Spheres</button>'
,'<div style=\'font-size:25px\'>' + my_instructions.innerHTML + '</div>' + '</td>'
,'</tr></table>'
,'</TR></TABLE>'
].join('');
bns.onclick=function(e){
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
{
cns = ins.value;
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
}
}
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
delete editor.KeyBinding;
let lastTime = Date.now();
let animating = true;
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let mousedx = 0, mousedy = 0, mousedz = 0;
let cx = 1, cy = 1, sx = 0, sy = 0;
let mouselastX, mouselastY;
let lastClick = undefined;
let pause_resume = function(){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
};
canvas1.addEventListener('click',function(ev){
if(!(shift && alt) && lastClick&& Date.now()-lastClick<400)
pause_resume();
lastClick = Date.now();
//moving = false;
});
canvas1.addEventListener('mouseover', function(e){
over = true;
const mask = 0x8;
flags |= mask;
setUniform('1i', 'flags', flags);
});
canvas1.addEventListener('mousedown', function(e){
moving = true
mouselastX = mouselastY = undefined;
});
canvas1.addEventListener('mousemove', function(e){
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
mousedx -= (mouselastX - e.offsetX)/60;
mousedy -= (mouselastY - e.offsetY)/60;
cx = Math.cos(mousedx);
sx = Math.sin(mousedx);
cy = Math.cos(mousedy);
sy = Math.sin(mousedy);
setUniform('4f', 'rot', cx, sx, cy, sy);
const mask = 0x4;
flags |= mask;
setUniform('1i', 'flags', flags);
}
// if(over){
// let x=e.offsetX/300-1;
// let y=e.offsetY/300-1;
// let z=-1-3-mousedz;
// let tx = cx*x+sy*sx*y+sx*cy*z;
// let ty = cy*y-sy*z;
// let tz = -sx*x+cx*sy*y+cx*cy*z;
// let len = Math.sqrt(tx*tx + ty*ty+tz*tz);
// setUniform('3f', 'fDir', tx/len, ty/len, tz/len);
// }
mouselastX = e.offsetX;
mouselastY = e.offsetY;
});
canvas1.addEventListener('mouseup', function(e){
// if(ctrl && alt && moving){
// }
moving = false;
});
canvas1.addEventListener('mouseout', function(e){
// if(ctrl && alt && moving){
// }
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false;
});
canvas1.addEventListener('wheel', function(e){
mousedz += e.wheelDelta/600;
setUniform('1f', 'dFL', mousedz);
e.stopImmediatePropagation();
});
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer";
let rtswitch = function(){
const mask = 0x2;
let rtstatus = !(flags&mask);
if (rtstatus)
rtx.src='./RTXoff.svg';
else
rtx.src='./RTXon.svg';
flags = (flags&(!mask)) | (rtstatus?mask:0);
setUniform('1i', 'flags', flags);
}
rtx.addEventListener('click', rtswitch);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let fpscounter = function(time){
if (start === undefined)
start = time;
else
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
start = time;
if(fpson)
requestAnimationFrame(fpscounter);
else{
start = undefined;
fps.innerHTML = '';
}
};
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Shift'))
shift = true;
if(e.code.startsWith('Control'))
ctrl = true;
if(e.code.startsWith('Alt'))
alt = true;
else if(ctrl && alt && e.code == 'KeyT'){
const mask = 0x1;
flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags);
}
else if (ctrl &&e.code == 'KeyS'){
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
else if(ctrl && alt&&e.code == 'KeyR')
rtswitch();
else if(ctrl && alt&&e.code == 'KeyN')
{
flags = 0;
moving = false;
mousedx = mousedy = mousedz = 0;
cx = Math.cos(mousedx);
sx = Math.sin(mousedx);
cy = Math.cos(mousedy);
sy = Math.sin(mousedy);
rtx.src='./RTXon.svg';
setUniform('4f', 'rot', cx, sx, cy, sy);
setUniform('1f', 'dFL', mousedz);
setUniform('1i', 'flags', flags);
}
else if(ctrl && alt&&e.code == 'KeyP')
pause_resume();
else if(ctrl && alt&&e.code == 'KeyF')
if(!fpson)
{
fpson = true;
requestAnimationFrame(fpscounter);
}
else
fpson = false;
// else if(e.code =='KeyV')
// alert(' '+ mousedx+ ' ' + mousedy + ' '+mousedz)
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
ctrl = false;
if(e.code.startsWith('Alt'))
alt = false;
if(e.code.startsWith('Shift'))
shift = false;
});
// SET THE CURRENT TIME IN SECONDS BEFORE RENDERING EACH FRAME.
let startTime = Date.now();
let lastFrameTime = 0;
function animate(gl) {
if(animating)
setUniform('1f', 'uTime', (Date.now() - startTime) / 1000);
else
setUniform('1f', 'uTime', (lastTime - startTime) / 1000);
}
let start;
requestAnimationFrame(fpscounter);
</script>

@ -0,0 +1,185 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
let ns = 4, cns = 4;
fragmentShaderHeader+= 'const int ns = ' + ns + ';\n';
let fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
let nfsh = fragmentShaderHeader.split('\n').length + 1; // NUMBER OF LINES OF CODE IN fragmentShaderHeader
let isFirefox = navigator.userAgent.indexOf('Firefox') > 0; // IS THIS THE FIREFOX BROWSER?
let errorMsg = '';
//
// Initialize a texture and load an image.
// When the image finished loading copy it into the texture.
//
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 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);
}
// Because images have to be downloaded over the internet
// they might take a moment until they are ready.
// Until then put a single pixel in the texture so we can
// use it immediately. When the image has finished downloading
// we'll update the texture with the contents of the image.
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);
// WebGL1 has different requirements for power of 2 images
// vs non power of 2 images so check if the image is a
// power of 2 in both dimensions.
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
// Yes, it's a power of 2. Generate mips.
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
} else {
// No, it's not a power of 2. Turn off mips and set
// wrapping to clamp to edge
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 isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
function gl_start(canvas, vertexShader, fragmentShader) { // START WEBGL RUNNING IN A CANVAS
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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = '<br>';
// 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;
for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i;
}
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
setUniform('4f', 'rot', Math.cos(mousedx), Math.sin(mousedx), Math.cos(mousedy), Math.sin(mousedz));
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);
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0);
}
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) {
let loc = gl.getUniformLocation(gl.program, name);
(gl['uniform' + type])(loc, a, b, c, d, e, f);
}

@ -0,0 +1,252 @@
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 int flags;
//FLAGS 0-TEX, 1-RT, 2-MOVED, 3-FLASH, 4-TEX_ROT, 5-CLOUD
uniform vec4 rot; //ROTATION VALUES USED TO CALCULATE TRANSFORMATION MATRIX
//rot=[cosx, sinx, cosy, siny], x, y BING ROTATED ANGLE
uniform float dFL; //DELTA on FOCAL LENGTH
uniform vec3 fDir;//Flash light direction
varying vec3 vPos;// -1 < vPos.x < +1
// -1 < vPos.y < +1
// vPos.z == 0
float fl=3.;//ORIGINAL FOCAL LENGTH
const float pi=3.14159265359;
const float _2pi=2.*pi;
const int n_ref=5; //<<=======***********************MAX NUMBER OF RAY TRACING RECURRSIONS. INCREASE IT IF YOUR GRAPHICS CARD CAN HANDLE.****************************
//const int ns=4; ns is added from .js
vec4 Sph[ns];
uniform sampler2D uSampler[ns];
vec3 Ambient[ns];
vec3 Diffuse[ns];
vec4 Specular[ns];
float ks[ns];
struct Sphere{ //UPDATED SPHERE STRUCTURE THAT SUPPORTS TRANSPARENCY.(UNUSED)
vec4 Pos;
vec3 Ambient;
vec3 Diffuse;
vec4 Specular;
int textureid;
float ks, kt;
};
struct RT{ //STACK FOR RECURSIVE RAY TRACING.
vec3 color;
float ks;
// vec3 colorr;
// float kt;
// vec3 ptr;
// vec3 normal;
} stack[n_ref];
bool getflag(int flag,int bit){
float shifted = float(int(float(flag)/ pow(2.,float(bit))));
return fract(shifted/2.)>0.;
}
float clampv(float val,float l,float h){
return val<l?l:val>h?h:val;
}
void main(){
////////////////////////////////////////////////
//
// HERE, FOR YOUR HOMEWORK, YOU CAN WRITE ANY
// CODE YOU LIKDEFINE A COLOR FOR THIS FRAGMENT.
// LIGHT DIRECTION AND COLOR
//* I USED LDir AS LIGHT POSITION
//* I NORMALIZED IT AFTER GETTING THE
//* DIRECTION BY SUBTRACTING IT FROM THE POINT
vec3 LDir=vec3(.5,.5,.5);
vec3 LCol=vec3(1.,1.,1.);
// SPHERE
Sph[3]=vec4(.9*sin(uTime*.4),0.,.9*cos(uTime*.4),.25);
Sph[2]=vec4(.22*sin(uTime*1.2),0.05,.22*cos(uTime*1.2),.02);
Sph[0]=vec4(.45*sin(uTime),0.05*cos(uTime + 1.),.45*cos(uTime),.1);
Sph[1]=vec4(0.,0.,0.,.15);
// SURFACE REFLECTANCE PROPERTIES, can be transferred from .js
Ambient[3]=vec3(.1,.1,.1);// r,g,b
Diffuse[3]=vec3(.71,.71,.71);// r,g,b
Specular[3]=vec4(.71,.71,.71,10.);// r,g,b,power
Ambient[2]=vec3(.1,.05,.05);// r,g,b
Diffuse[2]=vec3(.71,.71,.71);// r,g,b
Specular[2]=vec4(.71,.71,.71,10.);// r,g,b,power
Ambient[1]=vec3(.1,.05,.05);// r,g,b
Diffuse[1]=vec3(1.,.5,.5);// r,g,b
Specular[1]=vec4(1.,.5,.5,10.);// r,g,b,power
Ambient[0]=vec3(.05,.05,.1);// r,g,b
Diffuse[0]=vec3(.5,.5,1.);// r,g,b
Specular[0]=vec4(1.,.5,.5,20.);// r,g,b,power
ks[0] = 0.25;
ks[1] = 0.1;
ks[2] = 0.3;
ks[3] = 0.05;
// INITIALIZE TO A BACKGROUND COLOR
vec3 color=vec3(.2, .3, .5);
float ca=rot.x, sa = rot.y, cb=rot.z, sb=rot.w;
mat3 transformation, invTr;//Transformation matrix for viewpoint.
transformation[0] = vec3(ca, sb*sa, sa*cb);//because the matrices are all the same,
transformation[1] = vec3(0, cb, -sb);//We don't need to calculate it for every pixel
transformation[2] = vec3(-sa,ca*sb,ca*cb);//So, we get it from the CPU
invTr[0] = vec3(ca, 0, -sa);//it's inverse, to calculate texture mapping.
invTr[1] = vec3(sa*sb, cb, ca*sb);
invTr[2] = vec3(cb*sa, -sb, ca*cb);
vec3 trPos = transformation*((dFL+fl+1.)/(fl+1.))*vec3(vPos.xy, -1);
// COMPUTE THE RAY ORIGIN AND DIRECTION
vec3 V0=transformation*vec3(0.,0.,fl+dFL), V = V0;
vec3 W=normalize(trPos-V);
// RAY TRACE TO ALL OBJECTS IN THE SCENE
bool rtxoff = getflag(flags, 1),
showtexture = !getflag(flags,0),
moved = getflag(flags,2)//,
// flash = true;//getflag(flags, 3)
;//get flags.
// bool hit = false;
int cnt_ref = n_ref;
for(int j=0;j<n_ref;j++)
{
float tMin=10000.;
int iMin = -1;
for(int i=0;i<cns;i++){
// SHIFT COORDINATES, SO THAT SPHERE IS AT (0,0,0)
vec3 Vp=V-Sph[i].xyz;
// SOLVE FOR QUADRATIC EQUATION IN t
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. && 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!
}
}
}
// IF RAY HITS SPHERE
if(iMin >= 0){
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin) //* Because GLSL doesn't support non-const index,
{ //* we have to get Sph[iMin], uSampler[iMin], etc. this way
//*Good old TEXTURE MAPPING from hw1
vec3 tex_sph = (S-Sph[i].xyz);
if(moved)
tex_sph=invTr*tex_sph;//* transform the sphere to original place if view point moved;
//* This is super expensive! plus it's in the inner loop!!
//* We added a flag to disable it when the viewport is not moved!
float R=Sph[i].w;
float tex_x=acos(abs(tex_sph.x)/sqrt(R*R-tex_sph.y*tex_sph.y));
if(tex_sph.x>0.)
tex_x=pi-tex_x;
tex_x*=1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x=tex_x+float(uTime);
float quo=float(int(tex_x/_2pi));
tex_x=tex_x/_2pi -quo;
vec3 texture_color;
if(showtexture)
texture_color=texture2D(uSampler[i],vec2(tex_x,((R-tex_sph.y)/(2.*R)))).xyz;
else texture_color = foregroundColor;
vec3 N=normalize(S-Sph[i].xyz);
//*DIRECTIONS ARE NORMALIZED TO GET THE CORRECT PHONG LIGHTING
vec3 realLDir=normalize(LDir-S);
color=(
Ambient[i]
+Diffuse[i]*max(0.,dot(N,realLDir))*LCol
)*texture_color
;
// + SPECULAR COMPONENT GOES HERE
if(rtxoff || j == n_ref - 1) //if it's the last ray
color += sqrt(float(j+1)) * Specular[i].xyz*pow(max(0.,
dot(2.*dot(N,realLDir)*N-realLDir,-W)),Specular[i].w);
//*Pushing current color and ks into stack.
//*suppose ks is 0.15 for all spheres, we can
//*of course support different ks, kt for different object
//*but I didn't have time to do that, just a proof of concept,
//*I defined the new sphere structure that could be used in the future.
stack[j] = RT(color, ks[i]);
V = S; //*NEXT RAY SHOOTING FROM THE INTERSECTION POINT
// if(flash && j == 0){
// V0 = V - V0;
// hit = true;
// }
W = -normalize(2. * dot(N, W) * N - W);//*W is the next direction of the next ray.
break;// this is only the innerloop, RT is still going!
}
}
else {
// TO SIMIPIFY THINGS UP, I'LL ASSUME THAT EVERYTHING
// IS INSIDE THE BOUNDING BOX [(-1,-1,-1), (1,1,1)]
// AND THERE'S A FLOOR at [y = -1] THE NORMAL IS (0,1,0)
// Because We assumed that the light always hit sphere first,
// It will have wirld behavior when you rotate the scene upsidedown.
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+.6)<3.)
{
vec3 S = vec3(sx, -.2, sz);
vec3 realLDir=normalize(LDir - S);
color=(
0.5 //ambient for ground
+0.5*max(0.,realLDir.y)*LCol //diffusion for ground
)*groundColor
;
// + SPECULAR COMPONENT GOES HERE
if(rtxoff || j == n_ref - 1)
color += sqrt(float(j+1))*groundSpecular.xyz* //specular for ground.
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
stack[j] = RT(color, 0.15); //ks of ground is 0.1
V = S; //Same as above, trace again from S, dir = reflect(W, N).
// if(flash && j == 0){
// V0 = W;
// hit = true;
// }
W = vec3(W.x, -W.y, W.z);
}
else{
if(j > 0)
{
// If the light bounces away! The color of it is calculated by
stack[j] = RT(sqrt(float(j+1))*vec3(4.,4.,4)*pow(max(0.,dot(W, normalize(LDir - V))), 10.), 0.);
cnt_ref = j + 1;
}
else //If the light hits the void in the first place, it's just black!
cnt_ref = j;//j is always 0 in this case.
break; //The light is shooting into the void, let's stop RT.
}
}
// RTX off
if(rtxoff)
break;
}
if(rtxoff)
color = stack[0].color;
else
{
color = vec3(0,0,0);
float currks = 1.;
for(int i = 0; i < n_ref; ++i)
{
if(i >= cnt_ref)//same trick to use bounded non-const on indexes
{
color += currks * stack[i - 1].color; //if there're less than n_ref rays, e.g. ray go to the void.
break;
}
color += currks *(1.-stack[i].ks) * stack[i].color;
currks *= stack[i].ks;
}
if(n_ref == cnt_ref)
color += currks * stack[n_ref - 1].color;
}
// APPLY GAMMA CORRECTION AND SET THE PIXEL COLOR.
gl_FragColor=vec4(sqrt(color),1.);
}

3
hw3/.gitignore vendored

@ -0,0 +1,3 @@
.DS_Store
old/
new/

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

@ -0,0 +1,2 @@
# graphics_hw3
[link](https://billsun.dev/graphics/hw3)

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

@ -0,0 +1,341 @@
<script src=lib3.js></script>
<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>
<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>
<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=" overflow: hidden !important; width: 600px !important; height:600px !important;" width=600 height=600></canvas>
</center>
</body>
<!!-------- VERTEX SHADER: YOU PROBABLY DON'T WANT TO CHANGE THIS RIGHT NOW -------->
<script id='my_vertex_shader' type='x-shader/x-vertex'>
attribute vec3 aPos;
varying vec3 vPos;
void main() {
gl_Position = vec4(aPos, 1.);
vPos = aPos;
}
</script>
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
<!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag!! LOADED IN lib2.js -------->
<!--script src="shader.frag" id='my_fragment_shader' type='x-shader/x-fragment'> </script>
<!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW -------->
<script id='my_title' type='text/html'>
RTX Extreme
</script>
<!!-------- HERE IS WHERE YOU CAN PROVIDE A LONGER TEXT DESCRIPTION -------->
<script id='my_instructions' type='text/html'><font color=#909090>
<p style="font-size:30px; ">In this homework, I implemented Global illumination w/
Realtime Recursive Ray Tracing!
<p>
<i style="font-size:25px;">Usage: </i>
<ul>
<li>Ctrl+Alt/Option+T: Toggle Texture.</li>
<li>Ctrl+S: Download fragment shader.</li>
<li>Ctrl+Alt/Option+N: Reset ViewPoint.</li>
<li>Ctrl+Alt/Option+P: Toggle Pause/Resume.</li>
<li style="color:red;">Please unfocus the Editing area (click somewhere else on the page) to use hotkeys.</li>
<li>Double Click on canvas (WITHOUT key modifiers): Toggle Pause/Resume.</li>
<li>DRAG, SCROLL on canvas: Changing Viewing point.</li>
<li>Please use Chromium based browser.</li>
<li>Super Sampling(0.25x-4x): increase rendering size for better visual or decrease rendering size for better performance.</li>
<li>Spheres(1 - 5): number of spheres, performance will suffer if adding too many spheres.</li>
</ul>
<i style="font-size:25px;">How it works:</i>
<ul>
<li>I added recursive ray tracing with fraction support.</li>
<li><a style="color:red;">About the scene: </a>There're two spheres in the center, the bouncing one in the very center (the Earth) is not transparent nor is it reflective,
the outer one is both transparent and reflective and has the texture of the Sun(barely distinguishable).
The small sphere embedded running circle is reflective but not transparent. You can also add
two additional spheres via the button above. (up to 5).
</li>
<li>If your scene is clipped, this is a bug from chromium, you may reset the viewport by adjust super sampling.</li>
<li>Each hit will now spawn 2 rays, but there're serious performance issues, because
the number of rays increases exponentially. I resolved this issue by:
</li>
<ul>
<li>Pruning: If the weight of this ray is too small, dispose it.</li>
<li>Smarter Stack frame utilization: Now the stack frame will only store last rays and next rays.
By alternating 2 arrays storing last ray and next ray, I don't need to store other rays.
</li>
<li>By combining these methods I managed to significantly reduce RT depth and 'stack' size,
While supporting nested object and objects both reflection and refraction rays on the same surface.
</li>
</ul>
<img src="./img.jpg"></img>
</ul>
<p>
</script>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script>
// CREATE THE HTML DOCUMENT
let flags = 0x0;
let vs = my_vertex_shader.innerHTML;
//* LOADING FRAGMENT SHADER
var client = new XMLHttpRequest();
client.open('GET', './shader.frag');
client.onloadend = function() {
fs = (client.responseText);
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
gl_start(canvas1, vs, fs);
editor.getSession().setValue(fs);
editor.session.on('change', function(delta) {
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
});
}
client.send();
document.body.innerHTML = [''
,'<font size=7 color=#909090>' + my_title.innerHTML
,'<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><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="width:800px;height:2200px;"></div>'
,'</td><td valign=top>' + document.body.innerHTML
,'<input type="number" id="ins" style="margin-left:3px;font-size:24px;width:100px;height:45px" value="3" max="5" min = "1">'
,'<button id="bns" style="margin-left:5px;font-size:24px;width:180px;height:45px">Set Spheres</button>'
,'<input type="number" id="insamp" style="margin-left:3px;font-size:24px;width:100px;height:45px" value="1" max="4" min = "0.25" step="0.2">'
,'<button id="bnsamp" style="margin-left:5px;font-size:24px;width:200px;height:45px">Super Sampling</button>'
,'<div style=\'font-size:25px\'>' + my_instructions.innerHTML + '</div>' + '</td>'
,'</tr></table>'
,'</TR></TABLE>'
].join('');
bns.onclick=function(e){
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
{
cns = ins.value;
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue());
}
}
bnsamp.onclick=function(e){
let multiplier = insamp.value;
let w = parseInt(canvas1.style.width)*multiplier;
let h = parseInt(canvas1.style.height)*multiplier;
canvas1.height = h;
canvas1.width = w;
gl.viewport(0, 0, w, h);
gl.clearRect(0, 0, w, h);
}
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
delete editor.KeyBinding;
let lastTime = Date.now();
let animating = true;
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let mousedx = 0, mousedy = 0, mousedz = 0;
let cx = 1, cy = 1, sx = 0, sy = 0;
let mouselastX, mouselastY;
let lastClick = undefined;
let pause_resume = function(){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
};
canvas1.addEventListener('click',function(ev){
if(!(shift && alt) && lastClick&& Date.now()-lastClick<400)
pause_resume();
lastClick = Date.now();
//moving = false;
});
canvas1.addEventListener('mouseover', function(e){
over = true;
const mask = 0x8;
flags |= mask;
setUniform('1i', 'flags', flags);
});
canvas1.addEventListener('mousedown', function(e){
moving = true
mouselastX = mouselastY = undefined;
});
canvas1.addEventListener('mousemove', function(e){
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
mousedx -= (mouselastX - e.offsetX)/60;
mousedy -= (mouselastY - e.offsetY)/60;
cx = Math.cos(mousedx);
sx = Math.sin(mousedx);
cy = Math.cos(mousedy);
sy = Math.sin(mousedy);
setUniform('Matrix3fv', 'transformation', false, [cx, sy*sx, sx*cy, 0, cy, -sy, -sx, cx*sy, cx*cy]);
}
mouselastX = e.offsetX;
mouselastY = e.offsetY;
});
canvas1.addEventListener('mouseup', function(e){
moving = false;
});
canvas1.addEventListener('mouseout', function(e){
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false;
});
canvas1.addEventListener('wheel', function(e){
mousedz += e.wheelDelta/600;
setUniform('1f', 'dFL', mousedz);
e.stopImmediatePropagation();
});
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer";
let rtswitch = function(){
alert('Ray Tracing is always on. See hw2 where rt can be toggled on/off.')
rtx.src='./RTXon.svg';
}
rtx.addEventListener('click', rtswitch);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let fpscounter = function(time){
if (start === undefined)
start = time;
else
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
start = time;
if(fpson)
;//requestAnimationFrame(fpscounter);
else{
start = undefined;
fps.innerHTML = '';
}
};
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Shift'))
shift = true;
if(e.code.startsWith('Control'))
ctrl = true;
if(e.code.startsWith('Alt'))
alt = true;
else if(ctrl && alt && e.code == 'KeyT'){
const mask = 0x1;
flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags);
}
else if (ctrl &&e.code == 'KeyS'){
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
else if(ctrl && alt&&e.code == 'KeyR')
rtswitch();
else if(ctrl && alt&&e.code == 'KeyN')
{
flags = 0;
moving = false;
mousedx = mousedy = mousedz = 0;
cx = Math.cos(mousedx);
sx = Math.sin(mousedx);
cy = Math.cos(mousedy);
sy = Math.sin(mousedy);
rtx.src='./RTXon.svg';
setUniform('Matrix3fv', 'transformation', false, [cx, sy*sx, sx*cy, 0, cy, -sy, -sx, cx*sy, cx*cy]);
setUniform('1f', 'dFL', mousedz);
setUniform('1i', 'flags', flags);
}
else if(ctrl && alt&&e.code == 'KeyP')
pause_resume();
else if(ctrl && alt&&e.code == 'KeyF')
if(!fpson)
{
fpson = true;
requestAnimationFrame(fpscounter);
}
else
fpson = false;
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
ctrl = false;
if(e.code.startsWith('Alt'))
alt = false;
if(e.code.startsWith('Shift'))
shift = false;
});
let startTime = Date.now();
let lastFrameTime = 0;
function animate(gl) {
let uTime;
if(animating)
{
uTime = (Date.now() - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
else
{
uTime = (lastTime - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
setUniform('4f', 'Sph[4]', 0.5*Math.sin(uTime*1.),0.08*Math.sin(uTime *0.9),.5*Math.cos(uTime*1.),.12);
setUniform('4f', 'Sph[3]', .9*Math.sin(uTime*.4),0.,.9*Math.cos(uTime*.4),.25);
setUniform('4f', 'Sph[2]', .22*Math.sin(uTime*1.2),0.05,.22*Math.cos(uTime*1.2),.05);
setUniform('4f', 'Sph[0]', 0,0.05*Math.cos(uTime + 1.),.045*Math.cos(uTime),.15);
setUniform('4f', 'Sph[1]', 0,0.,0,.25);
}
let start;
requestAnimationFrame(fpscounter);
</script>

@ -0,0 +1,207 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
let ns = 5, cns = 3;
fragmentShaderHeader+= 'const int ns = ' + ns + ';\n';
let fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
let nfsh = fragmentShaderHeader.split('\n').length + 1; // NUMBER OF LINES OF CODE IN fragmentShaderHeader
let isFirefox = navigator.userAgent.indexOf('Firefox') > 0; // IS THIS THE FIREFOX BROWSER?
let errorMsg = '';
//
// Initialize a texture and load an image.
// When the image finished loading copy it into the texture.
//
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 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);
}
// Because images have to be downloaded over the internet
// they might take a moment until they are ready.
// Until then put a single pixel in the texture so we can
// use it immediately. When the image has finished downloading
// we'll update the texture with the contents of the image.
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);
// WebGL1 has different requirements for power of 2 images
// vs non power of 2 images so check if the image is a
// power of 2 in both dimensions.
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
// Yes, it's a power of 2. Generate mips.
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
} else {
// No, it's not a power of 2. Turn off mips and set
// wrapping to clamp to edge
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 isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
function gl_start(canvas, vertexShader, fragmentShader) { // START WEBGL RUNNING IN A CANVAS
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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = '<br>';
// 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;
for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i;
}
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
let cx = Math.cos(mousedx), cy = Math.cos(mousedy), sx = Math.sin(mousedx), sy = Math.sin(mousedy);
setUniform('Matrix3fv', 'transformation', false, [cx, sy*sx, sx*cy, 0, cy, -sy, -sx, cx*sy, cx*cy]);
let attribs = [
.05,.05,.1, .5,.5,1., 1.,.5,.5,20., 0., .0, 1.3,
.1,.05,.05, 1.,.5,.5, 1.,.5,.5,10., .3,1.,1.3, //
.1,.05,.05, .71,.71,.71, .71,.71,.71,10., 0.3,.0,1.5,
.1,.1,.1, .71,.71,.71, .71,.71,.71,10., 0.05,0., 1.,
.0,.0,.0, .0,.0,.0, .0,.0,.0,40., 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('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));
}
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);
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0);
}
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);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

@ -0,0 +1,264 @@
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 int flags;
//FLAGS 0-TEX, 1-RT, 2-MOVED, 3-FLASH, 4-TEX_ROT, 5-CLOUD
uniform vec4 rot; //ROTATION VALUES USED TO CALCULATE TRANSFORMATION MATRIX
//rot=[cosx, sinx, cosy, siny], x, y BING ROTATED ANGLE
uniform float dFL; //DELTA on FOCAL LENGTH
uniform vec3 fDir;//Flash light direction
varying vec3 vPos;// -1 < vPos.x < +1
// -1 < vPos.y < +1
// vPos.z == 0
float fl=3.;//ORIGINAL FOCAL LENGTH
const float pi=3.14159265359;
const float _2pi=2.*pi;
const int n_ref=9; //2^(hits) + 1 because each hit now spawn 2 rays.
//const int ns=4; ns is added from .js
vec4 Sph[ns];
uniform sampler2D uSampler[ns];
vec3 Ambient[ns];
vec3 Diffuse[ns];
vec4 Specular[ns];
float ks[ns];
float kr[ns];
float kf[ns], kf_air = 1.000293;
int type[ns];//Nested objects
// 1-sphere, 2-compost sphere, 3-
struct Object{ //UPDATED SPHERE STRUCTURE THAT SUPPORTS TRANSPARENCY.(UNUSED)
vec4 Pos;
vec3 Ambient;
vec3 Diffuse;
vec4 Specular;
int textureid;
float ks, kt, kr;
};
struct RT{ //STACK FOR RECURSIVE RAY TRACING.
vec3 color;
float ks;
} ;
vec3 scolor = vec3(0,0,0); //Actually 2^n_ref
struct Ray{
vec3 V;
vec3 W;
float kf, cumulativeK;
} lastRay[n_ref/2];
bool modulo2(int n){
return n-2*(n/2) == 1;
}
bool getflag(int flag,int bit){
int shifted = flag / int(pow(2.,float(bit)));
return modulo2(shifted);
}
float clampv(float val,float l,float h){
return val<l?l:val>h?h:val;
}
void main(){
vec3 LDir=vec3(.5,.5,.5);
vec3 LCol=vec3(1.,1.,1.);
// SPHERE
Sph[3]=vec4(.9*sin(uTime*.4),0.,.9*cos(uTime*.4),.25);
Sph[2]=vec4(.22*sin(uTime*1.2),0.05,.22*cos(uTime*1.2),.02);
Sph[0]=vec4(.45*sin(uTime),0.05*cos(uTime + 1.),.45*cos(uTime),.1);
Sph[1]=vec4(0.,0.,0.,.15);
// SURFACE REFLECTANCE PROPERTIES, can be transferred from .js
Ambient[3]=vec3(.1,.1,.1);// r,g,b
Diffuse[3]=vec3(.71,.71,.71);// r,g,b
Specular[3]=vec4(.71,.71,.71,10.);// r,g,b,power
Ambient[2]=vec3(.1,.05,.05);// r,g,b
Diffuse[2]=vec3(.71,.71,.71);// r,g,b
Specular[2]=vec4(.71,.71,.71,10.);// r,g,b,power
Ambient[1]=vec3(.1,.05,.05);// r,g,b
Diffuse[1]=vec3(1.,.5,.5);// r,g,b
Specular[1]=vec4(1.,.5,.5,10.);// r,g,b,power
Ambient[0]=vec3(.05,.05,.1);// r,g,b
Diffuse[0]=vec3(.5,.5,1.);// r,g,b
Specular[0]=vec4(1.,.5,.5,20.);// r,g,b,power
ks[0] = 0.25;
ks[1] = 0.1;
ks[2] = 0.3;
ks[3] = 0.05;
kr[0] = 0.25;
kr[1] = 0.1;
kr[2] = 0.3;
kr[3] = 0.05;
kf[0] = 1.3;
kf[1] = 1.3; //Water
kf[2] = 1.5; //Glass
kf[3] = 1.; //Vacuum
float currKf = kf_air;
vec3 color=vec3(.2, .3, .5);
float ca=rot.x, sa = rot.y, cb=rot.z, sb=rot.w;
mat3 transformation, invTr;//Transformation matrix for viewpoint.
transformation[0] = vec3(ca, sb*sa, sa*cb);//because the matrices are all the same,
transformation[1] = vec3(0, cb, -sb);//We don't need to calculate it for every pixel
transformation[2] = vec3(-sa,ca*sb,ca*cb);//So, we get it from the CPU
invTr[0] = vec3(ca, 0, -sa);//it's inverse, to calculate texture mapping.
invTr[1] = vec3(sa*sb, cb, ca*sb);
invTr[2] = vec3(cb*sa, -sb, ca*cb);
vec3 trPos = transformation*((dFL+fl+1.)/(fl+1.))*vec3(vPos.xy, -1);
vec3 V0=transformation*vec3(0.,0.,fl+dFL), V = V0;
vec3 W=normalize(trPos-V);
bool rtxoff = getflag(flags, 1),
showtexture = !getflag(flags,0),
moved = getflag(flags,2);
int cnt_ref = n_ref;
float currentK = 1.;
for(int j=0;j<n_ref;j++)
{
if(j > 0){
Ray currR = lastRay[(j-1)/2];
currKf = currR.kf;
currentK = currR.cumulativeK;
if(currKf <= 0.0000001 || currentK <= 0.0000001)
continue; // We make it terminate w/ kf=0
V = currR.V;
W = currR.W;
}
float tMin=10000.;
int iMin = -1;
for(int i=0;i<cns;i++){
// SHIFT COORDINATES, SO THAT SPHERE IS AT (0,0,0)
vec3 Vp=V-Sph[i].xyz;
// SOLVE FOR QUADRATIC EQUATION IN t
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.00001 && 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.00001){
t = -(t + 2.*B);
if(t < tMin){
tMin = t;
iMin = i;
}
}
}
}
// IF RAY HITS SPHERE
if(iMin >= 0){
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin)
{
vec3 tex_sph = (S-Sph[i].xyz);
if(moved)
tex_sph=invTr*tex_sph;
float R=Sph[i].w;
float tex_x=acos(abs(tex_sph.x)/sqrt(R*R-tex_sph.y*tex_sph.y));
if(tex_sph.x>0.)
tex_x=pi-tex_x;
tex_x*=1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x=tex_x+float(uTime);
float quo=float(int(tex_x/_2pi));
tex_x=tex_x/_2pi - quo;
vec3 texture_color;
if(showtexture)
texture_color=texture2D(uSampler[i],vec2(tex_x,((R-tex_sph.y)/(2.*R)))).xyz;
else texture_color = foregroundColor;
vec3 N=normalize(S-Sph[i].xyz);
vec3 realLDir=normalize(LDir-S);
color=(
Ambient[i]
+Diffuse[i]*max(0.,dot(N,realLDir))*LCol
)*texture_color
;
if(rtxoff || j >= n_ref/2) //if it's the last hit
{
color += sqrt(float(j+1)) * Specular[i].xyz*pow(max(0.,
dot(2.*dot(N,realLDir)*N-realLDir,-W)),Specular[i].w);
scolor += color * currentK;
}
else{
lastRay[2 * j + 1] = Ray(S, (-(2. * dot(N, W) * N - W)), currKf, currentK * ks[i]); //reflection
float ita = currKf/kf[i];
float c1 = dot(N, W);
float c2 = sqrt(1.-ita*ita*(1.-c1*c1));
lastRay[2 * j + 2] = Ray(S, normalize(ita*W + (ita*c1 - c2)*N), kf[i], currentK * kr[i]); //refraction
scolor += currentK*(1. - ks[i] - kr[i]) * color;//stack[j] = RT(color, currentK*(1. - ks[i] - kr[i]) * 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+.6)<3.)
{
vec3 S = vec3(sx, -.2, sz);
vec3 realLDir=normalize(LDir - S);
color=(
0.5 //ambient for ground
+0.5*max(0.,realLDir.y)*LCol //diffusion for ground
)*groundColor
;
// + SPECULAR COMPONENT GOES HERE
if(rtxoff || j == n_ref - 1)
{
color += sqrt(float(j+1))*groundSpecular.xyz* //specular for ground.
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
//stack[j] = RT(color, currentK); //ks of ground is 0.15
scolor += currentK * color;
}
else
{
lastRay[2 * j + 1] = Ray(S, vec3(W.x, -W.y, W.z), currKf, currentK * 0.15); //reflection
//stack[j] = RT(color, currentK * (1.-0.15)); //ks of ground is 0.15
scolor += (currentK*.85)*color;
}
//lastRay[2 * j + 2] = Ray(S, vec3(0,0,0), 0.); //refraction
}
else{
if(j > 0)
{
// If the light bounces away! The color of it is calculated by
//stack[j] = RT(sqrt(float(j+1))*vec3(4.,4.,4)*pow(max(0.,dot(W, normalize(LDir - V))), 10.), currentK);
scolor += currentK * sqrt(float(j+1)*pow(max(0.,dot(W, normalize(LDir - V))), 10.)) * vec3(4.,4.,4);
//cnt_ref = j + 1;
}
//else //If the light hits the void in the first place, it's just black!
//cnt_ref = j;//j is always 0 in this case.
break; //The light is shooting into the void, let's stop RT.
}
}
if(rtxoff)
break;
}
if(!rtxoff)
{
color = scolor;
// color = vec3(0,0,0);
// //float currks = 1.;
// for(int i = 0; i < n_ref; ++i)
// {
// //if(i >= cnt_ref)//same trick to use bounded non-const on indexes
// // {
// // color += currks * stack[i - 1].color; //if there're less than n_ref rays, e.g. ray go to the void.
// // break;
// // }
// if(stack[i].ks <0.0000001)
// continue;
// color += stack[i].ks * stack[i].color;//currks *(1.-stack[i].ks) * stack[i].color;
// //currks *= stack[i].ks;
// }
// // if(n_ref == cnt_ref)
// // color += currks * stack[n_ref - 1].color;
}
gl_FragColor=vec4(sqrt(color),1.);
}

@ -0,0 +1,268 @@
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 int f_tex, f_rt, f_moved;
uniform vec4 rot; //ROTATION VALUES USED TO CALCULATE TRANSFORMATION MATRIX
uniform float dFL; //DELTA on FOCAL LENGTH
uniform mat3 transformation, invTr;
uniform vec3 Ambient[ns], Diffuse[ns];
uniform vec4 Specular[ns];
uniform float ks[ns], kr[ns], kf[ns];
uniform vec4 Sph[ns];
uniform sampler2D uSampler[ns];
const float kf_air = 1.000293;
varying vec3 vPos;
float fl=3.;//ORIGINAL FOCAL LENGTH
const float pi=3.14159265359;
const float _2pi=2.*pi;
const int n_ref=15; //2^(hits) - 1 because each hit now spawn 2 rays.
const int max_stack = (n_ref+1)/4;
vec3 scolor = vec3(0,0,0); //Actually 2^n_ref
struct Ray{
vec3 V;
vec3 W;
float kf, cumulativeK;
} stack1[max_stack], stack2[max_stack];
bool modulo2(int n){
return n-2*(n/2) == 1;
}
vec3 getRefraction(vec3 N, vec3 W, float nextkr, float eta, float c1){
float c2 = (1.-eta*eta*(1.-c1*c1));
c2 = sqrt(abs(c2));
return normalize(eta*W + (eta*c1 - c2)*N);
}
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 trPos = transformation*((dFL+fl+1.)/(fl+1.))*vec3(vPos.xy, -1);
vec3 V0=transformation*vec3(0.,0.,fl+dFL), V = V0;
vec3 W=(trPos-V);
bool rtxoff = false, showtexture = true, moved = false;
float currentK = 1.;
int curr_ptr = 0, curr_top = 0, next_top = 0;
bool final = false, stackswap = false;
for(int j=0;j<n_ref;j++)
{
for(int curr = 0; curr < max_stack; ++curr){
if(curr == curr_ptr){
bool outward = false;
bool skip = false;
if(j > 0){
Ray currR;
if(stackswap)
currR = stack1[curr];
else
currR = stack2[curr];
currKf = currR.kf;
currentK = currR.cumulativeK;
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!
outward = false;
}
else if (t >= -0.01 && t <0.01){
t = -(t + 2.*B);
if(t > 0.01 && t < tMin){
tMin = t;
iMin = i;
outward = true;
}
}
}
}
if(iMin >= 0){
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin)
{
vec3 texture_color;
if(showtexture)
{
vec3 tex_sph = (S-Sph[i].xyz);
if(moved)
;//tex_sph=invTr*tex_sph;
float R=Sph[i].w;
float tex_x=acos(abs(tex_sph.x)/sqrt(R*R-tex_sph.y*tex_sph.y));
if(tex_sph.x>0.)
tex_x=pi-tex_x;
tex_x*=1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x=tex_x+float(uTime);
float quo=float(int(tex_x/_2pi));
tex_x=tex_x/_2pi - quo;
texture_color=texture2D(uSampler[i],vec2(tex_x,((R-tex_sph.y)/(2.*R)))).xyz;
}
else texture_color = foregroundColor;
vec3 N=normalize(S-Sph[i].xyz);
vec3 realLDir=normalize(LDir-S);
if(outward){
float c1 = dot(N, W);
if(c1 > 0.)
{
c1 = -c1;
N = -N;
outward = true;
}
else outward = false;
color=(Ambient[i]+Diffuse[i]*max(0.,dot(N,realLDir))*LCol)*texture_color;
if(rtxoff || final) //if it's the last hit
{
color += Specular[i].xyz*pow(max(0.,dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
scolor += color * currentK;
}
else{
float eta =kf[i]/currKf;
if(outward) eta = 1./eta;
float nextks = currentK * ks[i], nextkr = currentK * kr[i];
bool refl = nextks > 0.001, refr = nextkr > 0.001;
if(refl || refr)
for(int k = 0; k < max_stack; ++k)
if(k == next_top){
if(stackswap){
if(refl)
{
stack2[k] = Ray(S, getRefraction(N, W, nextkr, eta, c1), currKf, nextks); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack2[k+1] = Ray(S, getRefraction(N, W, nextkr, eta, c1), kf[i], nextkr); //refraction
else
stack2[k] = Ray(S, getRefraction(N, W, nextkr, eta, c1), kf[i], nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}else{
if(refl)
{
stack1[k] = Ray(S, (-(2. * c1 * N - W)), currKf, nextks); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack1[k+1] = Ray(S, getRefraction(N, W, nextkr, eta, c1), kf[i], nextkr); //refraction
else
stack1[k] = Ray(S, getRefraction(N, W, nextkr, eta, c1), kf[i], nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}
break;
}
scolor += currentK * color;
}
}
else{
float c1 = (dot(N, W));
float ita = kf_air/currKf;
if(c1<0.)
{
c1 = -c1;
N = - N;
}
float c2 = (1.-ita*ita*(1.-c1*c1));
if(c2 >= 0.)
c2 = sqrt(c2);
else c2 = -sqrt(-c2);
for(int k = 0; k < max_stack; ++k)
if(k == next_top){
if(stackswap)
{
//stack2[k] = Ray(S, ((2. * c1 * N - W)), currKf, currentK*ks[i]); //reflection
//if(c2>=0.)
{
stack2[k] = Ray(S, normalize(ita*W + (ita*c1 - c2)*N), kf_air, currentK*kr[i]); //refraction
next_top ++;
}
}else{
//stack1[k] = Ray(S, ((2. * c1 * N - W)), currKf, currentK*ks[i]); //reflection
//if(c2 >= 0.)
{
stack1[k] = Ray(S, normalize(ita*W + (ita*c1 - c2)*N), kf_air, currentK*kr[i]); //refraction
next_top ++;
}
}
// next_top ++;
break;
}
}
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.)
{
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+2.)/3., (sz+1.)/6.)).xyz;
if(rtxoff || 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); //reflection
else
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15); //reflection
next_top ++;
break;
}
scolor += (currentK*.85)*color;
}
}
else{
if(j > 0)
scolor += currentK * pow(max(0.,dot(W, normalize(LDir - V))), 10.) * vec3(1.,1.,1.);
}
}
}
if(++curr_ptr >= curr_top){
curr_top = next_top;
curr_ptr = 0;
if(next_top * 2 > max_stack)
final = true;
stackswap = !stackswap;
}
break;
}
}
}
gl_FragColor=vec4(sqrt(scolor),1.);
}

@ -0,0 +1,237 @@
#define _DEBUG_BREAK {gl_FragColor=vec4(1,0,0,1); return;}
#define REFRACTION normalize(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 int f_tex, f_rt, f_moved;
uniform float dFL; //DELTA on FOCAL LENGTH
uniform mat3 transformation, invTr;
uniform vec3 Ambient[ns], Diffuse[ns];
uniform vec4 Specular[ns];
uniform float ks[ns], kr[ns], kf[ns];
uniform vec4 Sph[ns];
uniform sampler2D uSampler[ns];
const float kf_air = 1.000293;
varying vec3 vPos;
float fl=3.;//ORIGINAL FOCAL LENGTH
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); //Actually 2^n_ref
struct Ray{
vec3 V;
vec3 W;
float kf, cumulativeK;
} 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.x,tex_sph.z)/_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);
}
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 trPos = transformation*((dFL+fl+1.)/(fl+1.))*vec3(vPos.xy, -1);
vec3 V0=transformation*vec3(0.,0.,fl+dFL), V = V0;
vec3 W=(trPos-V);
bool rtxoff = false, showtexture = true, moved = false;
float currentK = 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;
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){
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin)
{
vec3 texture_color;
if(showtexture)
{
vec3 tex_sph = (S-Sph[i].xyz);
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
}
else texture_color = foregroundColor;
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(rtxoff || final) //if it's the last hit
{
color += Specular[i].xyz*pow(max(0.,
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
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); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}else{
if(refl)
{ //remember, c1 = -NW now
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}
break;
}
scolor += color * currentK;
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.)
{
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(rtxoff || 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); //reflection
else
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15); //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;
}
gl_FragColor=vec4(sqrt(scolor),1.);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

@ -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,112 @@
<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=lib4.header.js></script>
<script src=lib4.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>
StarCraft RTX
<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><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="width:800px;height:2200px;"></div>
</td><td valign=top>
<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=" overflow: hidden !important; width: 600px !important; height:600px !important;" width=599 height=599></canvas>
</center>
</body>
<div id="controls">
<input type="number" id="ins" style="margin-left:0px;font-size:24px;width:35px;height:45px" value="5" max="5" min = "1">
<button id="bns" style="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="1" max="4" min = "0.25" 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="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>
<div style=\'font-size:25px\'>
<font color=#909090>
<i style="font-size:25px;">What's new: </i>
<p style="font-size:20px;">
&nbsp;&nbsp;&nbsp;&nbsp;As before, drag on the canvas to rotate the scene, scroll on it to change focal point (perspective projection).
Double click it to pause/resume.<br>
I now added Fullscreen mode so that we can scroll on the canvas without scrolling the whole page and use single-key
hotkeys without worrying about conflicts with the editor. <br>
&nbsp;&nbsp;&nbsp;&nbsp;<a style="color:red;">Now, you can select a sphere by clicking on it (literally, click the sphere on the canvas!). And drag it around
to move it.</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;When a sphere is selected, you can also scroll whe mouse wheel to change its radius, and <strong>in fullscreen mode</strong>, press B and F key to send
it backward or forward <strong>according to your view point!</strong><br>
&nbsp;&nbsp;&nbsp;&nbsp;I also optimized the code a little bit, so that the transformation matrix is completely computed in CPU,
and applied (multiplied) inside the <a href="./shader.vert">vertex shader</a>.<br>
&nbsp;&nbsp;&nbsp;&nbsp;I suggest moving spheres when pausing the scene by double clicking the canvas, otherwise the spheres are already moving.<br>
&nbsp;&nbsp;&nbsp;&nbsp;<strong>If you found the scene somehow clipped, it seems to be a bug of chromium, please simply click on 'Super Sampling' button
or refresh the page. Otherwise the interactions won't work because the coordinates are wrong.</strong>
</p>
<div id="howitworks">
<br>
<p style="font-size:20px;">
<i style="font-size:25px;">How it works:</i><br>
I used similar method in raytracing to find the sphere it hits.<br>
The transformation methods are implemented in <a href="./lib4.header.js">lib4.header.js</a><br>
Interaction parts are in <a href="./lib4.ext.js">lib4.ext.js</a><br>
<a href="./lib4.js">lib4.js</a> most contains initialization methods for the renderer.<br>
<a href="./index.html">index.html</a> is almost pure html.<br>
</p>
</div>
<p>
</div>
</div></td>
</tr></table>
</TR></TABLE>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script src="lib4.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,359 @@
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let lastClick = undefined;
let animating = true;
let flags = 0x0;
var startTime = Date.now();
let lastTime = Date.now();
var lastFrameTime = 0;
let oldDocument;
let fullscreen = false;
let oldparents = {};
var tr, div;
let canvas_originalsize;
let Sph = [];
let SphTr = [];
let SphDletaR = []
let selected = false, selection = -1, dragging = false;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
function toggleFullscreen(element){
if(fullscreen)
{
if (document.exitFullscreen)
document.exitFullscreen();
else if (document.webkitExitFullscreen)
document.webkitExitFullscreen();
else if (document.mozCancelFullScreen)
document.mozCancelFullScreen();
else if (document.msExitFullscreen)
document.msExitFullscreen();
fullscreen = false;
bnfs.innerText = "Fullscreen";
}
else{
if(element.requestFullscreen)
element.requestFullscreen();
else if (element.webkitRequestFullscreen)
element.webkitRequestFullscreen();
else if(element.msRequestFullscreen)
element.msRequestFullscreen();
fullscreen = true;
bnfs.innerText = "Exit Fullscreen";
}
}
bnfs.onclick = function(_){
if(fullscreen){
oldparents[controls].appendChild(controls);
oldparents[canvas1].appendChild(canvas1);
canvas1.style.width = canvas_originalsize[0];
canvas1.style.height = canvas_originalsize[1];
howitworks.hidden = false;
}else{
div = document.createElement("div");
tr = document.createElement("table").insertRow();
tr.style.backgroundColor="white";
let size = Math.min(screen.availHeight, screen.availWidth);
canvas_originalsize = [canvas1.style.width, canvas1.style.height, canvas1.width, canvas1.height];
canvas1.style.height = canvas1.style.width = size;
howitworks.hidden=true;
oldparents[controls] = controls.parentNode;
oldparents[canvas1] = canvas1.parentNode;
let td1 = tr.insertCell();
td1.appendChild(canvas1);
let td2;
td2 = tr.insertCell();
td2.style.verticalAlign="top";
td2.appendChild(controls);
div.appendChild(tr);
document.body.appendChild(div);
}
toggleFullscreen(div);
}
clrsel.onclick=function(_){
setUniform("1i", "sel", -1);
selected = false;
selection = -1;
}
reset.onclick = function(_){
clrsel.onclick();
if(!animating)
pause_resume();
flags = 0;
moving = false;
mousedx = mousedy = mousedz = 0;
positionsupdated = true;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
rtx.src='./RTXon.svg';
setUniform('1i', 'flags', flags);
}
bns.onclick=function(e){
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
{
cns = ins.value;
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue());
}
}
bnsamp.onclick=function(e){
let multiplier = insamp.value;
let w = parseInt(canvas1.style.width)*multiplier;
let h = parseInt(canvas1.style.height)*multiplier;
canvas1.height = h;
canvas1.width = w;
gl.viewport(0, 0, w, h);
//gl.clearRect(0, 0, w, h);
}
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
if(fs != undefined)
editor.getSession().setValue(fs);
editor.session.on('change', function(delta) {
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
});
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
delete editor.KeyBinding;
let pause_resume = function(){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
};
canvas1.addEventListener('click',function(ev){
if(!(shift && alt) && lastClick&& Date.now()-lastClick<400)
pause_resume();
lastClick = Date.now();
});
canvas1.addEventListener('mouseover', function(e){
over = true;
const mask = 0x8;
flags |= mask;
setUniform('1i', 'flags', flags);
});
canvas1.addEventListener('mousedown', function(e){
moving = true
mouselastX = mouselastY = undefined;
let i = hitTest([2*e.offsetX/ parseInt(canvas1.style.width)-1,
1-2*e.offsetY/ parseInt(canvas1.style.height), -1]);
if(i >= 0)
{
dragging = true;
selected = true;
setUniform("1i", "sel", i);
selection = i;
}
else if(selected = true){
dragging = false;
selected = false;
setUniform("1i", "sel", i);
selection = i;
}
});
canvas1.addEventListener('mousemove', function(e){
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
let dx = (mouselastX - e.offsetX),
dy = (mouselastY - e.offsetY);
if(!selected)
{
mousedx -= dx/60;
mousedy -= dy/60;
positionsupdated = true;
}else if(dragging){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
let dv = matrix_multiply(m, [2*-dx/ parseInt(canvas1.style.width),
2*dy/ parseInt(canvas1.style.height), 0, 1]).slice(0,3);
SphTr[selection] = matrix_multiply(SphTr[selection], matrix_translate(dv[0], dv[1], dv[2]));
}
}
mouselastX = e.offsetX;
mouselastY = e.offsetY;
});
canvas1.addEventListener('mouseup', function(e){
moving = false;
dragging = false;
});
canvas1.addEventListener('mouseout', function(e){
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false;
});
canvas1.addEventListener('wheel', function(e){
if(!selected){
mousedz += e.wheelDelta/600;
positionsupdated = true;
}
else{
SphDletaR[selection] += e.wheelDelta / 800;
}
});
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer";
let rtswitch = function(){
alert('Ray Tracing is always on. See hw2 where rt can be toggled on/off.')
rtx.src='./RTXon.svg';
}
rtx.addEventListener('click', rtswitch);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let fpscounter = function(time){
if (start === undefined)
start = time;
else
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
start = time;
if(fpson)
;//requestAnimationFrame(fpscounter);
else{
start = undefined;
fps.innerHTML = '';
}
};
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Shift'))
shift = true;
if(e.code.startsWith('Control'))
ctrl = true;
if(e.code.startsWith('Alt'))
alt = true;
else if(ctrl && alt && e.code == 'KeyT'){
const mask = 0x1;
flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags);
}
else if (ctrl &&e.code == 'KeyS'){
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
else if(ctrl && alt&&e.code == 'KeyR')
rtswitch();
else if(ctrl && alt&&e.code == 'KeyN')
{
reset.onclick();
}
else if(ctrl && alt&&e.code == 'KeyP')
pause_resume();
else if(ctrl && alt&&e.code == 'KeyF')
if(!fpson)
{
fpson = true;
requestAnimationFrame(fpscounter);
}
else
fpson = false;
if(fullscreen && selected ){
if(/*e.code == 'ArrowUp' || e.code == 'ArrowDown' || e.code =='ArrowLeft'
||e.code == 'ArrowRight' || e.code =='KeyW'||e.code =='KeyS'||*/e.code =='KeyF'||e.code =='KeyB'){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
m = const_multiply((fl + 1 + mousedz)/(fl+1), m);
switch(e.code){
// case 'ArrowUp':
// m = matrix_multiply(m, matrix_rotateX(0.1));
// break;
// case 'ArrowDown':
// m = matrix_multiply(m, matrix_rotateX(-0.1));
// break;
// case 'ArrowLeft':
// m = matrix_multiply(m, matrix_rotateY(-0.1));
// break;
// case 'ArrowRight':
// m = matrix_multiply(m, matrix_rotateY(0.1));
// break;
// case 'KeyW':
// m = matrix_multiply(m, matrix_rotateZ(0.1));
// break;
// case 'KeyS':
// m = matrix_multiply(m, matrix_rotateZ(-0.1));
// break;
case 'KeyB':
var dv = matrix_multiply(m, [0,0, -0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
case 'KeyF':
var dv = matrix_multiply(m, [0,0, 0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
}
SphTr[selection] = matrix_multiply(SphTr[selection], m);
}
}
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
ctrl = false;
if(e.code.startsWith('Alt'))
alt = false;
if(e.code.startsWith('Shift'))
shift = false;
});
function animate(gl) {
let uTime;
if(animating)
{
uTime = (Date.now() - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
else
{
uTime = (lastTime - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
Sph[0] = [0,0.05*Math.cos(uTime + 1.),.045*Math.cos(uTime), 1,.15];
Sph[1] = [0,0,0,1,.25];
Sph[2] = [.22*Math.sin(uTime*1.2),0.05,.22*Math.cos(uTime*1.2),1,.05];
Sph[3] = [.9*Math.sin(uTime*.4),0.,.9*Math.cos(uTime*.4),1,.25];
Sph[4] = [0.5*Math.sin(uTime*1.),0.08*Math.sin(uTime *0.9),.5*Math.cos(uTime*1.),1,.12];
for(let i = 0; i < ns; ++ i)
{
let trsph = matrix_multiply(SphTr[i], Sph[i]);
trsph[3] = Sph[i][4];
setUniform('4fv', 'Sph['+ i + ']', trsph);
}
if(positionsupdated)
updatePositions();
}
requestAnimationFrame(fpscounter);

@ -0,0 +1,165 @@
//Header file, contains global variable definitions,
// asynchronized shader loading and utility functions
let mousedx = 0, mousedy = 0, mousedz = 0;
let seldx = 0, seldy = 0, seldz = 0;
var cx = 1, cy = 1, sx = 0, sy = 0;
let mouselastX, mouselastY;
const fl = 3;
let start;
var vs, fs;
var vsfetch = new XMLHttpRequest();
var editor = undefined
let cos = Math.cos, sin = Math.sin, tan = Math.tan,
acos = Math.acos, asin = Math.asin, atan = Math.atan,
sqrt = Math.sqrt;
let positionsupdated = true;
vsfetch.open('GET', './shader.vert');
vsfetch.onloadend = function () {
vs = vsfetch.responseText;
};
vsfetch.send();
//* LOADING FRAGMENT SHADER
var client = new XMLHttpRequest();
client.open('GET', './shader.frag');
client.onloadend = function () {
fs = (client.responseText);
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
if (editor != undefined)
editor.getSession().setValue(fs);
};
client.send();
// 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;
}
// 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) => {
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) => {
let m = [];
for(let i = 0; i < a.length; ++ i)
m[i] = a[i] * c;
return m;
}
function dot(a, b){
let m = 0;
for(let i = 0; i < a.length; ++i)
m += a[i] * b[i];
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;
}
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]]);
positionsupdated = false;
}
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, 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;
}

@ -0,0 +1,189 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
let ns = 5, cns = 5;
fragmentShaderHeader+= 'const int ns = ' + ns + ';\n';
let fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
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 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 isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = 'Build Your Own Universe!';
// 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;
for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i;
}
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
positionsupdated = true;
let attribs = [
.05,.05,.1, .5,.5,1., 1.,.5,.5,20., 0., .0, 1.3,
.1,.05,.05, 1.,.5,.5, 1.,.5,.5,10., .3,1.,1.3,
.1,.05,.05, .71,.71,.71, .71,.71,.71,10., 0.3,.0,1.5,
.1,.1,.1, .71,.71,.71, .71,.71,.71,10., 0.05,0., 1.,
.0,.0,.0, .0,.0,.0, .0,.0,.0,40., 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('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));
}
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);
let aPos = gl.getAttribLocation(program, 'aPos'); // Set aPos attribute for each vertex.
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0);
}
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);
}
}

@ -0,0 +1,235 @@
#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 sampler2D uSampler[ns];
uniform vec3 V0;
uniform int sel;
const float kf_air = 1.000293;
varying vec3 trPos;
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;
} 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);
}
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);
bool rtxoff = false, showtexture = true, selected = false;
float currentK = 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;
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;
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin)
{
vec3 texture_color;
if(showtexture)
{
vec3 tex_sph = (S-Sph[i].xyz);
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
}
else texture_color = foregroundColor;
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(rtxoff || final) //if it's the last hit
{
color += Specular[i].xyz*pow(max(0.,
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
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); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}else{
if(refl)
{ //remember, c1 = -NW now
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}
break;
}
scolor += color * currentK;
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.)
{
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(rtxoff || 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); //reflection
else
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15); //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;
gl_FragColor=vec4(sqrt(scolor),1.);
}

@ -0,0 +1,16 @@
attribute vec3 aPos;
varying vec3 trPos;
uniform mat3 transformation;
//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() {
gl_Position = vec4(aPos, 1.);
trPos = transformation *vec3(aPos.xy, -1);
}

BIN
hw5/.DS_Store vendored

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

@ -0,0 +1,235 @@
#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 sampler2D uSampler[ns];
uniform vec3 V0;
uniform int sel;
const float kf_air = 1.000293;
varying vec3 trPos;
const float pi=3.14159265359;
const float _2pi=2.*pi;
/***********PLEASE DO INCREASE n_ref(RT DEPTH) FOR BETTER RESULTS************/
/*---->*/const int n_ref=7; //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;
} 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);
}
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);
bool rtxoff = false, showtexture = true, selected = false;
float currentK = 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;
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;
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin)
{
vec3 texture_color;
if(showtexture)
{
vec3 tex_sph = (S-Sph[i].xyz);
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
}
else texture_color = foregroundColor;
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(rtxoff || final) //if it's the last hit
{
color += Specular[i].xyz*pow(max(0.,
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
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); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}else{
if(refl)
{ //remember, c1 = -NW now
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}
break;
}
scolor += color * currentK;
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.)
{
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(rtxoff || 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); //reflection
else
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15); //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;
gl_FragColor=vec4(sqrt(scolor),1.);
}

@ -0,0 +1,16 @@
attribute vec3 aPos;
varying vec3 trPos;
uniform mat3 transformation;
//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() {
gl_Position = vec4(aPos, 1.);
trPos = transformation *vec3(aPos.xy, -1);
}

@ -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,111 @@
<!--<video src="pjsk.mp4" id="pjsk" 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=lib4.header.js></script>
<script src=lib4.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>
Space Walk
<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><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:800px;height:2200px;"></div>
</td><td valign=top style="background-color:azure;opacity: 95%;">
<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=" overflow: hidden !important; width: 600px !important; height:600px !important;" width=599 height=599></canvas>
</center>
</body>
<div id="controls">
<input type="number" id="ins" style="margin-left:0px;font-size:24px;width:35px;height:45px" value="5" max="5" min = "1">
<button id="bns" style="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="1" max="4" min = "0.25" 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="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:280px;height:45px">Move Lighting & Texture</button>
<div style='font-size:25px;'>
<font color=#909090>
<i style="font-size:25px;">What's new: </i>
<p style="font-size:20px;">
&nbsp;&nbsp;&nbsp;&nbsp;I created a little figure that can walk. First, press "Fullscreen" button. In fullscreen mode, <a style="font-size:25px;color:red;"><strong>the figure is able to walk
in four directions when pressing corresponding arrow keys.</strong></a><br>
&nbsp;&nbsp;&nbsp;&nbsp; I added normal calculation to every shape I created and then I added phong shading to the scene. <br>
&nbsp;&nbsp;&nbsp;&nbsp; As before, you can rotate the scene by dragging on the canvas.<br>
&nbsp;&nbsp;&nbsp;&nbsp;I added new shapes such as torus and cubes.</strong><br>
&nbsp;&nbsp;&nbsp;&nbsp;<strong>If you found the scene somehow clipped, it seems to be a bug of chromium, please simply click on 'Super Sampling' button
or refresh the page. .</strong>
</p>
<div id="howitworks">
<br>
<i style="font-size:25px;">How it works:</i><br>
<p style="font-size:20px;">
I used the matrix stack to push and pop transformations to create the figure and move it around. The entire scene is then transformed to apply movements and global rotations.<br>
The mesh creation functions and transformation methods are implemented in <a href="./lib4.header.js">lib4.header.js</a><br>
Animating function and are in <a href="./lib4.ext.js">lib4.ext.js</a><br>
<a href="./shader.vert">shader.vert</a> is the vertex shader.<br>
<a href="./lib4.js">lib4.js</a> most contains initialization methods for the renderer. You can also see how I passes more attributes like surface normal and
object id to the shaders.<br>
<a href="./index.html">index.html</a> is almost pure html.<br>
</p>
</div>
<p>
</div>
</div></td>
</tr></table>
</TR></TABLE>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script src="lib4.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,593 @@
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let lastClick = undefined;
let animating = true;
let flags = 0x0;
var startTime = Date.now();
let lastTime = Date.now();
var lastFrameTime = 0;
let oldDocument;
let fullscreen = false, btntoggled = false;
let movescene = true;
let oldparents = {};
var tr, div;
let canvas_originalsize;
let Sph = [];
let SphTr = [];
let SphDletaR = []
let selected = false, selection = -1, dragging = false;
let overall_trans = matrix_identity();
let rebuild = true, presentation = true, sRotation = matrix_identity();
let facing = 1, running = 0;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
function toggleFullscreen(element){
if(fullscreen)
{
if (document.exitFullscreen)
document.exitFullscreen();
else if (document.webkitExitFullscreen)
document.webkitExitFullscreen();
else if (document.mozCancelFullScreen)
document.mozCancelFullScreen();
else if (document.msExitFullscreen)
document.msExitFullscreen();
fullscreen = false;
bnfs.innerText = "Fullscreen";
}
else{
if(element.requestFullscreen)
element.requestFullscreen();
else if (element.webkitRequestFullscreen)
element.webkitRequestFullscreen();
else if(element.msRequestFullscreen)
element.msRequestFullscreen();
fullscreen = true;
bnfs.innerText = "Exit Fullscreen";
}
}
bnfs.onclick = function(e){
if(e === "no")
;
else
btntoggled = true;
if(fullscreen){
oldparents[controls].appendChild(controls);
oldparents[canvas1].appendChild(canvas1);
canvas1.style.width = canvas_originalsize[0];
canvas1.style.height = canvas_originalsize[1];
howitworks.hidden = false;
}else{
div = document.createElement("div");
tr = document.createElement("table").insertRow();
tr.style.backgroundColor="white";
let size = Math.min(screen.availHeight, screen.availWidth);
canvas_originalsize = [canvas1.style.width, canvas1.style.height, canvas1.width, canvas1.height];
canvas1.style.height = canvas1.style.width = size;
howitworks.hidden=true;
oldparents[controls] = controls.parentNode;
oldparents[canvas1] = canvas1.parentNode;
let td1 = tr.insertCell();
td1.appendChild(canvas1);
let td2;
td2 = tr.insertCell();
td2.style.verticalAlign="top";
td2.appendChild(controls);
div.appendChild(tr);
document.body.appendChild(div);
}
toggleFullscreen(div);
}
mov.onclick=function(_){
movescene = !movescene;
if(!movescene)
{
mov.innerText= "Move Scene";
mov.style.width = "170px";
}
else
{
mov.innerText = "Move Lighting&Texture";
mov.style.width = "280px";
}
}
document.addEventListener("webkitfullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
document.addEventListener("fullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
clrsel.onclick=function(_){
setUniform("1i", "sel", -1);
selected = false;
selection = -1;
}
reset.onclick = function(_){
clrsel.onclick();
if(!animating)
pause_resume();
flags = 0;
moving = false;
mousedx = mousedy = mousedz = 0;
positionsupdated = true;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
rtx.src='./RTXon.svg';
setUniform('1i', 'flags', flags);
}
bns.onclick=function(e){
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
{
cns = ins.value;
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue());
}
}
bnsamp.onclick=function(e){
let multiplier = insamp.value;
let w = parseInt(canvas1.style.width)*multiplier;
let h = parseInt(canvas1.style.height)*multiplier;
canvas1.height = h;
canvas1.width = w;
gl.viewport(0, 0, w, h);
//gl.clearRect(0, 0, w, h);
}
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
if(fs != undefined)
editor.getSession().setValue(fs);
editor.session.on('change', function(delta) {
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
});
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
delete editor.KeyBinding;
let pause_resume = function(){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
};
canvas1.addEventListener('click',function(ev){
if(!(shift && alt) && lastClick&& Date.now()-lastClick<400)
pause_resume();
lastClick = Date.now();
});
canvas1.addEventListener('mouseover', function(e){
over = true;
const mask = 0x8;
flags |= mask;
setUniform('1i', 'flags', flags);
});
canvas1.addEventListener('mousedown', function(e){
moving = true
mouselastX = mouselastY = undefined;
let i = hitTest([2*e.offsetX/ parseInt(canvas1.style.width)-1,
1-2*e.offsetY/ parseInt(canvas1.style.height), -1]);
if(i >= 0)
{
dragging = true;
selected = true;
setUniform("1i", "sel", i);
selection = i;
}
else if(selected = true){
dragging = false;
selected = false;
setUniform("1i", "sel", i);
selection = i;
}
});
canvas1.addEventListener('mousemove', function(e){
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
let dx = (mouselastX - e.offsetX),
dy = (mouselastY - e.offsetY);
if(movescene){
sRotation = matrix_multiply(sRotation, matrix_rotateY(-dy/60));
sRotation = matrix_multiply(sRotation, matrix_rotateX(-dx/60));
}
else if(!selected)
{
mousedx -= dx/60;
mousedy -= dy/60;
positionsupdated = true;
}else if(dragging){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
let dv = matrix_multiply(m, [2*-dx/ parseInt(canvas1.style.width),
2*dy/ parseInt(canvas1.style.height), 0, 1]).slice(0,3);
SphTr[selection] = matrix_multiply(SphTr[selection], matrix_translate(dv[0], dv[1], dv[2]));
}
}
mouselastX = e.offsetX;
mouselastY = e.offsetY;
});
canvas1.addEventListener('mouseup', function(e){
moving = false;
dragging = false;
});
canvas1.addEventListener('mouseout', function(e){
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false;
});
canvas1.addEventListener('wheel', function(e){
if(!selected){
mousedz += e.wheelDelta/600;
positionsupdated = true;
}
else{
SphDletaR[selection] += e.wheelDelta / 800;
}
});
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer";
let rtswitch = function(){
alert('Ray Tracing is always on. See hw2 where rt can be toggled on/off.')
rtx.src='./RTXon.svg';
}
rtx.addEventListener('click', rtswitch);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let fpscounter = function(time){
if (start === undefined)
start = time;
else
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
start = time;
if(fpson)
;//requestAnimationFrame(fpscounter);
else{
start = undefined;
fps.innerHTML = '';
}
};
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Shift'))
shift = true;
if(e.code.startsWith('Control'))
ctrl = true;
if(e.code.startsWith('Alt'))
alt = true;
else if(ctrl && alt && e.code == 'KeyT'){
const mask = 0x1;
flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags);
}
else if (ctrl &&e.code == 'KeyS'){
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
else if(ctrl && alt&&e.code == 'KeyR')
rtswitch();
else if(ctrl && alt&&e.code == 'KeyN')
{
reset.onclick();
}
else if(ctrl && alt&&e.code == 'KeyP')
pause_resume();
else if(ctrl && alt&&e.code == 'KeyF')
if(!fpson)
{
fpson = true;
requestAnimationFrame(fpscounter);
}
else
fpson = false;
if(e.code == 'ArrowUp' || e.code == 'ArrowDown' || e.code =='ArrowLeft'
||e.code == 'ArrowRight' || e.code =='KeyW'||e.code =='KeyS')
{
switch(e.code){
case 'ArrowUp':
facing = -2;
break;
case 'ArrowDown':
facing = 2;
break;
case 'ArrowLeft':
facing = -1;
break;
case 'ArrowRight':
facing = 1;
break;
case 'KeyW':
break;
case 'KeyS':
break;
}
running = 20;
rebuild = true;
}
if(fullscreen && selected ){
if(e.code =='KeyF'||e.code =='KeyB'){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
m = const_multiply((fl + 1 + mousedz)/(fl+1), m);
switch(e.code){
case 'KeyB':
var dv = matrix_multiply(m, [0,0, -0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
case 'KeyF':
var dv = matrix_multiply(m, [0,0, 0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
}
SphTr[selection] = matrix_multiply(SphTr[selection], m);
}
}
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
ctrl = false;
if(e.code.startsWith('Alt'))
alt = false;
if(e.code.startsWith('Shift'))
shift = false;
});
let squareMesh = new Float32Array([ -1,-1,1,0,0,0,0,0,-1, 1,1,0,0,0,0,0,-1, -1,-1,0,0,0,0,0, -1,1,-1,0 ,0,0,0,0]);
let sphereMesh = createMesh(32, 32, uvToSphere);
let tubeMesh = createMesh(32, 2, uvToTube,0,1);
let diskMesh = createMesh(32, 2, uvToDisk,0,1);
let tubeMesh2 = createMesh(32, 2, uvToTube,0,2);
let diskNMesh2 = createMesh(32, 2, uvToDisk, -1,2);
let diskPMesh2 = createMesh(32, 2, uvToDisk, 1,2);
let tubeMesh3 = createMesh(32, 2, uvToTube,0,3);
let diskNMesh3 = createMesh(32, 2, uvToDisk, -1,3);
let diskPMesh3 = createMesh(32, 2, uvToDisk, 1,3);
let diskNMesh = createMesh(32, 2, uvToDisk, -1,1);
let diskPMesh = createMesh(32, 2, uvToDisk, 1,1);
let cylinderMesh = glueMeshes(glueMeshes(tubeMesh, diskPMesh), diskNMesh);
let cylinderMesh2 = glueMeshes(glueMeshes(tubeMesh2, diskPMesh2), diskNMesh2);
let cylinderMesh3 = glueMeshes(glueMeshes(tubeMesh3, diskPMesh3), diskNMesh3);
let torusMash = createMesh(32, 32, uvToTorus, 1, 5);
let head = createCube(1.5,1,1, 4);
let objects = [];
let addObject = (obj, mat) => {
objects.push([obj, mat]);
};
let clearObject = () => {delete objects; objects = [];};
let delta_height = 0, delta_l = [0,0];
class State{
constructor() {
this.leg = true;
this.progress = 0;
this.rh = this.lh = .5*pi;
this.lf = this.rf = 0;
}
initialize(){
this.leg = true;
this.progress = 0;
}
next(){
//return this.presentation();
if(running <= 0)
return {rh:.5*pi, lh:.5*pi, rf:0, lf:0, dh:0,dl:0}
running --;
const steps = 100;
let dl = 0;
if(this.progress >= steps/2)
{
this.progress = 0;
this.leg = !this.leg;
}
let delta = [-pi/5, 0.5*pi, 0.44*pi, 0.55*pi];
for (let i = 0; i < 4; ++i) delta[i] /= steps;
if(this.leg)
{
if(this.progress < steps/4)
{
this.lh += delta[0];
this.rh += delta[3];
this.lf += delta[1];
this.rf += delta[2];
}
else{
this.lh -= delta[0];
this.rh -= delta[3];
this.lf -= delta[1];
this.rf-= delta[2];
}
}
else{
if(this.progress < steps/4)
{
this.lh += delta[3];
this.rh += delta[0];
this.lf += delta[2];
this.rf += delta[1];
}
else{
this.lh -= delta[3];
this.rh -= delta[0];
this.lf -= delta[2];
this.rf-= delta[1];
}
}
let delta_h = Math.max((1-cos(abs(this.lh - pi/2)))*.5+(1-cos(abs(this.lf)))*.6,(1-cos(abs(this.rh - pi/2)))*.5+(1-cos(abs(this.rf)))*.6);
this.progress++;
return {lh:this.lh, lf:this.lf, rh:this.rh,rf:this.rf, dh:delta_h, dl:1.8522/steps};
}
// presentation(){
// return {lh:.4*pi, lf:pi/6,rh:.7*pi, rf:pi/8, dh:0};
// }
};
let build_objects = (state)=>{
if(running === 0)
rebuild = false;
let {lh, lf, rh, rf, dh, dl} = state.next();
delta_l[abs(facing)-1] += 0.3* Math.sign(facing) * dl;
delta_height = dh;
clearObject();
M.save();
M.save();
M.rotateX(pi/2);
M.scale(0.5, 0.5, 1);
addObject(cylinderMesh, M.value());
M.restore();
M.save();
M.translate(0,1,0);
addObject(head, M.value());
M.restore();
M.save();
M.translate(0.5, 0.2, 0.3);
M.rotateX(pi/4);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.4);
M.rotateX(-0.53*pi);
M.scale(0.2, 0.2, 0.4);
M.translate(0,0,1);
addObject(cylinderMesh2, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh2, M.value());
M.restore();
M.save();
M.translate(-0.5, 0.2, 0.3);
M.rotateX(pi/4);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.4);
M.rotateX(-0.55*pi);
M.scale(0.2, 0.2, 0.4);
M.translate(0,0,1);
addObject(cylinderMesh2, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh2, M.value());
M.restore();
M.save();
M.translate(0.3, -1, 0.);
M.rotateX(lh);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.45);
M.rotateX(lf);
M.scale(0.2, 0.2, 0.6);
M.translate(0,0,1);
addObject(cylinderMesh3, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh3, M.value());
M.restore();
M.save();
M.translate(-0.3, -1, 0.);
M.rotateX(rh);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.45);
M.rotateX(rf);
M.scale(0.2, 0.2, 0.6);
M.translate(0,0,1);
addObject(cylinderMesh3, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh3, M.value());
M.restore();
M.restore();
//rebuild = false;
};
let state = new State();
var M = new Matrix();
function animate(gl) {
let uTime;
if(animating)
{
uTime = (Date.now() - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
else
{
uTime = (lastTime - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
Sph[0] = [0,0.05*Math.cos(uTime + 1.),.045*Math.cos(uTime), 1,.15];
Sph[1] = [0,0,0,1,.25];
Sph[2] = [.22*Math.sin(uTime*1.2),0.05,.22*Math.cos(uTime*1.2),1,.05];
Sph[3] = [.9*Math.sin(uTime*.4),0.,.9*Math.cos(uTime*.4),1,.25];
Sph[4] = [0.5*Math.sin(uTime*1.),0.08*Math.sin(uTime *0.9),.5*Math.cos(uTime*1.),1,.12];
for(let i = 0; i < ns; ++ i)
{
let trsph = matrix_multiply(SphTr[i], Sph[i]);
trsph[3] = Sph[i][4];
setUniform('4fv', 'Sph['+ i + ']', trsph);
}
if(presentation){
M.save();
M.scale(0.3);
M.rotateY(uTime/5);
M.rotateX(1);
M.translate(delta_l[0], -delta_height, delta_l[1]);
if(facing !=2)
M.rotateY(pi*(facing/2));
//M.translate(0, -delta_height, 0);
overall_trans = M.value();
M.restore();
}else{
M.save();
// M.rotateY(2);
M.rotateX(1);
M.scale(0.3);
M.translate(delta_l[0], -delta_height, delta_l[1]);
overall_trans = M.value();
M.restore();
}
if(rebuild)
build_objects(state);
for(const [obj, mat] of objects){
drawMesh(obj, matrix_multiply(sRotation,matrix_multiply(overall_trans, mat)));
}
M.save();
M.scale(0.1);
M.translate(6,0,1);
M.rotateX(1);
M.rotateY(uTime/4);
drawMesh(torusMash, M.value());
M.restore();
if(positionsupdated)
updatePositions();
}
requestAnimationFrame(fpscounter);
//pjsk.play();

@ -0,0 +1,332 @@
//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;
var mouselastX, mouselastY;
const fl = 3;
let start;
var vs, fs;
var vsfetch = new XMLHttpRequest();
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;
var positionsupdated = true;
vsfetch.open('GET', './shader.vert');
vsfetch.onloadend = function () {
vs = vsfetch.responseText;
};
vsfetch.send();
//* LOADING FRAGMENT SHADER
var client = new XMLHttpRequest();
client.open('GET', './shader.frag');
client.onloadend = function () {
fs = (client.responseText);
//* START EVERYTHING AFTER FRAGMENT SHADER IS DOWNLOADED.
if (editor != undefined)
editor.getSession().setValue(fs);
};
client.send();
// 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;
}
// 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) => {
let m = [];
for(let i = 0; i < a.length; ++ i)
m[i] = a[i] * c;
return m;
}
function dot(a, b){
let m = 0;
for(let i = 0; i < a.length; ++i)
m += a[i] * b[i];
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.value = () => m[top];
this.save = () => { m[top+1] = m[top].slice(); top++; }
this.restore = () => --top;
}
//------ 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);
}
// 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);
// let verts = [];
// for(let i = -w/2; i < w; i += w)
// for(let j = -h/2; j < h; j += h)
// for (let k = -l/2; k < l; k += l)
// verts.push([id, i, j, k]);
// let mesh = [];
// let n = 0;
// for(let j = 0; j < 4; ++ j)
// mesh = mesh.concat(verts[j]);
// for(let i = 0; i < 2; ++ i)
// for(let j = 0; j < 2; ++ j)
// mesh = mesh.concat(verts[6 - i*2 + j]);
// for(let j = 0; j < 2; ++ j)
// mesh = mesh.concat(verts[j]);
// mesh = mesh.concat(verts[5]);
// mesh = mesh.concat(verts[3]);
// mesh = mesh.concat(verts[7]);
// mesh = mesh.concat(verts[7]);
// mesh = mesh.concat(verts[6]);
// mesh = mesh.concat(verts[6]);
// mesh = mesh.concat(verts[4]);
// mesh = mesh.concat(verts[2]);
// mesh = mesh.concat(verts[0]);
// return new Float32Array(mesh);
//CREATING CUBES THIS WAY REDUCES VERTICES BUT MAKES IT HARDER TO DO LIGHTING
}
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]]);
positionsupdated = false;
}
function hitTest(pos){
if(!enableSelection)
return -1;
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, 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;
}

@ -0,0 +1,211 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
var ns = 5, cns = 5;
fragmentShaderHeader+= 'const int ns = ' + ns + ';\n';
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
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 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 isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = 'Build Your Own Universe!';
// 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;
for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i;
}
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
positionsupdated = true;
let attribs = [
.05,.05,.1, .5,.5,1., 1.,.5,.5,20., 0., .0, 1.3,
.1,.05,.05, 1.,.5,.5, 1.,.5,.5,10., .3,1.,1.3,
.1,.05,.05, .71,.71,.71, .71,.71,.71,10., 0.3,.0,1.5,
.1,.1,.1, .71,.71,.71, .71,.71,.71,10., 0.05,0., 1.,
.0,.0,.0, .0,.0,.0, .0,.0,.0,40., 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('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));
}
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);
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;
let drawMesh = (mesh, m) => {
setUniform('Matrix4fv', 'uMatrix', false, m);
gl.bufferData(gl.ARRAY_BUFFER, mesh, gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, mesh.length / VERTEX_SIZE);
}

Binary file not shown.

@ -0,0 +1,253 @@
#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 sampler2D uSampler[ns];
uniform vec3 V0;
uniform int sel;
const float kf_air = 1.000293;
varying vec3 trPos;
varying vec3 norm;
varying float id;
varying vec3 glpos;
varying vec3 apos;
const float pi=3.14159265359;
const float _2pi=2.*pi;
vec3 LDir=vec3(.5,.5,.5);
vec3 LCol=vec3(1.,1.,1.);
/***********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.
/**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;
} 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);
}
void rtx(){
float currKf = kf_air;
vec3 color=vec3(.2, .3, .5);
vec3 V = V0;
vec3 W=(trPos-V);
bool rtxoff = false, showtexture = true, selected = false;
float currentK = 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;
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;
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < cns; ++ i)
if(i == iMin)
{
vec3 texture_color;
if(showtexture)
{
vec3 tex_sph = (S-Sph[i].xyz);
texture_color=texture2D(uSampler[i],getTextCoord(tex_sph, Sph[i].w)).xyz;
}
else texture_color = foregroundColor;
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(rtxoff || final) //if it's the last hit
{
color += Specular[i].xyz*pow(max(0.,
dot(-2.*c1*N-realLDir,realLDir)),Specular[i].w);
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); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack2[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack2[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}else{
if(refl)
{ //remember, c1 = -NW now
stack1[k] = Ray(S, 2. * c1 * N + W, currKf, nextks); //reflection
currentK -= nextks;
next_top ++;
}
if(refr)
{
if(refl)
stack1[k+1] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
else
stack1[k] = Ray(S, REFRACTION, nextkf, nextkr); //refraction
currentK -= nextkr;
next_top ++;
}
}
break;
}
scolor += color * currentK;
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.)
{
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(rtxoff || 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); //reflection
else
stack1[k] = Ray(S, vec3(W.x, -W.y, W.z), kf_air, currentK * 0.15); //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;
gl_FragColor=vec4((scolor),1.);
}
void main(){
vec3 color =foregroundColor.xyz;
float sp = 0.4, df = 0.4, amb = 0.4;
if(id == 4.) {rtx();color = gl_FragColor.xyz;}
else if (id == 1.) color = vec3(1.,.4,.6);
else if (id == 5.) {color = vec3(1, .9375,.7329);sp = .5; df=.8; amb = .05;}
vec3 V = V0;
vec3 W=normalize(glpos-V);
vec3 realLDir=normalize(LDir - glpos);
color = color*(amb+ df*max(0.,dot(norm,realLDir)))//specular for ground.
+ sp*pow(max(0., dot(2.*dot(norm, realLDir)*norm-realLDir, -W)),5.)*vec3(1,1,1);
gl_FragColor=vec4(sqrt(color), 1.);
}

@ -0,0 +1,20 @@
uniform mat4 uMatrix;
uniform mat3 transformation;
attribute float oid;
attribute vec3 aPos;
attribute vec3 normal;
varying vec3 trPos;
varying float id;
varying vec3 norm;
varying vec3 glpos;
varying vec3 apos;
void main() {
vec4 pos = uMatrix * vec4(aPos, 1.);
gl_Position = pos * vec4(1., 1., -1., 1.);
id = oid;
norm = normalize((uMatrix*vec4(normal,0.)).xyz);
trPos = transformation *vec3(pos.xy, -1);
apos = aPos;
glpos = gl_Position.xyz;
}

@ -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,109 @@
<!--<video src="pjsk.mp4" id="pjsk" 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=lib6.header.js></script>
<script src=lib6.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>
Spring Break
<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><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:800px;height:2200px;"></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:100px;height:45px">Pause</button>
<div style='font-size:25px;'>
<font color=#909090>
<i style="font-size:25px;">What's new: </i>
<p style="font-size:20px;">
&nbsp;&nbsp;&nbsp;&nbsp; I corrected the Phong lighting, added perspective and implemented both splines.<br>
&nbsp;&nbsp;&nbsp;&nbsp; Since we're learning splines. I figured it would be interesting to
do vector graphics.<br>
&nbsp;&nbsp;&nbsp;&nbsp; It seems that most paths in a svg file (see <a href="./paths.txt">path.txt</a>)
are a combination multiple of end-to-end Bezier Splines.<br>
&nbsp;&nbsp;&nbsp;&nbsp; I created these shapes in Adobe Illustrator and output them to svg.<br>
&nbsp;&nbsp;&nbsp;&nbsp;I processed the path data in (see <a href="./lib6.header.js">lib6.header.js</a>) and
transformed them into multiple Bezier functions and then interpolated them in <a href="./lib6.ext.js">lib6.ext.js</a>
so that they appears to be smooth shapes.
<br>
&nbsp;&nbsp;&nbsp;&nbsp; I also made animations with Hermite Splines.<br>
&nbsp;&nbsp;&nbsp;&nbsp; As before, you can 'walk' by pressing arrow keys, it's now looked more like it because
I added a ground and the scene is now perspective. Again, better used in Fullscreen mode.<br>
</p>
<div id="howitworks">
<br>
</div>
<p>
</div>
</div></td>
</tr></table>
</TR></TABLE>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script src="lib6.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,795 @@
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let lastClick = undefined;
let animating = true;
let flags = 0x0;
var startTime = Date.now();
let lastTime = Date.now();
var lastFrameTime = 0;
let oldDocument;
let fullscreen = false, btntoggled = false;
let movescene = true;
let oldparents = {};
var tr, div;
let canvas_originalsize;
let Sph = [];
let SphTr = [];
let SphDletaR = []
let selected = false, selection = -1, dragging = false;
let overall_trans = matrix_identity(), overall_ground;
let rebuild = true, buildsplines = true, presentation = false, sRotation = matrix_identity();
let facing = 1, running = 0;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
function ev_supersample(e){
let multiplier = insamp.value;
let w = parseInt(canvas1.style.width)*multiplier;
let h = parseInt(canvas1.style.height)*multiplier;
canvas1.height = h;
canvas1.width = w;
gl.viewport(0, 0, w, h);
//gl.clearRect(0, 0, w, h);
}
function toggleFullscreen(element){
if(fullscreen)
{
if (document.exitFullscreen)
document.exitFullscreen();
else if (document.webkitExitFullscreen)
document.webkitExitFullscreen();
else if (document.mozCancelFullScreen)
document.mozCancelFullScreen();
else if (document.msExitFullscreen)
document.msExitFullscreen();
fullscreen = false;
bnfs.innerText = "Fullscreen";
}
else{
if(element.requestFullscreen)
element.requestFullscreen();
else if (element.webkitRequestFullscreen)
element.webkitRequestFullscreen();
else if(element.msRequestFullscreen)
element.msRequestFullscreen();
fullscreen = true;
bnfs.innerText = "Exit Fullscreen";
}
}
bnfs.onclick = function(e){
if(e === "no")
;
else
btntoggled = true;
if(fullscreen){
oldparents[controls].appendChild(controls);
oldparents[canvas1].appendChild(canvas1);
canvas1.style.width = canvas_originalsize[0];
canvas1.style.height = canvas_originalsize[1];
howitworks.hidden = false;
}else{
div = document.createElement("div");
tr = document.createElement("table").insertRow();
tr.style.backgroundColor="white";
let size = Math.min(screen.availHeight, screen.availWidth);
canvas_originalsize = [canvas1.style.width, canvas1.style.height, canvas1.width, canvas1.height];
canvas1.style.height = canvas1.style.width = size;
howitworks.hidden=true;
oldparents[controls] = controls.parentNode;
oldparents[canvas1] = canvas1.parentNode;
let td1 = tr.insertCell();
td1.appendChild(canvas1);
let td2;
td2 = tr.insertCell();
td2.style.verticalAlign="top";
td2.appendChild(controls);
div.appendChild(tr);
document.body.appendChild(div);
}
toggleFullscreen(div);
ev_supersample();
}
mov.onclick=function(_){
movescene = !movescene;
if(!movescene)
{
mov.innerText= "Move Scene";
mov.style.width = "170px";
}
else
{
mov.innerText = "Move Lighting";
mov.style.width = "180px";
}
}
document.addEventListener("webkitfullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
document.addEventListener("fullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
clrsel.onclick=function(_){
setUniform("1i", "sel", -1);
selected = false;
selection = -1;
}
reset.onclick = function(_){
clrsel.onclick();
if(!animating)
pause_resume();
flags = 0;
moving = false;
mousedx = mousedy = mousedz = 0;
positionsupdated = true;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
rtx.src='./RTXon.svg';
setUniform('1i', 'flags', flags);
}
bns.onclick=function(e){
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
{
cns = ins.value;
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue());
}
}
bnsamp.onclick=ev_supersample;
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
if(fs != undefined)
editor.getSession().setValue(fs);
editor.session.on('change', function(delta) {
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
});
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
delete editor.KeyBinding;
let pause_resume = function(){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
};
canvas1.addEventListener('click',function(ev){
if(!(shift && alt) && lastClick&& Date.now()-lastClick<200)
pause_resume();
lastClick = Date.now();
});
pause.onclick = pause_resume;
canvas1.addEventListener('mouseover', function(e){
over = true;
const mask = 0x8;
flags |= mask;
setUniform('1i', 'flags', flags);
});
canvas1.addEventListener('mousedown', function(e){
moving = true
mouselastX = mouselastY = undefined;
let i = hitTest([2*e.offsetX/ parseInt(canvas1.style.width)-1,
1-2*e.offsetY/ parseInt(canvas1.style.height), -1]);
if(i >= 0)
{
dragging = true;
selected = true;
setUniform("1i", "sel", i);
selection = i;
}
else if(selected = true){
dragging = false;
selected = false;
setUniform("1i", "sel", i);
selection = i;
}
});
canvas1.addEventListener('mousemove', function(e){
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
let dx = (mouselastX - e.offsetX),
dy = (mouselastY - e.offsetY);
if(movescene){
sRotation = matrix_multiply(sRotation, matrix_rotateY(-dy/60));
sRotation = matrix_multiply(sRotation, matrix_rotateX(-dx/60));
}
else if(!selected)
{
mousedx -= dx/60;
mousedy -= dy/60;
positionsupdated = true;
}else if(dragging){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
let dv = matrix_multiply(m, [2*-dx/ parseInt(canvas1.style.width),
2*dy/ parseInt(canvas1.style.height), 0, 1]).slice(0,3);
SphTr[selection] = matrix_multiply(SphTr[selection], matrix_translate(dv[0], dv[1], dv[2]));
}
}
mouselastX = e.offsetX;
mouselastY = e.offsetY;
});
canvas1.addEventListener('mouseup', function(e){
moving = false;
dragging = false;
});
canvas1.addEventListener('mouseout', function(e){
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false;
});
canvas1.addEventListener('wheel', function(e){
if(!selected){
mousedz += e.wheelDelta/600;
positionsupdated = true;
}
else{
SphDletaR[selection] += e.wheelDelta / 800;
}
});
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer";
let rtswitch = function(){
alert('Ray Tracing is off due to global silicon shortage. \nSend me an RTX 3090 to enable Ray Tracing again.')
rtx.src='./RTXon.svg';
}
rtx.addEventListener('click', rtswitch);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let fpscounter = function(time){
if (start === undefined)
start = time;
else
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
start = time;
if(fpson)
;//requestAnimationFrame(fpscounter);
else{
start = undefined;
fps.innerHTML = '';
}
};
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Shift'))
shift = true;
if(e.code.startsWith('Control'))
ctrl = true;
if(e.code.startsWith('Alt'))
alt = true;
else if(ctrl && alt && e.code == 'KeyT'){
const mask = 0x1;
flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags);
}
else if (ctrl &&e.code == 'KeyS'){
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
else if(ctrl && alt&&e.code == 'KeyR')
rtswitch();
else if(ctrl && alt&&e.code == 'KeyN')
{
reset.onclick();
}
else if(ctrl && alt&&e.code == 'KeyP')
pause_resume();
else if(ctrl && alt&&e.code == 'KeyF')
if(!fpson)
{
fpson = true;
requestAnimationFrame(fpscounter);
}
else
fpson = false;
if(e.code == 'ArrowUp' || e.code == 'ArrowDown' || e.code =='ArrowLeft'
||e.code == 'ArrowRight' || e.code =='KeyW'||e.code =='KeyS')
{
switch(e.code){
case 'ArrowUp':
facing = -2;
break;
case 'ArrowDown':
facing = 2;
break;
case 'ArrowLeft':
facing = -1;
break;
case 'ArrowRight':
facing = 1;
break;
case 'KeyW':
break;
case 'KeyS':
break;
}
running = 50;
rebuild = true;
}
if(fullscreen && selected ){
if(e.code =='KeyF'||e.code =='KeyB'){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
m = const_multiply((fl + 1 + mousedz)/(fl+1), m);
switch(e.code){
case 'KeyB':
var dv = matrix_multiply(m, [0,0, -0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
case 'KeyF':
var dv = matrix_multiply(m, [0,0, 0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
}
SphTr[selection] = matrix_multiply(SphTr[selection], m);
}
}
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
ctrl = false;
if(e.code.startsWith('Alt'))
alt = false;
if(e.code.startsWith('Shift'))
shift = false;
});
let squareMesh = new Float32Array([ -1,-1,1,0,0,0,1,-1, 1,1,0,0,0,1,-1, -1,-1,0,0,0,1, -1,1,-1,0 ,0,0,1]);
let sphereMesh = createMesh(32, 32, uvToSphere);
let tubeMesh = createMesh(32, 2, uvToTube,0,1);
let diskMesh = createMesh(32, 2, uvToDisk,0,1);
let tubeMesh2 = createMesh(32, 2, uvToTube,0,2);
let diskNMesh2 = createMesh(32, 2, uvToDisk, -1,2);
let diskPMesh2 = createMesh(32, 2, uvToDisk, 1,2);
let tubeMesh3 = createMesh(32, 2, uvToTube,0,3);
let diskNMesh3 = createMesh(32, 2, uvToDisk, -1,3);
let diskPMesh3 = createMesh(32, 2, uvToDisk, 1,3);
let diskNMesh = createMesh(32, 2, uvToDisk, -1,1);
let diskPMesh = createMesh(32, 2, uvToDisk, 1,1);
let cylinderMesh = glueMeshes(glueMeshes(tubeMesh, diskPMesh), diskNMesh);
let cylinderMesh2 = glueMeshes(glueMeshes(tubeMesh2, diskPMesh2), diskNMesh2);
let cylinderMesh3 = glueMeshes(glueMeshes(tubeMesh3, diskPMesh3), diskNMesh3);
let torusMash = createMesh(32, 32, uvToTorus, 1, 5);
let head = createCube(1.5,1,1, 4);
let objects = [];
let addObject = (obj, mat) => {
objects.push([obj, mat]);
};
let clearObject = () => {delete objects; objects = [];};
let delta_height = 0, delta_l = [0,0];
class State{
constructor() {
this.leg = true;
this.progress = 0;
this.rh = this.lh = .5*pi;
this.lf = this.rf = 0;
}
initialize(){
this.leg = true;
this.progress = 0;
}
next(){
//return this.presentation();
if(running <= 0)
return {rh:.5*pi, lh:.5*pi, rf:0, lf:0, dh:0,dl:0}
running --;
const steps = 100;
let dl = 0;
if(this.progress >= steps/2)
{
this.progress = 0;
this.leg = !this.leg;
}
let delta = [-pi/5, 0.5*pi, 0.44*pi, 0.55*pi];
for (let i = 0; i < 4; ++i) delta[i] /= steps;
if(this.leg)
{
if(this.progress < steps/4)
{
this.lh += delta[0];
this.rh += delta[3];
this.lf += delta[1];
this.rf += delta[2];
}
else{
this.lh -= delta[0];
this.rh -= delta[3];
this.lf -= delta[1];
this.rf-= delta[2];
}
}
else{
if(this.progress < steps/4)
{
this.lh += delta[3];
this.rh += delta[0];
this.lf += delta[2];
this.rf += delta[1];
}
else{
this.lh -= delta[3];
this.rh -= delta[0];
this.lf -= delta[2];
this.rf-= delta[1];
}
}
let delta_h = Math.max((1-cos(abs(this.lh - pi/2)))*.5+(1-cos(abs(this.lf)))*.6,(1-cos(abs(this.rh - pi/2)))*.5+(1-cos(abs(this.rf)))*.6);
this.progress++;
return {lh:this.lh, lf:this.lf, rh:this.rh,rf:this.rf, dh:delta_h, dl:1.8522/steps};
}
// presentation(){
// return {lh:.4*pi, lf:pi/6,rh:.7*pi, rf:pi/8, dh:0};
// }
};
let star1 = [], star = [];
let sakura = [];
let star2=[], newstar, star4;
const curvex = matrix_multiply(hermiteMat, [-.3,.8,.6,.5]);
const curvey = matrix_multiply(hermiteMat, [-.2,.5,.7,.2]);
const curvez = matrix_multiply(hermiteMat, [-.5,.2,.3,.8]);
let adt = [];
let build_objects = (state)=>{
if(running === 0)
rebuild = false;
let {lh, lf, rh, rf, dh, dl} = state.next();
delta_l[abs(facing)-1] += Math.sign(facing) * dl;
delta_height = dh;
clearObject();
M.save();
M.save();
M.rotateX(pi/2);
M.scale(0.5, 0.5, 1);
addObject(cylinderMesh, M.value());
M.restore();
M.save();
M.translate(0,1,0);
addObject(head, M.value());
M.restore();
M.save();
M.translate(0.5, 0.2, 0.3);
M.rotateX(pi/4);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.4);
M.rotateX(-0.53*pi);
M.scale(0.2, 0.2, 0.4);
M.translate(0,0,1);
addObject(cylinderMesh2, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh2, M.value());
M.restore();
M.save();
M.translate(-0.5, 0.2, 0.3);
M.rotateX(pi/4);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.4);
M.rotateX(-0.55*pi);
M.scale(0.2, 0.2, 0.4);
M.translate(0,0,1);
addObject(cylinderMesh2, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh2, M.value());
M.restore();
M.save();
M.translate(0.3, -1, 0.);
M.rotateX(lh);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.45);
M.rotateX(lf);
M.scale(0.2, 0.2, 0.6);
M.translate(0,0,1);
addObject(cylinderMesh3, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh3, M.value());
M.restore();
M.save();
M.translate(-0.3, -1, 0.);
M.rotateX(rh);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.45);
M.rotateX(rf);
M.scale(0.2, 0.2, 0.6);
M.translate(0,0,1);
addObject(cylinderMesh3, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh3, M.value());
M.restore();
M.restore();
if(running < 0)
rebuild = false;
};
let build_splines = ()=>{
star = [], star1 = [], star2 = [], star4 = [], newstar = [], adt = [], sakura = [];
var n = 11, innerN = Math.ceil((paths[0].length*n)/paths[1].length);
for(let j = 0; j < paths[0].length; ++j)
{
let xf = paths[0][j][0], yf = paths[0][j][1];
for(var k = 0; k <= n; ++k){
let t = k/n;
star1.push([7,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1]);
}
}
for(let j = 13; j >=0; j--)
{
let xf = paths[1][j][0], yf = paths[1][j][1];
for(var k = innerN-1; k >=0 ; --k){
let t = k/(innerN-1);
star2.push([7,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1]);
}
}
for(let j = paths[1].length-1; j >12; --j)
{
let xf = paths[1][j][0], yf = paths[1][j][1];
for(var k = innerN; k >=0 ; --k){
let t = k/innerN;
star2.push([7,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1]);
}
}
let concat = (a, b) => b.forEach(e => a.push(e));
for(let i = 0; i < star1.length; ++i){
concat(star, star1[i]);
concat(star, star2[i]);
}
n = 25;
for(let l = 2; l < 6; ++l)
{
adt[l - 2] = [];
for(let j = 0; j < paths[l].length; ++j)
{
let xf = paths[l][j][0], yf = paths[l][j][1];
for(var k = 0; k <= n; ++k){
let t = k/n;
adt[l-2].push(10+l,dot(xf, [t*t*t, t*t, t, 1]),
-dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1);
}
}
}
n = 20;
for(let l = 6; l < 13; ++l)
{
sakura[l-6] = [];
for(let j = 0; j < paths[l].length; ++j)
{
let xf = paths[l][j][0], yf = paths[l][j][1];
for(var k = 0; k <= n; ++k){
let t = k/n;
sakura[l-6].push(10,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1);
}
}
}
star4 = star.slice();
newstar = star.slice()
for(let i = 0; i < star.length; i+=7)
{
star4[i] = 9;
newstar[i] = 8;
}
return false;
}
let state = new State();
var M = new Matrix();
function animate(gl) {
let uTime;
buildsplines &&= build_splines();
if(animating)
{
uTime = (Date.now() - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
else
{
uTime = (lastTime - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
Sph[0] = [0,0.05*Math.cos(uTime + 1.),.045*Math.cos(uTime), 1,.15];
Sph[1] = [0,0,0,1,.25];
Sph[2] = [.22*Math.sin(uTime*1.2),0.05,.22*Math.cos(uTime*1.2),1,.05];
Sph[3] = [.9*Math.sin(uTime*.4),0.,.9*Math.cos(uTime*.4),1,.25];
Sph[4] = [0.5*Math.sin(uTime*1.),0.08*Math.sin(uTime *0.9),.5*Math.cos(uTime*1.),1,.12];
for(let i = 0; i < ns; ++ i)
{
let trsph = matrix_multiply(SphTr[i], Sph[i]);
trsph[3] = Sph[i][4];
setUniform('4fv', 'Sph['+ i + ']', trsph);
}
if(presentation){
M.save();
M.scale(0.3);
M.rotateY(uTime/5);
M.rotateX(1);
overall_ground = M.value();
if(facing !=2)
M.rotateY(pi*(facing/2));
M.translate(delta_l[0], -delta_height, delta_l[1]);
//M.translate(0, -delta_height, 0);
overall_trans = M.value();
M.restore();
}else{
M.save();
// M.rotateY(2);
M.translate(-.3, -.3, 0);
M.rotateX(.6);
M.rotateZ(.35);
M.scale(0.3);
overall_ground = M.value();
M.translate(delta_l[0], -delta_height, delta_l[1]);
if(facing !=2)
M.rotateY(pi*(facing/2));
overall_trans = M.value();
M.restore();
}
if(rebuild)
build_objects(state);
for(const [obj, mat] of objects){
let m = matrix_multiply(sRotation,matrix_multiply(overall_trans, mat));
setM(m);
drawMesh(obj);
}
M.save();
// M.rotateX(uTime/4);
const _curvez = matrix_multiply(hermiteMat, [-.5,-.2,.3,.8]);
// M.rotateZ(uTime/4);
M.rotateZ((uTime));
//M.scale(100);
setM(M.value());
drawMesh(new Float32Array(star));
M.restore();
M.save();
let t = (sin(uTime/1.5)), mat = [t*t*t, t*t, t, 1]
if(t < 0)
{ mat = const_multiply(-t, [1,1,1,1]);
mat[3] +=1;
}
M.translate(dot(curvex, mat)*2, dot(curvey, mat)*2, dot(curvez, mat)*2);
M.scale(0.2);
setM(M.value());
drawMesh(new Float32Array(newstar));
M.restore();
const __curvey = matrix_multiply(hermiteMat, [-.3,.5,1.9,.8]);
M.save();
M.translate(0,dot(__curvey, mat)*4, 0);
t = abs(((uTime%4)/1.2)), mat = [t*t*t, t*t, t, 1];
M.rotateZ(dot(__curvey, mat));
M.scale(0.2);
setM(M.value());
drawMesh(new Float32Array(star4));
M.restore();
M.save();
M.scale(0.1);
M.translate(6,0,1);
M.rotateX(1);
M.rotateY(uTime/4);
t = abs(sin((uTime%3.1415)/3.)), mat = [t*t*t, t*t, t, 1];
//M.scale(abs((dot(matrix_multiply(hermiteMat, [-.3,.9,1.7,2.8]), mat))));
setM(M.value());
drawMesh(torusMash,gl.LINES);
M.restore();
M.save();
M.translate(-.7,.75,0);
//M.rotateZ(pi);
M.scale(0.6)
setM(M.value());
for(let l = 2; l < 6; ++l)
drawMesh(new Float32Array(adt[l-2]),gl.LINE_LOOP);
M.restore();
M.save();
// M.scale(sin(uTime/2));
M.translate(-.23, .7, 0);
M.rotateZ(sin(uTime/6) + 0.2);
M.scale(0.4);
for(let i = 0; i < 10; i++){
M.scale(0.995);
M.save();
setM(M.value());
M.restore();
for(let l = 8; l < 13; ++l)
drawMesh(new Float32Array(sakura[l-8]),gl.LINE_LOOP);
}
M.restore();
M.save();
M.translate(0.2, .7, 0);
M.rotateZ(sin(uTime/6) + 0.2);
M.scale(0.4);
for(let i = 0; i < 10; i++){
M.scale(0.995);
M.save();
setM(M.value());
M.restore();
for(let l = 8; l < 13; ++l)
drawMesh(new Float32Array(sakura[l-8]),gl.LINE_LOOP);
}
M.restore();
M.save();
M.translate(.7, .7, 0);
M.rotateZ(sin(uTime/6) + 0.2);
M.scale(0.6);
for(let i = 0; i < 10; i++){
M.scale(0.995);
M.save();
setM(M.value());
M.restore();
for(let l = 8; l < 13; ++l)
drawMesh(new Float32Array(sakura[l-8]),gl.LINE_LOOP);
}
M.restore()
M.save();
M.translate(0,-3.155,0);
M.rotateX(pi/2);
M.scale(10);
setM(matrix_multiply(sRotation,matrix_multiply(overall_ground,M.value())));
drawMesh(squareMesh);
M.restore();
if(positionsupdated)
updatePositions();
// setM(M.value());
}
requestAnimationFrame(fpscounter);
//pjsk.play();

@ -0,0 +1,454 @@
//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;
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];
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;
var positionsupdated = true;
var paths = [], origpath= [];
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 = -1000, maxY = -1000, minX = 1000, minY = 1000;
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);
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]);
}
funcs.push([matrix_multiply(bezierMat, X),
matrix_multiply(bezierMat, Y)]);
}
}
paths.push(funcs);
}
}
}
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 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) => {
let m = [];
for(let i = 0; i < a.length; ++ i)
m[i] = a[i] * c;
return m;
}
function dot(a, b){
let m = 0;
for(let i = 0; i < a.length; ++i)
m += a[i] * b[i];
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.value = () => m[top];
this.save = () => { m[top+1] = m[top].slice(); top++; }
this.restore = () => --top;
}
let setM = (m) => {
let mm = matrix_perspective(m);
setUniform('Matrix4fv', 'uMatrix', false, mm);
setUniform('Matrix4fv', 'invMatrix', false, matrix_inverse(m));
}
//------ 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);
}
// 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]]);
positionsupdated = false;
}
function hitTest(pos){
if(!enableSelection)
return -1;
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, 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;
}

@ -0,0 +1,214 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
var ns = 0, cns = 0;
fragmentShaderHeader+= 'const int ns = ' + ns + ';\n';
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
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 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 isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = 'In Spring Break We Did Homeworks.';
// 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;
for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i;
}
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
positionsupdated = true;
let attribs = [
.05,.05,.1, .5,.5,1., 1.,.5,.5,20., 0., .0, 1.3,
.1,.05,.05, 1.,.5,.5, 1.,.5,.5,10., .3,1.,1.3,
.1,.05,.05, .71,.71,.71, .71,.71,.71,10., 0.3,.0,1.5,
.1,.1,.1, .71,.71,.71, .71,.71,.71,10., 0.05,0., 1.,
.0,.0,.0, .0,.0,.0, .0,.0,.0,40., 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('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);
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;
let 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,63 @@
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.76
c3.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.65
c0.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

@ -0,0 +1,39 @@
vec3 foregroundColor = vec3(.0841, .5329, .9604);
uniform vec3 starColors[10];
uniform vec3 V0;
varying vec3 norm;
varying float id;
varying vec3 glpos;
vec3 LDir=vec3(.5,.5,.5);
void main(){
vec3 color =foregroundColor.xyz;
float sp = 0.4, df = 0.4, amb = 0.4, ex=5.;
vec3 l = vec3(1,1,1);
if(id < 1.5) {color = vec3(0.,1.,0.2034);}
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;}
if(id < 0.){
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), 1.);
}

@ -0,0 +1,16 @@
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;
void main() {
vec4 pos = uMatrix * vec4(aPos, 1.);
gl_Position = pos ;
glpos = pos.xyz;
id = oid;
norm = normalize(vec4(normal,0.)*invMatrix).xyz;
}

@ -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 @@
<!--<video src="pjsk.mp4" id="pjsk" 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=lib7.header.js></script>
<script src=lib7.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>
Magician
<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><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:800px;height:2200px;"></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: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;">
&nbsp;&nbsp;&nbsp;&nbsp; I made a 3D character with Bezier splines and surface of revolution.<br>
&nbsp;&nbsp;&nbsp;&nbsp; Because human body is more complicated than the shapes I've created so far,
I first made up a simple and highly symmetric character and drew it on paper. Then I used the pen tool
in Adobe Illustrator to trace some segments of the contour in my drawing that I can use to create
the 3D mesh by rotating it. The selected paths are in the end of (see <a href="./paths.txt">path.txt</a>)<br>
&nbsp;&nbsp;&nbsp;&nbsp; The character is supposed to look like the below image (or <a href="./schema.svg">schema.svg</a>).
It would look much more realistic if I use another spline to make the radius change over u. But this would require
a 3D model, which is hard for me to create.<br>
<center><image id="schema" src='./schema.svg'></image></center>
</p>
<div id="howitworks">
<br>
</div>
<p>
</div>
</div></td>
</tr></table>
</TR></TABLE>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script src="lib7.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,783 @@
let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let lastClick = undefined;
let animating = true;
let flags = 0x0;
var uTime = 0, startTime = Date.now();
let lastTime = Date.now(), rotTime = 0;
var lastFrameTime = 0;
let oldDocument;
let fullscreen = false, btntoggled = false;
let movescene = true;
let oldparents = {};
var tr, div;
let canvas_originalsize;
let Sph = [];
let SphTr = [];
let SphDletaR = [];
let selected = false, selection = -1, dragging = false;
let overall_trans = matrix_identity(), overall_ground;
let rebuild = true, presentation = true, sRotation = matrix_identity();
let facing = 1, running = 0;
let curr_mouse_pos = [-10, -10];
schema.height=screen.height*.9;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
function ev_supersample(e){
let multiplier = insamp.value;
let w = parseInt(canvas1.style.width)*multiplier;
let h = parseInt(canvas1.style.height)*multiplier;
canvas1.height = h;
canvas1.width = w;
gl.viewport(0, 0, w, h);
//gl.clearRect(0, 0, w, h);
}
function toggleFullscreen(element){
if(fullscreen)
{
if (document.exitFullscreen)
document.exitFullscreen();
else if (document.webkitExitFullscreen)
document.webkitExitFullscreen();
else if (document.mozCancelFullScreen)
document.mozCancelFullScreen();
else if (document.msExitFullscreen)
document.msExitFullscreen();
fullscreen = false;
bnfs.innerText = "Fullscreen";
}
else{
if(element.requestFullscreen)
element.requestFullscreen();
else if (element.webkitRequestFullscreen)
element.webkitRequestFullscreen();
else if(element.msRequestFullscreen)
element.msRequestFullscreen();
fullscreen = true;
bnfs.innerText = "Exit Fullscreen";
}
}
bnfs.onclick = function(e){
if(e === "no")
;
else
btntoggled = true;
if(fullscreen){
oldparents[controls].appendChild(controls);
oldparents[canvas1].appendChild(canvas1);
canvas1.style.width = canvas_originalsize[0];
canvas1.style.height = canvas_originalsize[1];
howitworks.hidden = false;
}else{
div = document.createElement("div");
tr = document.createElement("table").insertRow();
tr.style.backgroundColor="white";
let size = Math.min(screen.availHeight, screen.availWidth);
canvas_originalsize = [canvas1.style.width, canvas1.style.height, canvas1.width, canvas1.height];
canvas1.style.height = canvas1.style.width = size;
howitworks.hidden=true;
oldparents[controls] = controls.parentNode;
oldparents[canvas1] = canvas1.parentNode;
let td1 = tr.insertCell();
td1.appendChild(canvas1);
let td2;
td2 = tr.insertCell();
td2.style.verticalAlign="top";
td2.appendChild(controls);
div.appendChild(tr);
document.body.appendChild(div);
}
toggleFullscreen(div);
ev_supersample();
}
mov.onclick=function(_){
movescene = !movescene;
if(!movescene)
{
mov.innerText= "Move Scene";
mov.style.width = "170px";
}
else
{
mov.innerText = "Move Lighting";
mov.style.width = "180px";
}
}
document.addEventListener("webkitfullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
document.addEventListener("fullscreenchange", ()=>{if(!btntoggled && fullscreen)bnfs.onclick("no");btntoggled = false;});
clrsel.onclick=function(_){
setUniform("1i", "sel", -1);
selected = false;
selection = -1;
}
reset.onclick = function(_){
clrsel.onclick();
if(!animating)
pause_resume();
flags = 0;
moving = false;
mousedx = mousedy = mousedz = 0;
positionsupdated = true;
for(let i = 0; i < ns; ++i)
{
SphTr[i]=matrix_identity();
SphDletaR[i] = 0;
}
rtx.src='./RTXon.svg';
setUniform('1i', 'flags', flags);
}
bns.onclick=function(e){
if(ins.value>0 &&ins.value<=ns &&cns!=ins.value)
{
cns = ins.value;
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
if(typeof canvas1.setShaders === "function")
canvas1.setShaders(vs, editor.getSession().getValue());
}
}
bnsamp.onclick=ev_supersample;
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", {
mode:"ace/mode/glsl",
theme:"ace/theme/crimson_editor"
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true,
fontSize: 14,
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
fixedWidthGutter: true,
showGutter: true,
showPrintMargin: false,
});
editor.setAutoScrollEditorIntoView(true);
if(fs != undefined)
editor.getSession().setValue(fs);
editor.session.on('change', function(delta) {
if(typeof canvas1.setShaders === "function")
{
canvas1.setShaders(vs, editor.getSession().getValue());
setUniform('1i', 'flags', flags);
}
});
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
delete editor.KeyBinding;
let pause_resume = function(){
if(animating)
lastTime = Date.now();
else
startTime += Date.now() - lastTime;
animating = !animating;
};
canvas1.addEventListener('click',function(ev){
if(!(shift && alt) && lastClick&& Date.now()-lastClick<200)
pause_resume();
lastClick = Date.now();
});
pause.onclick = pause_resume;
canvas1.addEventListener('mouseover', function(e){
over = true;
if(e.offsetX >0 && e.offsetY > 0)
curr_mouse_pos = [2*e.offsetX/ parseInt(canvas1.style.width)-1,
1-2*e.offsetY/ parseInt(canvas1.style.height), -1];
else over = false;
});
canvas1.addEventListener('mousedown', function(e){
moving = true;
rotTime = uTime;
presentation = false;
mouselastX = mouselastY = undefined;
let i = hitTest([2*e.offsetX/ parseInt(canvas1.style.width)-1,
1-2*e.offsetY/ parseInt(canvas1.style.height), -1]);
if(i >= 0)
{
dragging = true;
selected = true;
setUniform("1i", "sel", i);
selection = i;
}
else if(selected = true){
dragging = false;
selected = false;
setUniform("1i", "sel", i);
selection = i;
}
});
canvas1.addEventListener('mousemove', function(e){
curr_mouse_pos = [2*e.offsetX/ parseInt(canvas1.style.width)-1,
1-2*e.offsetY/ parseInt(canvas1.style.height), -1];
if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
let dx = (mouselastX - e.offsetX),
dy = (mouselastY - e.offsetY);
if(movescene){
sRotation = matrix_multiply(sRotation, matrix_rotateY(-dy/60));
sRotation = matrix_multiply(sRotation, matrix_rotateX(-dx/60));
}
else if(!selected)
{
mousedx -= dx/60;
mousedy -= dy/60;
positionsupdated = true;
}else if(dragging){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
let dv = matrix_multiply(m, [2*-dx/ parseInt(canvas1.style.width),
2*dy/ parseInt(canvas1.style.height), 0, 1]).slice(0,3);
SphTr[selection] = matrix_multiply(SphTr[selection], matrix_translate(dv[0], dv[1], dv[2]));
}
}
mouselastX = e.offsetX;
mouselastY = e.offsetY;
});
canvas1.addEventListener('mouseup', function(e){
moving = false;
dragging = false;
});
canvas1.addEventListener('mouseout', function(e){
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false;
});
canvas1.addEventListener('wheel', function(e){
if(!selected){
mousedz += e.wheelDelta/600;
positionsupdated = true;
}
else{
SphDletaR[selection] += e.wheelDelta / 800;
}
});
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer";
let rtswitch = function(){
alert('Ray Tracing is off for now. I\'ll try to add it back as some sort of background or texture later.')
rtx.src='./RTXon.svg';
}
rtx.addEventListener('click', rtswitch);
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
let fpscounter = function(time){
if (start === undefined)
start = time;
else
fps.innerHTML = Math.round(10000/(time-start))/10 + ' fps';
start = time;
if(fpson)
;//requestAnimationFrame(fpscounter);
else{
start = undefined;
fps.innerHTML = '';
}
};
document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Shift'))
shift = true;
if(e.code.startsWith('Control'))
ctrl = true;
if(e.code.startsWith('Alt'))
alt = true;
else if(ctrl && alt && e.code == 'KeyT'){
const mask = 0x1;
flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags);
}
else if (ctrl &&e.code == 'KeyS'){
let a = document.createElement('a');
a.href = "data:text/plain,"+encodeURIComponent(editor.getSession().getValue());
a.download = 'shader.frag';
a.click();
}
else if(ctrl && alt&&e.code == 'KeyR')
rtswitch();
else if(ctrl && alt&&e.code == 'KeyN')
{
reset.onclick();
}
else if(ctrl && alt&&e.code == 'KeyP')
pause_resume();
else if(ctrl && alt&&e.code == 'KeyF')
if(!fpson)
{
fpson = true;
requestAnimationFrame(fpscounter);
}
else
fpson = false;
if(e.code == 'ArrowUp' || e.code == 'ArrowDown' || e.code =='ArrowLeft'
||e.code == 'ArrowRight' || e.code =='KeyW'||e.code =='KeyS')
{
switch(e.code){
case 'ArrowUp':
facing = -2;
break;
case 'ArrowDown':
facing = 2;
break;
case 'ArrowLeft':
facing = -1;
break;
case 'ArrowRight':
facing = 1;
break;
case 'KeyW':
break;
case 'KeyS':
break;
}
running = 50;
rebuild = true;
}
if(fullscreen && selected ){
if(e.code =='KeyF'||e.code =='KeyB'){
let m = matrix_rotateY(-mousedx);
m = matrix_multiply(m, matrix_rotateX(-mousedy));
m = const_multiply((fl + 1 + mousedz)/(fl+1), m);
switch(e.code){
case 'KeyB':
var dv = matrix_multiply(m, [0,0, -0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
case 'KeyF':
var dv = matrix_multiply(m, [0,0, 0.1, 1]).slice(0,3);
m = matrix_translate(dv[0], dv[1], dv[2]);
break;
}
SphTr[selection] = matrix_multiply(SphTr[selection], m);
}
}
});
document.addEventListener('keyup',(e)=>{
if(e.code.startsWith('Control'))
ctrl = false;
if(e.code.startsWith('Alt'))
alt = false;
if(e.code.startsWith('Shift'))
shift = false;
});
let squareMesh = new Float32Array([ -1,-1,1,0,0,0,1,-1, 1,1,0,0,0,1,-1, -1,-1,0,0,0,1, -1,1,-1,0 ,0,0,1]);
let sphereMesh = createMesh(32, 32, uvToSphere);
let tubeMesh = createMesh(32, 2, uvToTube,0,1);
let diskMesh = createMesh(32, 2, uvToDisk,0,1);
let tubeMesh2 = createMesh(32, 2, uvToTube,0,2);
let diskNMesh2 = createMesh(32, 2, uvToDisk, -1,2);
let diskPMesh2 = createMesh(32, 2, uvToDisk, 1,2);
let tubeMesh3 = createMesh(32, 2, uvToTube,0,3);
let diskNMesh3 = createMesh(32, 2, uvToDisk, -1,3);
let diskPMesh3 = createMesh(32, 2, uvToDisk, 1,3);
let diskNMesh = createMesh(32, 2, uvToDisk, -1,1);
let diskPMesh = createMesh(32, 2, uvToDisk, 1,1);
let cylinderMesh = glueMeshes(glueMeshes(tubeMesh, diskPMesh), diskNMesh);
let cylinderMesh2 = glueMeshes(glueMeshes(tubeMesh2, diskPMesh2), diskNMesh2);
let cylinderMesh3 = glueMeshes(glueMeshes(tubeMesh3, diskPMesh3), diskNMesh3);
let torusMash = createMesh(32, 32, uvToTorus, 1, 5);
let head = createCube(1.5,1,1, 4);
let objects = [];
let addObject = (obj, mat) => {
objects.push([obj, mat]);
};
let clearObject = () => {delete objects; objects = [];};
let delta_height = 0, delta_l = [0,0];
class State{
constructor() {
this.leg = true;
this.progress = 0;
this.rh = this.lh = .5*pi;
this.lf = this.rf = 0;
}
initialize(){
this.leg = true;
this.progress = 0;
}
next(){
//return this.presentation();
if(running <= 0)
return {rh:.5*pi, lh:.5*pi, rf:0, lf:0, dh:0,dl:0}
running --;
const steps = 100;
let dl = 0;
if(this.progress >= steps/2)
{
this.progress = 0;
this.leg = !this.leg;
}
let delta = [-pi/5, 0.5*pi, 0.44*pi, 0.55*pi];
for (let i = 0; i < 4; ++i) delta[i] /= steps;
if(this.leg)
{
if(this.progress < steps/4)
{
this.lh += delta[0];
this.rh += delta[3];
this.lf += delta[1];
this.rf += delta[2];
}
else{
this.lh -= delta[0];
this.rh -= delta[3];
this.lf -= delta[1];
this.rf-= delta[2];
}
}
else{
if(this.progress < steps/4)
{
this.lh += delta[3];
this.rh += delta[0];
this.lf += delta[2];
this.rf += delta[1];
}
else{
this.lh -= delta[3];
this.rh -= delta[0];
this.lf -= delta[2];
this.rf-= delta[1];
}
}
let delta_h = Math.max((1-cos(abs(this.lh - pi/2)))*.5+(1-cos(abs(this.lf)))*.6,(1-cos(abs(this.rh - pi/2)))*.5+(1-cos(abs(this.rf)))*.6);
this.progress++;
return {lh:this.lh, lf:this.lf, rh:this.rh,rf:this.rf, dh:delta_h, dl:1.8522/steps};
}
// presentation(){
// return {lh:.4*pi, lf:pi/6,rh:.7*pi, rf:pi/8, dh:0};
// }
};
let star1 = [], star = [];
let sakura = [], stars = [], nstars = 25;
let star2=[], newstar, star4;
const curvex = matrix_multiply(hermiteMat, [-.3,.8,.6,.5]);
const curvey = matrix_multiply(hermiteMat, [-.2,.5,.7,.2]);
const curvez = matrix_multiply(hermiteMat, [-.5,.2,.3,.8]);
let adt = [];
let build_objects = (state)=>{
if(running === 0)
rebuild = false;
let {lh, lf, rh, rf, dh, dl} = state.next();
delta_l[abs(facing)-1] += Math.sign(facing) * dl;
delta_height = dh;
clearObject();
M.save();
M.save();
M.rotateX(pi/2);
M.scale(0.5, 0.5, 1);
addObject(cylinderMesh, M.value());
M.restore();
M.save();
M.translate(0,1,0);
addObject(head, M.value());
M.restore();
M.save();
M.translate(0.5, 0.2, 0.3);
M.rotateX(pi/4);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.4);
M.rotateX(-0.53*pi);
M.scale(0.2, 0.2, 0.4);
M.translate(0,0,1);
addObject(cylinderMesh2, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh2, M.value());
M.restore();
M.save();
M.translate(-0.5, 0.2, 0.3);
M.rotateX(pi/4);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.4);
M.rotateX(-0.55*pi);
M.scale(0.2, 0.2, 0.4);
M.translate(0,0,1);
addObject(cylinderMesh2, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh2, M.value());
M.restore();
M.save();
M.translate(0.3, -1, 0.);
M.rotateX(lh);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.45);
M.rotateX(lf);
M.scale(0.2, 0.2, 0.6);
M.translate(0,0,1);
addObject(cylinderMesh3, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh3, M.value());
M.restore();
M.save();
M.translate(-0.3, -1, 0.);
M.rotateX(rh);
M.translate(0,0,.5);
M.save();
M.translate(0,0,.45);
M.rotateX(rf);
M.scale(0.2, 0.2, 0.6);
M.translate(0,0,1);
addObject(cylinderMesh3, M.value());
M.restore();
M.scale(0.2, 0.2, 0.5);
addObject(cylinderMesh3, M.value());
M.restore();
M.restore();
if(running < 0)
rebuild = false;
};
let build_splines = ()=>{
star = [], star1 = [], star2 = [], star4 = [], newstar = [], adt = [], sakura = [];
var n = 11, innerN = Math.ceil((paths[0].length*n)/paths[1].length);
for(let j = 0; j < paths[0].length; ++j)
{
let xf = paths[0][j][0], yf = paths[0][j][1];
for(var k = 0; k <= n; ++k){
let t = k/n;
star1.push([7,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1]);
}
}
for(let j = 13; j >=0; j--)
{
let xf = paths[1][j][0], yf = paths[1][j][1];
for(var k = innerN-1; k >=0 ; --k){
let t = k/(innerN-1);
star2.push([7,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1]);
}
}
for(let j = paths[1].length-1; j >12; --j)
{
let xf = paths[1][j][0], yf = paths[1][j][1];
for(var k = innerN; k >=0 ; --k){
let t = k/innerN;
star2.push([7,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1]);
}
}
for(let i = 0; i < star1.length; ++i){
concat(star, star1[i]);
concat(star, star2[i]);
}
n = 25;
for(let l = 2; l < 6; ++l)
{
adt[l - 2] = [];
for(let j = 0; j < paths[l].length; ++j)
{
let xf = paths[l][j][0], yf = paths[l][j][1];
for(var k = 0; k <= n; ++k){
let t = k/n;
adt[l-2].push(10+l,dot(xf, [t*t*t, t*t, t, 1]),
-dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1);
}
}
}
n = 20;
for(let l = 6; l < 13; ++l)
{
sakura[l-6] = [];
for(let j = 0; j < paths[l].length; ++j)
{
let xf = paths[l][j][0], yf = paths[l][j][1];
for(var k = 0; k <= n; ++k){
let t = k/n;
sakura[l-6].push(10,dot(xf, [t*t*t, t*t, t, 1]),
dot(yf, [t*t*t, t*t, t, 1]),
0,0,0,1);
}
}
}
star4 = star.slice();
newstar = star.slice()
for(let i = 0; i < star.length; i+=7)
{
star4[i] = 9;
newstar[i] = 8;
}
for(let i = 0; i < nstars; ++i){
stars.push(star.slice());
startz.push(.6*Math.random());
random_rot.push(0);
random_rot_pos.push(0);
}
return false;
}
let state = new State();
var M = new Matrix();
var buildsplines = true;
let magician = false, magician_neck = false,
magician_houki = false, body = false,
leg = false, hand = false ;
let sa2 = [
1.6,0.4, .9, 1., .3,.2, -.4,.8,
-.8, -.1, -1.4, .5, -1.6, -.5
], fsa2 = [[matrix_multiply(bezierMat,[sa2[0], sa2[2], sa2[4], sa2[6]]),
matrix_multiply(bezierMat,[sa2[1], sa2[3], sa2[5], sa2[7]])],
[matrix_multiply(bezierMat,[sa2[6], sa2[8], sa2[10], sa2[12]]),
matrix_multiply(bezierMat,[sa2[7], sa2[9], sa2[11], sa2[13]])]],
random_rot = [0,0,0,0,0,0,0], random_rot_pos = [0,0,0,0,0,0,0], startz = [];
let division = -1;
let changeID = (id, obj) => {for(let i = 0; i < obj.length; i+=7) obj[i] = id;}
function animate(gl) {
buildsplines &&= build_splines();
magician = magician?magician:createMeshFromSpline( 13, 32, 4, 4, 0, (i,_,oid) => {
if (oid == 4 && i == 10) return 3;
else if (oid == 3 && i ==16) return 2;
else if(oid == 2 && i == 23) return 1;
});
magician_neck = magician_neck?magician_neck:createMeshFromSpline( 14, 32, 4, 5, -.2);
magician_houki = magician_houki?magician_houki:createMeshFromSpline( 15, 32, 4, 6);
body = body?body:createMeshFromSpline( 16, 32, 4, 7, 0, (i, tmp)=>{if(division < 0 && i == 25) division = tmp.length;});
leg = leg?leg:createMeshFromSpline(17, 32, 4, 8);
hand = hand?hand:createMeshFromSpline(18, 32, 4, 9,.015);
if(animating)
{
uTime = (Date.now() - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
else
{
uTime = (lastTime - startTime) / 1000;
setUniform('1f', 'uTime', uTime);
}
let curve = [];
let n = 8;
// for(let j = 0; j < paths[13].length; ++j)
// {
// let xf = paths[13][j][0], yf = paths[13][j][1];
// for(var k = 0; k <= n; ++k){
// let t = k/n;
// concat(curve, [7,dot(xf, [t*t*t, t*t, t, 1]),
// -dot(yf, [t*t*t, t*t, t, 1]),
// 0,0,0,1]);
// }
// }
// M.save()
// M.scale(0.3);
// setM(matrix_multiply(sRotation, M.value()));
// drawMesh(leg);
// M.restore();
// return;
M.save()
if(presentation){
M.rotateX(uTime/12);
M.rotateY(uTime/3);
M.rotateZ(uTime/6);
} else {
M.rotateX(rotTime/12);
M.rotateY(rotTime/3);
M.rotateZ(rotTime/6);
}
M.scale(0.6);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(body.slice(0, division));
drawMesh(body.slice(division - 7), gl.LINE_LOOP);
M.save();
M.translate(0,0,-1.05);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(magician);
M.restore();
M.save();
M.translate(0,0,-.53);
M.scale(.1);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(magician_neck);
M.restore();
M.save();
M.translate(-1,0,0);
M.scale(2);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(magician_houki);
M.restore();
M.save()
M.translate(-.06,0,.85);
M.rotateY(0.02);
M.scale(1.2);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(leg);
M.restore();
M.save()
M.translate(.06,0,.85);
M.rotateY(-0.02);
M.scale(1.2);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(leg);
M.restore();
M.save()
M.translate(-.35,0,-.1);
M.rotateY(-pi/6);
M.scale(.82);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(hand);
M.restore();
M.save()
M.translate(.35,0,-.1);
M.rotateY(pi/6);
M.scale(.82);
setM(matrix_multiply(sRotation, M.value()));
drawMesh(hand);
M.restore();
M.restore();
for(let i = 0; i < nstars; ++ i)
{M.save()
let f_idx = (uTime/(abs(sin(i*1234))*8 + 10))%2,
t = f_idx - Math.floor(f_idx);
f_idx -=t;
let curr_mat = [t*t*t, t*t, t, 1];
M.translate(1.2*sin(sin(uTime/(i+2)+i + 8)*.9 + dot(fsa2[f_idx][0], curr_mat)*5 + startz[Math.floor(2*startz[i]*nstars)%nstars]), 1.2*cos(i + sin(uTime/(i/2+18)+12)*.1 + startz[nstars-i-1] + dot(fsa2[f_idx][1], curr_mat)*startz[(nstars + i)%nstars]*.4 + i * sin(random_rot_pos[i]/30)/pi), .65*startz[i] + .3*sin(random_rot_pos[i]/20));
let epsilon = 1/(i*2+20);
let random = () => {
var u = 0, v = 0;
while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
while(v === 0) v = Math.random();
return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )/pi;
}
if((window.performance.now() + i*(2+abs(random()))) %69 <2){
changeID(Math.ceil(Math.random()*20)-5,stars[i])
}
random_rot[i] += random()*epsilon;
random_rot_pos[i] += .5 + abs(random())/(pi+i);
//setM(M.value);
M.rotateZ(sin(random_rot_pos[i]/10)*pi);
M.rotateX(.1*sin(random_rot_pos[i]/(i+50))*pi);
M.rotateY(.1*sin(random_rot_pos[i]/(i*2+50))*pi);
M.scale(0.2 + startz[i]*.2);
setM(M.value());
drawMesh(new Float32Array(stars[i]));
M.restore();}
if(over);
}
requestAnimationFrame(fpscounter);
//pjsk.play();

@ -0,0 +1,537 @@
//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;
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;
var positionsupdated = true;
var paths = [], origpath= [], path_misc = [];
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 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) => {
let m = [];
for(let i = 0; i < a.length; ++ i)
m[i] = a[i] * c;
return m;
}
function dot(a, b){
let m = 0;
for(let i = 0; i < a.length; ++i)
m += a[i] * b[i];
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.value = () => m[top];
this.save = () => { m[top+1] = m[top].slice(); top++; }
this.restore = () => --top;
}
let setM = (m) => {
let mm = matrix_perspective(m);
setUniform('Matrix4fv', 'uMatrix', false, mm);
setUniform('Matrix4fv', 'invMatrix', false, matrix_inverse(m));
}
//------ 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]]);
positionsupdated = false;
}
function hitTest(pos){
if(!enableSelection)
return -1;
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, 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,216 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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); }'
].join('\n');
var ns = 0, cns = 0;
fragmentShaderHeader+= 'const int ns = ' + ns + ';\n';
var fragmentShaderDefs = 'const int cns = ' + cns + ';\n';
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 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 isPowerOf2(value) {
return (value & (value - 1)) == 0;
}
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>&nbsp;</td></tr></table>';
}
errorMessage.innerHTML = 'There is no real magic, but Computer Graphics is a close one.';
// 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;
for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i;
}
gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
positionsupdated = true;
let attribs = [
.05,.05,.1, .5,.5,1., 1.,.5,.5,20., 0., .0, 1.3,
.1,.05,.05, 1.,.5,.5, 1.,.5,.5,10., .3,1.,1.3,
.1,.05,.05, .71,.71,.71, .71,.71,.71,10., 0.3,.0,1.5,
.1,.1,.1, .71,.71,.71, .71,.71,.71,10., 0.05,0., 1.,
.0,.0,.0, .0,.0,.0, .0,.0,.0,40., 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('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;
let 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,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

File diff suppressed because one or more lines are too long

@ -0,0 +1,435 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" 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 675 1365" overflow="visible" xml:space="preserve">
<path fill="none" stroke="#EE9CB0" stroke-miterlimit="10" d="M431.71,423.53c-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.46,5.27-0.33,10.47,0,12.64c3.63,23.6,85.93,34.57,106.09,37.06
c24.1,2.98,56.9,5.93,96.32,6.09"/>
<path fill="none" stroke="#8DC640" stroke-miterlimit="10" d="M432.03,19.57c-13.05,26-26.65,72.88-30.25,100.89
c-7.01,42.29-4.95,53.13-8.51,81.14c-1.92,17.81-11.93,57.11-13.54,91.28c0,1.51,0.06,6.41-2.36,7.51
c-33.42,0.01-67.42,8.42-111.33,29.92c8.54-2.52,19.83-5.8,33.38-9.62c13.45-3.79,19.14-5.29,26.57-5.88
c1.86-0.15,6.25-0.48,13.56-1.05c0,0,0,0,0.01,0c6.31-0.58,10.52-0.95,11.57-1.05c11.24-1.05,14.55,1.62,20.31-1.52
c3.09-1.68,5.23-4.13,5.42-3.92c0.22,0.24-2.86,2.92-5.35,6.55c-0.7,1.02-3.25,4.88-4.97,12.66c-3.02,13.63-0.83,27.11-0.23,30.51
c1.66,9.36,3.09,17.44,9.27,25.77c4.78,6.45,10.36,10.28,14.01,12.39c-0.26-2.08-0.66-5.38-1.13-9.45
c-1.22-10.49-1.22-11.48-1.81-14.69c-1.43-7.76-3.26-11.96-2.71-12.2c0.56-0.24,3.12,5.45,7.68,12.43
c5.21,7.97,10.58,13.9,11.07,13.56c0.5-0.35-5.07-6.46-7.91-16.95c-1.16-4.28-1.38-7.83-1.81-14.92
c-0.55-8.98,0.08-10.64-0.31-21.06c-0.27-7.31-0.91-15.11-1.04-15.1c-0.19,0.01,0.89,15.81,1.52,19.97
c0.83,5.53,0.95,4.28,2.08,10.49c1.13,6.23,2.25,16.85,3.89,20.31c0.8,1.69,1.78,3.58,3.22,5.62c8.32,11.71,24.5,17.12,29.05,18.47"
/>
<path fill="none" stroke="#00AEEF" stroke-miterlimit="10" d="M415.87,385.14c0.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.55"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M447.19,385.14c-0.4,0.5-0.94,1.28-1.36,2.32
c-0.67,1.66-0.67,3.07-0.67,4.45c0,0.92-0.04,4.84,0,6.15c0.19,6.59-0.61,7.24,0,11.71c0.34,2.51,0.83,4.02,1.19,4.96
c0.18,0.48,0.94,2.43,2.52,4.74c0.44,0.64,1.1,1.54,3.04,3.63c3.33,3.59,5.27,4.38,5.19,5.19c-0.13,1.26-4.86,2.51-24.83,2.53"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M432.35,423.53c1.76,0.11,4.62,0.27,8.17,0.38
c6.7,0.21,8.06-0.01,10.6,0.77c3.92,1.2,3.97,2.71,8.07,4.59c2.36,1.08,3.84,1.26,12.22,2.17c5.45,0.59,10.87,1.53,16.34,1.91
c5.84,0.41,9.63,0.36,12,3.2c1.04,1.25,1.47,2.63,1.66,3.56c3.32,18.64,2.48,32.37,1.02,41.62c-0.57,3.57-3.63,21.7-0.89,34.76
c0.17,0.79,0.64,2.93,1.15,5.97c0.28,1.67,1.58,9.69,1.66,17.62c0.05,5.4-1.24,12.84-3.83,27.7c-0.5,2.88-1.27,7.13-2.17,13.28
c-0.59,4.02-1.01,7.31-1.28,9.45c0.52,3.62,0.43,6.53,0.26,8.55c-0.29,3.26-0.86,4.56-0.13,6.77c0.77,2.31,1.92,2.45,2.43,4.85
c0.48,2.29-0.42,2.86,0.15,4.95c0.41,1.49,1.13,2.2,2.79,4.24c1.48,1.82,2.74,3.8,4.21,5.62c4.31,5.35,8.49,10.81,12.89,16.09
c5.78,6.93,6.86,8.58,17.49,21.96c18.52,23.3,21.63,26.32,32.55,40.21c24.98,31.79,37.81,53.07,40.72,57.96
c0,0,7.82,13.11,17.62,36.64c2.39,5.73,5.45,13.54,6.38,24.13c0.46,5.27,0.33,10.47,0,12.64c-3.63,23.6-85.93,34.57-106.09,37.06
c-24.1,2.98-56.9,5.93-96.32,6.09"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M432.03,19.57c13.05,26,26.65,72.88,30.25,100.89
c7.01,42.29,4.95,53.13,8.51,81.14c1.92,17.81,11.93,57.11,13.54,91.28c0,1.51-0.06,6.41,2.36,7.51
c33.42,0.01,67.42,8.42,111.33,29.92c-8.54-2.52-19.83-5.8-33.38-9.62c-13.45-3.79-19.14-5.29-26.57-5.88
c-1.86-0.15-6.25-0.48-13.56-1.05c0,0,0,0-0.01,0c-6.31-0.58-10.52-0.95-11.57-1.05c-11.24-1.05-14.55,1.62-20.31-1.52
c-3.09-1.68-5.23-4.13-5.42-3.92c-0.22,0.24,2.86,2.92,5.35,6.55c0.7,1.02,3.25,4.88,4.97,12.66c3.02,13.63,0.83,27.11,0.23,30.51
c-1.66,9.36-3.09,17.44-9.27,25.77c-4.78,6.45-10.36,10.28-14.01,12.39c0.26-2.08,0.66-5.38,1.13-9.45
c1.22-10.49,1.22-11.48,1.81-14.69c1.43-7.76,3.26-11.96,2.71-12.2c-0.56-0.24-3.12,5.45-7.68,12.43
c-5.21,7.97-10.58,13.9-11.07,13.56c-0.5-0.35,5.07-6.46,7.91-16.95c1.16-4.28,1.37-7.83,1.81-14.92
c0.55-8.98-0.08-10.64,0.31-21.06c0.27-7.31,0.91-15.11,1.04-15.1c0.19,0.01-0.89,15.81-1.52,19.97c-0.83,5.53-0.95,4.28-2.08,10.49
c-1.13,6.23-2.25,16.85-3.89,20.31c-0.8,1.69-1.78,3.58-3.22,5.62c-8.32,11.71-24.5,17.12-29.05,18.47"/>
<line fill="none" stroke="#544E4A" stroke-miterlimit="10" x1="432.03" y1="3.5" x2="432.03" y2="1362.2"/>
<line fill="none" stroke="#544E4A" stroke-miterlimit="10" x1="110.14" y1="1244.82" x2="110.14" y2="496.89"/>
<line fill="none" stroke="#544E4A" stroke-miterlimit="10" x1="379.72" y1="735.17" x2="408.61" y2="1340.2"/>
<path fill="none" stroke="#F79420" stroke-miterlimit="10" d="M365.6,436.3c-4.22,2.75-10.17,7.25-15.77,14.11
c-4.68,5.73-6.94,10.44-10.7,18c-8.12,16.32-14.75,28.87-16.33,31.83c-9.63,18.09-10.38,16.29-17.85,31.22
c-5.53,11.05-10.34,22.45-12.81,28.33c-5.67,13.46-6.85,17.62-11.6,25.16c-5.39,8.56-6.11,6.76-12.27,16.39
c-6.01,9.4-6.2,12.48-13.55,24.01c-4.04,6.33-4.14,5.65-7.77,11.58c-2.27,3.71-3.18,5.53-10.22,19.05
c-2.73,5.25-4.91,9.86-8.17,15.81c-3.06,5.59-5.86,10.34-7.33,12.82c-2.94,4.98-4.41,7.47-5.86,9.67
c-8.86,13.52-15.71,17.22-14.19,21.35c0.42,1.14,1.09,1.26,6.89,4.85c4.11,2.54,7.41,4.73,9.62,6.22"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M387.23,448.95c-0.15,5.04-0.89,12.46-3.83,20.82
c-2.45,6.97-5.29,11.36-9.79,18.51c-9.7,15.44-16.96,27.63-18.66,30.52c-10.42,17.64-8.5,17.35-17.35,31.5
c-6.55,10.48-13.78,20.52-17.5,25.7c-8.53,11.85-11.47,15.02-15.43,23.01c-4.5,9.06-2.58,8.74-7.6,19.02
c-4.89,10.03-7.42,11.79-13.44,24.07c-3.3,6.75-2.67,6.47-5.84,12.66c-1.98,3.87-3.06,5.59-10.94,18.65
c-3.06,5.07-5.85,9.33-9.24,15.21c-3.18,5.53-5.77,10.39-7.13,12.94c-2.72,5.11-4.08,7.66-5.21,10.04
c-6.93,14.61-6.51,22.38-10.83,23.23c-1.19,0.23-1.65-0.27-7.73-3.36c-4.31-2.18-7.9-3.86-10.32-4.97"/>
<line fill="none" stroke="#544E4A" stroke-miterlimit="10" x1="406.12" y1="396.42" x2="190.25" y2="770.32"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M498.46,434.44c4.22,2.75,10.17,7.25,15.77,14.11
c4.68,5.73,6.94,10.44,10.7,18c8.12,16.32,14.75,28.87,16.33,31.83c9.63,18.09,10.38,16.29,17.85,31.22
c5.53,11.05,10.34,22.45,12.81,28.33c5.67,13.46,6.85,17.62,11.6,25.16c5.39,8.56,6.11,6.76,12.27,16.39
c6.01,9.4,6.2,12.48,13.55,24.01c4.04,6.33,4.14,5.65,7.77,11.58c2.27,3.71,3.18,5.53,10.22,19.05c2.73,5.25,4.91,9.86,8.17,15.81
c3.06,5.59,5.86,10.34,7.33,12.82c2.94,4.98,4.41,7.47,5.86,9.67c8.86,13.52,15.71,17.22,14.19,21.35
c-0.42,1.14-1.09,1.26-6.89,4.85c-4.11,2.54-7.41,4.73-9.62,6.22"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M476.83,447.09c0.15,5.04,0.89,12.46,3.83,20.82
c2.45,6.97,5.29,11.36,9.79,18.51c9.7,15.44,16.96,27.63,18.66,30.52c10.42,17.64,8.5,17.35,17.35,31.5
c6.55,10.48,13.78,20.52,17.5,25.7c8.53,11.85,11.47,15.02,15.43,23.01c4.5,9.06,2.58,8.74,7.6,19.02
c4.89,10.03,7.42,11.79,13.44,24.07c3.3,6.75,2.67,6.47,5.84,12.66c1.98,3.87,3.06,5.59,10.94,18.65c3.06,5.07,5.85,9.33,9.24,15.21
c3.18,5.53,5.77,10.39,7.13,12.94c2.72,5.11,4.08,7.66,5.21,10.04c6.93,14.61,6.51,22.38,10.83,23.23c1.19,0.23,1.65-0.27,7.73-3.36
c4.31-2.18,7.9-3.86,10.32-4.97"/>
<line fill="none" stroke="#544E4A" stroke-miterlimit="10" x1="460.19" y1="393.28" x2="671.56" y2="769.73"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M111.14,549.81c7.27,2.1,16.75,4.87,27.83,8.17
c40.23,11.98,49.04,15.35,58.28,22.6c5.71,4.47,14.05,12.37,21.32,25.91c-4.57,9.23-11.16,22.21-19.53,37.53
c-13.51,24.74-22.16,40.57-35.49,58.91c-7.85,10.79-19.4,25.32-35.36,41.18c-0.72,5.12-1.23,9.06-1.53,11.49
c-0.57,4.57-0.8,6.77-2.34,9.27c-1.46,2.37-3.38,3.84-4.75,4.7c-0.63,143.54-1.26,287.08-1.89,430.62"/>
<path fill="none" stroke="#8299CE" stroke-miterlimit="10" d="M103.61,1200.19c-0.63-143.54-1.26-287.08-1.89-430.62
c-1.37-0.86-3.29-2.33-4.75-4.7c-1.54-2.5-1.77-4.71-2.34-9.27c-0.3-2.43-0.81-6.37-1.53-11.49
c-15.96-15.86-27.51-30.39-35.36-41.18c-13.33-18.34-21.98-34.16-35.49-58.91c-8.37-15.32-14.96-28.3-19.53-37.53
c7.27-13.55,15.61-21.44,21.32-25.91c9.24-7.25,18.05-10.61,58.28-22.6c11.08-3.3,20.55-6.07,27.83-8.17"/>
<path fill="none" stroke="#65C8D0" stroke-miterlimit="10" d="M339.67,776.15c3.06,18.01,4.7,31.97,5.64,41.64
c0,0,1.9,19.34,4.75,34.76c2.49,13.49,3.39,14.4,7.19,32.14c1.53,7.13,1.64,8.19,8.1,43.76c5.19,28.57,5.73,31.25,6.39,38.25
c0.47,4.93,1.49,17.11,1.14,32.86c-0.26,11.69-1.18,19.82-1.67,24.86c-2.38,24.85-1.19,45.77-0.02,66.24
c0.79,13.83,1.99,33.66,6.61,58.99c3.64,19.98,7.91,35.09,9.8,61.99c0.06,0.88,0.22,1.84,0.39,3.46c0.65,6.38,0.51,11.44,0.41,14.17
c-1.34,37.41-2.95,47.75-2.95,47.75c-0.8,4.76-2.36,11.12,0.64,13.39c1.15,0.87,2.47,0.8,9.83,0.45c3.87-0.19,7.02-0.34,8.27-0.4"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M421.97,771.39c-1.72,18.72-2.11,33.02-2.13,42.85
c0,0-0.05,19.43-1.42,35.06c-1.2,13.66-2,14.66-4.1,32.68c-0.84,7.24-0.86,8.31-3.9,44.33c-2.44,28.93-2.72,31.65-2.72,38.68
c0,4.95,0.15,17.18,1.99,32.82c1.37,11.62,3.07,19.62,4.03,24.59c4.74,24.51,5.54,45.45,6.33,65.94
c0.53,13.84,1.23,33.69-0.96,59.35c-1.72,20.24-4.53,35.68-3.84,62.64c0.02,0.88-0.05,1.85-0.06,3.48
c-0.04,6.42,0.58,11.43,0.94,14.14c4.9,37.11,7.49,47.25,7.49,47.25c1.25,4.66,3.41,10.84,0.64,13.39
c-1.07,0.98-2.38,1.03-9.75,1.38c-4.08,0.19-7.24,0.35-8.27,0.4"/>
<line fill="none" stroke="#544E4A" stroke-miterlimit="10" x1="485.19" y1="735.21" x2="458.6" y2="1340.34"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M440.69,772.07c2.09,18.38,2.61,32.52,2.68,42.27
c0,0,0.16,19.81,1.55,35.05c1.25,13.66,2.06,14.65,4.22,32.67c0.87,7.24,0.89,8.31,4.07,44.31c2.55,28.92,2.84,31.64,2.87,38.67
c0.02,4.95-0.08,17.18-1.87,32.83c-1.33,11.62-2.99,19.63-3.93,24.6c-4.65,24.53-5.37,45.47-6.08,65.96
c-0.48,13.85-1.1,33.7,1.18,59.35c1.8,20.23,4.66,35.66,4.08,62.62c-0.02,0.88,0.06,1.85,0.07,3.48c0.06,6.42-0.54,11.44-0.88,14.15
c-4.76,37.13-7.31,47.28-7.31,47.28c-1.24,4.66-3.36,10.86-0.59,13.39c1.07,0.98,2.38,1.03,9.75,1.35c3.88,0.17,7.03,0.31,8.28,0.36
"/>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M524.78,774.11c-4.09,19.09-5.94,33.57-6.87,43.5
c0,0-1.82,19.32-4.62,34.78c-2.44,13.5-3.33,14.41-7.07,32.17c-1.5,7.14-1.61,8.2-7.94,43.79c-5.08,28.59-5.61,31.27-6.25,38.27
c-0.45,4.93-1.42,17.12-1.02,32.87c0.3,11.69,1.26,19.82,1.76,24.85c2.48,24.84,1.36,45.77,0.27,66.24
c-0.74,13.83-1.86,33.66-6.38,59.02c-3.57,19.99-7.77,35.12-9.56,62.02c-0.06,0.88-0.22,1.84-0.38,3.46
c-0.63,6.39-0.47,11.44-0.36,14.17c1.48,37.4,3.13,47.74,3.13,47.74c0.82,4.75,2.4,11.11-0.59,13.39c-1.15,0.88-2.46,0.81-9.83,0.49
c-4.03-0.18-7.18-0.32-8.28-0.36"/>
<g>
<path fill="#8DC640" d="M206.52,203.97c-1.53,2.06-2.65,4.79-2.65,8.59c0,3.74,1.15,6.42,2.65,8.52h-1.45
c-1.32-1.74-2.75-4.43-2.75-8.52c0.02-4.14,1.43-6.82,2.75-8.59H206.52z"/>
<path fill="#8DC640" d="M208.48,211.13c0-1.05-0.02-1.91-0.08-2.75h1.62l0.08,1.64h0.06c0.57-0.97,1.51-1.87,3.19-1.87
c1.39,0,2.44,0.84,2.88,2.04h0.04c0.31-0.57,0.71-1.01,1.13-1.32c0.61-0.46,1.28-0.71,2.25-0.71c1.34,0,3.34,0.88,3.34,4.41v5.98
h-1.81v-5.75c0-1.95-0.71-3.13-2.2-3.13c-1.05,0-1.87,0.78-2.18,1.68c-0.08,0.25-0.15,0.59-0.15,0.92v6.28h-1.81v-6.09
c0-1.62-0.71-2.79-2.12-2.79c-1.15,0-1.99,0.92-2.29,1.85c-0.1,0.27-0.15,0.59-0.15,0.9v6.13h-1.81V211.13z"/>
<path fill="#8DC640" d="M231.62,218.54l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.95,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H231.62z M231.34,213.35c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.11-0.4,0.11-0.59V213.35z"/>
<path fill="#8DC640" d="M244.87,208.38c-0.04,0.73-0.08,1.55-0.08,2.79v5.9c0,2.33-0.46,3.76-1.45,4.64
c-0.99,0.92-2.41,1.22-3.7,1.22c-1.22,0-2.56-0.29-3.38-0.84l0.46-1.41c0.67,0.42,1.72,0.8,2.98,0.8c1.89,0,3.28-0.99,3.28-3.55
v-1.13h-0.04c-0.57,0.94-1.66,1.7-3.23,1.7c-2.52,0-4.33-2.14-4.33-4.96c0-3.44,2.25-5.4,4.58-5.4c1.76,0,2.73,0.92,3.17,1.76h0.04
l0.08-1.53H244.87z M242.96,212.39c0-0.31-0.02-0.59-0.11-0.84c-0.34-1.07-1.24-1.95-2.58-1.95c-1.76,0-3.02,1.49-3.02,3.84
c0,1.99,1.01,3.65,3,3.65c1.13,0,2.16-0.71,2.56-1.89c0.1-0.31,0.15-0.67,0.15-0.99V212.39z"/>
<path fill="#8DC640" d="M249.78,205.52c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.15,1.16-1.15
C249.34,204.37,249.78,204.87,249.78,205.52z M247.72,218.54v-10.16h1.85v10.16H247.72z"/>
<path fill="#8DC640" d="M259.88,218.16c-0.48,0.25-1.55,0.59-2.92,0.59c-3.06,0-5.06-2.08-5.06-5.19c0-3.13,2.14-5.4,5.46-5.4
c1.09,0,2.06,0.27,2.56,0.52l-0.42,1.43c-0.44-0.25-1.13-0.48-2.14-0.48c-2.33,0-3.59,1.72-3.59,3.84c0,2.35,1.51,3.8,3.53,3.8
c1.05,0,1.74-0.27,2.27-0.5L259.88,218.16z"/>
<path fill="#8DC640" d="M264.1,205.52c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.15,1.16-1.15
C263.66,204.37,264.1,204.87,264.1,205.52z M262.05,218.54v-10.16h1.85v10.16H262.05z"/>
<path fill="#8DC640" d="M272.59,218.54l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.95,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H272.59z M272.31,213.35c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.11-0.4,0.11-0.59V213.35z"/>
<path fill="#8DC640" d="M277.08,211.13c0-1.05-0.02-1.91-0.08-2.75h1.64l0.11,1.68h0.04c0.5-0.97,1.68-1.91,3.36-1.91
c1.41,0,3.59,0.84,3.59,4.33v6.07h-1.85v-5.86c0-1.64-0.61-3-2.35-3c-1.22,0-2.16,0.86-2.48,1.89c-0.08,0.23-0.12,0.55-0.12,0.86
v6.11h-1.85V211.13z"/>
<path fill="#8DC640" d="M287.62,221.08c1.49-2.08,2.65-4.81,2.65-8.59c0-3.76-1.13-6.45-2.65-8.52h1.43
c1.34,1.72,2.75,4.41,2.75,8.55c0,4.12-1.41,6.78-2.75,8.57H287.62z"/>
<path fill="#8DC640" d="M294.7,211.69c0-1.3-0.04-2.35-0.08-3.32h1.66l0.08,1.74h0.04c0.76-1.24,1.95-1.97,3.61-1.97
c2.46,0,4.3,2.08,4.3,5.17c0,3.65-2.22,5.46-4.62,5.46c-1.34,0-2.52-0.59-3.13-1.6h-0.04v5.52h-1.83V211.69z M296.53,214.4
c0,0.27,0.04,0.52,0.08,0.76c0.34,1.28,1.45,2.16,2.77,2.16c1.95,0,3.09-1.6,3.09-3.93c0-2.04-1.07-3.78-3.02-3.78
c-1.26,0-2.44,0.9-2.79,2.29c-0.06,0.23-0.13,0.5-0.13,0.76V214.4z"/>
<path fill="#8DC640" d="M312.28,218.54l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.95,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H312.28z M312,213.35c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.11-0.4,0.11-0.59V213.35z"/>
<path fill="#8DC640" d="M318.91,205.46v2.92h2.65v1.41h-2.65v5.48c0,1.26,0.36,1.97,1.39,1.97c0.48,0,0.84-0.06,1.07-0.13
l0.08,1.39c-0.36,0.15-0.92,0.25-1.64,0.25c-0.86,0-1.55-0.27-2-0.78c-0.52-0.55-0.71-1.45-0.71-2.65v-5.54h-1.58v-1.41h1.58v-2.44
L318.91,205.46z"/>
<path fill="#8DC640" d="M323.64,203.63h1.85v6.34h0.04c0.29-0.52,0.76-0.99,1.32-1.3c0.55-0.31,1.2-0.52,1.89-0.52
c1.37,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.12,0.52-0.12,0.88v6.13h-1.85V203.63z"/>
<path fill="#8DC640" d="M335.48,220.89v-16.73h3.84v1.15h-2.41v14.42h2.41v1.15H335.48z"/>
<path fill="#8DC640" d="M344.68,206.61h-0.04l-2.37,1.28l-0.36-1.41l2.98-1.6h1.58v13.65h-1.79V206.61z"/>
<path fill="#8DC640" d="M351.88,216.42c0.53,0.34,1.74,0.86,3.02,0.86c2.37,0,3.11-1.51,3.09-2.65c-0.02-1.91-1.74-2.73-3.53-2.73
h-1.03v-1.39h1.03c1.34,0,3.04-0.69,3.04-2.31c0-1.09-0.69-2.06-2.39-2.06c-1.09,0-2.14,0.48-2.73,0.9l-0.48-1.34
c0.71-0.52,2.1-1.05,3.57-1.05c2.69,0,3.91,1.6,3.91,3.25c0,1.41-0.84,2.6-2.52,3.21v0.04c1.68,0.34,3.04,1.6,3.04,3.51
c0,2.18-1.7,4.09-4.98,4.09c-1.53,0-2.88-0.48-3.55-0.92L351.88,216.42z"/>
<path fill="#8DC640" d="M365.51,204.14v16.75h-3.84v-1.15h2.42v-14.45h-2.42v-1.15H365.51z"/>
</g>
<g>
<path fill="#F79420" d="M180.83,505.96c-1.53,2.06-2.65,4.79-2.65,8.59c0,3.74,1.15,6.42,2.65,8.52h-1.45
c-1.32-1.74-2.75-4.43-2.75-8.52c0.02-4.14,1.43-6.82,2.75-8.59H180.83z"/>
<path fill="#F79420" d="M182.78,505.63h1.85v6.34h0.04c0.29-0.52,0.76-0.99,1.32-1.3c0.55-0.31,1.2-0.52,1.89-0.52
c1.36,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.13,0.52-0.13,0.88v6.13h-1.85V505.63z"/>
<path fill="#F79420" d="M200.06,520.53l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H200.06z M199.79,515.35c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V515.35z"/>
<path fill="#F79420" d="M204.56,513.12c0-1.05-0.02-1.91-0.08-2.75h1.64l0.1,1.68h0.04c0.5-0.97,1.68-1.91,3.36-1.91
c1.41,0,3.59,0.84,3.59,4.33v6.07h-1.85v-5.86c0-1.64-0.61-3-2.35-3c-1.22,0-2.16,0.86-2.48,1.89c-0.08,0.23-0.13,0.55-0.13,0.86
v6.11h-1.85V513.12z"/>
<path fill="#F79420" d="M224.99,505.63v12.28c0,0.9,0.02,1.93,0.08,2.62h-1.66l-0.08-1.76h-0.04c-0.57,1.13-1.81,1.99-3.46,1.99
c-2.46,0-4.35-2.08-4.35-5.17c-0.02-3.38,2.08-5.46,4.56-5.46c1.55,0,2.6,0.73,3.07,1.55h0.04v-6.07H224.99z M223.14,514.51
c0-0.23-0.02-0.55-0.08-0.78c-0.27-1.18-1.28-2.14-2.67-2.14c-1.91,0-3.04,1.68-3.04,3.93c0,2.06,1.01,3.76,3,3.76
c1.24,0,2.37-0.82,2.71-2.2c0.06-0.25,0.08-0.5,0.08-0.8V514.51z"/>
<path fill="#F79420" d="M226.94,523.07c1.49-2.08,2.65-4.81,2.65-8.59c0-3.76-1.13-6.45-2.65-8.52h1.43
c1.34,1.72,2.75,4.41,2.75,8.55c0,4.12-1.41,6.78-2.75,8.57H226.94z"/>
<path fill="#F79420" d="M234.02,513.69c0-1.3-0.04-2.35-0.08-3.32h1.66l0.08,1.74h0.04c0.76-1.24,1.95-1.97,3.61-1.97
c2.46,0,4.3,2.08,4.3,5.17c0,3.65-2.22,5.46-4.62,5.46c-1.34,0-2.52-0.59-3.13-1.6h-0.04v5.52h-1.83V513.69z M235.85,516.4
c0,0.27,0.04,0.52,0.08,0.76c0.34,1.28,1.45,2.16,2.77,2.16c1.95,0,3.09-1.6,3.09-3.93c0-2.04-1.07-3.78-3.02-3.78
c-1.26,0-2.44,0.9-2.79,2.29c-0.06,0.23-0.13,0.5-0.13,0.76V516.4z"/>
<path fill="#F79420" d="M251.59,520.53l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H251.59z M251.32,515.35c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V515.35z"/>
<path fill="#F79420" d="M258.23,507.45v2.92h2.65v1.41h-2.65v5.48c0,1.26,0.36,1.97,1.39,1.97c0.48,0,0.84-0.06,1.07-0.13
l0.08,1.39c-0.36,0.15-0.92,0.25-1.64,0.25c-0.86,0-1.55-0.27-2-0.78c-0.52-0.55-0.71-1.45-0.71-2.65v-5.54h-1.58v-1.41h1.58v-2.44
L258.23,507.45z"/>
<path fill="#F79420" d="M262.96,505.63h1.85v6.34h0.04c0.29-0.52,0.76-0.99,1.32-1.3c0.55-0.31,1.2-0.52,1.89-0.52
c1.37,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.12,0.52-0.12,0.88v6.13h-1.85V505.63z"/>
<path fill="#F79420" d="M274.8,522.88v-16.73h3.84v1.15h-2.42v14.42h2.42v1.15H274.8z"/>
<path fill="#F79420" d="M284,508.61h-0.04l-2.37,1.28l-0.36-1.41l2.98-1.6h1.57v13.65H284V508.61z"/>
<path fill="#F79420" d="M290.59,517.07c0-1.72,1.03-2.94,2.71-3.65l-0.02-0.06c-1.51-0.71-2.16-1.89-2.16-3.07
c0-2.16,1.83-3.63,4.22-3.63c2.64,0,3.97,1.66,3.97,3.36c0,1.15-0.57,2.39-2.25,3.19v0.06c1.7,0.67,2.75,1.87,2.75,3.53
c0,2.37-2.04,3.97-4.64,3.97C292.32,520.76,290.59,519.06,290.59,517.07z M297.94,516.98c0-1.66-1.16-2.46-3-2.98
c-1.6,0.46-2.46,1.51-2.46,2.81c-0.06,1.39,0.99,2.6,2.73,2.6C296.87,519.42,297.94,518.39,297.94,516.98z M292.86,510.16
c0,1.36,1.03,2.1,2.6,2.52c1.18-0.4,2.08-1.24,2.08-2.48c0-1.09-0.65-2.23-2.31-2.23C293.7,507.98,292.86,508.99,292.86,510.16z"/>
<path fill="#F79420" d="M304.83,506.13v16.75h-3.84v-1.15h2.42v-14.45h-2.42v-1.15H304.83z"/>
</g>
<g>
<path fill="#00AEEF" d="M115.68,394.36c-1.53,2.06-2.65,4.79-2.65,8.59c0,3.74,1.15,6.42,2.65,8.52h-1.45
c-1.32-1.74-2.75-4.43-2.75-8.52c0.02-4.14,1.43-6.82,2.75-8.59H115.68z"/>
<path fill="#00AEEF" d="M117.64,401.52c0-1.05-0.02-1.91-0.08-2.75h1.62l0.08,1.64h0.06c0.57-0.97,1.51-1.87,3.19-1.87
c1.39,0,2.44,0.84,2.88,2.04h0.04c0.31-0.57,0.71-1.01,1.13-1.32c0.61-0.46,1.28-0.71,2.25-0.71c1.34,0,3.34,0.88,3.34,4.41v5.98
h-1.81v-5.75c0-1.95-0.71-3.13-2.2-3.13c-1.05,0-1.87,0.78-2.18,1.68c-0.08,0.25-0.15,0.59-0.15,0.92v6.28H124v-6.09
c0-1.62-0.71-2.79-2.12-2.79c-1.15,0-1.99,0.92-2.29,1.85c-0.1,0.27-0.15,0.59-0.15,0.9v6.13h-1.81V401.52z"/>
<path fill="#00AEEF" d="M140.78,408.93l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H140.78z M140.5,403.74c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V403.74z"/>
<path fill="#00AEEF" d="M154.03,398.77c-0.04,0.73-0.08,1.55-0.08,2.79v5.9c0,2.33-0.46,3.76-1.45,4.64
c-0.99,0.92-2.42,1.22-3.7,1.22c-1.22,0-2.56-0.29-3.38-0.84l0.46-1.41c0.67,0.42,1.72,0.8,2.98,0.8c1.89,0,3.28-0.99,3.28-3.55
v-1.13h-0.04c-0.57,0.94-1.66,1.7-3.23,1.7c-2.52,0-4.33-2.14-4.33-4.96c0-3.44,2.25-5.4,4.58-5.4c1.76,0,2.73,0.92,3.17,1.76h0.04
l0.08-1.53H154.03z M152.12,402.78c0-0.31-0.02-0.59-0.11-0.84c-0.34-1.07-1.24-1.95-2.58-1.95c-1.76,0-3.02,1.49-3.02,3.84
c0,1.99,1.01,3.65,3,3.65c1.13,0,2.16-0.71,2.56-1.89c0.1-0.31,0.15-0.67,0.15-0.99V402.78z"/>
<path fill="#00AEEF" d="M158.94,395.91c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.15,1.15-1.15
C158.5,394.76,158.94,395.26,158.94,395.91z M156.88,408.93v-10.16h1.85v10.16H156.88z"/>
<path fill="#00AEEF" d="M169.04,408.55c-0.48,0.25-1.55,0.59-2.92,0.59c-3.07,0-5.06-2.08-5.06-5.19c0-3.13,2.14-5.4,5.46-5.4
c1.09,0,2.06,0.27,2.56,0.52l-0.42,1.43c-0.44-0.25-1.13-0.48-2.14-0.48c-2.33,0-3.59,1.72-3.59,3.84c0,2.35,1.51,3.8,3.53,3.8
c1.05,0,1.74-0.27,2.27-0.5L169.04,408.55z"/>
<path fill="#00AEEF" d="M173.26,395.91c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.15,1.15-1.15
C172.82,394.76,173.26,395.26,173.26,395.91z M171.21,408.93v-10.16h1.85v10.16H171.21z"/>
<path fill="#00AEEF" d="M181.75,408.93l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H181.75z M181.47,403.74c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V403.74z"/>
<path fill="#00AEEF" d="M186.24,401.52c0-1.05-0.02-1.91-0.08-2.75h1.64l0.1,1.68h0.04c0.5-0.97,1.68-1.91,3.36-1.91
c1.41,0,3.59,0.84,3.59,4.33v6.07h-1.85v-5.86c0-1.64-0.61-3-2.35-3c-1.22,0-2.16,0.86-2.48,1.89c-0.08,0.23-0.13,0.55-0.13,0.86
v6.11h-1.85V401.52z"/>
<path fill="#00AEEF" d="M206.86,410.5v1.05h-10.5v-1.05H206.86z"/>
<path fill="#00AEEF" d="M208.4,401.52c0-1.05-0.02-1.91-0.08-2.75h1.64l0.11,1.68h0.04c0.5-0.97,1.68-1.91,3.36-1.91
c1.41,0,3.59,0.84,3.59,4.33v6.07h-1.85v-5.86c0-1.64-0.61-3-2.35-3c-1.22,0-2.16,0.86-2.48,1.89c-0.08,0.23-0.12,0.55-0.12,0.86
v6.11h-1.85V401.52z"/>
<path fill="#00AEEF" d="M221.08,404.18c0.04,2.5,1.64,3.53,3.49,3.53c1.32,0,2.12-0.23,2.81-0.52l0.31,1.32
c-0.65,0.29-1.76,0.63-3.38,0.63c-3.13,0-5-2.06-5-5.12s1.81-5.48,4.77-5.48c3.32,0,4.2,2.92,4.2,4.79c0,0.38-0.04,0.67-0.06,0.86
H221.08z M226.5,402.86c0.02-1.18-0.48-3-2.56-3c-1.87,0-2.69,1.72-2.83,3H226.5z"/>
<path fill="#00AEEF" d="M237.82,408.55c-0.48,0.25-1.55,0.59-2.92,0.59c-3.06,0-5.06-2.08-5.06-5.19c0-3.13,2.14-5.4,5.46-5.4
c1.09,0,2.06,0.27,2.56,0.52l-0.42,1.43c-0.44-0.25-1.13-0.48-2.14-0.48c-2.33,0-3.59,1.72-3.59,3.84c0,2.35,1.51,3.8,3.53,3.8
c1.05,0,1.74-0.27,2.27-0.5L237.82,408.55z"/>
<path fill="#00AEEF" d="M241.81,403.43h0.04c0.25-0.36,0.61-0.8,0.9-1.15l2.98-3.51h2.23l-3.93,4.18l4.47,5.98h-2.25l-3.51-4.87
l-0.95,1.05v3.82h-1.83v-14.91h1.83V403.43z"/>
<path fill="#00AEEF" d="M248.72,411.47c1.49-2.08,2.65-4.81,2.65-8.59c0-3.76-1.13-6.45-2.65-8.52h1.43
c1.34,1.72,2.75,4.41,2.75,8.55c0,4.12-1.41,6.78-2.75,8.57H248.72z"/>
<path fill="#00AEEF" d="M260.24,402.08c0-1.3-0.04-2.35-0.08-3.32h1.66l0.08,1.74h0.04c0.76-1.24,1.95-1.97,3.61-1.97
c2.46,0,4.3,2.08,4.3,5.17c0,3.65-2.23,5.46-4.62,5.46c-1.34,0-2.52-0.59-3.13-1.6h-0.04v5.52h-1.83V402.08z M262.07,404.79
c0,0.27,0.04,0.52,0.08,0.76c0.34,1.28,1.45,2.16,2.77,2.16c1.95,0,3.09-1.6,3.09-3.93c0-2.04-1.07-3.78-3.02-3.78
c-1.26,0-2.44,0.9-2.79,2.29c-0.06,0.23-0.13,0.5-0.13,0.76V404.79z"/>
<path fill="#00AEEF" d="M277.82,408.93l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.95,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H277.82z M277.55,403.74c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.11-0.4,0.11-0.59V403.74z"/>
<path fill="#00AEEF" d="M284.46,395.85v2.92h2.64v1.41h-2.64v5.48c0,1.26,0.36,1.97,1.38,1.97c0.48,0,0.84-0.06,1.07-0.13
l0.08,1.39c-0.36,0.15-0.92,0.25-1.64,0.25c-0.86,0-1.55-0.27-1.99-0.78c-0.53-0.55-0.71-1.45-0.71-2.65v-5.54h-1.57v-1.41h1.57
v-2.44L284.46,395.85z"/>
<path fill="#00AEEF" d="M289.18,394.02h1.85v6.34h0.04c0.29-0.52,0.76-0.99,1.32-1.3c0.55-0.31,1.2-0.52,1.89-0.52
c1.36,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.11,0.25-0.13,0.52-0.13,0.88v6.13h-1.85V394.02z"/>
<path fill="#00AEEF" d="M301.03,411.28v-16.73h3.84v1.15h-2.41v14.42h2.41v1.15H301.03z"/>
<path fill="#00AEEF" d="M310.22,397h-0.04l-2.37,1.28l-0.36-1.41l2.98-1.6h1.58v13.65h-1.79V397z"/>
<path fill="#00AEEF" d="M322.7,408.93v-3.72h-6.34v-1.22l6.09-8.71h2v8.48h1.91v1.45h-1.91v3.72H322.7z M322.7,403.76v-4.56
c0-0.71,0.02-1.43,0.06-2.14h-0.06c-0.42,0.8-0.76,1.39-1.13,2.02l-3.34,4.64v0.04H322.7z"/>
<path fill="#00AEEF" d="M331.06,394.53v16.75h-3.84v-1.15h2.41v-14.45h-2.41v-1.15H331.06z"/>
</g>
<g>
<path fill="#8299CE" d="M131.81,1023.11c-1.53,2.06-2.65,4.79-2.65,8.59c0,3.74,1.15,6.42,2.65,8.52h-1.45
c-1.32-1.74-2.75-4.43-2.75-8.52c0.02-4.14,1.43-6.82,2.75-8.59H131.81z"/>
<path fill="#8299CE" d="M133.76,1030.27c0-1.05-0.02-1.91-0.08-2.75h1.62l0.08,1.64h0.06c0.57-0.97,1.51-1.87,3.19-1.87
c1.39,0,2.44,0.84,2.88,2.04h0.04c0.31-0.57,0.71-1.01,1.13-1.32c0.61-0.46,1.28-0.71,2.25-0.71c1.34,0,3.34,0.88,3.34,4.41v5.98
h-1.81v-5.75c0-1.95-0.71-3.13-2.2-3.13c-1.05,0-1.87,0.78-2.18,1.68c-0.08,0.25-0.15,0.59-0.15,0.92v6.28h-1.81v-6.09
c0-1.62-0.71-2.79-2.12-2.79c-1.15,0-1.99,0.92-2.29,1.85c-0.1,0.27-0.15,0.59-0.15,0.9v6.13h-1.81V1030.27z"/>
<path fill="#8299CE" d="M156.9,1037.68l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78V1031c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H156.9z M156.63,1032.5c-2.02-0.04-4.3,0.32-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V1032.5z"/>
<path fill="#8299CE" d="M170.15,1027.52c-0.04,0.74-0.08,1.55-0.08,2.79v5.9c0,2.33-0.46,3.76-1.45,4.64
c-0.99,0.92-2.41,1.22-3.7,1.22c-1.22,0-2.56-0.29-3.38-0.84l0.46-1.41c0.67,0.42,1.72,0.8,2.98,0.8c1.89,0,3.28-0.99,3.28-3.55
v-1.13h-0.04c-0.57,0.95-1.66,1.7-3.23,1.7c-2.52,0-4.33-2.14-4.33-4.96c0-3.44,2.25-5.4,4.58-5.4c1.76,0,2.73,0.92,3.17,1.76h0.04
l0.08-1.53H170.15z M168.24,1031.53c0-0.32-0.02-0.59-0.1-0.84c-0.34-1.07-1.24-1.95-2.58-1.95c-1.76,0-3.02,1.49-3.02,3.84
c0,2,1.01,3.65,3,3.65c1.13,0,2.16-0.71,2.56-1.89c0.1-0.31,0.15-0.67,0.15-0.99V1031.53z"/>
<path fill="#8299CE" d="M175.07,1024.66c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.16,1.15-1.16
C174.63,1023.51,175.07,1024.01,175.07,1024.66z M173.01,1037.68v-10.16h1.85v10.16H173.01z"/>
<path fill="#8299CE" d="M185.17,1037.3c-0.48,0.25-1.55,0.59-2.92,0.59c-3.07,0-5.06-2.08-5.06-5.19c0-3.13,2.14-5.4,5.46-5.4
c1.09,0,2.06,0.27,2.56,0.53l-0.42,1.43c-0.44-0.25-1.13-0.48-2.14-0.48c-2.33,0-3.59,1.72-3.59,3.84c0,2.35,1.51,3.8,3.53,3.8
c1.05,0,1.74-0.27,2.27-0.5L185.17,1037.3z"/>
<path fill="#8299CE" d="M189.39,1024.66c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.16,1.15-1.16
C188.95,1023.51,189.39,1024.01,189.39,1024.66z M187.33,1037.68v-10.16h1.85v10.16H187.33z"/>
<path fill="#8299CE" d="M197.87,1037.68l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78V1031c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H197.87z M197.6,1032.5c-2.02-0.04-4.3,0.32-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V1032.5z"/>
<path fill="#8299CE" d="M202.37,1030.27c0-1.05-0.02-1.91-0.08-2.75h1.64l0.1,1.68h0.04c0.5-0.97,1.68-1.91,3.36-1.91
c1.41,0,3.59,0.84,3.59,4.33v6.07h-1.85v-5.86c0-1.64-0.61-3-2.35-3c-1.22,0-2.16,0.86-2.48,1.89c-0.08,0.23-0.13,0.55-0.13,0.86
v6.11h-1.85V1030.27z"/>
<path fill="#8299CE" d="M222.99,1039.26v1.05h-10.5v-1.05H222.99z"/>
<path fill="#8299CE" d="M224.52,1022.77h1.85v6.34h0.04c0.29-0.52,0.76-0.99,1.32-1.3c0.55-0.31,1.2-0.53,1.89-0.53
c1.36,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.13,0.53-0.13,0.88v6.13h-1.85V1022.77z"/>
<path fill="#8299CE" d="M245.38,1032.52c0,3.76-2.6,5.4-5.06,5.4c-2.75,0-4.87-2.02-4.87-5.23c0-3.4,2.23-5.4,5.04-5.4
C243.4,1027.29,245.38,1029.41,245.38,1032.52z M237.31,1032.62c0,2.22,1.28,3.9,3.09,3.9c1.76,0,3.09-1.66,3.09-3.95
c0-1.72-0.86-3.9-3.04-3.9S237.31,1030.69,237.31,1032.62z"/>
<path fill="#8299CE" d="M256.21,1034.91c0,1.05,0.02,1.97,0.08,2.77h-1.64l-0.1-1.66h-0.04c-0.48,0.82-1.55,1.89-3.36,1.89
c-1.6,0-3.51-0.88-3.51-4.45v-5.94h1.85v5.63c0,1.93,0.59,3.23,2.27,3.23c1.24,0,2.1-0.86,2.44-1.68c0.1-0.27,0.17-0.61,0.17-0.95
v-6.24h1.85V1034.91z"/>
<path fill="#8299CE" d="M261.11,1032.18h0.04c0.25-0.36,0.61-0.8,0.9-1.15l2.98-3.51h2.23l-3.93,4.18l4.47,5.98h-2.25l-3.51-4.87
l-0.94,1.05v3.82h-1.83v-14.91h1.83V1032.18z"/>
<path fill="#8299CE" d="M271.54,1024.66c0.02,0.63-0.44,1.13-1.18,1.13c-0.65,0-1.11-0.5-1.11-1.13c0-0.65,0.48-1.16,1.15-1.16
C271.1,1023.51,271.54,1024.01,271.54,1024.66z M269.48,1037.68v-10.16h1.85v10.16H269.48z"/>
<path fill="#8299CE" d="M273.29,1040.22c1.49-2.08,2.65-4.81,2.65-8.59c0-3.76-1.13-6.45-2.65-8.52h1.43
c1.34,1.72,2.75,4.41,2.75,8.54c0,4.12-1.41,6.78-2.75,8.57H273.29z"/>
<path fill="#8299CE" d="M284.81,1030.84c0-1.3-0.04-2.35-0.08-3.32h1.66l0.08,1.74h0.04c0.76-1.24,1.95-1.97,3.61-1.97
c2.46,0,4.3,2.08,4.3,5.17c0,3.65-2.23,5.46-4.62,5.46c-1.34,0-2.52-0.59-3.13-1.6h-0.04v5.52h-1.83V1030.84z M286.64,1033.55
c0,0.27,0.04,0.52,0.08,0.76c0.34,1.28,1.45,2.16,2.77,2.16c1.95,0,3.09-1.6,3.09-3.93c0-2.04-1.07-3.78-3.02-3.78
c-1.26,0-2.44,0.9-2.79,2.29c-0.06,0.23-0.13,0.5-0.13,0.76V1033.55z"/>
<path fill="#8299CE" d="M302.39,1037.68l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78V1031c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H302.39z M302.12,1032.5c-2.02-0.04-4.3,0.32-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V1032.5z"/>
<path fill="#8299CE" d="M309.03,1024.6v2.92h2.65v1.41h-2.65v5.48c0,1.26,0.36,1.97,1.39,1.97c0.48,0,0.84-0.06,1.07-0.13
l0.08,1.39c-0.36,0.15-0.92,0.25-1.64,0.25c-0.86,0-1.55-0.27-1.99-0.78c-0.52-0.54-0.71-1.45-0.71-2.64v-5.54h-1.57v-1.41h1.57
v-2.44L309.03,1024.6z"/>
<path fill="#8299CE" d="M313.75,1022.77h1.85v6.34h0.04c0.29-0.52,0.76-0.99,1.32-1.3c0.55-0.31,1.2-0.53,1.89-0.53
c1.36,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.13,0.53-0.13,0.88v6.13h-1.85V1022.77z"/>
<path fill="#8299CE" d="M325.6,1040.03v-16.73h3.84v1.15h-2.41v14.42h2.41v1.16H325.6z"/>
<path fill="#8299CE" d="M334.79,1025.76h-0.04l-2.37,1.28l-0.36-1.41l2.98-1.6h1.58v13.65h-1.79V1025.76z"/>
<path fill="#8299CE" d="M349.7,1025.59h-5.21l-0.52,3.51c0.32-0.04,0.61-0.08,1.11-0.08c1.05,0,2.1,0.23,2.94,0.73
c1.07,0.61,1.95,1.79,1.95,3.51c0,2.67-2.12,4.66-5.08,4.66c-1.49,0-2.75-0.42-3.4-0.84l0.46-1.41c0.57,0.34,1.68,0.76,2.92,0.76
c1.74,0,3.23-1.13,3.23-2.96c-0.02-1.76-1.2-3.02-3.93-3.02c-0.78,0-1.39,0.08-1.89,0.15l0.88-6.55h6.53V1025.59z"/>
<path fill="#8299CE" d="M355.62,1023.28v16.75h-3.84v-1.16h2.42v-14.45h-2.42v-1.15H355.62z"/>
</g>
<g>
<path fill="none" stroke="#544E4A" stroke-miterlimit="10" d="M335.67,403.86c3.54,2.07,22.84,12.95,39.53,6.34
c10.32-4.09,15.68-9.77,15.68-9.77c5.12-5.42,6.07-10.05,10.7-10.78c2.69-0.42,5.88,0.6,8.43,2.42"/>
<g>
<path fill="#544E4A" d="M408.85,391.25l0.87-3.13l0.11,0.03l1.78,4.53c0.82,1.39,1.65,2.77,2.47,4.16
c-1.33-0.91-2.66-1.83-3.99-2.74l-4.4-2.07l-0.03-0.1L408.85,391.25z"/>
</g>
</g>
<g>
<path fill="#EE9CB0" d="M170.39,874.98c-1.53,2.06-2.65,4.79-2.65,8.59c0,3.74,1.15,6.43,2.65,8.53h-1.45
c-1.32-1.74-2.75-4.43-2.75-8.53c0.02-4.14,1.43-6.82,2.75-8.59H170.39z"/>
<path fill="#EE9CB0" d="M172.26,889.55c0.04-0.69,0.08-1.72,0.08-2.62v-12.28h1.83v6.38h0.04c0.65-1.13,1.83-1.87,3.46-1.87
c2.52,0,4.3,2.1,4.28,5.19c0,3.63-2.29,5.44-4.56,5.44c-1.47,0-2.65-0.57-3.4-1.91h-0.06l-0.08,1.68H172.26z M174.17,885.48
c0,0.23,0.04,0.46,0.08,0.67c0.36,1.28,1.43,2.16,2.77,2.16c1.93,0,3.09-1.58,3.09-3.91c0-2.04-1.05-3.78-3.02-3.78
c-1.26,0-2.44,0.86-2.81,2.27c-0.04,0.21-0.1,0.46-0.1,0.76V885.48z"/>
<path fill="#EE9CB0" d="M193.49,884.38c0,3.76-2.6,5.4-5.06,5.4c-2.75,0-4.87-2.02-4.87-5.23c0-3.4,2.23-5.4,5.04-5.4
C191.52,879.16,193.49,881.28,193.49,884.38z M185.43,884.49c0,2.23,1.28,3.91,3.09,3.91c1.76,0,3.09-1.66,3.09-3.95
c0-1.72-0.86-3.91-3.04-3.91S185.43,882.56,185.43,884.49z"/>
<path fill="#EE9CB0" d="M204.6,874.64v12.28c0,0.9,0.02,1.93,0.08,2.62h-1.66l-0.08-1.76h-0.04c-0.57,1.13-1.81,1.99-3.46,1.99
c-2.46,0-4.35-2.08-4.35-5.16c-0.02-3.38,2.08-5.46,4.56-5.46c1.55,0,2.6,0.73,3.07,1.55h0.04v-6.07H204.6z M202.75,883.52
c0-0.23-0.02-0.55-0.08-0.78c-0.27-1.18-1.28-2.14-2.67-2.14c-1.91,0-3.04,1.68-3.04,3.93c0,2.06,1.01,3.76,3,3.76
c1.24,0,2.37-0.82,2.71-2.21c0.06-0.25,0.08-0.5,0.08-0.8V883.52z"/>
<path fill="#EE9CB0" d="M208.34,879.39l2.23,6c0.23,0.67,0.48,1.47,0.65,2.08h0.04c0.19-0.61,0.4-1.39,0.65-2.12l2.02-5.96h1.95
l-2.77,7.24c-1.32,3.48-2.23,5.27-3.49,6.36c-0.9,0.8-1.81,1.11-2.27,1.2l-0.46-1.55c0.46-0.15,1.07-0.44,1.62-0.9
c0.5-0.4,1.13-1.11,1.55-2.06c0.08-0.19,0.15-0.34,0.15-0.44c0-0.11-0.04-0.25-0.13-0.48l-3.76-9.36H208.34z"/>
<path fill="#EE9CB0" d="M216.45,892.09c1.49-2.08,2.65-4.81,2.65-8.59c0-3.76-1.13-6.45-2.65-8.52h1.43
c1.34,1.72,2.75,4.41,2.75,8.55c0,4.12-1.41,6.78-2.75,8.57H216.45z"/>
<path fill="#EE9CB0" d="M227.98,882.71c0-1.3-0.04-2.35-0.08-3.32h1.66l0.08,1.74h0.04c0.76-1.24,1.95-1.97,3.61-1.97
c2.46,0,4.3,2.08,4.3,5.16c0,3.65-2.23,5.46-4.62,5.46c-1.34,0-2.52-0.59-3.13-1.6h-0.04v5.52h-1.83V882.71z M229.8,885.41
c0,0.27,0.04,0.53,0.08,0.76c0.34,1.28,1.45,2.16,2.77,2.16c1.95,0,3.09-1.6,3.09-3.93c0-2.04-1.07-3.78-3.02-3.78
c-1.26,0-2.44,0.9-2.79,2.29c-0.06,0.23-0.13,0.5-0.13,0.76V885.41z"/>
<path fill="#EE9CB0" d="M245.55,889.55l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.94,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H245.55z M245.28,884.36c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.1-0.4,0.1-0.59V884.36z"/>
<path fill="#EE9CB0" d="M252.19,876.47v2.92h2.65v1.41h-2.65v5.48c0,1.26,0.36,1.97,1.39,1.97c0.48,0,0.84-0.06,1.07-0.13
l0.08,1.39c-0.36,0.15-0.92,0.25-1.64,0.25c-0.86,0-1.55-0.27-1.99-0.78c-0.52-0.55-0.71-1.45-0.71-2.65v-5.54h-1.57v-1.41h1.57
v-2.44L252.19,876.47z"/>
<path fill="#EE9CB0" d="M256.91,874.64h1.85v6.34h0.04c0.29-0.53,0.76-0.99,1.32-1.3c0.55-0.32,1.2-0.52,1.89-0.52
c1.36,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.13,0.52-0.13,0.88v6.13h-1.85V874.64z"/>
<path fill="#EE9CB0" d="M268.76,891.9v-16.73h3.84v1.16h-2.41v14.42h2.41v1.15H268.76z"/>
<path fill="#EE9CB0" d="M277.96,877.62h-0.04l-2.37,1.28l-0.36-1.41l2.98-1.6h1.57v13.65h-1.78V877.62z"/>
<path fill="#EE9CB0" d="M292.51,877.2c-0.38-0.02-0.86,0-1.39,0.08c-2.9,0.48-4.43,2.6-4.75,4.85h0.06
c0.65-0.86,1.78-1.57,3.3-1.57c2.41,0,4.12,1.74,4.12,4.41c0,2.5-1.7,4.81-4.54,4.81c-2.92,0-4.83-2.27-4.83-5.82
c0-2.69,0.97-4.81,2.31-6.15c1.13-1.11,2.65-1.81,4.37-2.02c0.55-0.08,1.01-0.11,1.34-0.11V877.2z M291.98,885.08
c0-1.95-1.11-3.13-2.81-3.13c-1.11,0-2.14,0.69-2.65,1.68c-0.13,0.21-0.21,0.48-0.21,0.82c0.04,2.25,1.07,3.9,3,3.9
C290.91,888.35,291.98,887.03,291.98,885.08z"/>
<path fill="#EE9CB0" d="M298.79,875.15v16.75h-3.84v-1.15h2.41V876.3h-2.41v-1.16H298.79z"/>
</g>
<g>
<path fill="#65C8D0" d="M271.57,1185.62c-1.53,2.06-2.65,4.79-2.65,8.59c0,3.74,1.15,6.43,2.65,8.53h-1.45
c-1.32-1.74-2.75-4.43-2.75-8.53c0.02-4.14,1.43-6.82,2.75-8.59H271.57z"/>
<path fill="#65C8D0" d="M273.52,1185.29h1.85v14.91h-1.85V1185.29z"/>
<path fill="#65C8D0" d="M279.51,1195.45c0.04,2.5,1.64,3.53,3.49,3.53c1.32,0,2.12-0.23,2.81-0.52l0.31,1.32
c-0.65,0.29-1.76,0.63-3.38,0.63c-3.13,0-5-2.06-5-5.12s1.81-5.48,4.77-5.48c3.32,0,4.2,2.92,4.2,4.79c0,0.38-0.04,0.67-0.06,0.86
H279.51z M284.92,1194.12c0.02-1.18-0.48-3-2.56-3c-1.87,0-2.69,1.72-2.83,3H284.92z"/>
<path fill="#65C8D0" d="M297.75,1190.03c-0.04,0.73-0.08,1.55-0.08,2.79v5.9c0,2.33-0.46,3.76-1.45,4.64
c-0.99,0.92-2.41,1.22-3.7,1.22c-1.22,0-2.56-0.29-3.38-0.84l0.46-1.41c0.67,0.42,1.72,0.8,2.98,0.8c1.89,0,3.28-0.99,3.28-3.55
v-1.13h-0.04c-0.57,0.94-1.66,1.7-3.23,1.7c-2.52,0-4.33-2.14-4.33-4.96c0-3.44,2.25-5.4,4.58-5.4c1.76,0,2.73,0.92,3.17,1.76h0.04
l0.08-1.53H297.75z M295.84,1194.04c0-0.31-0.02-0.59-0.1-0.84c-0.34-1.07-1.24-1.95-2.58-1.95c-1.76,0-3.02,1.49-3.02,3.84
c0,1.99,1.01,3.65,3,3.65c1.13,0,2.16-0.71,2.56-1.89c0.1-0.32,0.15-0.67,0.15-0.99V1194.04z"/>
<path fill="#65C8D0" d="M299.62,1202.73c1.49-2.08,2.65-4.81,2.65-8.59c0-3.76-1.13-6.45-2.65-8.52h1.43
c1.34,1.72,2.75,4.41,2.75,8.55c0,4.12-1.41,6.78-2.75,8.57H299.62z"/>
<path fill="#65C8D0" d="M311.15,1193.35c0-1.3-0.04-2.35-0.08-3.32h1.66l0.08,1.74h0.04c0.76-1.24,1.95-1.97,3.61-1.97
c2.46,0,4.3,2.08,4.3,5.16c0,3.65-2.23,5.46-4.62,5.46c-1.34,0-2.52-0.59-3.13-1.6h-0.04v5.52h-1.83V1193.35z M312.98,1196.06
c0,0.27,0.04,0.53,0.08,0.76c0.34,1.28,1.45,2.16,2.77,2.16c1.95,0,3.09-1.6,3.09-3.93c0-2.04-1.07-3.78-3.02-3.78
c-1.26,0-2.44,0.9-2.79,2.29c-0.06,0.23-0.13,0.5-0.13,0.76V1196.06z"/>
<path fill="#65C8D0" d="M328.73,1200.19l-0.15-1.28h-0.06c-0.57,0.8-1.66,1.51-3.11,1.51c-2.06,0-3.11-1.45-3.11-2.92
c0-2.46,2.18-3.8,6.11-3.78v-0.21c0-0.84-0.23-2.35-2.31-2.35c-0.95,0-1.93,0.29-2.65,0.76l-0.42-1.22c0.84-0.55,2.06-0.9,3.34-0.9
c3.11,0,3.86,2.12,3.86,4.16v3.8c0,0.88,0.04,1.74,0.17,2.44H328.73z M328.46,1195.01c-2.02-0.04-4.3,0.31-4.3,2.29
c0,1.2,0.8,1.76,1.74,1.76c1.32,0,2.16-0.84,2.46-1.7c0.06-0.19,0.11-0.4,0.11-0.59V1195.01z"/>
<path fill="#65C8D0" d="M335.37,1187.11v2.92h2.64v1.41h-2.64v5.48c0,1.26,0.36,1.97,1.38,1.97c0.48,0,0.84-0.06,1.07-0.13
l0.08,1.39c-0.36,0.15-0.92,0.25-1.64,0.25c-0.86,0-1.55-0.27-1.99-0.78c-0.53-0.55-0.71-1.45-0.71-2.65v-5.54h-1.57v-1.41h1.57
v-2.44L335.37,1187.11z"/>
<path fill="#65C8D0" d="M340.09,1185.29h1.85v6.34h0.04c0.29-0.53,0.76-0.99,1.32-1.3c0.55-0.32,1.2-0.52,1.89-0.52
c1.37,0,3.55,0.84,3.55,4.35v6.05h-1.85v-5.84c0-1.64-0.61-3.02-2.35-3.02c-1.2,0-2.14,0.84-2.48,1.85
c-0.1,0.25-0.12,0.52-0.12,0.88v6.13h-1.85V1185.29z"/>
<path fill="#65C8D0" d="M351.93,1202.54v-16.73h3.84v1.16h-2.41v14.42h2.41v1.15H351.93z"/>
<path fill="#65C8D0" d="M361.13,1188.27h-0.04l-2.37,1.28l-0.36-1.41l2.98-1.6h1.58v13.65h-1.79V1188.27z"/>
<path fill="#65C8D0" d="M376.75,1186.54v1.22l-5.94,12.43h-1.91l5.92-12.07v-0.04h-6.68v-1.53H376.75z"/>
<path fill="#65C8D0" d="M381.96,1185.79v16.75h-3.84v-1.15h2.42v-14.45h-2.42v-1.16H381.96z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 41 KiB

@ -0,0 +1,39 @@
vec3 foregroundColor = vec3(.0841, .5329, .9604);
uniform vec3 starColors[10];
uniform vec3 V0;
varying vec3 norm;
varying float id;
varying vec3 glpos;
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 < 1.5) {color = vec3(1.0000, 0.7725, 0.7725);sp = 1.; df=.2; amb = .7, ex = 25.;}
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;}
if(id < 0.){
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,16 @@
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;
void main() {
vec4 pos = uMatrix * vec4(aPos, 1.);
gl_Position = pos ;
glpos = pos.xyz;
id = oid;
norm = normalize(vec4(normal,0.)*invMatrix).xyz;
}

@ -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"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save