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