| /**************************************************************************** |
| ** |
| ** Copyright (C) 2014 NVIDIA Corporation. |
| ** Copyright (C) 2019 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of Qt 3D Studio. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 or (at your option) any later version |
| ** approved by the KDE Free Qt Foundation. The licenses are as published by |
| ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #ifndef TESSELLATION_PHONG_GLSLLIB |
| #define TESSELLATION_PHONG_GLSLLIB |
| |
| struct PhongTessPatch |
| { |
| float projIJ; |
| float projJK; |
| float projIK; |
| }; |
| |
| #if TESSELLATION_CONTROL_SHADER |
| layout (vertices = 3) out; |
| |
| layout(location = 15) out PhongTessPatch tcTessPatch[]; |
| |
| // global setup in main |
| vec3 ctWorldPos[3]; |
| vec3 ctNorm[3]; |
| |
| uniform vec3 cameraPosition; |
| uniform vec2 distanceRange; |
| uniform float disableCulling; |
| |
| float isBackFace() |
| { |
| vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) ); |
| |
| vec3 ncd = normalize( ctWorldPos[0] - cameraPosition ); |
| |
| return sign( 0.2 + dot(faceNormal, ncd) ); // 0.2 is a conservative offset to account for curved surfaces |
| } |
| |
| float adaptiveCameraFactor( in float minTess, in float maxTess ) |
| { |
| float distanceValue0 = distance( cameraPosition, ctWorldPos[0] ); |
| float distanceValue1 = distance( cameraPosition, ctWorldPos[1] ); |
| float distanceValue2 = distance( cameraPosition, ctWorldPos[2] ); |
| |
| float range = distanceRange[1] - distanceRange[0]; |
| |
| vec3 edgeDistance; |
| edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range; |
| edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range; |
| edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range; |
| |
| edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) ); |
| |
| //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] ); |
| float af = 1.0 - edgeDistance[gl_InvocationID]; |
| af = clamp( af*af*maxTess , minTess, maxTess ); |
| |
| return af; |
| } |
| |
| float adaptiveFeatureFactor( in float minTess, in float maxTess ) |
| { |
| vec3 adaptValue; |
| adaptValue[0] = clamp( dot(ctNorm[1], ctNorm[2]), -1.0, 1.0 ); |
| adaptValue[1] = clamp( dot(ctNorm[2], ctNorm[0]), -1.0, 1.0 ); |
| adaptValue[2] = clamp( dot(ctNorm[0], ctNorm[1]), -1.0, 1.0 ); |
| |
| //float af = min( adaptValue[0], min(adaptValue[1], adaptValue[2]) ); |
| // map [-1, +1] range to [0, 1] range |
| float af = (adaptValue[gl_InvocationID] + 1.0) / 2.0; |
| |
| af = mix( minTess, maxTess, 1.0 - af ); |
| |
| return af; |
| } |
| |
| float mapToTangentPlane(int i, vec3 q) |
| { |
| vec3 q_minus_p = q - gl_in[i].gl_Position.xyz; |
| return q[gl_InvocationID] - dot(q_minus_p, ctNorm[i]) * ctNorm[i][gl_InvocationID]; |
| } |
| |
| void tessShader ( in float tessEdge, in float tessInner ) |
| { |
| // compute projections separate for each xyz component |
| tcTessPatch[gl_InvocationID].projIJ = mapToTangentPlane(0, gl_in[1].gl_Position.xyz) + mapToTangentPlane(1, gl_in[0].gl_Position.xyz); |
| tcTessPatch[gl_InvocationID].projJK = mapToTangentPlane(1, gl_in[2].gl_Position.xyz) + mapToTangentPlane(2, gl_in[1].gl_Position.xyz); |
| tcTessPatch[gl_InvocationID].projIK = mapToTangentPlane(2, gl_in[0].gl_Position.xyz) + mapToTangentPlane(0, gl_in[2].gl_Position.xyz); |
| |
| // compute backface |
| float bf = isBackFace(); |
| bf = max(disableCulling, bf); |
| // adapative tessellation factor regarding features |
| float af = adaptiveFeatureFactor( tessInner, tessEdge ); |
| // adapative tessellation factor regarding camera |
| //float cf = adaptiveFeatureFactor( tessInner, tessEdge ); |
| |
| // the camera tess factor is the limit |
| //af = min(af, cf); |
| |
| // Calculate the tessellation levels |
| gl_TessLevelInner[0] = af * bf; |
| gl_TessLevelOuter[gl_InvocationID] = af * bf; |
| } |
| |
| #endif |
| |
| #if TESSELLATION_EVALUATION_SHADER |
| layout (triangles, equal_spacing, ccw) in; |
| |
| layout(location = 15) in PhongTessPatch tcTessPatch[]; |
| |
| uniform float phongBlend; |
| |
| vec4 tessShader ( ) |
| { |
| // pre compute square tesselation coord |
| vec3 tessSquared = gl_TessCoord * gl_TessCoord; |
| |
| // barycentric linear position |
| vec3 linearPos = gl_TessCoord.x * gl_in[0].gl_Position.xyz |
| + gl_TessCoord.y * gl_in[1].gl_Position.xyz |
| + gl_TessCoord.z * gl_in[2].gl_Position.xyz; |
| |
| // projective terms |
| vec3 projJI = vec3(tcTessPatch[0].projIJ, tcTessPatch[1].projIJ, tcTessPatch[2].projIJ); |
| vec3 projKJ = vec3(tcTessPatch[0].projJK, tcTessPatch[1].projJK, tcTessPatch[2].projJK); |
| vec3 projIK = vec3(tcTessPatch[0].projIK, tcTessPatch[1].projIK, tcTessPatch[2].projIK); |
| |
| // phong interpolated position |
| vec3 phongPos = tessSquared.x * gl_in[0].gl_Position.xyz |
| + tessSquared.y * gl_in[1].gl_Position.xyz |
| + tessSquared.z * gl_in[2].gl_Position.xyz |
| + gl_TessCoord.x * gl_TessCoord.y * projJI |
| + gl_TessCoord.y * gl_TessCoord.z * projKJ |
| + gl_TessCoord.z * gl_TessCoord.x * projIK; |
| |
| // final blend between linear and phong interpolation |
| vec3 finalPos = (1.0-phongBlend)*linearPos + phongBlend*phongPos; |
| |
| return vec4( finalPos, 1.0 ); |
| } |
| #endif |
| |
| #endif |
| |