1/*
2 This Source Code Form is subject to the terms of the Mozilla Public
3 License, v. 2.0. If a copy of the MPL was not distributed with this
4 file, You can obtain one at http://mozilla.org/MPL/2.0/.
5*/
6
7#version 410 core
8
9layout(vertices = 9) out;
10
11uniform vec2 viewportSize;
12uniform float smoothness;
13
14in vec4 ctrl_position_obj[];
15in vec3 ctrl_normal_obj[];
16in vec3 ctrl_normal_view[];
17
18out vec4 eval_position_obj[];
19out vec3 eval_normal_obj[];
20out vec3 eval_normal_view[];
21out ScreenSpaceBlock {
22    flat vec3 heights_scr;
23    flat vec3 vertices_obj[3];
24    flat vec3 normEdges_obj[3];
25} eval_ss[];
26
27bool isLinear(int i) {
28    vec4 p0 = eval_position_obj[3*i + 0];
29    vec4 p1 = eval_position_obj[3*i + 1];
30    vec4 p2 = eval_position_obj[3*i + 2];
31    vec4 p3 = eval_position_obj[(3*i + 3)%9];
32
33    vec4 p1off = p1 - (2*p0 + p3) / 3;
34    vec4 p2off = p2 - (p0 + 2*p3) / 3;
35
36    return dot(p1off, p1off) < 0.0001
37        && dot(p2off, p2off) < 0.0001;
38}
39
40float curviness(int i) {
41    vec4 p0 = eval_position_obj[3*i + 0];
42    vec4 p1 = eval_position_obj[3*i + 1];
43    vec4 p2 = eval_position_obj[3*i + 2];
44    vec4 p3 = eval_position_obj[(3*i + 3)%9];
45
46    vec4 p1off = p1 - (2*p0 + p3) / 3;
47    vec4 p2off = p2 - (p0 + 2*p3) / 3;
48
49    return max(length(p1off), length(p2off)) / distance(p0, p3);
50}
51
52void main(void)
53{
54    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
55    eval_position_obj[gl_InvocationID]  = ctrl_position_obj[gl_InvocationID];
56    eval_normal_obj[gl_InvocationID]    = ctrl_normal_obj[gl_InvocationID];
57    eval_normal_view[gl_InvocationID]   = ctrl_normal_view[gl_InvocationID];
58
59    vec2 position_scr[3];
60    for(int i=0; i<3; ++i)
61    {
62        position_scr[i] = (viewportSize * gl_in[i*3].gl_Position.xy)
63                        / (2.0 * gl_in[i*3].gl_Position.z);
64    }
65    float area = abs(cross(vec3(position_scr[1] - position_scr[0], 0.0),
66                           vec3(position_scr[2] - position_scr[0], 0.0)).z);
67
68    for(int i=0; i<3; ++i)
69    {
70        eval_ss[gl_InvocationID].heights_scr[i]
71                = area / length(position_scr[(i+2)%3] - position_scr[(i+1)%3]);
72        eval_ss[gl_InvocationID].vertices_obj[i]
73                = ctrl_position_obj[i*3].xyz;
74        eval_ss[gl_InvocationID].normEdges_obj[i]
75                = normalize(ctrl_position_obj[((i+2)%3)*3].xyz - ctrl_position_obj[((i+1)%3)*3].xyz);
76    }
77
78    bvec3 isEdgeLinear = bvec3(isLinear(0), isLinear(1), isLinear(2));
79    gl_TessLevelOuter = float[4](
80                isEdgeLinear[1]? 1: smoothness,
81                isEdgeLinear[2]? 1: smoothness,
82                isEdgeLinear[0]? 1: smoothness,
83                1);
84    gl_TessLevelInner = float[2](all(isEdgeLinear)? 1: smoothness, 1);
85    // Uncomment this for adaptive smoothing (using a very rough heristic).
86//    gl_TessLevelOuter = float[4](
87//                max(curviness(1) * smoothness, 1),
88//                max(curviness(2) * smoothness, 1),
89//                max(curviness(0) * smoothness, 1),
90//                1);
91}
92