diff --git a/README.md b/README.md index 2d26873..5ed70d7 100644 --- a/README.md +++ b/README.md @@ -2,50 +2,14 @@ CIS565: Project 5: WebGL ------------------------------------------------------------------------------- Fall 2014 +![Completed globe, day side](resources/Cover.png) +![Completed globe, day side](resources/indicator.png) ------------------------------------------------------------------------------- -Due Monday 11/03/2014 -------------------------------------------------------------------------------- - -------------------------------------------------------------------------------- -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. +Playable WebGL demo: -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 Project5 root directory contains the following subdirectories: - -* js/ contains the javascript files, including external libraries, necessary. -* assets/ contains the textures that will be used in the second half of the - assignment. -* resources/ contains the screenshots found in this readme file. +http://cyborgyl.github.io/Project5-WebGL/ -------------------------------------------------------------------------------- -PART 1 REQUIREMENTS: -------------------------------------------------------------------------------- +video: http://youtu.be/qQ6FPbbUMQw In Part 1, you are given code for: @@ -57,66 +21,14 @@ You are required to implement the following: * A sin-wave based vertex shader: -![Example sin wave grid](resources/sinWaveGrid.png) +![part1](resources/sinwave.png) * One interesting vertex shader of your choice - -------------------------------------------------------------------------------- -PART 1 WALKTHROUGH: -------------------------------------------------------------------------------- -**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`. - - * Using dat.gui, you will add color pickers to modify the max and min colors - via GUI. You will do this by adding the proper uniforms to the fragment - shader, and using the addColor function from dat.GUI. - -* 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()`. - -**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. - +![part1](resources/gausswave.png) ------------------------------------------------------------------------------- PART 2 REQUIREMENTS: ------------------------------------------------------------------------------- -In Part 2, you are given code for: +In Part 2, given code: * Reading and loading textures * Rendering a sphere with textures mapped on @@ -127,7 +39,7 @@ In Part 2, you are given code for: * left-click and drag moves the camera around * right-click and drag moves the camera in and out -You are required to implement: +Features implemented: * Bump mapped terrain * Rim lighting to simulate atmosphere @@ -138,225 +50,18 @@ You are required to implement: 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. - -Some examples of what your completed globe renderer will look like: - -![Completed globe, day side](resources/globe_day.png) +* Dawn and twillight color blending +![Completed globe, day side](resources/indicator.png) Figure 0. Completed globe renderer, daylight side. - -![Completed globe, twilight](resources/globe_twilight.png) - +![Completed globe, twilight](resources/earth.png) Figure 1. Completed globe renderer, twilight border. - -![Completed globe, night side](resources/globe_night.png) - +![Completed globe, night side](resources/night.png) Figure 2. Completed globe renderer, night side. -------------------------------------------------------------------------------- -PART 2 WALKTHROUGH: -------------------------------------------------------------------------------- - -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. - -**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! - -![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. - -**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. - -![Globe with bump mapping](resources/globe_bumpmap.png) - -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/rim_effects/index.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. - -In this homework, we do not expect crazy performance evaluation in terms of -optimizations. However, it would be good to take performance benchmarks at -every step in this assignment to see how complicated fragment shaders affect the -overall speed. You can do this by using stats.js. - -------------------------------------------------------------------------------- -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 Harmony, - harmoli+cis565@seas.upenn.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. +#PERFORMANCE EVALUATION +-Always 60 fps on Desktop PC with GTX780, notebook with GT650M, or iphone 5s. +![performance](resources/fps.png) +#Third Party Code +-In drawing skybox, cube vectices and index matrix from http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_06 diff --git a/assets/GalaxyBk.png b/assets/GalaxyBk.png new file mode 100644 index 0000000..d50afb7 Binary files /dev/null and b/assets/GalaxyBk.png differ diff --git a/assets/GalaxyDn.png b/assets/GalaxyDn.png new file mode 100644 index 0000000..3c74bda Binary files /dev/null and b/assets/GalaxyDn.png differ diff --git a/assets/GalaxyFt.png b/assets/GalaxyFt.png new file mode 100644 index 0000000..6c3bc0f Binary files /dev/null and b/assets/GalaxyFt.png differ diff --git a/assets/GalaxyLf.png b/assets/GalaxyLf.png new file mode 100644 index 0000000..c80f06d Binary files /dev/null and b/assets/GalaxyLf.png differ diff --git a/assets/GalaxyRt.png b/assets/GalaxyRt.png new file mode 100644 index 0000000..4675f45 Binary files /dev/null and b/assets/GalaxyRt.png differ diff --git a/assets/GalaxyUp.png b/assets/GalaxyUp.png new file mode 100644 index 0000000..4a123df Binary files /dev/null and b/assets/GalaxyUp.png differ diff --git a/assets/normalmap.png b/assets/normalmap.png new file mode 100644 index 0000000..7104f43 Binary files /dev/null and b/assets/normalmap.png differ diff --git a/assets/wavemap18.png b/assets/wavemap18.png new file mode 100644 index 0000000..fc32ede Binary files /dev/null and b/assets/wavemap18.png differ diff --git a/frag_globe.html b/frag_globe.html index e074492..a929a62 100644 --- a/frag_globe.html +++ b/frag_globe.html @@ -1,4 +1,4 @@ - + Fragment Globe @@ -9,6 +9,35 @@
+
+

0

+ + + + @@ -61,6 +91,10 @@ //Bump map uniform sampler2D u_Bump; + //water wave + uniform sampler2D u_waterSpec; + uniform sampler2D u_waterBump; + uniform float u_time; uniform mat4 u_InvTrans; @@ -73,26 +107,82 @@ void main(void) { + // surface normal - normalized after rasterization 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); + //bump map + + + vec3 bumpCenter = (texture2D(u_Bump, v_Texcoord).rgb); + vec3 bumpRight = (texture2D(u_Bump, vec2(v_Texcoord.s + 1.0/1024.0, v_Texcoord.t)).rgb); + vec3 bumpTop = (texture2D(u_Bump, vec2(v_Texcoord.s, v_Texcoord.t + 1.0/512.0)).rgb); + + float center = length(bumpCenter); + float right = length(bumpRight); + float top = length(bumpTop); + vec3 bumpNormal = normalize(vec3(center - right, center - top, 0.2)).xyz; + bumpNormal = normalize(eastNorthUpToEyeCoordinates(v_positionMC, normal) * bumpNormal); + float specCoef = length(texture2D(u_EarthSpec, v_Texcoord).rgb); - vec3 toReflectedLight = reflect(-u_CameraSpaceDirLight, normal); + //water bump + vec2 wTexCoord0 = vec2(v_Texcoord.s + u_time * 0.01, v_Texcoord.t) * 20.0; + vec2 wTexCoord1 = vec2(v_Texcoord.s - u_time * 0.01, v_Texcoord.t) * 20.0; + vec3 waterNormal = normalize((2.0 * texture2D(u_waterBump, wTexCoord0).rgb - vec3(1.0) + 2.0 * texture2D(u_waterBump, wTexCoord1).rgb - vec3(1.0)) * 0.5 + normal * 0.5); + vec3 waterNormalEC = normalize(eastNorthUpToEyeCoordinates(v_positionMC, normal) * waterNormal); + + float waterBlendCoef = length(texture2D(u_waterSpec, vec2(v_Texcoord.s + u_time * 0.01, v_Texcoord.t) * 20.0).rgb) * specCoef; + + bumpNormal = normalize(mix(bumpNormal, waterNormalEC, specCoef)); + + float diffuse = clamp(dot(u_CameraSpaceDirLight, normal), 0.0, 1.0); + float bumpDiffuse = clamp(dot(u_CameraSpaceDirLight, bumpNormal), 0.0, 1.0); + // specular highlight + vec3 toReflectedLight = reflect(-u_CameraSpaceDirLight, bumpNormal); float specular = max(dot(toReflectedLight, -eyeToPosition), 0.0); specular = pow(specular, 20.0); + + specular *= specCoef; - float gammaCorrect = 1.0/1.2; //gamma correct by 1/1.2 + float gammaCorrect = 1.0/1.0; //gamma correct by 1/1.2 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; + float blendCoef = clamp(dot(u_CameraSpaceDirLight, normal),0.0, 1.0); + dayColor = ((0.6 * bumpDiffuse) + (0.4 * specular)) * dayColor; + + //dawn and dusk + float vdl = abs(dot(u_CameraSpaceDirLight, normal)); + float dawn = clamp( 0.1 + vdl, 0.0, 1.0); + + //draw clouds + float cloudTrans = clamp(length(texture2D(u_CloudTrans, vec2(v_Texcoord.s - u_time * 0.1, v_Texcoord.t)).rgb), 0.0,1.0); + vec3 cloudColor = texture2D(u_Cloud, vec2(v_Texcoord.s - u_time * 0.1, v_Texcoord.t)).rgb; + cloudColor = mix(vec3(255.0 / 256.0, 75.0/ 256.0, 10.0 / 256.0), cloudColor, clamp(dawn * 2.0 - 0.4, 0.0, 1.0)); + dayColor = mix(vec3(255.0 / 256.0, 75.0/ 256.0, 10.0 / 256.0), dayColor, clamp(dawn * 1.0 + 0.5, 0.0, 1.0)); + dayColor = mix(cloudColor, dayColor, cloudTrans); + nightColor = mix(vec3(0.0), nightColor, cloudTrans); + //rim color + float vdn = abs(dot(normal, -eyeToPosition)); + float rim = 1.0 - vdn; + rim = smoothstep(0.4, 1.0, rim); + vec3 rimColor = vec3(rim/5.0, rim/2.5, rim /1.5); + dayColor = mix(dayColor, rimColor, rim); + nightColor = mix(nightColor, rimColor * 0.2, rim); + //blend dayColor and nightColor + vec3 color = mix(nightColor, dayColor, blendCoef); + + //debug + //color = (waterNormalEC + vec3(1.0)) * 0.5; + //color = (bumpNormal + vec3(1.0)) /2.0; + //color = texture2D(u_waterSpec, v_Texcoord*10.0).rgb * specCoef; + //rim mixing + //color = mix(color, rimColor, rim); gl_FragColor = vec4(color, 1.0); + } mat3 eastNorthUpToEyeCoordinates(vec3 positionMC, vec3 normalEC) diff --git a/index.html b/index.html new file mode 100644 index 0000000..a929a62 --- /dev/null +++ b/index.html @@ -0,0 +1,209 @@ + + + +Fragment Globe + + + + + +
+ +
+

0

+ + + + + + + + + + + + + + + diff --git a/js/frag_globe.js b/js/frag_globe.js index f37830d..48a618c 100644 --- a/js/frag_globe.js +++ b/js/frag_globe.js @@ -10,6 +10,9 @@ return [x,y,z]; } + var FPS = 0; + var ticks = 0; + var lastFPS = 0; var NUM_WIDTH_PTS = 64; var NUM_HEIGHT_PTS = 64; @@ -55,12 +58,24 @@ var u_EarthSpecLocation; var u_BumpLocation; var u_timeLocation; - + var u_waterSpecLocation; + var u_waterBumpLocation; + + var u_skyboxLocation = new Array(); + //var u_skyboxInvTransLocation; + var u_skyboxModelLocation; + var u_skyboxViewLocation; + var u_skyboxPerspLocation; + var skyboxPosLocation; + + var program; + var skyboxProgram; (function initializeShader() { + //render the earth var vs = getShaderSource(document.getElementById("vs")); var fs = getShaderSource(document.getElementById("fs")); - var program = createProgram(gl, vs, fs, message); + program = createProgram(gl, vs, fs, message); positionLocation = gl.getAttribLocation(program, "Position"); normalLocation = gl.getAttribLocation(program, "Normal"); texCoordLocation = gl.getAttribLocation(program, "Texcoord"); @@ -76,8 +91,21 @@ u_BumpLocation = gl.getUniformLocation(program,"u_Bump"); u_timeLocation = gl.getUniformLocation(program,"u_time"); u_CameraSpaceDirLightLocation = gl.getUniformLocation(program,"u_CameraSpaceDirLight"); + u_waterSpecLocation = gl.getUniformLocation(program, "u_waterSpec"); + u_waterBumpLocation = gl.getUniformLocation(program, "u_waterBump"); + + //render skybox + vs = getShaderSource(document.getElementById("skyboxvs")); + fs = getShaderSource(document.getElementById("skyboxfs")); + + skyboxProgram = createProgram(gl, vs, fs, message); + u_skyboxLocation[0] = gl.getUniformLocation(skyboxProgram, "u_Skybox"); + skyboxPosLocation = gl.getAttribLocation(skyboxProgram, "Position"); + u_skyboxModelLocation = gl.getUniformLocation(skyboxProgram, "u_Model"); + u_skyboxViewLocation = gl.getUniformLocation(skyboxProgram, "u_View"); + u_skyboxPerspLocation = gl.getUniformLocation(skyboxProgram, "u_Persp"); + //u_skyboxInvTransLocation = gl.getUniformLocation(skyboxProgram, "u_InvTrans"); - gl.useProgram(program); })(); var dayTex = gl.createTexture(); @@ -85,7 +113,12 @@ var cloudTex = gl.createTexture(); var transTex = gl.createTexture(); var lightTex = gl.createTexture(); - var specTex = gl.createTexture(); + var specTex = gl.createTexture(); + var waterSpec = gl.createTexture(); + var waterBump = gl.createTexture(); + + var skyboxTex = gl.createTexture(); + var skyboxFaces = new Array(); function initLoadedTexture(texture){ gl.bindTexture(gl.TEXTURE_2D, texture); @@ -97,34 +130,111 @@ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.bindTexture(gl.TEXTURE_2D, null); } + //function initLoadedCubeMapTexture(texture, face, image) { + // gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); + // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.REPEAT); + // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.REPEAT); + // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + // gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + // gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); + // gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + // gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + // gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); + //} + // cube vectices and index matrix from http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_06 + var cubePositionBuffer; + var cubeIndexBuffer; + (function initailzeCube() { + cubePositionBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, cubePositionBuffer); + var vertices = [ + // Front face + -1.0, -1.0, 1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0, + + // Back face + -1.0, -1.0, -1.0, + -1.0, 1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, -1.0, -1.0, + + // Top face + -1.0, 1.0, -1.0, + -1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, -1.0, + + // Bottom face + -1.0, -1.0, -1.0, + 1.0, -1.0, -1.0, + 1.0, -1.0, 1.0, + -1.0, -1.0, 1.0, + + // Right face + 1.0, -1.0, -1.0, + 1.0, 1.0, -1.0, + 1.0, 1.0, 1.0, + 1.0, -1.0, 1.0, + + // Left face + -1.0, -1.0, -1.0, + -1.0, -1.0, 1.0, + -1.0, 1.0, 1.0, + -1.0, 1.0, -1.0 + ]; + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); + cubePositionBuffer.itemSize = 3; + cubePositionBuffer.numItems = 24; + + + cubeIndexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer); + var cubeVertexIndices = [ + 0, 1, 2, 0, 2, 3, // Front face + 4, 5, 6, 4, 6, 7, // Back face + 8, 9, 10, 8, 10, 11, // Top face + 12, 13, 14, 12, 14, 15, // Bottom face + 16, 17, 18, 16, 18, 19, // Right face + 20, 21, 22, 20, 22, 23 // Left face + ]; + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW); + cubeIndexBuffer.itemSize = 1; + cubeIndexBuffer.numItems = 36; + } + )(); var numberOfIndices; - + var positionsName; + var normalsName; + var texCoordsName; + var indicesName; (function initializeSphere() { function uploadMesh(positions, texCoords, indices) { // Positions - var positionsName = gl.createBuffer(); + positionsName = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionsName); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(positionLocation); // Normals - var normalsName = gl.createBuffer(); + normalsName = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, normalsName); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(normalLocation); // TextureCoords - var texCoordsName = gl.createBuffer(); + texCoordsName = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordsName); gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW); gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(texCoordLocation); // Indices - var indicesName = gl.createBuffer(); + indicesName = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesName); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); } @@ -237,10 +347,9 @@ function animate() { /////////////////////////////////////////////////////////////////////////// // Update - var model = mat4.create(); mat4.identity(model); - mat4.rotate(model, 23.4/180*Math.PI, [0.0, 0.0, 1.0]); + mat4.rotate(model, 23.4 / 180 * Math.PI, [0.0, 0.0, 1.0]); mat4.rotate(model, Math.PI, [1.0, 0.0, 0.0]); mat4.rotate(model, -time, [0.0, 1.0, 0.0]); var mv = mat4.create(); @@ -254,18 +363,69 @@ var lightdest = vec4.create(); vec3.normalize(lightdir); mat4.multiplyVec4(view, [lightdir[0], lightdir[1], lightdir[2], 0.0], lightdest); - lightdir = vec3.createFrom(lightdest[0],lightdest[1],lightdest[2]); + lightdir = vec3.createFrom(lightdest[0], lightdest[1], lightdest[2]); vec3.normalize(lightdir); + //Render skybox + //var skyModel = mat4.create(); + //mat4.identity(skyModel); + //var skyMV = mat4.create(); + //mat4.multiply(view, skyModel, skyMV); + + //mat4.scale(skyModel, vec3.create([50.0, 50.0, 50.0])); + //mat4.multiply(view, skyModel, skyMV); + + //invTrans = mat4.create(); + //mat4.inverse(mv, invTrans); + //mat4.transpose(invTrans); + + //gl.useProgram(skyboxProgram); + //gl.enableVertexAttribArray(skyboxPosLocation); + + + //gl.bindBuffer(gl.ARRAY_BUFFER, cubePositionBuffer); + //gl.vertexAttribPointer(skyboxPosLocation, cubePositionBuffer.itemSize, gl.FLOAT, false, 0, 0); + + //gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer); + + //gl.uniformMatrix4fv(u_skyboxModelLocation, false, skyModel); + //gl.uniformMatrix4fv(u_skyboxViewLocation, false, view); + //gl.uniformMatrix4fv(u_skyboxPerspLocation, false, persp); + ////gl.uniformMatrix4fv(u_skyboxInvTransLocation, false, invTrans); + + //gl.activeTexture(gl.TEXTURE0); + //gl.bindTexture(gl.TEXTURE_CUBE_MAP, skyboxTex); + //gl.uniform1i(u_skyboxLocation[0], 0); + + //gl.drawElements(gl.TRIANGLES, cubeIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0); + + //gl.disableVertexAttribArray(skyboxPosLocation); + /////////////////////////////////////////////////////////////////////////// - // Render gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + /////////////////////////////////// + // Render the earth + gl.useProgram(program); + gl.enableVertexAttribArray(positionLocation); + gl.enableVertexAttribArray(normalLocation); + gl.enableVertexAttribArray(texCoordLocation); + + gl.bindBuffer(gl.ARRAY_BUFFER, positionsName); + gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ARRAY_BUFFER, normalsName); + gl.vertexAttribPointer(normalLocation, 3, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ARRAY_BUFFER, texCoordsName); + gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesName); gl.uniformMatrix4fv(u_ModelLocation, false, model); gl.uniformMatrix4fv(u_ViewLocation, false, view); gl.uniformMatrix4fv(u_PerspLocation, false, persp); gl.uniformMatrix4fv(u_InvTransLocation, false, invTrans); - + gl.uniform3fv(u_CameraSpaceDirLightLocation, lightdir); gl.activeTexture(gl.TEXTURE0); @@ -286,10 +446,61 @@ gl.activeTexture(gl.TEXTURE5); gl.bindTexture(gl.TEXTURE_2D, specTex); gl.uniform1i(u_EarthSpecLocation, 5); + gl.activeTexture(gl.TEXTURE6); + gl.bindTexture(gl.TEXTURE_2D, waterSpec); + gl.uniform1i(u_waterSpecLocation, 6) + gl.activeTexture(gl.TEXTURE7); + gl.bindTexture(gl.TEXTURE_2D, waterBump); + gl.uniform1i(u_waterBumpLocation, 7); + gl.drawElements(gl.TRIANGLES, numberOfIndices, gl.UNSIGNED_SHORT,0); + gl.disableVertexAttribArray(positionLocation); + gl.disableVertexAttribArray(normalLocation); + gl.disableVertexAttribArray(texCoordLocation); + //Render skybox + //scale the box first + mat4.scale(model, vec3.create([50.0, 50.0, 50.0])); + mat4.multiply(view, model, mv); + + invTrans = mat4.create(); + mat4.inverse(mv, invTrans); + mat4.transpose(invTrans); + + gl.useProgram(skyboxProgram); + gl.enableVertexAttribArray(skyboxPosLocation); + + + gl.bindBuffer(gl.ARRAY_BUFFER, cubePositionBuffer); + gl.vertexAttribPointer(skyboxPosLocation, cubePositionBuffer.itemSize, gl.FLOAT, false, 0, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer); + + gl.uniformMatrix4fv(u_skyboxModelLocation, false, model); + gl.uniformMatrix4fv(u_skyboxViewLocation, false, view); + gl.uniformMatrix4fv(u_skyboxPerspLocation, false, persp); + //gl.uniformMatrix4fv(u_skyInvTransLocation, false, invTrans); + + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, skyboxTex); + gl.uniform1i(u_skyboxLocation[0], 0); + + gl.drawElements(gl.TRIANGLES, cubeIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0); + + gl.disableVertexAttribArray(skyboxPosLocation); + + gl.useProgram(program); time += 0.001; + gl.uniform1f(u_timeLocation, time); window.requestAnimFrame(animate); + var now = Date.now(); + if (now - lastFPS >= 1000) { + lastFPS = now; + FPS = ticks; + ticks = 0; + document.getElementById("FPS").innerHTML = 'FPS=' + FPS; + } + ticks++; } var textureCount = 0; @@ -313,4 +524,37 @@ initializeTexture(transTex, "assets/earthtrans1024.png"); initializeTexture(lightTex, "assets/earthlight1024.png"); initializeTexture(specTex, "assets/earthspec1024.png"); + initializeTexture(waterBump, "assets/normalmap.png"); + initializeTexture(waterSpec, "assets/wavemap18.png"); + + function initCubeTextrue(texture, faces) { + for (var i = 0; i < faces.length; i++) { + var face = faces[i][0]; + var image = new Image(); + image.onload = function (texture, face, image) { + return function () { + //connect the cube map and return as one texture + gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); + gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.REPEAT); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); + } + }(texture, face, image); + image.src = faces[i][1]; + } + } + + skyboxFaces[0] = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, "assets/GalaxyLf.png"]; + skyboxFaces[1] = [gl.TEXTURE_CUBE_MAP_NEGATIVE_X, "assets/GalaxyRt.png"]; + skyboxFaces[2] = [gl.TEXTURE_CUBE_MAP_POSITIVE_Y, "assets/GalaxyUp.png"]; + skyboxFaces[3] = [gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, "assets/GalaxyDn.png"]; + skyboxFaces[4] = [gl.TEXTURE_CUBE_MAP_POSITIVE_Z, "assets/GalaxyFt.png"]; + skyboxFaces[5] = [gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, "assets/GalaxyBk.png"]; + + initCubeTextrue(skyboxTex, skyboxFaces); + }()); diff --git a/resources/Cover.png b/resources/Cover.png new file mode 100644 index 0000000..19e2c12 Binary files /dev/null and b/resources/Cover.png differ diff --git a/resources/dawn.png b/resources/dawn.png new file mode 100644 index 0000000..91f34a4 Binary files /dev/null and b/resources/dawn.png differ diff --git a/resources/earth.png b/resources/earth.png new file mode 100644 index 0000000..e474cd8 Binary files /dev/null and b/resources/earth.png differ diff --git a/resources/emptyGrid.png b/resources/emptyGrid.png deleted file mode 100644 index 2ee870f..0000000 Binary files a/resources/emptyGrid.png and /dev/null differ diff --git a/resources/fps.png b/resources/fps.png new file mode 100644 index 0000000..c61b04a Binary files /dev/null and b/resources/fps.png differ diff --git a/resources/gausswave.png b/resources/gausswave.png new file mode 100644 index 0000000..f221203 Binary files /dev/null and b/resources/gausswave.png differ diff --git a/resources/globe_bumpmap.png b/resources/globe_bumpmap.png deleted file mode 100644 index fa91a9f..0000000 Binary files a/resources/globe_bumpmap.png and /dev/null differ diff --git a/resources/globe_day.png b/resources/globe_day.png deleted file mode 100644 index e3cbf1f..0000000 Binary files a/resources/globe_day.png and /dev/null differ diff --git a/resources/globe_daycloud.png b/resources/globe_daycloud.png deleted file mode 100644 index ff00096..0000000 Binary files a/resources/globe_daycloud.png and /dev/null differ diff --git a/resources/globe_initial.png b/resources/globe_initial.png deleted file mode 100644 index 1e3bde5..0000000 Binary files a/resources/globe_initial.png and /dev/null differ diff --git a/resources/globe_night.png b/resources/globe_night.png deleted file mode 100644 index 6401768..0000000 Binary files a/resources/globe_night.png and /dev/null differ diff --git a/resources/globe_nightcloud.png b/resources/globe_nightcloud.png deleted file mode 100644 index 781aec0..0000000 Binary files a/resources/globe_nightcloud.png and /dev/null differ diff --git a/resources/globe_nospecmap.png b/resources/globe_nospecmap.png deleted file mode 100644 index c370735..0000000 Binary files a/resources/globe_nospecmap.png and /dev/null differ diff --git a/resources/globe_specmap.png b/resources/globe_specmap.png deleted file mode 100644 index 7ff01a5..0000000 Binary files a/resources/globe_specmap.png and /dev/null differ diff --git a/resources/globe_twilight.png b/resources/globe_twilight.png deleted file mode 100644 index ac5ea5c..0000000 Binary files a/resources/globe_twilight.png and /dev/null differ diff --git a/resources/indicator.png b/resources/indicator.png new file mode 100644 index 0000000..7389307 Binary files /dev/null and b/resources/indicator.png differ diff --git a/resources/night.png b/resources/night.png new file mode 100644 index 0000000..fa2b636 Binary files /dev/null and b/resources/night.png differ diff --git a/resources/oceanWave.png b/resources/oceanWave.png deleted file mode 100644 index 73b65d5..0000000 Binary files a/resources/oceanWave.png and /dev/null differ diff --git a/resources/sinWaveGrid.png b/resources/sinWaveGrid.png deleted file mode 100644 index 733f8d8..0000000 Binary files a/resources/sinWaveGrid.png and /dev/null differ diff --git a/resources/sinwave.png b/resources/sinwave.png new file mode 100644 index 0000000..f7fc3a7 Binary files /dev/null and b/resources/sinwave.png differ diff --git a/vert_wave - New.html b/vert_wave - New.html new file mode 100644 index 0000000..d90d0e0 --- /dev/null +++ b/vert_wave - New.html @@ -0,0 +1,244 @@ + + + +Vertex Wave + + + + + +
+ + + + + + + + + + + + + + diff --git a/vert_wave.html b/vert_wave.html index 5c7495b..9a7da2d 100644 --- a/vert_wave.html +++ b/vert_wave.html @@ -1,4 +1,4 @@ - + Vertex Wave @@ -15,14 +15,21 @@ @@ -44,9 +52,11 @@ // Globals var positionLocation = 0; var heightLocation = 1; + var timeLocation = 2; var u_modelViewPerspectiveLocation; - var u_color; - + var uColor0Loaction = 0; + var uColor1Location = 0; + var time = 0; var heights; var numberOfIndices; @@ -61,15 +71,26 @@ var message; var canvas; var context; + var FizzyText = function () { + + this.color0 = [180.0, 80.0, 30.0, 255.0]; // CSS string + this.color1 = [0.0, 128.0, 255.0, 255.0]; // RGB array + + + // Define render logic ... + + }; + var guiText = new FizzyText(); var persp = mat4.create(); var view = mat4.create(); - + // Function called when the window is loaded window.onload = function() { - // Add GUI component + // Add GUI component var gui = new dat.GUI(); - + gui.addColor(guiText, 'color0'); + gui.addColor(guiText, 'color1'); init(); animate(); @@ -99,7 +120,9 @@ function animate(){ - // Update + // Update + time += 0.02; + var model = mat4.create(); mat4.identity(model); mat4.translate(model, [-0.5, -0.5, 0.0]); @@ -108,9 +131,13 @@ var mvp = mat4.create(); mat4.multiply(persp, mv, mvp); + // Render context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT); - + + context.uniform4fv(uColor0Loaction, guiText.color0); + context.uniform4fv(uColor1Location, guiText.color1); + context.uniform1f(timeLocation, time); context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp); context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0); @@ -126,7 +153,9 @@ context.bindAttribLocation(program, positionLocation, "position"); u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective"); u_colorLocation = context.getUniformLocation(program, "u_color"); - + timeLocation = context.getUniformLocation(program, "u_time"); + uColor0Loaction = context.getUniformLocation(program, "u_color0"); + uColor1Location = context.getUniformLocation(program, "u_color1"); context.useProgram(program); }