diff --git a/earthmap1k.jpg b/1.jpg
similarity index 100%
rename from earthmap1k.jpg
rename to 1.jpg
diff --git a/2.jpg b/2.jpg
new file mode 100644
index 0000000..9d787d8
Binary files /dev/null and b/2.jpg differ
diff --git a/index.html b/index.html
index 29017b4..7480594 100644
--- a/index.html
+++ b/index.html
@@ -1,4 +1,4 @@
-
+
-
+
@@ -39,197 +39,22 @@
-
-
+
+
-
+
diff --git a/lib1.js b/lib2.js
similarity index 83%
rename from lib1.js
rename to lib2.js
index 33a7345..3247002 100644
--- a/lib1.js
+++ b/lib2.js
@@ -24,15 +24,17 @@ 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.
+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;
@@ -40,23 +42,36 @@ function loadTexture(gl, url) {
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);
+ 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.bindTexture(gl.TEXTURE_2D, texture);
+ 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
@@ -66,8 +81,6 @@ function loadTexture(gl, url) {
}
};
image.src = url;
-
- return texture;
}
function isPowerOf2(value) {
@@ -77,12 +90,13 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
setTimeout(function () {
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.'; }
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 spacer(color, width, height) {
@@ -131,15 +145,12 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
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);
-
+ const ns = 2;
+ 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);
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.
@@ -151,7 +162,6 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
}
canvas.setShaders(vertexShader, fragmentShader); // Initialize everything,
-
setInterval(function () { // Start the animation loop.
gl = canvas.gl;
if (gl.startTime === undefined) // First time through,
@@ -167,7 +177,6 @@ function gl_start(canvas, vertexShader, fragmentShader) { // START WEB
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);
diff --git a/shader.frag b/shader.frag
new file mode 100644
index 0000000..ee12c36
--- /dev/null
+++ b/shader.frag
@@ -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 valh?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;j0.){
+ 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.);
+}
+
\ No newline at end of file