-- 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/hdSt/shaders/meshWire.glslfx #import $TOOLS/hdx/shaders/selection.glslfx --- -------------------------------------------------------------------------- -- glsl MeshWire.Geometry.NoEdge void ProcessEdgeDistance(vec4 Peye0, vec4 Peye1, vec4 Peye2, vec4 Peye3, vec3 edgeClip) { // do nothing. } void ProcessTriEdgeDistance(vec4 Peye0, vec4 Peye1, vec4 Peye2, vec4 Peye3, int inEdgeFlag) { // do nothing. } void ProcessQuadEdgeDistance(vec4 Peye0, vec4 Peye1, vec4 Peye2, vec4 Peye3, int triCounter) { // do nothing. } --- -------------------------------------------------------------------------- -- glsl MeshWire.Geometry.Edge out EdgeData { noperspective out vec3 edgeDistance; } outEdgeData; vec3 edgeDistance(vec2 p, vec2 p0, vec2 p1, vec2 p2) { vec3 r; r.x = abs((p.x - p0.x) * (p1.y - p0.y) - (p.y - p0.y) * (p1.x - p0.x)) / length(p1.xy - p0.xy); r.y = abs((p.x - p1.x) * (p2.y - p1.y) - (p.y - p1.y) * (p2.x - p1.x)) / length(p2.xy - p1.xy); r.z = abs((p.x - p2.x) * (p0.y - p2.y) - (p.y - p2.y) * (p0.x - p2.x)) / length(p0.xy - p2.xy); return r; } void ProcessEdgeDistance(vec4 Peye0, vec4 Peye1, vec4 Peye2, vec4 Peye3, vec3 edgeClip) { // note: // we expect the GLSL compiler optimizes out the redundant computations of // following projection. vec4 viewport = GetViewport(); vec4 viewportScale = vec4(0.5*viewport[2], 0.5*viewport[3], 1, 1); // screen space position vec4 v0 = GetProjectionMatrix() * Peye0; vec4 v1 = GetProjectionMatrix() * Peye1; vec4 v2 = GetProjectionMatrix() * Peye2; vec4 v3 = GetProjectionMatrix() * Peye3; v0.xy = (v0.xy/v0.w) * viewportScale.xy; v1.xy = (v1.xy/v1.w) * viewportScale.xy; v2.xy = (v2.xy/v2.w) * viewportScale.xy; v3.xy = (v3.xy/v3.w) * viewportScale.xy; outEdgeData.edgeDistance = max(edgeDistance(v0.xy, v1.xy, v2.xy, v3.xy), edgeClip); } void ProcessTriEdgeDistance(vec4 Peye0, vec4 Peye1, vec4 Peye2, vec4 Peye3, int inEdgeFlag) { // see hd/meshUtil.cpp // // 0__ 0 0 0__ // _/|\ \_ _/. .. . \_ // _/ | \ \_ -> _/ . . . . \_ // / A |C \ B \_ / A . .C . . B \_ // 1-----2---3----4 1-----2 1---2 1----2 // // Type EdgeFlag Draw // - 0 show all edges // A 1 hide [2-0] // B 2 hide [0-1] // C 3 hide [0-1] and [2-0] // D 4 hide [1-2] // // edgeDistance returns 3 floats, distances from // given vertex to edge [0-1], [1-2], [2-0] as (x, y, z). // i.e. to remove edge [2-0], make edgeDistance.z big in viewport pixel. // similary edgeDistance.x can be used for edge [0-1]. int edgeFlag = GetEdgeFlag(inEdgeFlag); vec3 edgeClip = vec3(0); // it might be nice to use the viewport scale, but constant is much faster. edgeClip.z = ((edgeFlag & 1) != 0) ? 1000.0 : 0; edgeClip.x = ((edgeFlag & 2) != 0) ? 1000.0 : 0; edgeClip.y = ((edgeFlag & 4) != 0) ? 1000.0 : 0; ProcessEdgeDistance(Peye0, Peye1, Peye2, Peye3, edgeClip); } void ProcessQuadEdgeDistance(vec4 Peye0, vec4 Peye1, vec4 Peye2, vec4 Peye3, int triCounter) { // see hd/meshUtil.cpp // Case EdgeFlag Draw // Quad/Refined face 0 hide common edge for the tri-pair // Non-Quad face 1/2/3 hide common edge for the tri-pair & // hide interior quadrangulated edges // // The first quad of a non-quad face is marked 1; the last as 2; and // intermediate quads as 3. int edgeFlag = GetEdgeFlag(0); // 0---3 // |. 0| // | . | // |1 .| // 1---2 // // triCounter == 0 : skip the second edge of (3,0,2), i.e., (0-2) // triCounter == 1 : skip the first edge of (2,0,1), i.e., (2-0) vec3 edgeClip = triCounter == 0 ? vec3(0, 1000.0, 0) : vec3(1000.0, 0, 0); if (edgeFlag != 0) { // the quad face stems from quadrangulation // 0 - original (coarse) vertex // 1,3 - edge vertices // 2 - center vertex // skip the third edge (i.e. edge-center, 2-3 or 1-2 depending on // triCounter). edgeClip.z = 1000.0; } ProcessEdgeDistance(Peye0, Peye1, Peye2, Peye3, edgeClip); } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.NoFilter void ApplySelectionFilter() { // do nothing } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.FilterElementSelActive // Fwd decl methods used (from selection.glslfx) int GetActiveSelectionMode(); bool IsFaceSelected(int mode, int elementId); int GetElementID(); // code gen void ApplySelectionFilter() { if (!IsFaceSelected(GetActiveSelectionMode(), GetElementID())) { discard; } } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.FilterElementSelRollover // Fwd decl methods used (from selection.glslfx) int GetRolloverSelectionMode(); bool IsFaceSelected(int mode, int elementId); int GetElementID(); // code gen void ApplySelectionFilter() { if (!IsFaceSelected(GetRolloverSelectionMode(), GetElementID())) { discard; } } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.EdgeCommon in EdgeData { noperspective vec3 edgeDistance; } inEdgeData; // Returns the distance of the current fragment (in viewport pixel units) from // the nearest edge. float GetMinEdgeDistance() { vec3 edgeDistance = inEdgeData.edgeDistance; return min(edgeDistance.x, min(edgeDistance.y, edgeDistance.z)); } // Use edge distance to compute a smooth opacity falloff for good looking edges. float GetEdgeOpacity() { float d = GetMinEdgeDistance(); float p = exp2(-4 * d * d); return p; } // Override for subdivided faces to make the boundary of the face stand out. float GetEdgeOpacity(vec2 patchCoord) { float d = GetMinEdgeDistance(); // Is the fragment on a face boundary? if (patchCoord.x < 0.01 || patchCoord.x > 0.99 || patchCoord.y < 0.01 || patchCoord.y > 0.99) d *= 0.25; float p = exp2(-4 * d * d); return p; } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.NoEdge vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) { return Cfill; } // Return a large value, signifying that the fragment isn't near an edge. float GetMinEdgeDistance() { return 1000.0; } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.EdgeOnSurface vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) { // Skip the selection filter since the line rasterization draw order issue // isn't relevant. // XXX: We don't use the patchCoord below to make the face boundary // stand out. Should we? float p = GetEdgeOpacity(/*patchCoord.xy*/); vec4 wireColor = GetWireframeColor(); // If wireColor is unset (zero), the fill color is just dimmed a bit. if (wireColor == vec4(0)) wireColor.a = 0.5; vec4 Cedge = vec4(mix(Cfill.rgb, wireColor.rgb, wireColor.a), 1); Cfill.rgb = mix(Cfill.rgb, Cedge.rgb, p); return Cfill; } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.EdgeOnlyBlendColor void ApplySelectionFilter(); vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) { ApplySelectionFilter(); float p = GetEdgeOpacity(); if (p < 0.5) discard; vec4 wireColor = GetWireframeColor(); // If wireColor is unset (zero), ignore it altogether Cfill.rgb = mix(Cfill.rgb, wireColor.rgb, wireColor.a); Cfill.a = 1.0; // edges ignore input opacity and are opaque. return Cfill; } --- -------------------------------------------------------------------------- -- glsl MeshWire.Fragment.EdgeOnlyNoBlend void ApplySelectionFilter(); vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) { ApplySelectionFilter(); float p = GetEdgeOpacity(); if (p < 0.5) discard; Cfill.a = 1.0; // edges ignore input opacity and are opaque. return Cfill; } --- -------------------------------------------------------------------------- -- glsl MeshPatchWire.Fragment.EdgeOnSurface vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) { // Skip the selection filter since the line rasterization draw order issue // isn't relevant. float p = GetEdgeOpacity(patchCoord.xy); vec4 wireColor = GetWireframeColor(); // If wireColor is unset (zero), the fill color is just dimmed a bit. if (wireColor == vec4(0)) wireColor.a = 0.5; vec4 Cedge = vec4(mix(Cfill.rgb, wireColor.rgb, wireColor.a), 1); Cfill.rgb = mix(Cfill.rgb, Cedge.rgb, p); return Cfill; } --- -------------------------------------------------------------------------- -- glsl MeshPatchWire.Fragment.EdgeOnly void ApplySelectionFilter(); vec4 ApplyEdgeColor(vec4 Cfill, vec4 patchCoord) { ApplySelectionFilter(); float p = GetEdgeOpacity(); if (p < 0.5) discard; Cfill.a = 1.0; // edges ignore input opacity and are opaque. return Cfill; }