Welcome to mirror list, hosted at ThFree Co, Russian Federation.

common_subdiv_lib.glsl « shaders « intern « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d76a7369f795ccab1690ee02ec84d95a80908ed0 (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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;

/* Uniform block for #DRWSubivUboStorage. */
layout(std140) uniform shader_data
{
  /* Offsets in the buffers data where the source and destination data start. */
  int src_offset;
  int dst_offset;

  /* Parameters for the DRWPatchMap. */
  int min_patch_face;
  int max_patch_face;
  int max_depth;
  int patches_are_triangular;

  /* Coarse topology information. */
  int coarse_poly_count;
  uint edge_loose_offset;

  /* Subdiv topology information. */
  uint num_subdiv_loops;

  /* Subdivision settings. */
  bool optimal_display;

  /* Sculpt data. */
  bool has_sculpt_mask;

  /* Masks for the extra coarse face data. */
  uint coarse_face_select_mask;
  uint coarse_face_smooth_mask;
  uint coarse_face_active_mask;
  uint coarse_face_hidden_mask;
  uint coarse_face_loopstart_mask;

  /* Total number of elements to process. */
  uint total_dispatch_size;
};

uint get_global_invocation_index()
{
  uint invocations_per_row = gl_WorkGroupSize.x * gl_NumWorkGroups.x;
  return gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * invocations_per_row;
}

/* Structure for #CompressedPatchCoord. */
struct BlenderPatchCoord {
  int patch_index;
  uint encoded_uv;
};

vec2 decode_uv(uint encoded_uv)
{
  float u = float((encoded_uv >> 16) & 0xFFFFu) / 65535.0;
  float v = float(encoded_uv & 0xFFFFu) / 65535.0;
  return vec2(u, v);
}

/* This structure is a carbon copy of OpenSubDiv's PatchTable::PatchHandle. */
struct PatchHandle {
  int array_index;
  int patch_index;
  int vertex_index;
};

/* This structure is a carbon copy of OpenSubDiv's PatchCoord. */
struct PatchCoord {
  int array_index;
  int patch_index;
  int vertex_index;
  float u;
  float v;
};

/* This structure is a carbon copy of OpenSubDiv's PatchCoord.QuadNode.
 * Each child is a bitfield. */
struct QuadNode {
  uvec4 child;
};

bool is_set(uint i)
{
  /* QuadNode.Child.isSet is the first bit of the bitfield. */
  return (i & 0x1u) != 0;
}

bool is_leaf(uint i)
{
  /* QuadNode.Child.isLeaf is the second bit of the bitfield. */
  return (i & 0x2u) != 0;
}

uint get_index(uint i)
{
  /* QuadNode.Child.index is made of the remaining bits. */
  return (i >> 2) & 0x3FFFFFFFu;
}

/* Duplicate of #PosNorLoop from the mesh extract CPU code.
 * We do not use a vec3 for the position as it will be padded to a vec4 which is incompatible with
 * the format. */
struct PosNorLoop {
  float x, y, z;
  /* TODO(@kevindietrich): figure how to compress properly as GLSL does not have char/short types,
   * bit operations get tricky. */
  float nx, ny, nz;
  float flag;
};

struct LoopNormal {
  float nx, ny, nz, flag;
};

vec3 get_vertex_pos(PosNorLoop vertex_data)
{
  return vec3(vertex_data.x, vertex_data.y, vertex_data.z);
}

vec3 get_vertex_nor(PosNorLoop vertex_data)
{
  return vec3(vertex_data.nx, vertex_data.ny, vertex_data.nz);
}

LoopNormal get_normal_and_flag(PosNorLoop vertex_data)
{
  LoopNormal loop_nor;
  loop_nor.nx = vertex_data.nx;
  loop_nor.ny = vertex_data.ny;
  loop_nor.nz = vertex_data.nz;
  loop_nor.flag = vertex_data.flag;
  return loop_nor;
}

void set_vertex_pos(inout PosNorLoop vertex_data, vec3 pos)
{
  vertex_data.x = pos.x;
  vertex_data.y = pos.y;
  vertex_data.z = pos.z;
}

/* Set the vertex normal but preserve the existing flag. This is for when we compute manually the
 * vertex normals when we cannot use the limit surface, in which case the flag and the normal are
 * set by two separate compute pass. */
void set_vertex_nor(inout PosNorLoop vertex_data, vec3 nor)
{
  vertex_data.nx = nor.x;
  vertex_data.ny = nor.y;
  vertex_data.nz = nor.z;
}

void set_vertex_nor(inout PosNorLoop vertex_data, vec3 nor, float flag)
{
  set_vertex_nor(vertex_data, nor);
  vertex_data.flag = flag;
}

void add_newell_cross_v3_v3v3(inout vec3 n, vec3 v_prev, vec3 v_curr)
{
  n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]);
  n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]);
  n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]);
}

#define ORIGINDEX_NONE -1

#ifdef SUBDIV_POLYGON_OFFSET
layout(std430, binding = 0) readonly buffer inputSubdivPolygonOffset
{
  uint subdiv_polygon_offset[];
};

/* Given the index of the subdivision quad, return the index of the corresponding coarse polygon.
 * This uses subdiv_polygon_offset and since it is a growing list of offsets, we can use binary
 * search to locate the right index. */
uint coarse_polygon_index_from_subdiv_quad_index(uint subdiv_quad_index, uint coarse_poly_count)
{
  uint first = 0;
  uint last = coarse_poly_count;

  while (first != last) {
    uint middle = (first + last) / 2;

    if (subdiv_polygon_offset[middle] < subdiv_quad_index) {
      first = middle + 1;
    }
    else {
      last = middle;
    }
  }

  if (subdiv_polygon_offset[first] == subdiv_quad_index) {
    return first;
  }

  return first - 1;
}
#endif