diff --git a/README.md b/README.md
index 06fcfd4..3ed38c3 100644
--- a/README.md
+++ b/README.md
@@ -1,373 +1,47 @@
-------------------------------------------------------------------------------
-CIS565: Project 5: WebGL
+
Project 5: WebGL
-------------------------------------------------------------------------------
-Fall 2013
+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.
-
--------------------------------------------------------------------------------
-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:
-
-* Drawing a VBO through WebGL
-* Javascript code for interfacing with WebGL
-* Functions for generating simplex noise
-
-You are required to implement the following:
-
-* A sin-wave based vertex shader:
-
-
-
-* A simplex noise based vertex shader:
-
-
-
-* One interesting vertex shader of your choice
-------------------------------------------------------------------------------
-PART 1 WALKTHROUGH:
+INTRODUCTION:
-------------------------------------------------------------------------------
-**Sin Wave**
+This project is an introductory project into the world of GLSL. In the first part of this project, I implemented a GLSL vertex shader as part of a WebGL demo. I created three dynamic wave animations using code that runs entirely on the GPU.
-* 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:
-
-
-
-* 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.
+In the second part of this project, I implemented a GLSL fragment shader to render an interactive globe in WebGL. This includes texture blending, bump mapping, specular masking, and adding a cloud layer.
-------------------------------------------------------------------------------
-PART 2 REQUIREMENTS:
+RENDERS:
-------------------------------------------------------------------------------
-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
+Here are some renders:
-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
+First wave calculated using a producto of sin and cosine waves. Link: http://josephto.github.io/Project5-WebGL/part1/vert_wave.html
-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.
+
-Some examples of what your completed globe renderer will look like:
+Second simplex wave. Link: http://josephto.github.io/Project5-WebGL/part1/simplex_wave.html
-
+
-Figure 0. Completed globe renderer, daylight side.
+Third original wave that mimics a wave of water as it experiences initial turbulence and then calms down. The screen shot doesn't really depict the motion of the wave. Its better to watch the video. Link: http://josephto.github.io/Project5-WebGL/part1/wave_wave.html
-
+
-Figure 1. Completed globe renderer, twilight border.
-
-
-
-Figure 2. Completed globe renderer, night side.
+A globe render. Link: http://josephto.github.io/Project5-WebGL/part2/frag_globe.html
-------------------------------------------------------------------------------
-PART 2 WALKTHROUGH:
+PERFORMANCE REPORT:
-------------------------------------------------------------------------------
-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.
-
-
-
-Figure 3. Initial globe with diffuse and specular lighting.
-
-**Night Lights**
-
-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.
-
-The base code shows an example of how to gamma correct the nighttime texture:
-
-```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!
-
-
-
-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.
-
-
-
-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`.
-
-
-
-Figure 6. Clouds with day time shading.
-
-
-
-Figure 7. Clouds observing city nights on the dark side of the globe.
-
-**Bump Mapping**
-
-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:
-
-`normalize(vec3(center - right, center - top, 0.2))`
-
-Use `eastNorthUpToEyeCoordinates` to transform this normal to eye coordinates,
-normalize it, then use it for diffuse lighting the ground instead of the
-original normal.
-
-
-
-Figure 8. Bump mapping brings attention to mountains.
-
-**Rim 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.
-
-For more information on rim lighting,
-read http://www.fundza.com/rman_shaders/surface/fake_rim/fake_rim1.html.
-
--------------------------------------------------------------------------------
-GH-PAGES
--------------------------------------------------------------------------------
-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`
-
-Switch to your new branch:
-
-`git checkout gh-pages`
-
-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
-
-`.github.io/`
-
-to see your beautiful globe from anywhere.
-
--------------------------------------------------------------------------------
-README
--------------------------------------------------------------------------------
-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).
-
--------------------------------------------------------------------------------
-PERFORMANCE EVALUATION
--------------------------------------------------------------------------------
-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.
-
-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.
-
--------------------------------------------------------------------------------
-THIRD PARTY CODE POLICY
--------------------------------------------------------------------------------
-* 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
+It was hard for me to figure out how exactly to do a good performance evaluation for this project so I just printed out the FPS for each of the programs. The table is as follows:
-* 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.
+Program | Frames per second
+------------------|------------------------
+Sin/Cos Wave | around 36 fps
+Simplex Wave | around 38 fps
+Wave Wave | around 37 fps
+Globe | around 33 fps
\ No newline at end of file
diff --git a/globe.png b/globe.png
new file mode 100644
index 0000000..72747c7
Binary files /dev/null and b/globe.png differ
diff --git a/part1/simplex_wave.html b/part1/simplex_wave.html
new file mode 100644
index 0000000..6d24265
--- /dev/null
+++ b/part1/simplex_wave.html
@@ -0,0 +1,88 @@
+
+
+
+Vertex Wave
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/part1/vert_wave.html b/part1/vert_wave.html
index 57107ca..4e83cff 100644
--- a/part1/vert_wave.html
+++ b/part1/vert_wave.html
@@ -14,10 +14,15 @@
attribute vec2 position;
uniform mat4 u_modelViewPerspective;
+ uniform float u_time;
+ varying vec3 color;
void main(void)
{
- float height = 0.0;
+ 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;
+ color = mix(vec3(1.0,0.2,0.0), vec3(0.0,0.8,1.0), (height+1.0)/1.0);
gl_Position = u_modelViewPerspective * vec4(vec3(position, height), 1.0);
}
@@ -25,9 +30,11 @@
diff --git a/part1/vert_wave.js b/part1/vert_wave.js
index b90b9cf..3d267d7 100644
--- a/part1/vert_wave.js
+++ b/part1/vert_wave.js
@@ -3,8 +3,8 @@
/*global window,document,Float32Array,Uint16Array,mat4,vec3,snoise*/
/*global getShaderSource,createWebGLContext,createProgram*/
- var NUM_WIDTH_PTS = 32;
- var NUM_HEIGHT_PTS = 32;
+ var NUM_WIDTH_PTS = 100;
+ var NUM_HEIGHT_PTS = 100;
var message = document.getElementById("message");
var canvas = document.getElementById("canvas");
@@ -19,6 +19,8 @@
context.clearColor(1.0, 1.0, 1.0, 1.0);
context.enable(context.DEPTH_TEST);
+ var time = 0.0;
+
var persp = mat4.create();
mat4.perspective(45.0, 0.5, 0.1, 100.0, persp);
@@ -31,6 +33,7 @@
var positionLocation = 0;
var heightLocation = 1;
var u_modelViewPerspectiveLocation;
+ var u_time;
(function initializeShader() {
var program;
@@ -40,6 +43,7 @@
var program = createProgram(context, vs, fs, message);
context.bindAttribLocation(program, positionLocation, "position");
u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective");
+ u_time = context.getUniformLocation(program,"u_time");
context.useProgram(program);
})();
@@ -138,10 +142,13 @@
var mvp = mat4.create();
mat4.multiply(persp, mv, mvp);
+ time += 0.01;
+
///////////////////////////////////////////////////////////////////////////
// Render
context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT);
+ context.uniform1f(u_time, time);
context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp);
context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0);
diff --git a/part1/vert_waveTEST.html b/part1/vert_waveTEST.html
new file mode 100644
index 0000000..3505ace
--- /dev/null
+++ b/part1/vert_waveTEST.html
@@ -0,0 +1,46 @@
+
+
+
+Vertex Wave
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/part1/vert_waveTEST.js b/part1/vert_waveTEST.js
new file mode 100644
index 0000000..56cbcf0
--- /dev/null
+++ b/part1/vert_waveTEST.js
@@ -0,0 +1,158 @@
+(function() {
+ "use strict";
+ /*global window,document,Float32Array,Uint16Array,mat4,vec3,snoise*/
+ /*global getShaderSource,createWebGLContext,createProgram*/
+
+ var NUM_WIDTH_PTS = 1024;
+ var NUM_HEIGHT_PTS = 512;
+
+ var message = document.getElementById("message");
+ var canvas = document.getElementById("canvas");
+ var context = createWebGLContext(canvas, message);
+ if (!context) {
+ return;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ context.viewport(0, 0, canvas.width, canvas.height);
+ context.clearColor(1.0, 1.0, 1.0, 1.0);
+ context.enable(context.DEPTH_TEST);
+
+ var time = 0.0;
+
+ var persp = mat4.create();
+ mat4.perspective(45.0, 0.5, 0.1, 100.0, persp);
+
+ var eye = [2.0, 1.0, 3.0];
+ var center = [0.0, 0.0, 0.0];
+ var up = [0.0, 0.0, 1.0];
+ var view = mat4.create();
+ mat4.lookAt(eye, center, up, view);
+
+ var positionLocation = 0;
+ var heightLocation = 1;
+ var u_modelViewPerspectiveLocation;
+ var u_time;
+
+ (function initializeShader() {
+ var program;
+ var vs = getShaderSource(document.getElementById("vs"));
+ var fs = getShaderSource(document.getElementById("fs"));
+
+ var program = createProgram(context, vs, fs, message);
+ context.bindAttribLocation(program, positionLocation, "position");
+ u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective");
+ u_time = context.getUniformLocation(program,"u_time");
+
+ context.useProgram(program);
+ })();
+
+ var heights;
+ var numberOfIndices;
+
+ (function initializeGrid() {
+ function uploadMesh(positions, heights, indices) {
+ // Positions
+ var positionsName = context.createBuffer();
+ context.bindBuffer(context.ARRAY_BUFFER, positionsName);
+ context.bufferData(context.ARRAY_BUFFER, positions, context.STATIC_DRAW);
+ context.vertexAttribPointer(positionLocation, 2, context.FLOAT, false, 0, 0);
+ context.enableVertexAttribArray(positionLocation);
+
+ if (heights)
+ {
+ // Heights
+ var heightsName = context.createBuffer();
+ context.bindBuffer(context.ARRAY_BUFFER, heightsName);
+ context.bufferData(context.ARRAY_BUFFER, heights.length * heights.BYTES_PER_ELEMENT, context.STREAM_DRAW);
+ context.vertexAttribPointer(heightLocation, 1, context.FLOAT, false, 0, 0);
+ context.enableVertexAttribArray(heightLocation);
+ }
+
+ // Indices
+ var indicesName = context.createBuffer();
+ context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indicesName);
+ context.bufferData(context.ELEMENT_ARRAY_BUFFER, indices, context.STATIC_DRAW);
+ }
+
+ var WIDTH_DIVISIONS = NUM_WIDTH_PTS - 1;
+ var HEIGHT_DIVISIONS = NUM_HEIGHT_PTS - 1;
+
+ var numberOfPositions = NUM_WIDTH_PTS * NUM_HEIGHT_PTS;
+
+ var positions = new Float32Array(2 * numberOfPositions);
+ var indices = new Uint16Array(2 * ((NUM_HEIGHT_PTS * (NUM_WIDTH_PTS - 1)) + (NUM_WIDTH_PTS * (NUM_HEIGHT_PTS - 1))));
+
+ var positionsIndex = 0;
+ var indicesIndex = 0;
+ var length;
+
+ for (var j = 0; j < NUM_WIDTH_PTS; ++j)
+ {
+ positions[positionsIndex++] = j /(NUM_WIDTH_PTS - 1);
+ positions[positionsIndex++] = 0.0;
+
+ if (j>=1)
+ {
+ length = positionsIndex / 2;
+ indices[indicesIndex++] = length - 2;
+ indices[indicesIndex++] = length - 1;
+ }
+ }
+
+ for (var i = 0; i < HEIGHT_DIVISIONS; ++i)
+ {
+ var v = (i + 1) / (NUM_HEIGHT_PTS - 1);
+ positions[positionsIndex++] = 0.0;
+ positions[positionsIndex++] = v;
+
+ length = (positionsIndex / 2);
+ indices[indicesIndex++] = length - 1;
+ indices[indicesIndex++] = length - 1 - NUM_WIDTH_PTS;
+
+ for (var k = 0; k < WIDTH_DIVISIONS; ++k)
+ {
+ positions[positionsIndex++] = (k + 1) / (NUM_WIDTH_PTS - 1);
+ positions[positionsIndex++] = v;
+
+ length = positionsIndex / 2;
+ var new_pt = length - 1;
+ indices[indicesIndex++] = new_pt - 1; // Previous side
+ indices[indicesIndex++] = new_pt;
+
+ indices[indicesIndex++] = new_pt - NUM_WIDTH_PTS; // Previous bottom
+ indices[indicesIndex++] = new_pt;
+ }
+ }
+
+ uploadMesh(positions, heights, indices);
+ numberOfIndices = indices.length;
+ })();
+
+ (function animate(){
+ ///////////////////////////////////////////////////////////////////////////
+ // Update
+
+ var model = mat4.create();
+ mat4.identity(model);
+ mat4.translate(model, [-0.5, -0.5, 0.0]);
+ var mv = mat4.create();
+ mat4.multiply(view, model, mv);
+ var mvp = mat4.create();
+ mat4.multiply(persp, mv, mvp);
+
+ time += 0.01;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Render
+ context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT);
+
+ context.uniform1f(u_time, time);
+ context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp);
+ context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0);
+
+ window.requestAnimFrame(animate);
+ })();
+
+}());
diff --git a/part1/wave_wave.html b/part1/wave_wave.html
new file mode 100644
index 0000000..df1cadb
--- /dev/null
+++ b/part1/wave_wave.html
@@ -0,0 +1,47 @@
+
+
+
+Vertex Wave
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/part1/wave_wave.js b/part1/wave_wave.js
new file mode 100644
index 0000000..ab5646e
--- /dev/null
+++ b/part1/wave_wave.js
@@ -0,0 +1,158 @@
+(function() {
+ "use strict";
+ /*global window,document,Float32Array,Uint16Array,mat4,vec3,snoise*/
+ /*global getShaderSource,createWebGLContext,createProgram*/
+
+ var NUM_WIDTH_PTS = 50;
+ var NUM_HEIGHT_PTS = 50;
+
+ var message = document.getElementById("message");
+ var canvas = document.getElementById("canvas");
+ var context = createWebGLContext(canvas, message);
+ if (!context) {
+ return;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ context.viewport(0, 0, canvas.width, canvas.height);
+ context.clearColor(1.0, 1.0, 1.0, 1.0);
+ context.enable(context.DEPTH_TEST);
+
+ var time = 0.0;
+
+ var persp = mat4.create();
+ mat4.perspective(45.0, 0.5, 0.1, 100.0, persp);
+
+ var eye = [2.0, 1.0, 3.0];
+ var center = [0.0, 0.0, 0.0];
+ var up = [0.0, 0.0, 1.0];
+ var view = mat4.create();
+ mat4.lookAt(eye, center, up, view);
+
+ var positionLocation = 0;
+ var heightLocation = 1;
+ var u_modelViewPerspectiveLocation;
+ var u_time;
+
+ (function initializeShader() {
+ var program;
+ var vs = getShaderSource(document.getElementById("vs"));
+ var fs = getShaderSource(document.getElementById("fs"));
+
+ var program = createProgram(context, vs, fs, message);
+ context.bindAttribLocation(program, positionLocation, "position");
+ u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective");
+ u_time = context.getUniformLocation(program,"u_time");
+
+ context.useProgram(program);
+ })();
+
+ var heights;
+ var numberOfIndices;
+
+ (function initializeGrid() {
+ function uploadMesh(positions, heights, indices) {
+ // Positions
+ var positionsName = context.createBuffer();
+ context.bindBuffer(context.ARRAY_BUFFER, positionsName);
+ context.bufferData(context.ARRAY_BUFFER, positions, context.STATIC_DRAW);
+ context.vertexAttribPointer(positionLocation, 2, context.FLOAT, false, 0, 0);
+ context.enableVertexAttribArray(positionLocation);
+
+ if (heights)
+ {
+ // Heights
+ var heightsName = context.createBuffer();
+ context.bindBuffer(context.ARRAY_BUFFER, heightsName);
+ context.bufferData(context.ARRAY_BUFFER, heights.length * heights.BYTES_PER_ELEMENT, context.STREAM_DRAW);
+ context.vertexAttribPointer(heightLocation, 1, context.FLOAT, false, 0, 0);
+ context.enableVertexAttribArray(heightLocation);
+ }
+
+ // Indices
+ var indicesName = context.createBuffer();
+ context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indicesName);
+ context.bufferData(context.ELEMENT_ARRAY_BUFFER, indices, context.STATIC_DRAW);
+ }
+
+ var WIDTH_DIVISIONS = NUM_WIDTH_PTS - 1;
+ var HEIGHT_DIVISIONS = NUM_HEIGHT_PTS - 1;
+
+ var numberOfPositions = NUM_WIDTH_PTS * NUM_HEIGHT_PTS;
+
+ var positions = new Float32Array(2 * numberOfPositions);
+ var indices = new Uint16Array(2 * ((NUM_HEIGHT_PTS * (NUM_WIDTH_PTS - 1)) + (NUM_WIDTH_PTS * (NUM_HEIGHT_PTS - 1))));
+
+ var positionsIndex = 0;
+ var indicesIndex = 0;
+ var length;
+
+ for (var j = 0; j < NUM_WIDTH_PTS; ++j)
+ {
+ positions[positionsIndex++] = j /(NUM_WIDTH_PTS - 1);
+ positions[positionsIndex++] = 0.0;
+
+ if (j>=1)
+ {
+ length = positionsIndex / 2;
+ indices[indicesIndex++] = length - 2;
+ indices[indicesIndex++] = length - 1;
+ }
+ }
+
+ for (var i = 0; i < HEIGHT_DIVISIONS; ++i)
+ {
+ var v = (i + 1) / (NUM_HEIGHT_PTS - 1);
+ positions[positionsIndex++] = 0.0;
+ positions[positionsIndex++] = v;
+
+ length = (positionsIndex / 2);
+ indices[indicesIndex++] = length - 1;
+ indices[indicesIndex++] = length - 1 - NUM_WIDTH_PTS;
+
+ for (var k = 0; k < WIDTH_DIVISIONS; ++k)
+ {
+ positions[positionsIndex++] = (k + 1) / (NUM_WIDTH_PTS - 1);
+ positions[positionsIndex++] = v;
+
+ length = positionsIndex / 2;
+ var new_pt = length - 1;
+ indices[indicesIndex++] = new_pt - 1; // Previous side
+ indices[indicesIndex++] = new_pt;
+
+ indices[indicesIndex++] = new_pt - NUM_WIDTH_PTS; // Previous bottom
+ indices[indicesIndex++] = new_pt;
+ }
+ }
+
+ uploadMesh(positions, heights, indices);
+ numberOfIndices = indices.length;
+ })();
+
+ (function animate(){
+ ///////////////////////////////////////////////////////////////////////////
+ // Update
+
+ var model = mat4.create();
+ mat4.identity(model);
+ mat4.translate(model, [-0.5, -0.5, 0.0]);
+ var mv = mat4.create();
+ mat4.multiply(view, model, mv);
+ var mvp = mat4.create();
+ mat4.multiply(persp, mv, mvp);
+
+ time += 0.01;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Render
+ context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT);
+
+ context.uniform1f(u_time, time);
+ context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp);
+ context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0);
+
+ window.requestAnimFrame(animate);
+ })();
+
+}());
diff --git a/part2/frag_globe.html b/part2/frag_globe.html
index 6aa5609..01d5cfd 100644
--- a/part2/frag_globe.html
+++ b/part2/frag_globe.html
@@ -62,6 +62,7 @@
uniform sampler2D u_Bump;
uniform float u_time;
+ uniform float u_water;
uniform mat4 u_InvTrans;
varying vec3 v_Normal; // surface normal in camera coordinates
@@ -70,6 +71,47 @@
varying vec3 v_positionMC; // position in model coordinates
mat3 eastNorthUpToEyeCoordinates(vec3 positionMC, vec3 normalEC);
+ float rand(vec2 seed);
+
+ vec3 permute(vec3 x) {
+ x = ((x*34.0)+1.0)*x;
+ return x - floor(x * (1.0 / 289.0)) * 289.0;
+ }
+
+ float simplexNoise(vec2 v)
+ {
+ const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
+
+ vec2 i = floor(v + dot(v, C.yy) );
+ vec2 x0 = v - i + dot(i, C.xx);
+
+ vec2 i1;
+ i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
+
+ vec4 x12 = x0.xyxy + C.xxzz;
+ x12.xy -= i1;
+
+ i = i - floor(i * (1.0 / 289.0)) * 289.0;
+
+ vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ + i.x + vec3(0.0, i1.x, 1.0 ));
+
+ vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
+ m = m*m ;
+ m = m*m ;
+
+ vec3 x = 2.0 * fract(p * C.www) - 1.0;
+ vec3 h = abs(x) - 0.5;
+ vec3 ox = floor(x + 0.5);
+ vec3 a0 = x - ox;
+
+ m *= inversesqrt( a0*a0 + h*h );
+
+ vec3 g;
+ g.x = a0.x * x0.x + h.x * x0.y;
+ g.yz = a0.yz * x12.xz + h.yz * x12.yw;
+ return 130.0 * dot(m, g);
+ }
void main(void)
{
@@ -77,21 +119,68 @@
vec3 normal = normalize(v_Normal);
// normalized eye-to-position vector in camera coordinates
vec3 eyeToPosition = normalize(v_Position);
-
- float diffuse = clamp(dot(u_CameraSpaceDirLight, normal), 0.0, 1.0);
- vec3 toReflectedLight = reflect(-u_CameraSpaceDirLight, normal);
+ float center = texture2D(u_Bump, v_Texcoord).r;
+ float top = texture2D(u_Bump, v_Texcoord+vec2(0.0,1.0/512.0)).r;
+ float right = texture2D(u_Bump, v_Texcoord+vec2(1.0/1024.0,0.0)).r;
+
+ vec3 normalBump = normalize(vec3(center - right, center - top, 0.2));
+
+ if (texture2D(u_EarthSpec, v_Texcoord).r > 0.3){
+ normalBump.x = .0125 * simplexNoise(45.0*vec2(v_positionMC)-22.0*vec2(u_time*0.1, u_time*0.1)) *
+ simplexNoise(20.0*vec2(v_positionMC.z-15.0*u_time*0.1,v_positionMC.y-7.0*u_time*0.1));
+ }
+
+ vec3 normalBumpEye = eastNorthUpToEyeCoordinates(v_positionMC, normal) * normalBump;
+
+ // float a =2.0;
+
+ // float s_contrib = a*sin(v_Texcoord.s*200.0*3.14159 + u_water);
+ // float t_contrib = a*cos(v_Texcoord.t*200.0*3.14159 + u_water);
+ // float centerWater = s_contrib*t_contrib;
+ // s_contrib = a*sin(v_Texcoord.s*200.0*3.14159 + u_water);
+ // t_contrib = a*cos(v_Texcoord.t*200.0*3.14159 + u_water)+1.0/512.0;
+ // float topWater = s_contrib*t_contrib;
+ // s_contrib = a*sin(v_Texcoord.s*200.0*3.14159 + u_water+1.0/1024.0);
+ // t_contrib = a*cos(v_Texcoord.t*200.0*3.14159 + u_water+1.0/512.0);
+ // float rightWater = s_contrib*t_contrib;
+ // vec3 normalWaterBump = normalize(vec3(centerWater - rightWater, centerWater - topWater, 0.2));
+ // vec3 normalWaterBumpEye = eastNorthUpToEyeCoordinates(v_positionMC, normal) * normalWaterBump;
+ //vec3 waterColor = vec3(height+.5, height+.5, height+.5)*texture2D(u_EarthSpec, v_Texcoord).r;
+
+ float diffuse = clamp(dot(u_CameraSpaceDirLight, normalBumpEye), 0.0, 1.0);
+
+ vec3 toReflectedLight = reflect(-u_CameraSpaceDirLight, normalBumpEye);
float specular = max(dot(toReflectedLight, -eyeToPosition), 0.0);
- specular = pow(specular, 20.0);
+ specular = pow(specular, 10.0);
+ specular *= texture2D(u_EarthSpec, v_Texcoord).r;
float gammaCorrect = 1.0/1.2; //gamma correct by 1/1.2
vec3 dayColor = texture2D(u_DayDiffuse, v_Texcoord).rgb;
vec3 nightColor = texture2D(u_Night, v_Texcoord).rgb;
+ vec3 cloudColor = texture2D(u_Cloud, v_Texcoord-vec2(u_time*0.05,0.0)).rgb;
+ float cloudAlpha = texture2D(u_CloudTrans, v_Texcoord-vec2(u_time*0.05,0.0)).r;
+
+ // dayColor += normalBumpWater*specular;
+
+ specular *= cloudAlpha;
+
//apply gamma correction to nighttime texture
nightColor = pow(nightColor,vec3(gammaCorrect));
- vec3 color = ((0.6 * diffuse) + (0.4 * specular)) * dayColor;
+ nightColor = mix( vec3(.2,.2,.3), nightColor, cloudAlpha);
+ dayColor = mix(cloudColor, dayColor, cloudAlpha);
+
+ vec3 color = mix(nightColor, ((0.6 * diffuse) + (0.4 * specular)) * dayColor, (diffuse+1.0)/2.0);
+
+ float rim = dot(v_Normal, v_Position)+1.0;
+
+ if (rim > 0.0){
+ color += vec3(rim/4.0, rim/2.0, rim/2.0);
+ }
+
+
gl_FragColor = vec4(color, 1.0);
}
@@ -109,6 +198,10 @@
bitangentEC.x, bitangentEC.y, bitangentEC.z,
normalEC.x, normalEC.y, normalEC.z);
}
+
+ float rand(vec2 co){
+ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+ }
diff --git a/part2/frag_globe.js b/part2/frag_globe.js
index 1d8a877..e067c57 100644
--- a/part2/frag_globe.js
+++ b/part2/frag_globe.js
@@ -55,6 +55,7 @@
var u_EarthSpecLocation;
var u_BumpLocation;
var u_timeLocation;
+ var u_waterLocation;
(function initializeShader() {
var vs = getShaderSource(document.getElementById("vs"));
@@ -75,6 +76,7 @@
u_EarthSpecLocation = gl.getUniformLocation(program,"u_EarthSpec");
u_BumpLocation = gl.getUniformLocation(program,"u_Bump");
u_timeLocation = gl.getUniformLocation(program,"u_time");
+ u_waterLocation = gl.getUniformLocation(program,"u_water");
u_CameraSpaceDirLightLocation = gl.getUniformLocation(program,"u_CameraSpaceDirLight");
gl.useProgram(program);
@@ -176,6 +178,7 @@
})();
var time = 0;
+ var water = 0;
var mouseLeftDown = false;
var mouseRightDown = false;
var lastMouseX = null;
@@ -287,8 +290,11 @@
gl.bindTexture(gl.TEXTURE_2D, specTex);
gl.uniform1i(u_EarthSpecLocation, 5);
gl.drawElements(gl.TRIANGLES, numberOfIndices, gl.UNSIGNED_SHORT,0);
+ gl.uniform1f(u_timeLocation, time);
+ gl.uniform1f(u_waterLocation, water);
time += 0.001;
+ water += 0.001;//*Math.Random();
window.requestAnimFrame(animate);
}
diff --git a/simplex_wave.png b/simplex_wave.png
new file mode 100644
index 0000000..4a0cbd2
Binary files /dev/null and b/simplex_wave.png differ
diff --git a/vert_wave.png b/vert_wave.png
new file mode 100644
index 0000000..bca56bd
Binary files /dev/null and b/vert_wave.png differ
diff --git a/wave_wave.png b/wave_wave.png
new file mode 100644
index 0000000..e917c4f
Binary files /dev/null and b/wave_wave.png differ