1$input v_view, v_normal 2 3/* 4 * Copyright 2014-2016 Dario Manesku. All rights reserved. 5 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause 6 */ 7 8#include "../common/common.sh" 9#include "uniforms.sh" 10 11SAMPLERCUBE(s_texCube, 0); 12SAMPLERCUBE(s_texCubeIrr, 1); 13 14vec3 calcFresnel(vec3 _cspec, float _dot, float _strength) 15{ 16 return _cspec + (1.0 - _cspec)*pow(1.0 - _dot, 5.0) * _strength; 17} 18 19vec3 calcLambert(vec3 _cdiff, float _ndotl) 20{ 21 return _cdiff*_ndotl; 22} 23 24vec3 calcBlinn(vec3 _cspec, float _ndoth, float _ndotl, float _specPwr) 25{ 26 float norm = (_specPwr+8.0)*0.125; 27 float brdf = pow(_ndoth, _specPwr)*_ndotl*norm; 28 return _cspec*brdf; 29} 30 31float specPwr(float _gloss) 32{ 33 return exp2(10.0*_gloss+2.0); 34} 35 36void main() 37{ 38 // Light. 39 vec3 ld = normalize(u_lightDir); 40 vec3 clight = u_lightCol; 41 42 // Input. 43 vec3 nn = normalize(v_normal); 44 vec3 vv = normalize(v_view); 45 vec3 hh = normalize(vv + ld); 46 47 float ndotv = clamp(dot(nn, vv), 0.0, 1.0); 48 float ndotl = clamp(dot(nn, ld), 0.0, 1.0); 49 float ndoth = clamp(dot(nn, hh), 0.0, 1.0); 50 float hdotv = clamp(dot(hh, vv), 0.0, 1.0); 51 52 // Material params. 53 vec3 inAlbedo = u_rgbDiff.xyz; 54 float inReflectivity = u_reflectivity; 55 float inGloss = u_glossiness; 56 57 // Reflection. 58 vec3 refl; 59 if (0.0 == u_metalOrSpec) // Metalness workflow. 60 { 61 refl = mix(vec3_splat(0.04), inAlbedo, inReflectivity); 62 } 63 else // Specular workflow. 64 { 65 refl = u_rgbSpec.xyz * vec3_splat(inReflectivity); 66 } 67 vec3 albedo = inAlbedo * (1.0 - inReflectivity); 68 vec3 dirFresnel = calcFresnel(refl, hdotv, inGloss); 69 vec3 envFresnel = calcFresnel(refl, ndotv, inGloss); 70 71 vec3 lambert = u_doDiffuse * calcLambert(albedo * (1.0 - dirFresnel), ndotl); 72 vec3 blinn = u_doSpecular * calcBlinn(dirFresnel, ndoth, ndotl, specPwr(inGloss)); 73 vec3 direct = (lambert + blinn)*clight; 74 75 // Note: Environment textures are filtered with cmft: https://github.com/dariomanesku/cmft 76 // Params used: 77 // --excludeBase true //!< First level mip is not filtered. 78 // --mipCount 7 //!< 7 mip levels are used in total, [256x256 .. 4x4]. Lower res mip maps should be avoided. 79 // --glossScale 10 //!< Spec power scale. See: specPwr(). 80 // --glossBias 2 //!< Spec power bias. See: specPwr(). 81 // --edgeFixup warp //!< This must be used on DirectX9. When fileted with 'warp', fixCubeLookup() should be used. 82 float mip = 1.0 + 5.0*(1.0 - inGloss); // Use mip levels [1..6] for radiance. 83 84 mat4 mtx; 85 mtx[0] = u_mtx0; 86 mtx[1] = u_mtx1; 87 mtx[2] = u_mtx2; 88 mtx[3] = u_mtx3; 89 vec3 vr = 2.0*ndotv*nn - vv; // Same as: -reflect(vv, nn); 90 vec3 cubeR = normalize(instMul(mtx, vec4(vr, 0.0)).xyz); 91 vec3 cubeN = normalize(instMul(mtx, vec4(nn, 0.0)).xyz); 92 cubeR = fixCubeLookup(cubeR, mip, 256.0); 93 94 vec3 radiance = toLinear(textureCubeLod(s_texCube, cubeR, mip).xyz); 95 vec3 irradiance = toLinear(textureCube(s_texCubeIrr, cubeN).xyz); 96 vec3 envDiffuse = albedo * irradiance * u_doDiffuseIbl; 97 vec3 envSpecular = envFresnel * radiance * u_doSpecularIbl; 98 vec3 indirect = envDiffuse + envSpecular; 99 100 // Color. 101 vec3 color = direct + indirect; 102 color = color * exp2(u_exposure); 103 gl_FragColor.xyz = toFilmic(color); 104 gl_FragColor.w = 1.0; 105} 106