-- glslfx version 0.1 // // Copyright 2018 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/hdSt/shaders/edgeId.glslfx --- -------------------------------------------------------------------------- -- glsl EdgeId.Geometry.None // called from Mesh.Geometry.* void ProcessEdgeId(int index, vec2 faceUV) { // do nothing } --- -------------------------------------------------------------------------- -- glsl EdgeId.Geometry.EdgeParam // Interpolate linearly since we want to be able to // reason about the distance from the edge in fragment space. noperspective out vec2 gsEdgeParam; // called from Mesh.Geometry.* void ProcessEdgeId(int index, vec2 faceUV) { // The local triangular parameterization is a subset of the // local rectangular parameterization, so for both cases // we just record the uv parameterization at the face vertex // and can reconstruct the third coordinate when necessary. gsEdgeParam = faceUV; } --- -------------------------------------------------------------------------- -- glsl EdgeId.Fragment.Fallback // Mixin version to use for meshes when the geometry shader stage is inactive. // Note: When rendering a mesh as points, this mixin isn't used. We handle it // in code gen. int GetPrimitiveEdgeId() { return -1; } bool IsFragmentOnEdge() { return false; } float GetSelectedEdgeOpacity() { return 0.0; } --- -------------------------------------------------------------------------- -- glsl EdgeId.Fragment.Common float GetMinEdgeDistance(); // meshWire.glslfx // Returns whether a fragment is on or close to an unhidden triangle edge. const float edgePickRadius = 2; // in viewport pixels bool IsFragmentOnEdge() { float d = GetMinEdgeDistance(); if (d < edgePickRadius) return true; return false; } // For smooth looking edges, use an exponential falloff for the opacity. // Note: We use a slower falloff fn than in meshWire.glslfx to make the selected // edges stand out. float GetSelectedEdgeOpacity() { float d = GetMinEdgeDistance(); return exp2(-1 * d * d); } --- -------------------------------------------------------------------------- -- glsl EdgeId.Fragment.TriangleParam vec3 ExpandBarycentricCoord(vec2 bc) { return vec3(bc.x, bc.y, 1 - bc.x - bc.y); } noperspective in vec2 gsEdgeParam; // called from hdx/renderPass.glslfx and selection.glslfx int GetPrimitiveEdgeId() { // Use edge distance to reject fragments that aren't on/near // (unhidden) triangle edges. if (!IsFragmentOnEdge()) return -1; // Find out which edge the fragment is on. vec3 bc = ExpandBarycentricCoord(gsEdgeParam.xy); // 2 (0,1,0) // ^ // e2 / \ e1 // / \' // (0,0,1) 0 ----- 1 (1,0,0) // e0 int edgeId = -1; float delta = 0.02; bvec3 ltResult = lessThan(bc, vec3(delta)); if (ltResult.y && (bc.y < bc.x) && (bc.y < bc.z)) { edgeId = 0; } else if (ltResult.z && (bc.z < bc.x)) { edgeId = 1; } else if (ltResult.x) { edgeId = 2; } return edgeId; } --- -------------------------------------------------------------------------- -- glsl EdgeId.Fragment.RectangleParam noperspective in vec2 gsEdgeParam; // called from hdx/renderPass.glslfx and selection.glslfx int GetPrimitiveEdgeId() { // Use edge distance to reject fragments that aren't on/near (unhidden) // triangle edges. if (!IsFragmentOnEdge()) return -1; // e2 // (0,1) 3 ------ 2 (1,1) // | | // e3 | | e1 // | | // (0,0) 0 ------ 1 (1,0) // e0 int edgeId = -1; const float delta = 0.02; const float delLow = delta; const float delHigh = 1 - delLow; vec2 uv = gsEdgeParam.xy; if (uv.y < delLow && uv.y < uv.x) { edgeId = 0; } else if (uv.x < delLow) { edgeId = 3; } else if (uv.x > delHigh && uv.x > uv.y) { edgeId = 1; } else if (uv.y > delHigh) { edgeId = 2; } return edgeId; }