From e285fdbdd09c870f2889bc76cc734b0ebaf7b3c5 Mon Sep 17 00:00:00 2001 From: wulinjiansheng Date: Thu, 30 Oct 2014 16:56:57 -0400 Subject: [PATCH 1/7] Finally can change color Finally can change color --- Links.txt | 4 ++++ vert_wave.html | 65 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 Links.txt diff --git a/Links.txt b/Links.txt new file mode 100644 index 0000000..ead50cc --- /dev/null +++ b/Links.txt @@ -0,0 +1,4 @@ +http://msdn.microsoft.com/en-us/library/ie/dn302449(v=vs.85).aspx +http://workshop.chromeexperiments.com/examples/gui/#4--Color-Controllers +http://jsfiddle.net/mortennobel/URvtx/ +http://bl.ocks.org/g-k/5847236 \ No newline at end of file diff --git a/vert_wave.html b/vert_wave.html index 5c7495b..3417d2b 100644 --- a/vert_wave.html +++ b/vert_wave.html @@ -18,11 +18,21 @@ uniform mat4 u_modelViewPerspective; + uniform float u_time; + uniform vec3 u_mincolor; + uniform vec3 u_maxcolor; + + varying vec3 fs_color; //input + void main(void) { // NOTE : according to the WebGL standard, 0.0f is not accepted - 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; + float alpha = (height+1.0)/2.0; + fs_color = mix(u_maxcolor/255.0, u_mincolor/255.0,alpha ); // NOTE : gl_Position is always a vec4 gl_Position = u_modelViewPerspective * vec4(vec3(position, height), 1.0); } @@ -32,11 +42,11 @@ precision mediump float; uniform vec4 u_color; - + varying vec3 fs_color; //output void main(void) { // NOTE : gl_FragColor is always a vec4 - gl_FragColor = u_color; + gl_FragColor = vec4(fs_color,1.0); } @@ -64,15 +74,27 @@ var persp = mat4.create(); var view = mat4.create(); - - // Function called when the window is loaded - window.onload = function() { - // Add GUI component - var gui = new dat.GUI(); - init(); + //Added + var time = 0.0; + var u_timeLocation; + var u_mincolorLocation; + var u_maxcolorLocation; - animate(); + var Colors = { + mincolor : [0, 204, 255], + maxcolor : [255, 51, 0] + }; + + // Function called when the window is loaded + window.onload = function () { + // Add GUI component + var gui = new dat.GUI(); + + gui.addColor(Colors, 'mincolor'); + gui.addColor(Colors, 'maxcolor'); + init(); + animate(); }; function init() { @@ -94,7 +116,7 @@ mat4.lookAt(eye, center, up, view); initializeShader(); - initializeGrid(); + initializeGrid(); } @@ -108,11 +130,23 @@ var mvp = mat4.create(); mat4.multiply(persp, mv, mvp); + //Added + time = time + 0.02; + if (time == 3.14159 * 100.0) + time = 0.0; + + // Render context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT); - context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp); - context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0); + context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp); + context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT, 0); + + //Added + context.uniform1f(u_timeLocation, time); + + context.uniform3f(u_mincolorLocation, Colors.mincolor[0], Colors.mincolor[1], Colors.mincolor[2]); + context.uniform3f(u_maxcolorLocation, Colors.maxcolor[0], Colors.maxcolor[1], Colors.maxcolor[2]); window.requestAnimFrame(animate); } @@ -127,6 +161,11 @@ u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective"); u_colorLocation = context.getUniformLocation(program, "u_color"); + //Added + u_timeLocation = context.getUniformLocation(program, "u_time"); + u_mincolorLocation = context.getUniformLocation(program, "u_mincolor"); + u_maxcolorLocation = context.getUniformLocation(program, "u_maxcolor"); + context.useProgram(program); } From 753df9b0df66707042448bc6972059a478a790d4 Mon Sep 17 00:00:00 2001 From: wulinjiansheng Date: Fri, 31 Oct 2014 17:24:09 -0400 Subject: [PATCH 2/7] Custom vertex shader finished:ripple Custom vertex shader finished:ripple --- vert_wave_custom.html | 288 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 vert_wave_custom.html diff --git a/vert_wave_custom.html b/vert_wave_custom.html new file mode 100644 index 0000000..4eb5ecc --- /dev/null +++ b/vert_wave_custom.html @@ -0,0 +1,288 @@ + + + + Ripple + + + + + +
+ + + + + + + + + + + + + + From a77a861d954601724e6167bd646141a1c06eb5cb Mon Sep 17 00:00:00 2001 From: wulinjiansheng Date: Fri, 31 Oct 2014 21:41:35 -0400 Subject: [PATCH 3/7] Finish Part 2 basics Finish Part 2 basics --- Links.txt | 4 +- frag_globe.html | 64 ++++++++++++++++++++++++-- js/frag_globe.js | 104 ++++++++++++++++++++---------------------- vert_wave.html | 2 +- vert_wave_custom.html | 6 +-- 5 files changed, 117 insertions(+), 63 deletions(-) diff --git a/Links.txt b/Links.txt index ead50cc..8d88b66 100644 --- a/Links.txt +++ b/Links.txt @@ -1,4 +1,6 @@ http://msdn.microsoft.com/en-us/library/ie/dn302449(v=vs.85).aspx http://workshop.chromeexperiments.com/examples/gui/#4--Color-Controllers http://jsfiddle.net/mortennobel/URvtx/ -http://bl.ocks.org/g-k/5847236 \ No newline at end of file +http://bl.ocks.org/g-k/5847236 +http://jayconrod.com/posts/34/water-simulation-in-glsl +https://glsleffects.codeplex.com/wikipage?title=Ripple \ No newline at end of file diff --git a/frag_globe.html b/frag_globe.html index e074492..c72c0b2 100644 --- a/frag_globe.html +++ b/frag_globe.html @@ -73,8 +73,22 @@ void main(void) { - // surface normal - normalized after rasterization - vec3 normal = normalize(v_Normal); + + float center = texture2D(u_Bump, v_Texcoord).r; + float r = clamp((v_Texcoord.s*1024.0 + 1.0)/1024.0, 0.0, 1.0); + if(v_Texcoord.s*1024.0 + 1.0>1024.0) + r = 1.0/1024.0; + float right = texture2D(u_Bump, vec2(r,v_Texcoord.t)).r; + float u = clamp((v_Texcoord.t*512.0 + 1.0)/512.0, 0.0, 1.0); + if(v_Texcoord.t*512.0 + 1.0>512.0) + u = 1.0/512.0; + + float above = texture2D(u_Bump, vec2(v_Texcoord.s,u)).r; + + vec3 normal = normalize(vec3(center - right, center - above, 0.2)); + normal = eastNorthUpToEyeCoordinates(v_Position,v_Normal) * normal; + normal = normalize(normal); + // normalized eye-to-position vector in camera coordinates vec3 eyeToPosition = normalize(v_Position); @@ -91,8 +105,50 @@ //apply gamma correction to nighttime texture nightColor = pow(nightColor,vec3(gammaCorrect)); - vec3 color = ((0.6 * diffuse) + (0.4 * specular)) * dayColor; - gl_FragColor = vec4(color, 1.0); + + + //Specular Map + float EarthSpec = texture2D(u_EarthSpec, v_Texcoord).r; //0 for land,1 for ocean + float diffpart = 0.6,specpart = 0.4; + + if(EarthSpec<0.1) + { + specpart = 0.0; + specular = 0.0; + } + + vec3 color; + vec3 d_color = ((diffpart * diffuse) + (specpart * specular)) * dayColor; + vec3 n_color = nightColor; + + + //Clouds + vec3 cloudsColor = texture2D(u_Cloud,vec2(v_Texcoord.s - 0.05 * u_time,v_Texcoord.t)).rgb; + float cloudMix = texture2D(u_CloudTrans,vec2(v_Texcoord.s - 0.05 * u_time,v_Texcoord.t)).r; + d_color = mix(cloudsColor,d_color,cloudMix); + n_color = mix(vec3(0.0,0.0,0.0),n_color,cloudMix); + + //Night Lights + float rperiod = 0.2; //transition from day to night + float diffjudge = dot(u_CameraSpaceDirLight, normal); + if(diffjudge >= rperiod) + color = d_color; + else if(diffjudge <= -rperiod) + color = n_color; + else + { + float alpha = (diffjudge + rperiod)/(2.0*rperiod); + color = mix(n_color,d_color,alpha); + } + + //Rim Lighting + float rim = dot(v_Normal,v_Position) + 1.0; + vec3 rimcolor = vec3(0.0,0.0,0.0); + if(rim>0.0) + rimcolor = vec3(rim/4.0, rim/2.0, rim/2.0); + + + gl_FragColor = vec4(color + rimcolor, 1.0); } mat3 eastNorthUpToEyeCoordinates(vec3 positionMC, vec3 normalEC) diff --git a/js/frag_globe.js b/js/frag_globe.js index f37830d..96a2be6 100644 --- a/js/frag_globe.js +++ b/js/frag_globe.js @@ -1,14 +1,14 @@ -(function() { +(function () { "use strict"; /*global window,document,Float32Array,Uint16Array,mat4,vec3,snoise*/ /*global getShaderSource,createWebGLContext,createProgram*/ - function sphericalToCartesian( r, a, e ) { + function sphericalToCartesian(r, a, e) { var x = r * Math.cos(e) * Math.cos(a); var y = r * Math.sin(e); var z = r * Math.cos(e) * Math.sin(a); - return [x,y,z]; + return [x, y, z]; } var NUM_WIDTH_PTS = 64; @@ -28,7 +28,7 @@ gl.enable(gl.DEPTH_TEST); var persp = mat4.create(); - mat4.perspective(45.0, canvas.width/canvas.height, 0.1, 100.0, persp); + mat4.perspective(45.0, canvas.width / canvas.height, 0.1, 100.0, persp); var radius = 5.0; var azimuth = Math.PI; @@ -64,30 +64,30 @@ positionLocation = gl.getAttribLocation(program, "Position"); normalLocation = gl.getAttribLocation(program, "Normal"); texCoordLocation = gl.getAttribLocation(program, "Texcoord"); - u_ModelLocation = gl.getUniformLocation(program,"u_Model"); - u_ViewLocation = gl.getUniformLocation(program,"u_View"); - u_PerspLocation = gl.getUniformLocation(program,"u_Persp"); - u_InvTransLocation = gl.getUniformLocation(program,"u_InvTrans"); - u_DayDiffuseLocation = gl.getUniformLocation(program,"u_DayDiffuse"); - u_NightLocation = gl.getUniformLocation(program,"u_Night"); - u_CloudLocation = gl.getUniformLocation(program,"u_Cloud"); - u_CloudTransLocation = gl.getUniformLocation(program,"u_CloudTrans"); - u_EarthSpecLocation = gl.getUniformLocation(program,"u_EarthSpec"); - u_BumpLocation = gl.getUniformLocation(program,"u_Bump"); - u_timeLocation = gl.getUniformLocation(program,"u_time"); - u_CameraSpaceDirLightLocation = gl.getUniformLocation(program,"u_CameraSpaceDirLight"); + u_ModelLocation = gl.getUniformLocation(program, "u_Model"); + u_ViewLocation = gl.getUniformLocation(program, "u_View"); + u_PerspLocation = gl.getUniformLocation(program, "u_Persp"); + u_InvTransLocation = gl.getUniformLocation(program, "u_InvTrans"); + u_DayDiffuseLocation = gl.getUniformLocation(program, "u_DayDiffuse"); + u_NightLocation = gl.getUniformLocation(program, "u_Night"); + u_CloudLocation = gl.getUniformLocation(program, "u_Cloud"); + u_CloudTransLocation = gl.getUniformLocation(program, "u_CloudTrans"); + u_EarthSpecLocation = gl.getUniformLocation(program, "u_EarthSpec"); + u_BumpLocation = gl.getUniformLocation(program, "u_Bump"); + u_timeLocation = gl.getUniformLocation(program, "u_time"); + u_CameraSpaceDirLightLocation = gl.getUniformLocation(program, "u_CameraSpaceDirLight"); gl.useProgram(program); })(); - var dayTex = gl.createTexture(); - var bumpTex = gl.createTexture(); + var dayTex = gl.createTexture(); + var bumpTex = gl.createTexture(); var cloudTex = gl.createTexture(); var transTex = gl.createTexture(); var lightTex = gl.createTexture(); - var specTex = gl.createTexture(); + var specTex = gl.createTexture(); - function initLoadedTexture(texture){ + function initLoadedTexture(texture) { gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image); @@ -108,14 +108,14 @@ 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(); 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(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordsName); @@ -143,31 +143,27 @@ var indicesIndex = 0; var length; - for( var j = 0; j < NUM_HEIGHT_PTS; ++j ) - { + for (var j = 0; j < NUM_HEIGHT_PTS; ++j) { var inclination = Math.PI * (j / HEIGHT_DIVISIONS); - for( var i = 0; i < NUM_WIDTH_PTS; ++i ) - { + for (var i = 0; i < NUM_WIDTH_PTS; ++i) { var azimuth = 2 * Math.PI * (i / WIDTH_DIVISIONS); - positions[positionsIndex++] = Math.sin(inclination)*Math.cos(azimuth); + positions[positionsIndex++] = Math.sin(inclination) * Math.cos(azimuth); positions[positionsIndex++] = Math.cos(inclination); - positions[positionsIndex++] = Math.sin(inclination)*Math.sin(azimuth); + positions[positionsIndex++] = Math.sin(inclination) * Math.sin(azimuth); texCoords[texCoordsIndex++] = i / WIDTH_DIVISIONS; texCoords[texCoordsIndex++] = j / HEIGHT_DIVISIONS; - } + } } - for( var j = 0; j < HEIGHT_DIVISIONS; ++j ) - { - var index = j*NUM_WIDTH_PTS; - for( var i = 0; i < WIDTH_DIVISIONS; ++i ) - { - indices[indicesIndex++] = index + i; - indices[indicesIndex++] = index + i+1; - indices[indicesIndex++] = index + i+NUM_WIDTH_PTS; - indices[indicesIndex++] = index + i+NUM_WIDTH_PTS; - indices[indicesIndex++] = index + i+1; - indices[indicesIndex++] = index + i+NUM_WIDTH_PTS+1; + for (var j = 0; j < HEIGHT_DIVISIONS; ++j) { + var index = j * NUM_WIDTH_PTS; + for (var i = 0; i < WIDTH_DIVISIONS; ++i) { + indices[indicesIndex++] = index + i; + indices[indicesIndex++] = index + i + 1; + indices[indicesIndex++] = index + i + NUM_WIDTH_PTS; + indices[indicesIndex++] = index + i + NUM_WIDTH_PTS; + indices[indicesIndex++] = index + i + 1; + indices[indicesIndex++] = index + i + NUM_WIDTH_PTS + 1; } } @@ -182,7 +178,7 @@ var lastMouseY = null; function handleMouseDown(event) { - if( event.button == 2 ) { + if (event.button == 2) { mouseLeftDown = false; mouseRightDown = true; } @@ -208,15 +204,13 @@ var deltaX = newX - lastMouseX; var deltaY = newY - lastMouseY; - - if( mouseLeftDown ) - { + + if (mouseLeftDown) { azimuth += 0.01 * deltaX; elevation += 0.01 * deltaY; - elevation = Math.min(Math.max(elevation, -Math.PI/2+0.001), Math.PI/2-0.001); + elevation = Math.min(Math.max(elevation, -Math.PI / 2 + 0.001), Math.PI / 2 - 0.001); } - else - { + else { radius += 0.01 * deltaY; radius = Math.min(Math.max(radius, 2.0), 10.0); } @@ -229,7 +223,7 @@ } canvas.onmousedown = handleMouseDown; - canvas.oncontextmenu = function(ev) {return false;}; + canvas.oncontextmenu = function (ev) { return false; }; document.onmouseup = handleMouseUp; document.onmousemove = handleMouseMove; @@ -240,7 +234,7 @@ 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,7 +248,7 @@ 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); /////////////////////////////////////////////////////////////////////////// @@ -286,17 +280,19 @@ gl.activeTexture(gl.TEXTURE5); gl.bindTexture(gl.TEXTURE_2D, specTex); gl.uniform1i(u_EarthSpecLocation, 5); - gl.drawElements(gl.TRIANGLES, numberOfIndices, gl.UNSIGNED_SHORT,0); + gl.drawElements(gl.TRIANGLES, numberOfIndices, gl.UNSIGNED_SHORT, 0); + gl.uniform1f(u_timeLocation, time); + time += 0.001; window.requestAnimFrame(animate); } var textureCount = 0; - + function initializeTexture(texture, src) { texture.image = new Image(); - texture.image.onload = function() { + texture.image.onload = function () { initLoadedTexture(texture); // Animate once textures load. @@ -313,4 +309,4 @@ initializeTexture(transTex, "assets/earthtrans1024.png"); initializeTexture(lightTex, "assets/earthlight1024.png"); initializeTexture(specTex, "assets/earthspec1024.png"); -}()); +} ()); diff --git a/vert_wave.html b/vert_wave.html index 3417d2b..b895111 100644 --- a/vert_wave.html +++ b/vert_wave.html @@ -32,7 +32,7 @@ float height = s_contrib * t_contrib; float alpha = (height+1.0)/2.0; - fs_color = mix(u_maxcolor/255.0, u_mincolor/255.0,alpha ); + fs_color = mix(u_mincolor/255.0, u_maxcolor/255.0,alpha ); // NOTE : gl_Position is always a vec4 gl_Position = u_modelViewPerspective * vec4(vec3(position, height), 1.0); } diff --git a/vert_wave_custom.html b/vert_wave_custom.html index 4eb5ecc..81eede5 100644 --- a/vert_wave_custom.html +++ b/vert_wave_custom.html @@ -41,7 +41,7 @@ float height = Amplitude*sin(dist/(Wavelength/10.0) + u_time)*pow(Attenuation,dist); float alpha = (height+Amplitude)/Amplitude; - fs_color = mix(u_maxcolor/255.0, u_mincolor/255.0,alpha ); + fs_color = mix(u_mincolor/255.0, u_maxcolor/255.0,alpha ); // NOTE : gl_Position is always a vec4 gl_Position = u_modelViewPerspective * vec4(vec3(position, height), 1.0); } @@ -96,8 +96,8 @@ var CenterPointyLocation; var Datas = { - mincolor: [0, 204, 255], - maxcolor: [255, 51, 0], + mincolor: [255, 51, 0], + maxcolor: [0, 204, 255], Amplitude: 0.2, Attenuation: 0.1, Wavelength: 0.3, From 774be7a1388e3ce9d2fafee98acff1c50d8997c4 Mon Sep 17 00:00:00 2001 From: wulinjiansheng Date: Sun, 2 Nov 2014 16:50:32 -0500 Subject: [PATCH 4/7] Add two extras Add two extras --- Links.txt | 5 +- Pics/All Effects.bmp | Bin 0 -> 3232054 bytes Pics/HeightMap Shader.bmp | Bin 0 -> 889074 bytes Pics/Ripple.bmp | Bin 0 -> 3235254 bytes Pics/Vertex Wave.bmp | Bin 0 -> 3244854 bytes Pics/Water.bmp | Bin 0 -> 504666 bytes frag_globe.html | 390 +++++++++++++++++++++++--------------- js/frag_globe.js | 67 +++++++ js/lib/Stats.js | 149 +++++++++++++++ js/lib/stats.min.js | 6 + 10 files changed, 465 insertions(+), 152 deletions(-) create mode 100644 Pics/All Effects.bmp create mode 100644 Pics/HeightMap Shader.bmp create mode 100644 Pics/Ripple.bmp create mode 100644 Pics/Vertex Wave.bmp create mode 100644 Pics/Water.bmp create mode 100644 js/lib/Stats.js create mode 100644 js/lib/stats.min.js diff --git a/Links.txt b/Links.txt index 8d88b66..909f324 100644 --- a/Links.txt +++ b/Links.txt @@ -3,4 +3,7 @@ http://workshop.chromeexperiments.com/examples/gui/#4--Color-Controllers http://jsfiddle.net/mortennobel/URvtx/ http://bl.ocks.org/g-k/5847236 http://jayconrod.com/posts/34/water-simulation-in-glsl -https://glsleffects.codeplex.com/wikipage?title=Ripple \ No newline at end of file +https://glsleffects.codeplex.com/wikipage?title=Ripple +http://www.dreamincode.net/forums/topic/66480-perlin-noise/ +https://github.com/mrdoob/stats.js +http://gamedev.stackexchange.com/questions/60313/implementing-a-skybox-with-glsl-version-330 \ No newline at end of file diff --git a/Pics/All Effects.bmp b/Pics/All Effects.bmp new file mode 100644 index 0000000000000000000000000000000000000000..b769eec74ac7ca6082b8eff521a931d580fea804 GIT binary patch literal 3232054 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