-- glslfx version 0.1 // // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // --- This is what an import might look like. --- #import $TOOLS/glos/shaders/simpleLighting.glslfx --- #import /user/anim/global/shaders/simpleLighting.glslfx -- glsl SimpleLighting.GeometryInjection #ifndef NUM_SHADOWS #define NUM_SHADOWS 0 #endif #if NUM_SHADOWS == 0 #else // NUM_SHADOWS == 0 struct ShadowMatrix { mat4 eyeToShadowMatrix; mat4 shadowToEyeMatrix; float blur; float bias; float padding0; float padding1; }; layout(std140) uniform Shadow { ShadowMatrix shadow[NUM_SHADOWS]; }; out vec2 FshadowFilterWidth[NUM_SHADOWS]; // Transforms a unit tangent vector parallel to a coordinate axis in // shadow space to eye space and returns the length of the result // (without doing the perspective division). // // The first argument is assumed to be a column of the shadow to eye // matrix (using first column corresponds to unit tangent vector // pointing in x-direction, ...). The second argument is supposed to // be the (homogeneous) coordinates of the point in eye space. // float shadowTangentLength(vec4 dir, vec4 Peye) { // Computation similar to computeRayDirectionEye in volume.glslfx. const vec3 shadowTangent = dir.xyz * Peye.w - dir.w * Peye.xyz; return length(shadowTangent); } // Computes the lengths that tangent vectors parallel to the x-, // respectively, y-direction in shadow space at the current location // need to have such that their image in eye space have length blur // (without perspective division). // void computeShadowFilterWidth(vec4 Peye) { // interpolate filter width for (int i = 0; i < NUM_SHADOWS; ++i) { FShadowFilterWidth[i] = vec2(shadow[i].blur) / vec2(shadowTangentLength(shadow[i].shadowToEyeMatrix[0], Peye), shadowTangentLength(shadow[i].shadowToEyeMatrix[1], Peye)); } } #define COMPUTE_SHADOW_FILTER_WIDTH 1 #endif // NUM_SHADOWS == 0 -- glsl SimpleLighting.LightIntegrator // --------------------------------------------------------------------------- // struct definitions // --------------------------------------------------------------------------- #ifndef NUM_LIGHTS #define NUM_LIGHTS 0 #endif #ifndef NUM_SHADOWS #define NUM_SHADOWS 0 #endif #ifndef HD_HAS_integrateLights #define HD_HAS_integrateLights #endif struct LightSource { vec4 position; vec4 ambient; vec4 diffuse; vec4 specular; vec4 spotDirection; vec4 spotCutoffAndFalloff; vec4 attenuation; mat4 worldToLightTransform; int shadowIndexStart; int shadowIndexEnd; bool hasShadow; bool isIndirectLight; }; struct ShadowMatrix { mat4 eyeToShadowMatrix; mat4 shadowToEyeMatrix; float blur; float bias; float padding0; float padding1; }; struct LightingContribution { vec3 ambient; vec3 diffuse; vec3 specular; }; struct LightingInterfaceProperties { float shininess; }; // --------------------------------------------------------------------------- // uniform blocks // --------------------------------------------------------------------------- #if NUM_LIGHTS == 0 #else // NUM_LIGHTS == 0 layout(std140) uniform Lighting { bool useLighting; bool useColorMaterialDiffuse; LightSource lightSource[NUM_LIGHTS]; }; #endif // NUM_LIGHTS == 0 #if NUM_SHADOWS == 0 #else // NUM_SHADOWS == 0 layout(std140) uniform Shadow { ShadowMatrix shadow[NUM_SHADOWS]; }; float shadowTangentLength(vec4 dir, vec4 Peye) { const vec3 shadowTangent = dir.xyz * Peye.w - dir.w * Peye.xyz; return length(shadowTangent); } vec2 computeShadowFilterWidth(int index, vec4 Peye) { return vec2(shadow[index].blur) / vec2(shadowTangentLength(shadow[index].shadowToEyeMatrix[0], Peye), shadowTangentLength(shadow[index].shadowToEyeMatrix[1], Peye)); } #endif // NUM_SHADOWS == 0 // --------------------------------------------------------------------------- // textures // --------------------------------------------------------------------------- #if USE_BINDLESS_SHADOW_TEXTURES #if NUM_SHADOWS > 0 uniform BindlessShadowSamplers { uvec2 shadowCompareTextures[NUM_SHADOWS]; }; #endif // NUM_SHADOWS > 0 #else // USE_BINDLESS_SHADOW_TEXTURES uniform sampler2DArray shadowTexture; uniform sampler2DArrayShadow shadowCompareTexture; #endif // !USE_BINDLESS_SHADOW_TEXTURES // --------------------------------------------------------------------------- // lighting functions // --------------------------------------------------------------------------- #if NUM_LIGHTS == 0 LightingContribution integrateLightsConstant(vec4 Peye, vec3 Neye, LightingInterfaceProperties props) { LightingContribution result; result.ambient = vec3(0.0); //pefectly diffuse white hemisphere contribution result.diffuse = vec3(1.0); result.specular = vec3(0.0); return result; } LightingContribution integrateLightsDefault(vec4 Peye, vec3 Neye, LightingInterfaceProperties props) { return integrateLightsConstant(Peye, Neye, props); } #else // NUM_LIGHTS == 0 #if NUM_SHADOWS > 0 float shadowCompare(int shadowIndex, vec4 coord) { coord /= coord.w; coord.z = min(1, coord.z + shadow[shadowIndex].bias); // Cascade selection (in shadowing()) ensures Pshadow.xy is in [0,1], // but shadowFilter() can throw that off so we need to clamp. // XXX: sample the next cascade over? coord.xy = clamp(coord.xy, vec2(0), vec2(1)); #if USE_BINDLESS_SHADOW_TEXTURES return texture(sampler2DShadow(shadowCompareTextures[shadowIndex]), coord.xyz); #else return texture(shadowCompareTexture, vec4(coord.x, coord.y, shadowIndex, coord.z)); #endif } #ifndef SHADOW_FILTER float shadowFilter(int shadowIndex, vec4 coord, vec4 Peye) { return shadowCompare(index, coord); } #endif // SHADOW_FILTER #endif // NUM_SHADOWS > 0 float shadowing(int lightIndex, vec4 Peye) { #if NUM_SHADOWS > 0 for (int shadowIndex = lightSource[lightIndex].shadowIndexStart; shadowIndex <= lightSource[lightIndex].shadowIndexEnd; ++shadowIndex) { vec4 coord = shadow[shadowIndex].eyeToShadowMatrix * Peye; // If the point-to-be-lit isn't covered by this cascade, skip to // the next one... if (any(lessThan(coord.xyz, vec3(0))) || any(greaterThan(coord.xyz, coord.www))) { continue; } return shadowFilter(shadowIndex, coord, Peye); } #endif // NUM_SHADOWS > 0 // ... either no shadows, or no coverage. return 1.0; } float lightDistanceAttenuation(vec4 Peye, int index) { float distAtten = 1.0; if (lightSource[index].position.w != 0.0) { float d = distance(lightSource[index].position, Peye); distAtten = 1.0 / (lightSource[index].attenuation[0] + lightSource[index].attenuation[1] * d + lightSource[index].attenuation[2] * d*d); } return distAtten; } float lightSpotAttenuation(vec3 l, int index) { float spotAtten = 1.0; if (lightSource[index].spotCutoffAndFalloff.x < 180.0) { float cosLight = dot(-l, lightSource[index].spotDirection.xyz); spotAtten = (cosLight < cos(radians(lightSource[index].spotCutoffAndFalloff.x))) ? 0.0 : pow(cosLight, lightSource[index].spotCutoffAndFalloff.y); } return spotAtten; } // for the comaptibility, turn on shadowing by default. #ifndef USE_SHADOWS #define USE_SHADOWS 1 #endif LightingContribution integrateLightsDefault(vec4 Peye, vec3 Neye, LightingInterfaceProperties props) { LightingContribution result; result.ambient = vec3(0); result.diffuse = vec3(0); result.specular = vec3(0); vec3 n = normalize(Neye); vec3 e = normalize(-Peye.xyz); float shininess = props.shininess; for (int i = 0; i < NUM_LIGHTS; ++i) { vec4 Plight = lightSource[i].position; vec3 l = (Plight.w == 0.0) ? normalize(Plight.xyz) : normalize(Plight - Peye).xyz; vec3 h = normalize(l + vec3(0,0,1)); // directional viewer //cosine of incident angle of lightn float NdotL = max(0.0, dot(n, l)); //cosine of incident angle from halfway vector between the eye and the light float NdotH = max(0.0, dot(n, h)); //Lambert float d = NdotL; //Blinn-Phong float s = pow(NdotH, shininess); float atten = lightDistanceAttenuation(Peye, i); atten *= lightSpotAttenuation(l, i); #if USE_SHADOWS float shadow = (lightSource[i].hasShadow) ? shadowing(/*lightIndex=*/i, Peye) : 1.0; #else float shadow = 1.0; #endif result.ambient += atten * lightSource[i].ambient.rgb; result.diffuse += atten * shadow * d * lightSource[i].diffuse.rgb; result.specular += atten * shadow * s * lightSource[i].specular.rgb; } return result; } LightingContribution integrateLightsConstant(vec4 Peye, vec3 Neye, LightingInterfaceProperties props) { LightingContribution result; result.ambient = vec3(0); result.specular = vec3(0); result.diffuse = vec3(1); return result; } #endif // NUM_LIGHTS == 0 -- glsl SimpleLighting.SimpleLighting // --------------------------------------------------------------------------- // struct definitions // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // uniform blocks // --------------------------------------------------------------------------- layout(std140) uniform Material { vec4 ambient; vec4 diffuse; vec4 specular; vec4 emission; vec4 sceneColor; float shininess; } material; // --------------------------------------------------------------------------- // textures // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // lighting functions // --------------------------------------------------------------------------- #if NUM_LIGHTS == 0 vec4 simpleLighting(vec4 color, vec4 Peye, vec3 Neye, vec4 Ctint, vec4 matDiffuse, vec4 matAmbient, vec4 matSpecular, float matShininess) { return color; } vec4 simpleLightingMaterial(vec4 color, vec4 Peye, vec3 Neye, vec4 Ctint) { return material.emission + (material.sceneColor * material.ambient); } vec4 simpleLighting(vec4 color, vec4 Peye, vec3 Neye, vec4 Ctint) { return simpleLightingMaterial(color, Peye, Neye, Ctint); } #else // NUM_LIGHTS == 0 LightingContribution integrateLights(vec4 Peye, vec3 Neye, LightingInterfaceProperties props); vec4 simpleLighting(vec4 color, vec4 Peye, vec3 Neye, vec4 Ctint, vec4 matDiffuse, vec4 matAmbient, vec4 matSpecular, float matShininess) { // Get the roughness and metallic values #if defined(HD_HAS_displayRoughness) float roughness = max(0.0, min(1.0, float(HdGet_displayRoughness()))); #else float roughness = 0.0; #endif #if defined(HD_HAS_displayMetallic) float metallic = max(0.0, min(1.0, float(HdGet_displayMetallic()))); #else float metallic = 0.0; #endif // determine the specular and diffuse intensity float Ks = (1.0 - roughness) + 2.0 * metallic; LightingInterfaceProperties props; #if defined(HD_HAS_displayRoughness) float specularExp = (1.0 - roughness) * 120.0 + 8.0; props.shininess = specularExp; matSpecular.rgb = mix(vec3(1.0), matDiffuse.rgb, metallic); #else props.shininess = matShininess; #endif LightingContribution light = integrateLights(Peye, Neye, props); color.rgb += light.ambient * matAmbient.rgb; color.rgb += Ctint.rgb * light.diffuse * matDiffuse.rgb; color.rgb += Ks * light.specular * matSpecular.rgb; color.a = matDiffuse.a; return color; } vec4 simpleLightingMaterial(vec4 color, vec4 Peye, vec3 Neye, vec4 Ctint) { // XXX todo: useColorMaterialDiffuse vec4 diffuse = color; vec4 ambient = material.ambient; vec4 specular = material.specular; float shininess = material.shininess; color = material.emission + (material.sceneColor * material.ambient); return simpleLighting(color, Peye, Neye, Ctint, diffuse, ambient, specular, shininess); } vec4 simpleLighting(vec4 color, vec4 Peye, vec3 Neye, vec4 Ctint) { return simpleLightingMaterial(color, Peye, Neye, Ctint); } #endif // NUM_LIGHTS == 0