finalize(sync with website)

master
bill 4 years ago
parent f60573a5fe
commit 6bb72b6dfb

BIN
22.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

BIN
3.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
4.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

@ -22,7 +22,7 @@
<body bgcolor=white text=black link=black alink=blue vlink=blue> <body bgcolor=white text=black link=black alink=blue vlink=blue>
<center> <center>
<!!--- SUPER SAMPLING THE W/H PARAMS FOR CANVAS ARE RENDER SIZE, IN THE CSS IS ACTUAL(DISPLAY) SIZE.---> <!!--- SUPER SAMPLING THE W/H PARAMS FOR CANVAS ARE RENDER SIZE, IN THE CSS IS ACTUAL(DISPLAY) SIZE.--->
<canvas id='canvas1' style="width: 600px; height:600px;" width=1200 height=1200></canvas> <canvas id='canvas1' style="overflow: auto; width: 600px; height:600px;" width=1200 height=1200></canvas>
</center> </center>
</body> </body>
@ -40,7 +40,7 @@
<!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK --------> <!!-------- FRAGMENT SHADER: THIS IS WHERE YOU WILL DO YOUR WORK -------->
<!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag LOADED IN lib2.js --------> <!!-------- FRAGMENT SHADER: MOVED TO ./shader.frag!! LOADED IN lib2.js -------->
<!--script src="shader.frag" id='my_fragment_shader' type='x-shader/x-fragment'> </script> <!--script src="shader.frag" id='my_fragment_shader' type='x-shader/x-fragment'> </script>
@ -65,24 +65,24 @@ Solar RTX
<li>Ctrl+Alt/Option+N: Reset ViewPoint.</li> <li>Ctrl+Alt/Option+N: Reset ViewPoint.</li>
<li>Ctrl+Alt/Option+P: Toggle Pause/Resume.</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 style="color:red;">Please unfocus the Editing area (click somewhere else on the page) to use hotkeys.</li>
<li>Click on canvas (WITHOUT key modifiers): Toggle Pause/Resume.</li> <li>Double Click on canvas (WITHOUT key modifiers): Toggle Pause/Resume.</li>
<li>SHIFT+Alt/Option+MOUSE DRAG/WHEEL ZOOM: Changing Viewing point.</li> <li>MOUSE DRAG, SCROLL/WHEEL ZOOM: Changing Viewing point.</li>
<li>Use Chromium based browser for better performance.</li>
</ul> </ul>
<i style="font-size:25px;">How it works:</i> <i style="font-size:25px;">How it works:</i>
<ul> <ul>
<li>First, I started with what I've already done in homework 1. Which already included complete Phong shading with <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). Specular light and much more (spherical texture mapping, simple interactions, improved UI/shader editor).
</li> </li>
<li> I then merged the code from hw2 and added texture to each sphere.</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 returning color calculated from <li> I modified the ray tracing algorithm so that when hitting an object, instead of just returning color calculated from
Phong model:<br> Phong model:<br>
<ul> <ul>
<li>It recursively bounces and/or refract(NOT IMPLEMENTED YET) itself spawning new rays.</li> <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]. <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> (<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 reflected/refracted n_ref times. </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 of the final light is computed via specular component from the Phong model.</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>You may increase n_ref for more iterations, but please proceed with caution, because it may halt the computer.
</li> </li>
</ul> </ul>
@ -91,7 +91,7 @@ Solar RTX
or holding shift and alt while scrolling on canvas to change focal length. 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. This is implemented by applying a transformation matrix to the viewpoint and projection surface.
</li> </li>
<li>Finally, I used super sampling via doubling the render dimensions of the canvas to reduce aliasing.</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>Repo on <a href="https://github.com/sunyinqi0508/graphics_hw1">Github</a>.</li>
</li> </li>
</ul> </ul>
@ -135,13 +135,26 @@ document.body.innerHTML = [''
,'<table cellspacing=0>' ,'<table cellspacing=0>'
,'<tr>' ,'<tr>'
,'<td valign=top>' ,'<td valign=top>'
,'<div id="ace" style="width:800px;height:1780px;"></div>' ,'<div id="ace" style="width:800px;height:2200px;"></div>'
,'</td><td valign=top>' + document.body.innerHTML ,'</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>' ,'<div style=\'font-size:25px\'>' + my_instructions.innerHTML + '</div>' + '</td>'
,'</tr></table>' ,'</tr></table>'
,'</TR></TABLE>' ,'</TR></TABLE>'
].join(''); ].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. // SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
ace.require("ace/ext/language_tools"); ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", { var editor = ace.edit("ace", {
@ -163,9 +176,11 @@ editor.setAutoScrollEditorIntoView(true);
delete editor.KeyBinding; delete editor.KeyBinding;
let lastTime = Date.now(); let lastTime = Date.now();
let animating = true; let animating = true;
let ctrl = false, alt = false, shift = false, fpson = true, moving = false; let ctrl = false, alt = false, shift = false, fpson = true, moving = false, over = false;
let mousedx = 0, mousedy = 0, mousedz = 0; let mousedx = 0, mousedy = 0, mousedz = 0;
let cx = 1, cy = 1, sx = 0, sy = 0;
let mouselastX, mouselastY; let mouselastX, mouselastY;
let lastClick = undefined;
let pause_resume = function(){ let pause_resume = function(){
if(animating) if(animating)
lastTime = Date.now(); lastTime = Date.now();
@ -174,30 +189,46 @@ let pause_resume = function(){
animating = !animating; animating = !animating;
}; };
canvas1.addEventListener('click',function(ev){ canvas1.addEventListener('click',function(ev){
if(!(shift && alt)) if(!(shift && alt) && lastClick&& Date.now()-lastClick<400)
pause_resume(); pause_resume();
lastClick = Date.now();
//moving = false; //moving = false;
}); });
canvas1.addEventListener('mouseover', function(e){
over = true;
const mask = 0x8;
flags |= mask;
setUniform('1i', 'flags', flags);
});
canvas1.addEventListener('mousedown', function(e){ canvas1.addEventListener('mousedown', function(e){
if(shift && alt){
moving = true moving = true
mouselastX = mouselastY = undefined; mouselastX = mouselastY = undefined;
}
else
moving = false;
}); });
canvas1.addEventListener('mousemove', function(e){ canvas1.addEventListener('mousemove', function(e){
if(shift && alt && moving){ if(!(mouselastX==undefined || mouselastY == undefined)&&moving){
if(!(mouselastX==undefined || mouselastY == undefined)){ mousedx -= (mouselastX - e.offsetX)/60;
mousedx += (mouselastX - e.offsetX)/60; mousedy -= (mouselastY - e.offsetY)/60;
mousedy += (mouselastY - e.offsetY)/60; cx = Math.cos(mousedx);
setUniform('4f', 'rot', Math.cos(mousedx), Math.sin(mousedx), Math.cos(mousedy), Math.sin(mousedy)); 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; mouselastX = e.offsetX;
mouselastY = e.offsetY; mouselastY = e.offsetY;
}
else
moving = false;
}); });
canvas1.addEventListener('mouseup', function(e){ canvas1.addEventListener('mouseup', function(e){
// if(ctrl && alt && moving){ // if(ctrl && alt && moving){
@ -207,14 +238,18 @@ canvas1.addEventListener('mouseup', function(e){
canvas1.addEventListener('mouseout', function(e){ canvas1.addEventListener('mouseout', function(e){
// if(ctrl && alt && moving){ // if(ctrl && alt && moving){
// } // }
const mask = 0x8;
flags &= !mask;
setUniform('1i', 'flags', flags);
over = false;
moving = false; moving = false;
}); });
canvas1.addEventListener('wheel', function(e){ canvas1.addEventListener('wheel', function(e){
if(shift && alt){
mousedz += e.wheelDelta/600; mousedz += e.wheelDelta/600;
setUniform('1f', 'dFL', mousedz); setUniform('1f', 'dFL', mousedz);
} e.stopImmediatePropagation();
}); });
canvas1.scroll(function(e) {e.stopPropagation();});
rtx.style.cursor="pointer"; rtx.style.cursor="pointer";
let rtswitch = function(){ let rtswitch = function(){
const mask = 0x2; const mask = 0x2;
@ -223,7 +258,7 @@ let rtswitch = function(){
rtx.src='./RTXoff.svg'; rtx.src='./RTXoff.svg';
else else
rtx.src='./RTXon.svg'; rtx.src='./RTXon.svg';
flags = flags&!mask | (rtstatus?mask:0); flags = (flags&(!mask)) | (rtstatus?mask:0);
setUniform('1i', 'flags', flags); setUniform('1i', 'flags', flags);
} }
rtx.addEventListener('click', rtswitch); rtx.addEventListener('click', rtswitch);
@ -267,7 +302,12 @@ document.addEventListener('keydown',(e)=>{
flags = 0; flags = 0;
moving = false; moving = false;
mousedx = mousedy = mousedz = 0; mousedx = mousedy = mousedz = 0;
setUniform('4f', 'rot', Math.cos(mousedx), Math.sin(mousedx), Math.cos(mousedy), Math.sin(mousedy)); 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('1f', 'dFL', mousedz);
setUniform('1i', 'flags', flags); setUniform('1i', 'flags', flags);
} }

@ -15,8 +15,10 @@ let fragmentShaderHeader = ['' // WHATEVER CODE WE WANT TO
, ' r+=sin(6.3*dot(P,fract(D)-.5))*pow(max(0.,1.-2.*dot(P,P)),4.);' , ' r+=sin(6.3*dot(P,fract(D)-.5))*pow(max(0.,1.-2.*dot(P,P)),4.);'
, '} return .5 * sin(r); }' , '} return .5 * sin(r); }'
].join('\n'); ].join('\n');
let ns = 4, cns = 4;
let nfsh = fragmentShaderHeader.split('\n').length; // NUMBER OF LINES OF CODE IN fragmentShaderHeader 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 isFirefox = navigator.userAgent.indexOf('Firefox') > 0; // IS THIS THE FIREFOX BROWSER?
let errorMsg = ''; let errorMsg = '';
@ -138,14 +140,13 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
}; };
addshader(gl.VERTEX_SHADER, vertexShader); // Add the vertex and fragment shaders. addshader(gl.VERTEX_SHADER, vertexShader); // Add the vertex and fragment shaders.
addshader(gl.FRAGMENT_SHADER, fragmentShaderHeader + fragmentShader); addshader(gl.FRAGMENT_SHADER, fragmentShaderHeader +fragmentShaderDefs+ fragmentShader);
gl.linkProgram(program); // Link the program, report any errors. gl.linkProgram(program); // Link the program, report any errors.
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) if (!gl.getProgramParameter(program, gl.LINK_STATUS))
console.log('Could not link the shader program!'); console.log('Could not link the shader program!');
gl.useProgram(program); gl.useProgram(program);
gl.program = program; gl.program = program;
const ns = 2;
for(let i = 0; i < ns; ++i){ for(let i = 0; i < ns; ++i){
loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading. loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
textures[i] = i; textures[i] = i;

@ -1,26 +1,31 @@
vec3 foregroundColor = vec3(.0841, .5329, .9604); vec3 foregroundColor = vec3(.0841, .5329, .9604);
vec3 groundColor = vec3(.2, .3, .5); vec3 groundColor = vec3(.2, .3, .5);
vec4 groundSpecular = vec4(.71, .71, .71, 10.); vec4 groundSpecular = vec4(.71, .71, .71, 10.);
uniform float uTime;// TIME, IN SECONDS uniform float uTime;// TIME, IN SECONDS
uniform int flags; uniform int flags;
uniform vec4 rot; //FLAGS 0-TEX, 1-RT, 2-MOVED, 3-FLASH, 4-TEX_ROT, 5-CLOUD
uniform float dFL;
//FLAGS 0-TEX, 1-RT, 2-CLOUD, 3-TEX_ROT 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 varying vec3 vPos;// -1 < vPos.x < +1
// -1 < vPos.y < +1 // -1 < vPos.y < +1
// vPos.z == 0 // vPos.z == 0
float fl=3.; float fl=3.;//ORIGINAL FOCAL LENGTH
const float pi=3.14159265359; const float pi=3.14159265359;
const int n_ref=6; const float _2pi=2.*pi;
const int ns=2; 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]; vec4 Sph[ns];
uniform sampler2D uSampler[ns]; uniform sampler2D uSampler[ns];
vec3 Ambient[ns]; vec3 Ambient[ns];
vec3 Diffuse[ns]; vec3 Diffuse[ns];
vec4 Specular[ns]; vec4 Specular[ns];
struct Sphere{ float ks[ns];
struct Sphere{ //UPDATED SPHERE STRUCTURE THAT SUPPORTS TRANSPARENCY.(UNUSED)
vec4 Pos; vec4 Pos;
vec3 Ambient; vec3 Ambient;
vec3 Diffuse; vec3 Diffuse;
@ -28,7 +33,7 @@ struct Sphere{
int textureid; int textureid;
float ks, kt; float ks, kt;
}; };
struct RT{ struct RT{ //STACK FOR RECURSIVE RAY TRACING.
vec3 color; vec3 color;
float ks; float ks;
// vec3 colorr; // vec3 colorr;
@ -45,24 +50,31 @@ float clampv(float val,float l,float h){
return val<l?l:val>h?h:val; return val<l?l:val>h?h:val;
} }
void main(){ void main(){
//////////////////////////////////////////////// ////////////////////////////////////////////////
// //
// HERE, FOR YOUR HOMEWORK, YOU CAN WRITE ANY // HERE, FOR YOUR HOMEWORK, YOU CAN WRITE ANY
// CODE YOU LIKDEFINE A COLOR FOR THIS FRAGMENT. // CODE YOU LIKDEFINE A COLOR FOR THIS FRAGMENT.
// LIGHT DIRECTION AND COLOR // 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 LDir=vec3(.5,.5,.5);
vec3 LCol=vec3(1.,1.,1.); vec3 LCol=vec3(1.,1.,1.);
// SPHERE // 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);
Sph[0]=vec4(.5*sin(uTime),0.,.5*cos(uTime),.2); // SURFACE REFLECTANCE PROPERTIES, can be transferred from .js
Sph[1]=vec4(0.,0.,0.,.2); Ambient[3]=vec3(.1,.1,.1);// r,g,b
Diffuse[3]=vec3(.71,.71,.71);// r,g,b
// SURFACE REFLECTANCE PROPERTIES 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 Ambient[1]=vec3(.1,.05,.05);// r,g,b
Diffuse[1]=vec3(1.,.5,.5);// r,g,b Diffuse[1]=vec3(1.,.5,.5);// r,g,b
Specular[1]=vec4(1.,.5,.5,10.);// r,g,b,power Specular[1]=vec4(1.,.5,.5,10.);// r,g,b,power
@ -70,32 +82,37 @@ void main(){
Ambient[0]=vec3(.05,.05,.1);// r,g,b Ambient[0]=vec3(.05,.05,.1);// r,g,b
Diffuse[0]=vec3(.5,.5,1.);// r,g,b Diffuse[0]=vec3(.5,.5,1.);// r,g,b
Specular[0]=vec4(1.,.5,.5,20.);// r,g,b,power 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 // INITIALIZE TO A BACKGROUND COLOR
vec3 color=vec3(.2, .3, .5); vec3 color=vec3(.2, .3, .5);
float ca=rot.x, sa = rot.y, cb=rot.z, sb=rot.w; float ca=rot.x, sa = rot.y, cb=rot.z, sb=rot.w;
// COMPUTE THE RAY ORIGIN AND DIRECTION mat3 transformation, invTr;//Transformation matrix for viewpoint.
mat3 transformation, invTr; transformation[0] = vec3(ca, sb*sa, sa*cb);//because the matrices are all the same,
transformation[0] = vec3(ca, sb*sa, sa*cb); transformation[1] = vec3(0, cb, -sb);//We don't need to calculate it for every pixel
transformation[1] = vec3(0, cb, -sb); transformation[2] = vec3(-sa,ca*sb,ca*cb);//So, we get it from the CPU
transformation[2] = vec3(-sa,ca*sb,ca*cb); invTr[0] = vec3(ca, 0, -sa);//it's inverse, to calculate texture mapping.
invTr[0] = vec3(ca, 0, -sa);
invTr[1] = vec3(sa*sb, cb, ca*sb); invTr[1] = vec3(sa*sb, cb, ca*sb);
invTr[2] = vec3(cb*sa, -sb, ca*cb); invTr[2] = vec3(cb*sa, -sb, ca*cb);
vec3 trPos = transformation*((dFL+fl+1.)/(fl+1.))*vec3(vPos.xy, -1);
vec3 trPos = transformation*vec3(vPos.xy, -2); // COMPUTE THE RAY ORIGIN AND DIRECTION
vec3 V0=transformation*vec3(0.,0.,fl+dFL), V = V0;
vec3 V=transformation*vec3(0.,0.,fl+dFL);
vec3 W=normalize(trPos-V); vec3 W=normalize(trPos-V);
// RAY TRACE TO ALL OBJECTS IN THE SCENE // RAY TRACE TO ALL OBJECTS IN THE SCENE
bool rtxoff = getflag(flags, 1); 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; int cnt_ref = n_ref;
for(int j=0;j<n_ref;j++) for(int j=0;j<n_ref;j++)
{ {
float tMin=10000.; float tMin=10000.;
int iMin = -1; int iMin = -1;
for(int i=0;i<ns;i++){ for(int i=0;i<cns;i++){
// SHIFT COORDINATES, SO THAT SPHERE IS AT (0,0,0) // SHIFT COORDINATES, SO THAT SPHERE IS AT (0,0,0)
vec3 Vp=V-Sph[i].xyz; vec3 Vp=V-Sph[i].xyz;
// SOLVE FOR QUADRATIC EQUATION IN t // SOLVE FOR QUADRATIC EQUATION IN t
@ -105,8 +122,8 @@ void main(){
if(D>0.){ if(D>0.){
float t=-B-sqrt(D); float t=-B-sqrt(D);
if(t > 0. && t < tMin){ if(t > 0. && t < tMin){
tMin = t; tMin = t; //This is an optimization, we don't have to do lighting/tex
iMin = i; iMin = i; // for objects that are occuluded, which is expensive!
} }
} }
} }
@ -114,47 +131,61 @@ void main(){
if(iMin >= 0){ if(iMin >= 0){
float t = tMin; float t = tMin;
vec3 S=V+t*W; vec3 S=V+t*W;
for(int i = 0; i < ns; ++ i) for(int i = 0; i < cns; ++ i)
if(i == iMin) if(i == iMin) //* Because GLSL doesn't support non-const index,
{ { //* we have to get Sph[iMin], uSampler[iMin], etc. this way
//*TEXTURE MAPPING //*Good old TEXTURE MAPPING from hw1
vec3 tex_sph=invTr*(S-Sph[i].xyz); 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 R=Sph[i].w;
float tex_x=acos(abs(tex_sph.x)/sqrt(R*R-tex_sph.y*tex_sph.y)); float tex_x=acos(abs(tex_sph.x)/sqrt(R*R-tex_sph.y*tex_sph.y));
if(tex_sph.x>0.) if(tex_sph.x>0.)
tex_x=pi-tex_x; 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*=1.5708;//*Correct aspect ratio of texture 2:1 -> 2pir:2r
tex_x=tex_x+float(uTime)*R; tex_x=tex_x+float(uTime);
float _2pir=2.*pi*R; float quo=float(int(tex_x/_2pi));
float quo=float(int(tex_x/_2pir)); tex_x=tex_x/_2pi -quo;
tex_x=clampv((tex_x-quo*_2pir),0.,_2pir)/_2pir;
vec3 texture_color; vec3 texture_color;
if(!getflag(flags,0)) if(showtexture)
texture_color=texture2D(uSampler[i],vec2(tex_x,((R-tex_sph.y)/(2.*R)))).xyz; texture_color=texture2D(uSampler[i],vec2(tex_x,((R-tex_sph.y)/(2.*R)))).xyz;
else texture_color = foregroundColor; else texture_color = foregroundColor;
vec3 N=normalize(S-Sph[i].xyz); vec3 N=normalize(S-Sph[i].xyz);
//*DIRECTIONS ARE NORMALIZED TO GET THE CORRECT PHONG LIGHTING //*DIRECTIONS ARE NORMALIZED TO GET THE CORRECT PHONG LIGHTING
vec3 realLDir=normalize(LDir-S); vec3 realLDir=normalize(LDir-S);
color=( color=(
Ambient[i] Ambient[i]
+Diffuse[i]*max(0.,dot(N,realLDir))*LCol +Diffuse[i]*max(0.,dot(N,realLDir))*LCol
)*texture_color )*texture_color
; ;
// + SPECULAR COMPONENT GOES HERE // + SPECULAR COMPONENT GOES HERE
if(rtxoff || j == n_ref - 1) 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); color += sqrt(float(j+1)) * Specular[i].xyz*pow(max(0.,
stack[j] = RT(color, 0.15); dot(2.*dot(N,realLDir)*N-realLDir,-W)),Specular[i].w);
V = S; //*Pushing current color and ks into stack.
W = -normalize(2. * dot(N, W) * N - W); //*suppose ks is 0.15 for all spheres, we can
break; //*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 { else {
// TO SIMIPIFY THINGS UP, I'LL ASSUME THAT EVERYTHING // TO SIMIPIFY THINGS UP, I'LL ASSUME THAT EVERYTHING
// IS INSIDE THE BOUNDING BOX [(-1,-1,-1), (1,1,1)] // IS INSIDE THE BOUNDING BOX [(-1,-1,-1), (1,1,1)]
// AND THERE'S A FLOOR at [y = -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 t = -(.2+V.y)/W.y;
float sx = V.x + t* W.x, sz = V.z + t * W.z; float sx = V.x + t* W.x, sz = V.z + t * W.z;
@ -163,28 +194,32 @@ void main(){
vec3 S = vec3(sx, -.2, sz); vec3 S = vec3(sx, -.2, sz);
vec3 realLDir=normalize(LDir - S); vec3 realLDir=normalize(LDir - S);
color=( color=(
0.5 0.5 //ambient for ground
+0.5*max(0.,realLDir.y)*LCol +0.5*max(0.,realLDir.y)*LCol //diffusion for ground
)*groundColor )*groundColor
; ;
// + SPECULAR COMPONENT GOES HERE // + SPECULAR COMPONENT GOES HERE
if(rtxoff || j == n_ref - 1) if(rtxoff || j == n_ref - 1)
color += sqrt(float(j+1))*groundSpecular.xyz* color += sqrt(float(j+1))*groundSpecular.xyz* //specular for ground.
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w); pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
stack[j] = RT(color, 0.1); stack[j] = RT(color, 0.15); //ks of ground is 0.1
V = S; V = S; //Same as above, trace again from S, dir = reflect(W, N).
W = vec3(W.x, -W.y, W.z); // if(flash && j == 0){
// V0 = W;
// hit = true;
// }
W = vec3(W.x, -W.y, W.z);
} }
else{ else{
if(j > 0) 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.); 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; cnt_ref = j + 1;
} }
else else //If the light hits the void in the first place, it's just black!
cnt_ref = j; cnt_ref = j;//j is always 0 in this case.
break; //The light is shooting into the void, let's stop RT.
break;
} }
} }
// RTX off // RTX off
@ -199,9 +234,9 @@ void main(){
float currks = 1.; float currks = 1.;
for(int i = 0; i < n_ref; ++i) for(int i = 0; i < n_ref; ++i)
{ {
if(i >= cnt_ref) if(i >= cnt_ref)//same trick to use bounded non-const on indexes
{ {
color += currks * stack[i - 1].color; color += currks * stack[i - 1].color; //if there're less than n_ref rays, e.g. ray go to the void.
break; break;
} }
color += currks *(1.-stack[i].ks) * stack[i].color; color += currks *(1.-stack[i].ks) * stack[i].color;
@ -211,6 +246,7 @@ void main(){
color += currks * stack[n_ref - 1].color; color += currks * stack[n_ref - 1].color;
} }
// APPLY GAMMA CORRECTION AND SET THE PIXEL COLOR. // APPLY GAMMA CORRECTION AND SET THE PIXEL COLOR.
gl_FragColor=vec4(sqrt(color),1.); gl_FragColor=vec4(sqrt(color),1.);
} }
Loading…
Cancel
Save