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

overlay_extra_vert.glsl « shaders « overlay « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b2578970c9b0001efd5e05ed02fce65692e7bcc4 (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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)

#define lamp_area_size inst_data.xy
#define lamp_clip_sta inst_data.z
#define lamp_clip_end inst_data.w

#define lamp_spot_cosine inst_data.x
#define lamp_spot_blend inst_data.y

#define camera_corner inst_data.xy
#define camera_center inst_data.zw
#define camera_dist color.a
#define camera_dist_sta inst_data.z
#define camera_dist_end inst_data.w
#define camera_distance_color inst_data.x

#define empty_size inst_data.xyz
#define empty_scale inst_data.w

/* TODO(fclem): Share with C code. */
#define VCLASS_LIGHT_AREA_SHAPE (1 << 0)
#define VCLASS_LIGHT_SPOT_SHAPE (1 << 1)
#define VCLASS_LIGHT_SPOT_BLEND (1 << 2)
#define VCLASS_LIGHT_SPOT_CONE (1 << 3)
#define VCLASS_LIGHT_DIST (1 << 4)

#define VCLASS_CAMERA_FRAME (1 << 5)
#define VCLASS_CAMERA_DIST (1 << 6)
#define VCLASS_CAMERA_VOLUME (1 << 7)

#define VCLASS_SCREENSPACE (1 << 8)
#define VCLASS_SCREENALIGNED (1 << 9)

#define VCLASS_EMPTY_SCALED (1 << 10)
#define VCLASS_EMPTY_AXES (1 << 11)
#define VCLASS_EMPTY_AXES_NAME (1 << 12)
#define VCLASS_EMPTY_AXES_SHADOW (1 << 13)
#define VCLASS_EMPTY_SIZE (1 << 14)

void main()
{
  /* Extract data packed inside the unused mat4 members. */
  vec4 inst_data = vec4(inst_obmat[0][3], inst_obmat[1][3], inst_obmat[2][3], inst_obmat[3][3]);
  float inst_color_data = color.a;
  mat4 obmat = inst_obmat;
  obmat[0][3] = obmat[1][3] = obmat[2][3] = 0.0;
  obmat[3][3] = 1.0;

  finalColor = color;
  if (color.a < 0.0) {
    finalColor.a = 1.0;
  }

  float lamp_spot_sine;
  vec3 vpos = pos;
  vec3 vofs = vec3(0.0);
  /* Lights */
  if ((vclass & VCLASS_LIGHT_AREA_SHAPE) != 0) {
    /* HACK: use alpha color for spots to pass the area_size. */
    if (inst_color_data < 0.0) {
      lamp_area_size.xy = vec2(-inst_color_data);
    }
    vpos.xy *= lamp_area_size.xy;
  }
  else if ((vclass & VCLASS_LIGHT_SPOT_SHAPE) != 0) {
    lamp_spot_sine = sqrt(1.0 - lamp_spot_cosine * lamp_spot_cosine);
    lamp_spot_sine *= ((vclass & VCLASS_LIGHT_SPOT_BLEND) != 0) ? lamp_spot_blend : 1.0;
    vpos = vec3(pos.xy * lamp_spot_sine, -lamp_spot_cosine);
  }
  else if ((vclass & VCLASS_LIGHT_DIST) != 0) {
    /* Meh nasty mess. Select one of the 6 axes to display on. (see light_distance_z_get()) */
    int dist_axis = int(pos.z);
    float dist = pos.z - floor(pos.z) - 0.5;
    float inv = sign(dist);
    dist = (abs(dist) > 0.15) ? lamp_clip_end : lamp_clip_sta;
    vofs[dist_axis] = inv * dist / length(obmat[dist_axis].xyz);
    vpos.z = 0.0;
    if (lamp_clip_end < 0.0) {
      vpos = vofs = vec3(0.0);
    }
  }
  /* Camera */
  else if ((vclass & VCLASS_CAMERA_FRAME) != 0) {
    if ((vclass & VCLASS_CAMERA_VOLUME) != 0) {
      vpos.z = mix(color.b, color.a, pos.z);
    }
    else if (camera_dist > 0.0) {
      vpos.z = -abs(camera_dist);
    }
    else {
      vpos.z *= -abs(camera_dist);
    }
    vpos.xy = (camera_center + camera_corner * vpos.xy) * abs(vpos.z);
  }
  else if ((vclass & VCLASS_CAMERA_DIST) != 0) {
    vofs.xy = vec2(0.0);
    vofs.z = -mix(camera_dist_sta, camera_dist_end, pos.z);
    vpos.z = 0.0;
    /* Distance line endpoints color */
    if (any(notEqual(pos.xy, vec2(0.0)))) {
      /* Override color. */
      switch (int(camera_distance_color)) {
        case 0: /* Mist */
          finalColor = vec4(0.5, 0.5, 0.5, 1.0);
          break;
        case 1: /* Mist Active */
          finalColor = vec4(1.0, 1.0, 1.0, 1.0);
          break;
        case 2: /* Clip */
          finalColor = vec4(0.5, 0.5, 0.25, 1.0);
          break;
        case 3: /* Clip Active */
          finalColor = vec4(1.0, 1.0, 0.5, 1.0);
          break;
      }
    }
    /* Focus cross */
    if (pos.z == 2.0) {
      vofs.z = 0.0;
      if (camera_dist < 0.0) {
        vpos.z = -abs(camera_dist);
      }
      else {
        /* Disabled */
        vpos = vec3(0.0);
      }
    }
  }
  /* Empties */
  else if ((vclass & VCLASS_EMPTY_SCALED) != 0) {
    /* This is a bit silly but we avoid scaling the object matrix on CPU (saving a mat4 mul) */
    vpos *= empty_scale;
  }
  else if ((vclass & VCLASS_EMPTY_SIZE) != 0) {
    /* This is a bit silly but we avoid scaling the object matrix on CPU (saving a mat4 mul) */
    vpos *= empty_size;
  }
  else if ((vclass & VCLASS_EMPTY_AXES) != 0) {
    float axis = vpos.z;
    vofs[int(axis)] = (1.0 + fract(axis)) * empty_scale;
    /* Scale uniformly by axis length */
    vpos *= length(obmat[int(axis)].xyz) * empty_scale;

    vec3 axis_color = vec3(0.0);
    axis_color[int(axis)] = 1.0;
    finalColor.rgb = mix(axis_color + fract(axis), color.rgb, color.a);
    finalColor.a = 1.0;
  }

  /* Not exclusive with previous flags. */
  if ((vclass & VCLASS_CAMERA_VOLUME) != 0) {
    /* Unpack final color. */
    int color_class = int(floor(color.r));
    float color_intensity = fract(color.r);
    switch (color_class) {
      case 0: /* No eye (convergence plane). */
        finalColor = vec4(1.0, 1.0, 1.0, 1.0);
        break;
      case 1: /* Left eye. */
        finalColor = vec4(0.0, 1.0, 1.0, 1.0);
        break;
      case 2: /* Right eye. */
        finalColor = vec4(1.0, 0.0, 0.0, 1.0);
        break;
    }
    finalColor *= vec4(vec3(color_intensity), color.g);
  }

  vec3 world_pos;
  if ((vclass & VCLASS_SCREENSPACE) != 0) {
    /* Relative to DPI scaling. Have constant screen size. */
    vec3 screen_pos = screenVecs[0].xyz * vpos.x + screenVecs[1].xyz * vpos.y;
    vec3 p = (obmat * vec4(vofs, 1.0)).xyz;
    float screen_size = mul_project_m4_v3_zfac(p) * sizePixel;
    world_pos = p + screen_pos * screen_size;
  }
  else if ((vclass & VCLASS_SCREENALIGNED) != 0) {
    /* World sized, camera facing geometry. */
    vec3 screen_pos = screenVecs[0].xyz * vpos.x + screenVecs[1].xyz * vpos.y;
    world_pos = (obmat * vec4(vofs, 1.0)).xyz + screen_pos;
  }
  else {
    world_pos = (obmat * vec4(vofs + vpos, 1.0)).xyz;
  }

  if ((vclass & VCLASS_LIGHT_SPOT_CONE) != 0) {
    /* Compute point on the cone before and after this one. */
    vec2 perp = vec2(pos.y, -pos.x);
    const float incr_angle = 2.0 * 3.1415 / 32.0;
    const vec2 slope = vec2(cos(incr_angle), sin(incr_angle));
    vec3 p0 = vec3((pos.xy * slope.x + perp * slope.y) * lamp_spot_sine, -lamp_spot_cosine);
    vec3 p1 = vec3((pos.xy * slope.x - perp * slope.y) * lamp_spot_sine, -lamp_spot_cosine);
    p0 = (obmat * vec4(p0, 1.0)).xyz;
    p1 = (obmat * vec4(p1, 1.0)).xyz;
    /* Compute normals of each side. */
    vec3 edge = obmat[3].xyz - world_pos;
    vec3 n0 = normalize(cross(edge, p0 - world_pos));
    vec3 n1 = normalize(cross(edge, world_pos - p1));
    bool persp = (ProjectionMatrix[3][3] == 0.0);
    vec3 V = (persp) ? normalize(ViewMatrixInverse[3].xyz - world_pos) : ViewMatrixInverse[2].xyz;
    /* Discard non-silhouette edges. */
    bool facing0 = dot(n0, V) > 0.0;
    bool facing1 = dot(n1, V) > 0.0;
    if (facing0 == facing1) {
      /* Hide line by making it cover 0 pixels. */
      world_pos = obmat[3].xyz;
    }
  }

  gl_Position = point_world_to_ndc(world_pos);

  /* Convert to screen position [0..sizeVp]. */
  edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;

#ifdef SELECT_EDGES
  /* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the
   * wire to at least create one fragment that will pass the occlusion query. */
  /* TODO(fclem): Limit this workaround to selection. It's not very noticeable but still... */
  gl_Position.xy += drw_view.viewport_size_inverse * gl_Position.w *
                    ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
#endif

  view_clipping_distances(world_pos);
}