In computer graphic 2 we were supposed to create a earth seasons shader. Here is the one I did for android:
Simple vertex shader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | precision mediump float; // uniforms uniform mat4 u_ModelViewMatrix; uniform mat4 u_WorldView; uniform mat4 u_WorldViewProjection; uniform vec3 u_LightPosition; // in attribute vec3 in_Position; attribute vec3 in_Normal; attribute vec2 in_TexCoords; // out varying vec3 v_Position; varying vec3 v_Normal; varying vec3 v_EyeDir; varying vec2 v_TexCoords; void main() { mat4 m_ModelWorldView = u_WorldView * u_ModelViewMatrix; // position v_Position = (m_ModelWorldView * vec4(in_Position, 1.0)).xyz; gl_Position = u_WorldViewProjection * vec4(v_Position,1.0); // normal v_Normal = ( normalize( m_ModelWorldView * vec4(in_Normal, 0.0) ) ).xyz; // lightning v_EyeDir = -v_Position.xyz; // uv v_TexCoords = in_TexCoords; } |
and the fragment/pixel shader:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | precision mediump float; // phong material struct PhongMaterial { vec4 ambient; // Acm vec4 diffuse; // Dcm vec4 specular; // Scm float shininess; // Srm }; // uniforms uniform PhongMaterial material; uniform mat4 u_WorldViewProjection; uniform sampler2D texture_01; // day and seasonal uniform sampler2D texture_02; // night uniform sampler2D texture_03; // clouds uniform sampler2D texture_04; // specular uniform sampler2D texture_05; // bump map uniform int u_ShowClouds; int u_LightOn = 1; uniform vec3 u_LightPosition; uniform vec3 u_LightDirection; uniform vec3 u_LightIntensity; vec3 u_LightColor = vec3(1.0, 1.0, 1.0); uniform vec2 u_CloudShift; uniform float u_CloudIntensity; int u_ShowNight = 1; vec3 ambientLight = vec3(0.4, 0.4, 0.4); // in varying vec3 v_Position; varying vec3 v_Normal; varying vec3 v_EyeDir; varying vec2 v_TexCoords; vec3 getDayNightColor(sampler2D day, sampler2D night, vec2 uv, float cosineAngleSunToNormal) { vec3 dayColor = texture2D( day, uv ).rgb; vec3 nightColor = texture2D( night, uv ).rgb; // sharpen the edge beween the transition cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 5.0, -1.0, 1.0); // convert to 0 to 1 for mixing float mixAmount = cosineAngleSunToNormal * 0.5 + 0.5; // Select day or night texture based on mixAmount. return mix( nightColor, dayColor, mixAmount ); } // clouds vec4 clouds(vec3 baseColor, sampler2D cloudTexture, vec2 uv, float intensity, float cosineAngleSunToNormal) { // cloud map float c = texture2D(cloudTexture, uv).r; // sharpen the edge beween the transition cosineAngleSunToNormal = clamp( cosineAngleSunToNormal * 5.0, -1.0, 1.0); // convert to 0 to 1 for mixing float mixAmount = cosineAngleSunToNormal * 0.5 + 0.2; // mix intensity c = pow(c,intensity); // mixed cloud color vec4 mixedColor = vec4((1.0-c) * baseColor + c * vec3(1,1,1),1.0); return mix(vec4(baseColor,1.0),mixedColor, mixAmount); } /* Calculate surface color based on Phong illumination model. - pos: position of point on surface, in eye coordinates - n: surface normal at pos - v: direction pointing towards the viewer, in eye coordinates + assuming directional light */ vec3 phong(vec3 pos, vec3 n, vec3 v, PhongMaterial material) { // ambient part vec3 ambient = material.ambient.rgb * ambientLight; // back face towards viewer? float ndotv = dot(n,v); if(ndotv<0.0) return vec3(0,0,0); // light enabled? if(u_LightOn != 1) return ambient + texture2D(texture_01, v_TexCoords).rgb; // vector from light to current point vec3 l = normalize(u_LightDirection); // cos of angle between light and surface. 0 = light behind surface float ndotl = dot(n,-l); // diffuse contribution vec3 diffuse; // day night if(u_ShowNight == 1) // compute day and night contribution diffuse = ambient + getDayNightColor(texture_01, texture_02, v_TexCoords, ndotl); else { // no light only ambient color if(ndotl<=0.0) return ambient; // compute day contribution only diffuse = texture2D(texture_01,v_TexCoords).rgb * u_LightColor * ndotl; } // clouds & night if(u_ShowClouds == 1) diffuse = clouds(diffuse, texture_03, mod(v_TexCoords+u_CloudShift,1.0), u_CloudIntensity, ndotl).rgb; // reflected light direction = perfect reflection direction vec3 r = reflect(l,n); // angle between reflection dir and viewing dir float rdotv = max( dot(r,v), 0.0); // shininess float shininess = material.shininess; // specular contribution vec3 ps = material.specular.rgb * u_LightColor * pow(rdotv,shininess); // mix specular map with specular vec3 specular = ps; // return sum of all contributions return ambient + diffuse + specular; } void main() { // normalize normal after projection vec3 normalEC = normalize(v_Normal); // do we use a perspective or an orthogonal projection matrix? bool usePerspective = u_WorldViewProjection[2][3] != 0.0; // for perspective mode, the viewing direction (in eye coords) points // from the vertex to the origin (0,0,0) --> use -ecPosition as direction. // for orthogonal mode, the viewing direction is simply (0,0,1) vec3 viewdirEC = usePerspective ? normalize(-v_Position.xyz) : vec3(0,0,1); // calculate color using phong illumination vec3 phongColor = phong( v_Position.xyz, normalEC, viewdirEC, material); // set fragment color gl_FragColor = vec4(phongColor,1.0); } |
Maybe this isn’t the most efficient way but it is a way and one that works nonetheless. (: