Merge pull request #1 from sunyinqi0508/hw2

Hw2
master
sunyinqi0508 4 years ago committed by GitHub
commit e87f15d2a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

Before

Width:  |  Height:  |  Size: 336 KiB

After

Width:  |  Height:  |  Size: 336 KiB

BIN
2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

@ -1,4 +1,4 @@
<script src=lib1.js></script> <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/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="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js" crossorigin="anonymous"></script>
<style> <style>
@ -21,7 +21,7 @@
</style> </style>
<body bgcolor=white text=black link=black alink=blue vlink=blue> <body bgcolor=white text=black link=black alink=blue vlink=blue>
<center> <center>
<canvas id='canvas1' width=600 height=600></canvas> <canvas id='canvas1' style="width: 600px; height:600px;" width=1200 height=1200></canvas>
</center> </center>
</body> </body>
@ -39,197 +39,22 @@
<!!-------- 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 -------->
<script id='my_fragment_shader' type='x-shader/x-fragment'> <!--script src="shader.frag" id='my_fragment_shader' type='x-shader/x-fragment'> </script>
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 --------> <!!-------- CREATE A PROPERLY DESCRIPTIVE TITLE BELOW -------->
<script id='my_title' type='text/html'> <script id='my_title' type='text/html'>
The Bouncing Earth Solar RTX
</script> </script>
<!!-------- HERE IS WHERE YOU CAN PROVIDE A LONGER TEXT DESCRIPTION --------> <!!-------- HERE IS WHERE YOU CAN PROVIDE A LONGER TEXT DESCRIPTION -------->
<script id='my_instructions' type='text/html'><font color=#909090> <script id='my_instructions' type='text/html'><font color=#909090>
<p style="font-size:30px; ">This is a description <p style="font-size:30px; ">In this homework, I implemented Global illumination w/
of my cool homework Realtime Recursive Ray Tracing!
that you are seeing now.</p>
<p> <p>
<i style="font-size:25px;">Here is how it works:</i> <i style="font-size:25px;">Here is how it works:</i>
<ul> <ul>
@ -245,7 +70,7 @@ that you are seeing now.</p>
<ul> <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 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 <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> towards the light source or from the background point towards the camera position intersect with the sphere.</li>
</ul> </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. <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> Just a proof of concept.</li>
@ -260,16 +85,30 @@ that you are seeing now.</p>
</script> </script>
<!!-------- YOU PROBABLY DON'T WANT TO CHANGE ANYTHING BELOW FOR NOW --------> <!!-------- YOU PROBABLY WANT TO CHANGE ANYTHING BELOW RIGHT NOW -------->
<script> <script>
// CREATE THE HTML DOCUMENT // CREATE THE HTML DOCUMENT
let flags = 0x0; let flags = 0x0;
let vs = my_vertex_shader.innerHTML, let vs = my_vertex_shader.innerHTML;
fs = my_fragment_shader.innerHTML; //* LOADING FRAGMENT SHADER
fs = fs.substring(1, fs.length); 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 = ['' document.body.innerHTML = [''
,'<font size=7 color=#909090>' + my_title.innerHTML ,'<font size=7 color=#909090>' + my_title.innerHTML
,'<TABLE cellspacing=0 cellpadding=0><TR>' ,'<TABLE cellspacing=0 cellpadding=0><TR>'
@ -285,10 +124,6 @@ document.body.innerHTML = [''
].join(''); ].join('');
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE. // 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"); ace.require("ace/ext/language_tools");
var editor = ace.edit("ace", { var editor = ace.edit("ace", {
mode:"ace/mode/glsl", mode:"ace/mode/glsl",
@ -305,12 +140,8 @@ editor.setOptions({
showPrintMargin: false, showPrintMargin: false,
}); });
editor.setAutoScrollEditorIntoView(true); editor.setAutoScrollEditorIntoView(true);
editor.getSession().setValue(fs);
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE. // REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
editor.session.on('change', function(delta) { delete editor.KeyBinding;
canvas1.setShaders(vs, editor.getSession().getValue());
});
let lastTime = Date.now(); let lastTime = Date.now();
let animating = true; let animating = true;
let ctrl = false; let ctrl = false;
@ -322,17 +153,23 @@ canvas1.addEventListener('click',function(ev){
animating = !animating; animating = !animating;
}); });
document.addEventListener('keydown',(e)=>{ document.addEventListener('keydown',(e)=>{
if(e.code.startsWith('Control'))
if(e.code.startsWith('Control')) {
{ ctrl = true;
ctrl = true; }
} else if(ctrl && e.code == 'KeyT')
else if(ctrl && e.code == 'KeyT')
{ {
mask = 0x1; mask = 0x1;
flags = flags&!mask | (!(flags&mask)*mask); flags = flags&!mask | (!(flags&mask)?mask:0);
setUniform('1i', 'flags', flags); 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();
}
}); });
document.addEventListener('keyup',(e)=>{ document.addEventListener('keyup',(e)=>{
@ -353,8 +190,6 @@ function animate(gl) {
} }
// START EVERYTHING.
gl_start(canvas1, vs, fs);
</script> </script>

@ -24,15 +24,17 @@ let errorMsg = '';
// Initialize a texture and load an image. // Initialize a texture and load an image.
// When the image finished loading copy it into the texture. // When the image finished loading copy it into the texture.
// //
function loadTexture(gl, url) { function getBlob(data) {
const texture = gl.createTexture(); let bytes = new Array(data.length);
gl.bindTexture(gl.TEXTURE_2D, texture); for (let i = 0; i < data.length; i++) {
bytes[i] = data.charCodeAt(i);
// Because images have to be downloaded over the internet }
// they might take a moment until they are ready. return new Blob([new Uint8Array(bytes)]);
// Until then put a single pixel in the texture so we can }
// use it immediately. When the image has finished downloading let texture = [], gl, program;
// we'll update the texture with the contents of the image. let textures = [];
let lock = false;
function loadTexture(gl, url, i) {
const level = 0; const level = 0;
const internalFormat = gl.RGBA; const internalFormat = gl.RGBA;
const width = 1; const width = 1;
@ -40,23 +42,36 @@ function loadTexture(gl, url) {
const border = 0; const border = 0;
const srcFormat = gl.RGBA; const srcFormat = gl.RGBA;
const srcType = gl.UNSIGNED_BYTE; const srcType = gl.UNSIGNED_BYTE;
const pixel = new Uint8Array([0, 0, 255, 255]); // opaque blue if (texture[i] == null)
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, {
width, height, border, srcFormat, srcType, texture[i] = gl.createTexture();
pixel); 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(); const image = new Image();
image.onload = function () { image.onload = function () {
gl.bindTexture(gl.TEXTURE_2D, texture); gl.activeTexture(gl.TEXTURE0+i);
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, gl.texImage2D(gl.TEXTURE_2D, level, internalFormat,
srcFormat, srcType, image); srcFormat, srcType, image);
// WebGL1 has different requirements for power of 2 images // WebGL1 has different requirements for power of 2 images
// vs non power of 2 images so check if the image is a // vs non power of 2 images so check if the image is a
// power of 2 in both dimensions. // power of 2 in both dimensions.
if (isPowerOf2(image.width) && isPowerOf2(image.height)) { if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
// Yes, it's a power of 2. Generate mips. // Yes, it's a power of 2. Generate mips.
gl.generateMipmap(gl.TEXTURE_2D); gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
} else { } else {
// No, it's not a power of 2. Turn off mips and set // No, it's not a power of 2. Turn off mips and set
// wrapping to clamp to edge // wrapping to clamp to edge
@ -66,8 +81,6 @@ function loadTexture(gl, url) {
} }
}; };
image.src = url; image.src = url;
return texture;
} }
function isPowerOf2(value) { function isPowerOf2(value) {
@ -77,12 +90,13 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
setTimeout(function () { setTimeout(function () {
try { try {
canvas.gl = canvas.getContext('experimental-webgl'); // Make sure WebGl is supported. IT WOULD BE GREAT TO USE WEBGL2 INSTEAD. canvas.gl = canvas.getContext('webgl2'); // Make sure WebGl is supported. IT WOULD BE GREAT TO USE WEBGL2 INSTEAD.
} catch (e) { throw 'Sorry, your browser does not support WebGL.'; } } catch (e) { throw 'Sorry, your browser does not support WebGL.'; }
canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders: canvas.setShaders = function (vertexShader, fragmentShader) { // Add the vertex and fragment shaders:
let gl = this.gl, program = gl.createProgram(); // Create the WebGL program. gl = this.gl;
program = gl.createProgram(); // Create the WebGL program.
function addshader(type, src) { // Create and attach a WebGL shader. function addshader(type, src) { // Create and attach a WebGL shader.
function spacer(color, width, height) { function spacer(color, width, height) {
@ -131,15 +145,12 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
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;
let texture = loadTexture(gl, './earthmap1k.jpg') //Texture loading. for(let i = 0; i < ns; ++i){
// Tell WebGL we want to affect texture unit 0 loadTexture(gl, './'+(i+1)+'.jpg', i); //Texture loading.
gl.activeTexture(gl.TEXTURE0); textures[i] = i;
// Bind the texture to texture unit 0 }
gl.bindTexture(gl.TEXTURE_2D, texture); gl.uniform1iv(gl.getUniformLocation(program, 'uSampler'), textures);
// 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.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); // Create a square as a triangle strip
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( // consisting of two triangles. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( // consisting of two triangles.
@ -151,7 +162,6 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
} }
canvas.setShaders(vertexShader, fragmentShader); // Initialize everything, canvas.setShaders(vertexShader, fragmentShader); // Initialize everything,
setInterval(function () { // Start the animation loop. setInterval(function () { // Start the animation loop.
gl = canvas.gl; gl = canvas.gl;
if (gl.startTime === undefined) // First time through, if (gl.startTime === undefined) // First time through,
@ -167,7 +177,6 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
function animate() { } function animate() { }
let gl;
function setUniform(type, name, a, b, c, d, e, f) { function setUniform(type, name, a, b, c, d, e, f) {
let loc = gl.getUniformLocation(gl.program, name); let loc = gl.getUniformLocation(gl.program, name);
(gl['uniform' + type])(loc, a, b, c, d, e, f); (gl['uniform' + type])(loc, a, b, c, d, e, f);

@ -0,0 +1,197 @@
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-RT, 1-TEX, 2-
varying vec3 vPos;// -1 < vPos.x < +1
// -1 < vPos.y < +1
// vPos.z == 0
float fl=3.;
const float pi=3.14159265359;
const int n_ref=2;
const int ns=2;
vec4 Sph[ns];
uniform sampler2D uSampler[ns];
vec3 Ambient[ns];
vec3 Diffuse[ns];
vec4 Specular[ns];
struct RT{
vec3 color;
float ks;
// 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
vec3 LDir=vec3(.5,.5,.5);
vec3 LCol=vec3(1.,1.,1.);
// SPHERE
Sph[0]=vec4(.5*sin(uTime),0.,.5*cos(uTime),.2);
Sph[1]=vec4(0.,0.,0.,.2);
// SURFACE REFLECTANCE PROPERTIES
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
// INITIALIZE TO A BACKGROUND COLOR
vec3 color=vec3(.2, .3, .5);
// COMPUTE THE RAY ORIGIN AND DIRECTION
float x=vPos.x;
float y=vPos.y;
vec3 V=vec3(0.,0.,fl);
vec3 W=normalize(vec3(x,y,-fl));
// RAY TRACE TO ALL OBJECTS IN THE SCENE
bool rtxoff = getflag(flags, 1);
int cnt_ref = n_ref;
for(int j=0;j<n_ref;j++)
{
float tMin=10000.;
int iMin = -1;
for(int i=0;i<ns;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;
iMin = i;
}
}
}
// IF RAY HITS SPHERE
if(iMin >= 0){
float t = tMin;
vec3 S=V+t*W;
for(int i = 0; i < ns; ++ i)
if(i == iMin)
{
//*TEXTURE MAPPING
vec3 tex_sph=S-Sph[i].xyz;
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=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=clampv((tex_x-quo*_2pir),0.,_2pir)/_2pir;
vec3 texture_color;
if(!getflag(flags,0))
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)
color += float(j) * Specular[i].xyz*pow(max(0.,dot(2.*dot(N,realLDir)*N-realLDir,-W)),Specular[i].w);
stack[j] = RT(color, 0.15);
V = S;
W = -normalize(2. * dot(N, W) * N - W);
break;
}
}
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 INFINITE FLOOR [y = -1]
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
+0.5*max(0.,realLDir.y)*LCol
)*groundColor
;
// + SPECULAR COMPONENT GOES HERE
if(rtxoff || j == n_ref - 1)
color += float(j)*groundSpecular.xyz*
pow(max(0., dot(vec3(-realLDir.x, realLDir.y,-realLDir.z),-W)),groundSpecular.w);
stack[j] = RT(color, 0.1);
V = S;
W = vec3(W.x, -W.y, W.z);
}
else{
if(j > 0)
{
stack[j] = RT(vec3(12.,12.,12.)*pow(max(0.,dot(W, normalize(LDir - V))), 10.), 0.);
cnt_ref = j + 1;
}
else
cnt_ref = j;
break;
}
}
// 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)
{
color += currks * stack[i - 1].color;
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.);
}
Loading…
Cancel
Save