diff --git a/README.md b/README.md index 06fcfd4..cfbcea2 100644 --- a/README.md +++ b/README.md @@ -1,373 +1,189 @@ +------------------------------------------------------------------------------------ +Project 5: WebGL +==================================================================================== +Ricky Arietta Fall 2013 ------------------------------------------------------------------------------- -CIS565: Project 5: WebGL -------------------------------------------------------------------------------- -Fall 2013 -------------------------------------------------------------------------------- -Due Friday 11/08/2013 -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- -NOTE: -------------------------------------------------------------------------------- -This project requires any graphics card with support for a modern OpenGL -pipeline. Any AMD, NVIDIA, or Intel card from the past few years should work -fine, and every machine in the SIG Lab and Moore 100 is capable of running -this project. -This project also requires a WebGL capable browser. The project is known to -have issues with Chrome on windows, but Firefox seems to run it fine. +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_final.png) -------------------------------------------------------------------------------- +------------------------------------------------------------------------------------ INTRODUCTION: -------------------------------------------------------------------------------- -In this project, you will get introduced to the world of GLSL in two parts: -vertex shading and fragment shading. The first part of this project is the -Image Processor, and the second part of this project is a Wave Vertex Shader. - -In the first part of this project, you will implement a GLSL vertex shader as -part of a WebGL demo. You will create a dynamic wave animation using code that -runs entirely on the GPU. - -In the second part of this project, you will implement a GLSL fragment shader -to render an interactive globe in WebGL. This will include texture blending, -bump mapping, specular masking, and adding a cloud layer to give your globe a -uniquie feel. - -------------------------------------------------------------------------------- -CONTENTS: -------------------------------------------------------------------------------- -The Project4 root directory contains the following subdirectories: - -* part1/ contains the base code for the Wave Vertex Shader. -* part2/ contains the base code for the Globe Fragment Shader. -* resources/ contains the screenshots found in this readme file. - -------------------------------------------------------------------------------- -PART 1 REQUIREMENTS: -------------------------------------------------------------------------------- +==================================================================================== -In Part 1, you are given code for: +This project explores GLSL and WebGL in two parts: -* Drawing a VBO through WebGL -* Javascript code for interfacing with WebGL -* Functions for generating simplex noise +The first part of this project implements a series of GLSL vertex shaders as +part of a WebGL demo. I have created three dynamic wave animation using code +that runs entirely on the GPU. They use a variety of noise functions to +simulate waves on a grid of vertices. -You are required to implement the following: +In the second part of this project, I have implemented a GLSL fragment shader +to render an interactive globe in WebGL. This include texture blending, bump +mapping, specular masking, adding an animated cloud layer, and ocean waves and +currents generated via noise functions that are dependent on the land mass +geometry. -* A sin-wave based vertex shader: +------------------------------------------------------------------------------------ +NOTES: +==================================================================================== -![Example sin wave grid](resources/sinWaveGrid.png) +To access any of the live demos at any time, please follow these links: -* A simplex noise based vertex shader: - -![Example simplex noise wave grid](resources/oceanWave.png) - -* One interesting vertex shader of your choice +*Live Globe Render: http://rarietta.github.io/WebGL/part2/frag_globe.html +*Live Wave Shader 1: http://rarietta.github.io/WebGL/part1/vert_wave.html +*Live Wave Shader 2: http://rarietta.github.io/WebGL/part1/vert_simplex.html +*Live Wave Shader 3: http://rarietta.github.io/WebGL/part1/vert_custom.html + +------------------------------------------------------------------------------------ +PART 1: GLSL Vertex Shader Waves +==================================================================================== ------------------------------------------------------------------------------- -PART 1 WALKTHROUGH: +Sine-Based Wave ------------------------------------------------------------------------------- -**Sin Wave** - -* For this assignment, you will need the latest version of Firefox. -* Begin by opening index.html. You should see a flat grid of black and white - lines on the xy plane: - -![Example boring grid](resources/emptyGrid.png) - -* In this assignment, you will animate the grid in a wave-like pattern using a - vertex shader, and determine each vertex’s color based on its height, as seen - in the example in the requirements. -* The vertex and fragment shader are located in script tags in `index.html`. -* The JavaScript code that needs to be modified is located in `index.js`. -* Required shader code modifications: - * Add a float uniform named u_time. - * Modify the vertex’s height using the following code: - - ```glsl - float s_contrib = sin(position.x*2.0*3.14159 + u_time); - float t_contrib = cos(position.y*2.0*3.14159 + u_time); - float height = s_contrib*t_contrib; - ``` - - * Use the GLSL mix function to blend together two colors of your choice based - on the vertex’s height. The lowest possible height should be assigned one - color (for example, `vec3(1.0, 0.2, 0.0)`) and the maximum height should be - another (`vec3(0.0, 0.8, 1.0)`). Use a varying variable to pass the color to - the fragment shader, where you will assign it `gl_FragColor`. - -* Required JavaScript code modifications: - * A floating-point time value should be increased every animation step. - Hint: the delta should be less than one. - * To pass the time to the vertex shader as a uniform, first query the location - of `u_time` using `context.getUniformLocation` in `initializeShader()`. - Then, the uniform’s value can be set by calling `context.uniform1f` in - `animate()`. - -**Simplex Wave** - -* Now that you have the sin wave working, create a new copy of `index.html`. - Call it `index_simplex.html`, or something similar. -* Open up `simplex.vert`, which contains a compact GLSL simplex noise - implementation, in a text editor. Copy and paste the functions included - inside into your `index_simplex.html`'s vertex shader. -* Try changing s_contrib and t_contrib to use simplex noise instead of sin/cos - functions with the following code: - -```glsl -vec2 simplexVec = vec2(u_time, position); -float s_contrib = snoise(simplexVec); -float t_contrib = snoise(vec2(s_contrib,u_time)); -``` - -**Wave Of Your Choice** - -* Create another copy of `index.html`. Call it `index_custom.html`, or - something similar. -* Implement your own interesting vertex shader! In your README.md with your - submission, describe your custom vertex shader, what it does, and how it - works. + +This first vertex shader implements a sin-based noise funtion varying over +time. As is the case with all subsequent vertex shaders in this readme, the +grid has been colored with a gradient value from red (minimum value) to +blue (maximum value). + +[![Video](https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/waves/preview_001.png)] (http://rarietta.github.io/Project5-WebGL/part1/vert_wave.html) ------------------------------------------------------------------------------- -PART 2 REQUIREMENTS: +Simplex Noise Wave ------------------------------------------------------------------------------- -In Part 2, you are given code for: - -* Reading and loading textures -* Rendering a sphere with textures mapped on -* Basic passthrough fragment and vertex shaders -* A basic globe with Earth terrain color mapping -* Gamma correcting textures -* javascript to interact with the mouse - * left-click and drag moves the camera around - * right-click and drag moves the camera in and out - -You are required to implement: - -* Bump mapped terrain -* Rim lighting to simulate atmosphere -* Night-time lights on the dark side of the globe -* Specular mapping -* Moving clouds - -You are also required to pick one open-ended effect to implement: - -* Procedural water rendering and animation using noise -* Shade based on altitude using the height map -* Cloud shadows via ray-tracing through the cloud map in the fragment shader -* Orbiting Moon with texture mapping and shadow casting onto Earth -* Draw a skybox around the entire scene for the stars. -* Your choice! Email Liam and Patrick to get approval first -Finally in addition to your readme, you must also set up a gh-pages branch -(explained below) to expose your beautiful WebGL globe to the world. +Instead of a sin-based noise function, this vertex shader implements a +simplex noise function. -Some examples of what your completed globe renderer will look like: - -![Completed globe, day side](resources/globe_day.png) - -Figure 0. Completed globe renderer, daylight side. - -![Completed globe, twilight](resources/globe_twilight.png) - -Figure 1. Completed globe renderer, twilight border. - -![Completed globe, night side](resources/globe_night.png) - -Figure 2. Completed globe renderer, night side. +[![Video](https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/waves/preview_002.png)] (http://rarietta.github.io/Project5-WebGL/part1/vert_simplex.html) ------------------------------------------------------------------------------- -PART 2 WALKTHROUGH: +Custom Wave ------------------------------------------------------------------------------- -Open part2/frag_globe.html in Firefox to run it. You’ll see a globe -with Phong lighting like the one in Figure 3. All changes you need to make -will be in the fragment shader portion of this file. - -![Initial globe](resources/globe_initial.png) - -Figure 3. Initial globe with diffuse and specular lighting. +This third vertex shader is also a sin-based shader. Although it is similar +to the first shader shown in terms of computation, the generation of this +shader was a crucial stepping stone in the development of the noise-based +wave generation in the WebGL globe fragment shader below, and for that +reason I have chosen to include it as my third vertex noise shader. -**Night Lights** +[![Video](https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/waves/preview_003.png)] (http://rarietta.github.io/Project5-WebGL/part1/vert_custom.html) -The backside of the globe not facing the sun is completely black in the -initial globe. Use the `diffuse` lighting component to detect if a fragment -is on this side of the globe, and, if so, shade it with the color from the -night light texture, `u_Night`. Do not abruptly switch from day to night; -instead use the `GLSL mix` function to smoothly transition from day to night -over a reasonable period. The resulting globe will look like Figure 4. -Consider brightening the night lights by multiplying the value by two. +------------------------------------------------------------------------------------ +PART 2: WebGL Interactive Globe Rendering with GLSL Fragment Shaders +==================================================================================== -The base code shows an example of how to gamma correct the nighttime texture: +This writeup will go through the generation of an animated, interactive +globe using GLSL fragment shaders and WebGL, individually exploring each +stage and feature implemented in the final rendering. -```glsl -float gammaCorrect = 1/1.2; -vec4 nightColor = pow(texture2D(u_Night, v_Texcoord), vec4(gammaCorrect)); -``` - -Feel free to play with gamma correcting the night and day textures if you -wish. Find values that you think look nice! - -![Day/Night without specular mapping](resources/globe_nospecmap.png) - -Figure 4. Globe with night lights and day/night blending at dusk/dawn. - -**Specular Map** - -Our day/night color still shows specular highlights on landmasses, which -should only be diffuse lit. Only the ocean should receive specular highlights. -Use `u_EarthSpec` to determine if a fragment is on ocean or land, and only -include the specular component if it is in ocean. - -![Day/Night with specular mapping](resources/globe_specmap.png) - -Figure 5. Globe with specular map. Compare to Figure 4. Here, the specular -component is not used when shading the land. - -**Clouds** - -In day time, clouds should be diffuse lit. Use `u_Cloud` to determine the -cloud color, and `u_CloudTrans` and `mix` to determine how much a daytime -fragment is affected by the day diffuse map or cloud color. See Figure 6. - -In night time, clouds should obscure city lights. Use `u_CloudTrans` and `mix` -to blend between the city lights and solid black. See Figure 7. - -Animate the clouds by offseting the `s` component of `v_Texcoord` by `u_time` -when reading `u_Cloud` and `u_CloudTrans`. - -![Day with clouds](resources/globe_daycloud.png) - -Figure 6. Clouds with day time shading. - -![Night with clouds](resources/globe_nightcloud.png) - -Figure 7. Clouds observing city nights on the dark side of the globe. +------------------------------------------------------------------------------- +Texture Mapped Sphere +------------------------------------------------------------------------------- -**Bump Mapping** +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_001.png) -Add the appearance of mountains by perturbing the normal used for diffuse -lighting the ground (not the clouds) by using the bump map texture, `u_Bump`. -This texture is 1024x512, and is zero when the fragment is at sea-level, and -one when the fragment is on the highest mountain. Read three texels from this -texture: once using `v_Texcoord`; once one texel to the right; and once one -texel above. Create a perturbed normal in tangent space: +This project began in the bare-bones state seen above, with a simple sphere +surface texture mapped with the globe. + +------------------------------------------------------------------------------- +Diffuse & Specular Lighting +------------------------------------------------------------------------------- -`normalize(vec3(center - right, center - top, 0.2))` +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_002.png) -Use `eastNorthUpToEyeCoordinates` to transform this normal to eye coordinates, -normalize it, then use it for diffuse lighting the ground instead of the -original normal. +From the texture mapping above, along with the normal and position data at +each fragment, diffuse and specular lighting calculations were simply +performed for each fragment. -![Globe with bump mapping](resources/globe_bumpmap.png) +------------------------------------------------------------------------------- +Specular Mask for Land Masses +------------------------------------------------------------------------------- -Figure 8. Bump mapping brings attention to mountains. +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_003.png) -**Rim Lighting** +Using a second texture map of the globe as a mask, in which land mass points +were colored black and water surface points were colored white, I was able to +restrict the specular highlights to only the ocean surfaces. Whenever the +luminance of a texel on the mask was under a very low threshold, the +specular component of the lighting calculation was ignored, thus leading +to flat shading on solid land masses. + +------------------------------------------------------------------------------- +Night-Time Lighting +------------------------------------------------------------------------------- -Rim lighting is a simple post-processed lighting effect we can apply to make -the globe look as if it has an atmospheric layer catching light from the sun. -Implementing rim lighting is simple; we being by finding the dot product of -`v_Normal` and `v_Position`, and add 1 to the dot product. We call this value -our rim factor. If the rim factor is greater than 0, then we add a blue color -based on the rim factor to the current fragment color. You might use a color -something like `vec4(rim/4, rim/2, rim/2, 1)`. If our rim factor is not greater -than 0, then we leave the fragment color as is. Figures 0,1 and 2 show our -finished globe with rim lighting. +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_004.png) -For more information on rim lighting, -read http://www.fundza.com/rman_shaders/surface/fake_rim/fake_rim1.html. +The next step involved mapping a nightime globe texture to any point where +the diffuse lighting calculation was zero. I scaled the diffuse calculations +appropriately to achieve a gradient across the light boundary, and gamma +multiplied the nighttime texture to bring out the luminance. The values +across the boundary were linearly interpolated between the night and day +globe textures. ------------------------------------------------------------------------------- -GH-PAGES +Bump Mapping ------------------------------------------------------------------------------- -Since this assignment is in WebGL you will make your project easily viewable by -taking advantage of GitHub's project pages feature. - -Once you are done you will need to create a new branch named gh-pages: -`git branch gh-pages` +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_005.png) -Switch to your new branch: +To achieve bump mapping in my fragment shader, I used yet another globe +texture map. The luminance at each texel corresponded to the elevation of +the fragment. By calculating the difference between any one texel and its +neighbors in the right and up s-t-coordinate grid directions, I calculated +the gradients in the "east" and "north" model directions. These could +then be converted to eye space and used to perturb the fragment normal +for diffuse lighting calculations. -`git checkout gh-pages` +------------------------------------------------------------------------------- +Noise-Generated Ocean Waves & Currents (Additional Feature) +------------------------------------------------------------------------------- -Create an index.html file that is either your renamed frag_globe.html or -contains a link to it, commit, and then push as usual. Now you can go to +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_006.png) -`.github.io/` +Using a variation of the third sine-based wave shader above, converted to +use texture coordinates. Furthermore, I created a new texture map to +reflect the ocean elevation and currents, seen below this description. +Using these luminance values as another coefficient in the wave calculations, +I was able to make the strongest and most frequent waves occur in parallel +and close to the shore lines and along current paths, while the more gradual +and less frequent waves occurred out at sea. -to see your beautiful globe from anywhere. +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/waveintensity.png) ------------------------------------------------------------------------------- -README +Global Rim Lighting ------------------------------------------------------------------------------- -All students must replace or augment the contents of this Readme.md in a clear -manner with the following: -* A brief description of the project and the specific features you implemented. -* At least one screenshot of your project running. -* A 30 second or longer video of your project running. To create the video you - can use http://www.microsoft.com/expression/products/Encoder4_Overview.aspx -* A performance evaluation (described in detail below). +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_007.png) + +Rim lighting was calculated at each fragment using the dot product of the +fragment normal and model space position to replicate an atmospheric lighting +effect. ------------------------------------------------------------------------------- -PERFORMANCE EVALUATION +Animated Cloud Cover ------------------------------------------------------------------------------- -The performance evaluation is where you will investigate how to make your -program more efficient using the skills you've learned in class. You must have -performed at least one experiment on your code to investigate the positive or -negative effects on performance. -We encourage you to get creative with your tweaks. Consider places in your code -that could be considered bottlenecks and try to improve them. +![Screenshot] (https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/screenshot_008.png) -Each student should provide no more than a one page summary of their -optimizations along with tables and or graphs to visually explain any -performance differences. +Cloud cover was calculated using two more texture maps, one for the cloud +color and one for the cloud layer transparency at each fragment. This +was mixed with the underlying surface luminance values. ------------------------------------------------------------------------------- -THIRD PARTY CODE POLICY +Final WebGL Render Video ------------------------------------------------------------------------------- -* Use of any third-party code must be approved by asking on the Google groups. - If it is approved, all students are welcome to use it. Generally, we approve - use of third-party code that is not a core part of the project. For example, - for the ray tracer, we would approve using a third-party library for loading - models, but would not approve copying and pasting a CUDA function for doing - refraction. -* Third-party code must be credited in README.md. -* Using third-party code without its approval, including using another - student's code, is an academic integrity violation, and will result in you - receiving an F for the semester. -------------------------------------------------------------------------------- -SELF-GRADING -------------------------------------------------------------------------------- -* On the submission date, email your grade, on a scale of 0 to 100, to Liam, - liamboone@gmail.com, with a one paragraph explanation. Be concise and - realistic. Recall that we reserve 30 points as a sanity check to adjust your - grade. Your actual grade will be (0.7 * your grade) + (0.3 * our grade). We - hope to only use this in extreme cases when your grade does not realistically - reflect your work - it is either too high or too low. In most cases, we plan - to give you the exact grade you suggest. -* Projects are not weighted evenly, e.g., Project 0 doesn't count as much as - the path tracer. We will determine the weighting at the end of the semester - based on the size of each project. - - ---- -SUBMISSION ---- -As with the previous project, you should fork this project and work inside of -your fork. Upon completion, commit your finished project back to your fork, and -make a pull request to the master repository. You should include a README.md -file in the root directory detailing the following - -* A brief description of the project and specific features you implemented -* At least one screenshot of your project running. -* A link to a video of your project running. -* Instructions for building and running your project if they differ from the - base code. -* A performance writeup as detailed above. -* A list of all third-party code used. -* This Readme file edited as described above in the README section. +Here is a live version of the final rendered globe running in the +browser. + +[![Video](https://raw.github.com/rarietta/Project5-WebGL/master/readme_imgs/globe/preview_001.png)] (http://rarietta.github.io/Project5-WebGL/part2/frag_globe.html) + +------------------------------------------------------------------------------------ +ACKNOWLEDGMENTS: +==================================================================================== +This project was built on a basic framework provided by Patrick Cozzi and Liam +Boone for CIS 565 at The University of Pennsylvania, Fall 2013. diff --git a/part1/vert_custom.html b/part1/vert_custom.html new file mode 100644 index 0000000..2e9abaf --- /dev/null +++ b/part1/vert_custom.html @@ -0,0 +1,50 @@ + + + +Vertex Wave + + + + + +
+ + + + + + + + + + + + diff --git a/part1/vert_simplex.html b/part1/vert_simplex.html new file mode 100644 index 0000000..bab0610 --- /dev/null +++ b/part1/vert_simplex.html @@ -0,0 +1,90 @@ + + + +Vertex Simplex + + + + + +
+ + + + + + + + + + + + diff --git a/part1/vert_wave.html b/part1/vert_wave.html index 57107ca..8e10830 100644 --- a/part1/vert_wave.html +++ b/part1/vert_wave.html @@ -13,21 +13,32 @@ diff --git a/part1/vert_wave.js b/part1/vert_wave.js index b90b9cf..57d66fa 100644 --- a/part1/vert_wave.js +++ b/part1/vert_wave.js @@ -31,6 +31,11 @@ var positionLocation = 0; var heightLocation = 1; var u_modelViewPerspectiveLocation; + var u_timeLocation; + var u_time; + + //var minColor = vec3(0.0, 0.0, 1.0); + //var maxColor = vec3(1.0, 0.0, 0.0); (function initializeShader() { var program; @@ -41,6 +46,8 @@ context.bindAttribLocation(program, positionLocation, "position"); u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective"); + u_timeLocation = context.getUniformLocation(program, "u_time"); + u_time = 0.0; context.useProgram(program); })(); @@ -145,6 +152,7 @@ context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp); context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0); + context.uniform1f(u_timeLocation, u_time += 0.005); window.requestAnimFrame(animate); })(); diff --git a/part2/frag_globe.html b/part2/frag_globe.html index 6aa5609..f5010ca 100644 --- a/part2/frag_globe.html +++ b/part2/frag_globe.html @@ -60,6 +60,8 @@ uniform sampler2D u_EarthSpec; //Bump map uniform sampler2D u_Bump; + //Wave Intensity + uniform sampler2D u_Wave; uniform float u_time; uniform mat4 u_InvTrans; @@ -73,26 +75,69 @@ void main(void) { + // what is water and what is land? + float earthSpecMask = texture2D(u_EarthSpec, v_Texcoord).r; + float waveIntensity = texture2D(u_Wave, v_Texcoord).r; + + //read 3 texels from bump map for land, noise for water + float bumpCenter, bumpRight, bumpTop; + if (earthSpecMask == 0.00) { + bumpCenter = texture2D(u_Bump, vec2(v_Texcoord.s, v_Texcoord.t)).r; + bumpRight = texture2D(u_Bump, vec2(v_Texcoord.s + (1.0/512.0), v_Texcoord.t)).r; + bumpTop = texture2D(u_Bump, vec2(v_Texcoord.s, v_Texcoord.t + (1.0/1024.0))).r; + } else { + bumpCenter = ((1.2 - waveIntensity) * sin(33.0 * v_Texcoord.s*v_positionMC.y + 53.0 * (1.2 - waveIntensity) * (abs(fract(0.75*u_time) - 0.5) + 0.2))) + * ((1.2 - waveIntensity) * cos(50.0 * v_Texcoord.t*v_positionMC.y + 35.0 * (1.2 - waveIntensity) * (abs(fract(0.75*u_time) - 0.5) + 0.2))); + bumpRight = ((1.2 - waveIntensity) * sin(33.0 *(v_Texcoord.s+(1.0/1024.0)) + 53.0 * (1.2 - waveIntensity) * (abs(fract(0.75*u_time) - 0.5) + 0.2))) + * ((1.2 - waveIntensity) * cos(50.0 * v_Texcoord.t + 35.0 * (1.2 - waveIntensity) * (abs(fract(0.75*u_time) - 0.5) + 0.2))); + bumpTop = ((1.2 - waveIntensity) * sin(33.0 * v_Texcoord.s + 53.0 * (1.2 - waveIntensity) * (abs(fract(0.75*u_time) - 0.5) + 0.2))) + * ((1.2 - waveIntensity) * cos(50.0 *(v_Texcoord.t+(1.0/512.0)) + 35.0 * (1.2 - waveIntensity) * (abs(fract(0.75*u_time) - 0.5) + 0.2))); + } + vec3 tangentSpaceBumpNormal = normalize(vec3(bumpCenter-bumpRight, bumpCenter-bumpTop, 0.2)); + + // surface normal - normalized after rasterization - vec3 normal = normalize(v_Normal); + vec3 v_normalEC = normalize(v_Normal); // normalized eye-to-position vector in camera coordinates vec3 eyeToPosition = normalize(v_Position); + mat3 tangentToEyeSpace = eastNorthUpToEyeCoordinates(v_positionMC, v_normalEC); + vec3 normal = normalize(tangentToEyeSpace*tangentSpaceBumpNormal); + float diffuse = clamp(dot(u_CameraSpaceDirLight, normal), 0.0, 1.0); vec3 toReflectedLight = reflect(-u_CameraSpaceDirLight, normal); float specular = max(dot(toReflectedLight, -eyeToPosition), 0.0); specular = pow(specular, 20.0); - float gammaCorrect = 1.0/1.2; //gamma correct by 1/1.2 + float gammaCorrect = 1.0/1.1; //gamma correct by 1/1.1 vec3 dayColor = texture2D(u_DayDiffuse, v_Texcoord).rgb; vec3 nightColor = texture2D(u_Night, v_Texcoord).rgb; + //apply gamma correction to nighttime texture nightColor = pow(nightColor,vec3(gammaCorrect)); - - vec3 color = ((0.6 * diffuse) + (0.4 * specular)) * dayColor; + + //apply specular mask to daytime texture + dayColor = ((0.6 * diffuse) + (0.4 * earthSpecMask * specular)) * dayColor; + + //apply clouds + vec2 cloudTexCoord = vec2(v_Texcoord.s - u_time/5.0, v_Texcoord.t); + vec3 cloudColor = texture2D(u_Cloud, cloudTexCoord).rgb; + float cloudTrans = texture2D(u_CloudTrans, cloudTexCoord).r; + dayColor = mix(cloudColor, dayColor, cloudTrans); + nightColor = mix(vec3(0.0), nightColor, cloudTrans); + + float reDiffuse = clamp(diffuse*2.5, 0.0, 1.0); + vec3 color = mix(nightColor, dayColor, reDiffuse); gl_FragColor = vec4(color, 1.0); + + //rim lighting + float rimFactor = dot(v_Normal, v_Position) + 1.0; + if (rimFactor > 0.0) { + vec4 rimColor = vec4(rimFactor/4.0, rimFactor/2.0, rimFactor/2.0, 1.0); + gl_FragColor += rimColor; + } } mat3 eastNorthUpToEyeCoordinates(vec3 positionMC, vec3 normalEC) diff --git a/part2/frag_globe.js b/part2/frag_globe.js index 1d8a877..10d9a5e 100644 --- a/part2/frag_globe.js +++ b/part2/frag_globe.js @@ -54,7 +54,10 @@ var u_CloudTransLocation; var u_EarthSpecLocation; var u_BumpLocation; + var u_WaveLocation; var u_timeLocation; + + var u_time; (function initializeShader() { var vs = getShaderSource(document.getElementById("vs")); @@ -74,6 +77,7 @@ u_CloudTransLocation = gl.getUniformLocation(program,"u_CloudTrans"); u_EarthSpecLocation = gl.getUniformLocation(program,"u_EarthSpec"); u_BumpLocation = gl.getUniformLocation(program,"u_Bump"); + u_WaveLocation = gl.getUniformLocation(program, "u_Wave"); u_timeLocation = gl.getUniformLocation(program,"u_time"); u_CameraSpaceDirLightLocation = gl.getUniformLocation(program,"u_CameraSpaceDirLight"); @@ -86,6 +90,7 @@ var transTex = gl.createTexture(); var lightTex = gl.createTexture(); var specTex = gl.createTexture(); + var waveTex = gl.createTexture(); function initLoadedTexture(texture){ gl.bindTexture(gl.TEXTURE_2D, texture); @@ -286,9 +291,13 @@ gl.activeTexture(gl.TEXTURE5); gl.bindTexture(gl.TEXTURE_2D, specTex); gl.uniform1i(u_EarthSpecLocation, 5); + gl.activeTexture(gl.TEXTURE6); + gl.bindTexture(gl.TEXTURE_2D, waveTex); + gl.uniform1i(u_WaveLocation, 6); gl.drawElements(gl.TRIANGLES, numberOfIndices, gl.UNSIGNED_SHORT,0); time += 0.001; + gl.uniform1f(u_timeLocation, time); window.requestAnimFrame(animate); } @@ -313,4 +322,5 @@ initializeTexture(transTex, "earthtrans1024.png"); initializeTexture(lightTex, "earthlight1024.png"); initializeTexture(specTex, "earthspec1024.png"); + initializeTexture(waveTex, "waveintensity.png"); }()); diff --git a/part2/waveintensity.png b/part2/waveintensity.png new file mode 100644 index 0000000..907c553 Binary files /dev/null and b/part2/waveintensity.png differ diff --git a/readme_imgs/globe/preview_001.png b/readme_imgs/globe/preview_001.png new file mode 100644 index 0000000..7610053 Binary files /dev/null and b/readme_imgs/globe/preview_001.png differ diff --git a/readme_imgs/globe/screenshot_001.png b/readme_imgs/globe/screenshot_001.png new file mode 100644 index 0000000..151cf41 Binary files /dev/null and b/readme_imgs/globe/screenshot_001.png differ diff --git a/readme_imgs/globe/screenshot_002.png b/readme_imgs/globe/screenshot_002.png new file mode 100644 index 0000000..502b0a3 Binary files /dev/null and b/readme_imgs/globe/screenshot_002.png differ diff --git a/readme_imgs/globe/screenshot_003.png b/readme_imgs/globe/screenshot_003.png new file mode 100644 index 0000000..72e0ae5 Binary files /dev/null and b/readme_imgs/globe/screenshot_003.png differ diff --git a/readme_imgs/globe/screenshot_004.png b/readme_imgs/globe/screenshot_004.png new file mode 100644 index 0000000..3aa7c51 Binary files /dev/null and b/readme_imgs/globe/screenshot_004.png differ diff --git a/readme_imgs/globe/screenshot_005.png b/readme_imgs/globe/screenshot_005.png new file mode 100644 index 0000000..02e243c Binary files /dev/null and b/readme_imgs/globe/screenshot_005.png differ diff --git a/readme_imgs/globe/screenshot_006.png b/readme_imgs/globe/screenshot_006.png new file mode 100644 index 0000000..8421bd6 Binary files /dev/null and b/readme_imgs/globe/screenshot_006.png differ diff --git a/readme_imgs/globe/screenshot_007.png b/readme_imgs/globe/screenshot_007.png new file mode 100644 index 0000000..c744219 Binary files /dev/null and b/readme_imgs/globe/screenshot_007.png differ diff --git a/readme_imgs/globe/screenshot_008.png b/readme_imgs/globe/screenshot_008.png new file mode 100644 index 0000000..a3ab01a Binary files /dev/null and b/readme_imgs/globe/screenshot_008.png differ diff --git a/readme_imgs/globe/screenshot_final.png b/readme_imgs/globe/screenshot_final.png new file mode 100644 index 0000000..c235563 Binary files /dev/null and b/readme_imgs/globe/screenshot_final.png differ diff --git a/readme_imgs/globe/waveintensity.png b/readme_imgs/globe/waveintensity.png new file mode 100644 index 0000000..547bd61 Binary files /dev/null and b/readme_imgs/globe/waveintensity.png differ diff --git a/readme_imgs/waves/Thumbs.db b/readme_imgs/waves/Thumbs.db new file mode 100644 index 0000000..9240167 Binary files /dev/null and b/readme_imgs/waves/Thumbs.db differ diff --git a/readme_imgs/waves/preview_001.png b/readme_imgs/waves/preview_001.png new file mode 100644 index 0000000..2a938c7 Binary files /dev/null and b/readme_imgs/waves/preview_001.png differ diff --git a/readme_imgs/waves/preview_002.png b/readme_imgs/waves/preview_002.png new file mode 100644 index 0000000..40089b9 Binary files /dev/null and b/readme_imgs/waves/preview_002.png differ diff --git a/readme_imgs/waves/preview_003.png b/readme_imgs/waves/preview_003.png new file mode 100644 index 0000000..370656f Binary files /dev/null and b/readme_imgs/waves/preview_003.png differ