varying vec3 frontLighting; varying vec3 backLighting; varying vec3 frontSpecular; varying vec3 backSpecular; varying vec3 eyePos; varying vec2 texCoord; uniform int lightCount; uniform vec3 diffuseColor; uniform vec3 specularColor; uniform float hardness; uniform float diffuseIntensity; uniform float time; uniform float strength; uniform float speed; uniform float deforming; uniform float bending; uniform vec2 direction; uniform float ground; uniform mat4 ModelMatrix; uniform mat4 ViewMatrix; #define maxLights 16 uniform int lightType[maxLights]; uniform vec3 lightColor[maxLights]; uniform vec3 lightPosition[maxLights]; uniform vec3 lightOrientation[maxLights]; uniform float lightDistance[maxLights]; uniform float lightSpotsize[maxLights]; uniform float lightSpotblend[maxLights]; #define SPOT 0 #define SUN 1 #define POINT 2 #define NORMAL 2 #define HEMI 3 #define M_PI 3.14159265358979323846 vec2 windDirection = direction; //direction of the wind float windStrength = strength; //strength of the wind float groundLevel = ground; //everything over ground level will have movement const int windSamples = 3; //number of wind sine waves to add // ########################################Functions for material######################################## float exp_blender(float f) { return pow(2.71828182846, f); } float linearrgb_to_srgb(float c) { if(c < 0.0031308) return (c < 0.0) ? 0.0: c * 12.92; else return 1.055 * pow(c, 1.0/2.4) - 0.055; } vec3 linearrgb_to_srgb(vec3 col_from) { vec3 col_to; col_to.r = linearrgb_to_srgb(col_from.r); col_to.g = linearrgb_to_srgb(col_from.g); col_to.b = linearrgb_to_srgb(col_from.b); return col_to; } float shade_hemi_spec(vec3 N, vec3 H, float hard) { float NdotH = dot(N, H) * 0.5 + 0.5; float specfac = pow(max(NdotH, 0.0), hard); return specfac; } float shade_phong_spec(vec3 N, vec3 H, vec3 L, vec3 E, float hard) { float rslt = max(dot(H, N), 0.0); float specfac = pow(rslt, hard); return specfac; } float shade_cooktorr_spec(vec3 H, vec3 N, vec3 E) { float specfac; float NdotH = dot(N, H); if(NdotH < 0.0) { specfac = 0.0; } else { float maxNdotE = max(dot(N, E), 0.0); specfac = pow(NdotH, hardness); specfac = specfac / (0.1 + maxNdotE); } return specfac; } float shade_blinn_spec(vec3 N, vec3 H, vec3 L, vec3 E, float refrac, float spec_power) { float specfac; if(refrac < 1.0) { specfac = 0.0; } else if(spec_power == 0.0) { specfac = 0.0; } else { if(spec_power<100.0) spec_power= sqrt(1.0/spec_power); else spec_power= 10.0/spec_power; float NdotH = dot(N, H); if(NdotH < 0.0) { specfac = 0.0; } else { float maxNdotE = max(dot(N, E), 0.01); float NdotL = dot(N, L); if(NdotL <= 0.01) { specfac = 0.0; } else { float maxEdotH = max(dot(E, H), 0.01); float a = 1.0; float b = (2.0 * NdotH * maxNdotE) / maxEdotH; float c = (2.0 * NdotH * NdotL) / maxEdotH; float g = 0.0; if(a < b && a < c) g = a; else if(b < a && b < c) g = b; else if(c < a && c < b) g = c; float p = sqrt(((refrac * refrac)+(maxEdotH*maxEdotH)-1.0)); float f = (((p-maxEdotH)*(p-maxEdotH))/((p+maxEdotH)*(p+maxEdotH)))*(1.0+((((maxEdotH*(p+maxEdotH))-1.0)*((maxEdotH*(p+maxEdotH))-1.0))/(((maxEdotH*(p-maxEdotH))+1.0)*((maxEdotH*(p-maxEdotH))+1.0)))); float ang = acos(NdotH); specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0); } } } return specfac; } float shade_wardiso_spec(vec3 N, vec3 H, vec3 E, vec3 L, float rms) { float maxNdotH = max(dot(N, H), 0.001); float maxNdotE = max(dot(N, E), 0.001); float maxNdotL = max(dot(N, L), 0.001); float angle = tan(acos(maxNdotH)); float alpha = max(rms, 0.001); float specfac= maxNdotL * (1.0/(4.0 * M_PI * alpha * alpha)) * (exp_blender(-(angle * angle)/(alpha * alpha))/(sqrt(maxNdotE * maxNdotL))); return specfac; } float shade_toon_spec(vec3 N, vec3 H, float size, float tsmooth) { float specfac; float rslt; float NdotH = dot(N, H); float ang = acos(NdotH); if(ang < size) rslt = 1.0; else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0; else rslt = 1.0 - ((ang - size)/tsmooth); specfac = rslt; return specfac; } void getLighting(vec3 normal, vec3 eyePos, out vec3 fLighting, out vec3 bLighting, out vec3 fSpecular, out vec3 bSpecular) { fLighting = vec3(0, 0, 0); bLighting = vec3(0, 0, 0); fSpecular = vec3(0, 0, 0); bSpecular = vec3(0, 0, 0); //workaround for for loop unrolling. Change type from int to float. for (float c = 0.0; c < float(lightCount); c++) { int i = int(c); float attenuation = 1.0; vec3 lightVec = vec3(0.0, 0.0, 1.0); if (lightType[i] == SPOT || lightType[i] == POINT) { lightVec = eyePos - lightPosition[i]; float lightDist = length(lightVec); // The invsquare attenuation calculation in Blender is not correct // I use Blenders attenuation calculation to get the same attenuation attenuation = lightDistance[i] / (lightDistance[i] + lightDist * lightDist); //attenuation = visifac in Blender shader code } else { lightVec = lightOrientation[i]; } vec3 fN = normalize(-normal); //frontface vec3 bN = normalize(normal); //backface vec3 E = normalize(eyePos); /* handle perspective/orthographic */ E = (gl_ProjectionMatrix[3][3] == 0.0) ? E : vec3(0.0, 0.0, -1.0); vec3 L = normalize(lightVec); //L = lv in Blender shader code vec3 H = normalize(L+E); if (lightType[i] == SPOT) { float inpr = 0.0; vec2 scale = vec2(1.0, 1.0); float visifac = attenuation; inpr = dot(L, lightOrientation[i]); float t = lightSpotsize[i]; //spot size if(inpr <= t) { attenuation = 0.0; } else { /* soft area */ if(lightSpotblend[i] != 0.0) inpr *= smoothstep(0.0, 1.0, (inpr - t) / lightSpotblend[i]); attenuation = attenuation * inpr; } } float fNdotL = dot(fN, L); float bNdotL = dot(bN, L); //float NdotH = dot(N, H); //float NdotE = dot(N, E); float fks; float bks; float fkd; float bkd; if (lightType[i] == HEMI) { fNdotL = fNdotL* 0.5 + 0.5; bNdotL = bNdotL* 0.5 + 0.5; //NdotH = NdotH * 0.5 + 0.5; //ks = pow(max(NdotH, 0.0), hardness); fks = shade_hemi_spec(fN, H, hardness); bks = shade_hemi_spec(bN, H, hardness); } else { //Phong specular shading fks = shade_phong_spec(fN, H, L, E, hardness); bks = shade_phong_spec(bN, H, L, E, hardness); //CookTorr specular shading //fks = shade_cooktorr_spec(H, fN, E); //bks = shade_cooktorr_spec(H, bN, E); //Toon specular shading /* float size = 0.5; float smooth = 0.1; fks = shade_toon_spec(fN, H, size, smooth); bks = shade_toon_spec(bN, H, size, smooth); */ //Wardiso specular shading /* float slope = 0.1; fks = shade_wardiso_spec(fN, H, E, L, slope); bks = shade_wardiso_spec(bN, H, E, L, slope); */ //Blinn specular shading /* float refrac = 4.0; fks = shade_blinn_spec(fN, H, L, E, refrac, hardness); bks = shade_blinn_spec(bN, H, L, E, refrac, hardness); */ } fkd = max(fNdotL, 0.0) * attenuation; fLighting += fkd * lightColor[i]; bkd = max(bNdotL, 0.0) * attenuation; bLighting += bkd * lightColor[i]; fks = fks * attenuation; fSpecular += fks * specularColor * lightColor[i]; bks = bks * attenuation; bSpecular += bks * specularColor * lightColor[i]; } } // ########################################Functions for vertex deforming######################################## //function to generate the wind vec2 getWind(vec4 worldPos, float height) { vec2 wind; if (height > groundLevel) { float windTime = time*speed; float windDisplacement = cos(0.375*((17.5+worldPos.x)+(17.5+worldPos.y))+(windTime*1.25)); //worldPos.xy += vec2(1000.0); //making sure the position is positive for calculations for (int w = 0; w < windSamples; w++) { float rAnd = float(w)+1.0-(float(windSamples)/2.0); float rCnd = float(w)-1.0+(float(windSamples)/2.0); windDisplacement += sin(0.5*((17.5+rAnd+worldPos.x)+(rAnd+worldPos.y))+(windTime*(rAnd*0.1+1.75))); windDisplacement -= cos(0.5*((17.5+rCnd+worldPos.x)+(rAnd+worldPos.y))+(windTime*(rCnd*0.1+1.75))); } wind = windStrength*(height-0.25)*sin((worldPos.xy*normalize(windDirection))+vec2(windTime*0.5))*windDisplacement; wind *= ((height - groundLevel) * bending + 1.0 - bending); } else { wind = vec2(0.0,0.0); } return wind; } mat4 addWorldPos(mat4 modelMat, vec3 pos) { modelMat[3][0] += pos.x; modelMat[3][1] += pos.y; modelMat[3][2] += pos.z; return modelMat; } // ########################################Main-Function######################################## void main() { vec4 vert = gl_Vertex; vec4 worldSpacePos = ModelMatrix * (vert*deforming+1.0-deforming); vec2 wind = getWind(worldSpacePos, vert.z); mat4 modelViewMatix = ViewMatrix * addWorldPos(ModelMatrix, vec3(wind, 0.0)); //dot(gl_Color.rgb, vec3(0.299, 0.587, 0.114) texCoord = gl_MultiTexCoord0.xy; vec3 normal = gl_NormalMatrix * gl_Normal; eyePos = (modelViewMatix * vert).xyz; gl_Position = gl_ProjectionMatrix * modelViewMatix * vert; getLighting(normal, eyePos, frontLighting, backLighting, frontSpecular, backSpecular); }