summaryrefslogtreecommitdiffstats
path: root/src/Runtime/res/effectlib/tessellationPhong.glsllib
blob: 98a683dccd3164d89fc160291efe2977c34f37e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/****************************************************************************
**
** Copyright (C) 2014 NVIDIA Corporation.
** Copyright (C) 2017 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 camera_position;
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] - camera_position );

    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( camera_position, ctWorldPos[0] );
    float distanceValue1 = distance( camera_position, ctWorldPos[1] );
    float distanceValue2 = distance( camera_position, 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