You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Graphics/index.html

351 lines
12 KiB

<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>
4 years ago
<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>
4 years ago
</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>
4 years ago
<!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW -------->
<script id='my_title' type='text/html'>
Solar RTX
4 years ago
</script>
<!!-------- HERE IS WHERE YOU CAN PROVIDE A LONGER TEXT DESCRIPTION -------->
<script id='my_instructions' type='text/html'><font color=#909090>
4 years ago
<p style="font-size:30px; ">In this homework, I implemented Global illumination w/
Realtime Recursive Ray Tracing!
4 years ago
<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>
4 years ago
<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>
4 years ago
<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>
4 years ago
</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>
4 years ago
</li>
</ul>
<p>
</script>
<!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
4 years ago
<script>
// CREATE THE HTML DOCUMENT
4 years ago
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();
4 years ago
document.body.innerHTML = [''
4 years ago
,'<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>'
4 years ago
,'<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>'
4 years ago
,'</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);
}
}
}
4 years ago
// 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.
4 years ago
delete editor.KeyBinding;
4 years ago
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(){
4 years ago
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;
4 years ago
});
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 = '';
}
};
4 years ago
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);
4 years ago
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)
4 years ago
});
4 years ago
4 years ago
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;
4 years ago
});
4 years ago
// SET THE CURRENT TIME IN SECONDS BEFORE RENDERING EACH FRAME.
let startTime = Date.now();
let lastFrameTime = 0;
4 years ago
function animate(gl) {
4 years ago
if(animating)
setUniform('1f', 'uTime', (Date.now() - startTime) / 1000);
else
setUniform('1f', 'uTime', (lastTime - startTime) / 1000);
4 years ago
}
let start;
requestAnimationFrame(fpscounter);
4 years ago
</script>