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

gpu_shader_instance_bone_envelope_solid_vert.glsl « shaders « gpu « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d0f2a8dcd51f4557c98ba84a08bec19cb1f73021 (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


/* This shader essentially operates in Object space, where it aligns given geometry with bone, scales it accordingly
 * to given radii, and then does usual basic solid operations.
 * Note that if one of head/tail radius is negative, it assumes it only works on the other end of the bone
 * (used to draw head/tail spheres). */


uniform mat4 ViewMatrix;
uniform mat4 ViewProjectionMatrix;


/* ---- Instanciated Attribs ---- */
in vec4 pos;  /* w encodes head (== 0.0f), tail (== 1.0f) or in-between. */

/* ---- Per instance Attribs ---- */
in mat4 InstanceModelMatrix;
in vec4 color;

in float radius_head;
in float radius_tail;


out vec3 normal;
flat out vec4 finalColor;


void main()
{
	/* We get head/tail in object space. */
	vec4 head = InstanceModelMatrix * vec4(0.0f, 0.0f, 0.0f, 1.0f);
	vec4 tail = InstanceModelMatrix * vec4(0.0f, 1.0f, 0.0f, 1.0f);

	/* We need rotation from bone mat, but not scaling. */
	mat3 bone_mat = mat3(InstanceModelMatrix);
	bone_mat[0] = normalize(bone_mat[0]);
	bone_mat[1] = normalize(bone_mat[1]);
	bone_mat[2] = normalize(bone_mat[2]);

	mat3 nor_mat = transpose(inverse(mat3(ViewMatrix) * bone_mat));

	/* Where does this comes from???? Don't know why, but is mandatory anyway... :/ */
	const float size = 2.0f;

	head.xyz *= size;
	tail.xyz *= size;

	bool head_only = (radius_tail < 0.0f);
	bool tail_only = (radius_head < 0.0f);
	/* == 0: head; == 1: tail; in-between: along bone. */
	float head_fac = head_only ? 0.0f : (tail_only ? 1.0f : pos.w);

	vec4 ob_pos;
	vec4 ob_bone_origin;
	float radius;

	/* head */
	if (head_fac <= 0.0f) {
		if (!head_only) {
			/* We are drawing the body itself, need to adjust start/end positions and radius! */
			vec3 bone_vec = tail.xyz - head.xyz;
			float len = length(bone_vec);

			if (len > (radius_head + radius_tail)) {
				float fac = (len - radius_head) / len;
				radius = fac * radius_head + (1.0f - fac) * radius_tail;
				bone_vec /= len;
				ob_bone_origin = vec4(head.xyz + bone_vec * radius_head * size, 1.0f);
			}
			else {
				radius = (radius_head + radius_tail) / 2.0f;
				ob_bone_origin = (head + tail) / 2.0f;
			}
		}
		else {
			radius = radius_head;
			ob_bone_origin = head;
		}
	}
	/* tail */
	else if (head_fac >= 1.0f) {
		if (!tail_only) {
			/* We are drawing the body itself, need to adjust start/end positions and radius! */
			vec3 bone_vec = tail.xyz - head.xyz;
			float len = length(bone_vec);

			if (len > (radius_head + radius_tail)) {
				float fac = (len - radius_tail) / len;
				radius = fac * radius_tail + (1.0f - fac) * radius_head;
				bone_vec /= len;
				ob_bone_origin = vec4(tail.xyz - bone_vec * radius_tail * size, 1.0f);
			}
			else {
				radius = (radius_head + radius_tail) / 2.0f;
				ob_bone_origin = (head + tail) / 2.0f;
			}
		}
		else {
			radius = radius_tail;
			ob_bone_origin = tail;
		}
	}
	/* Body of the bone */
#if 0  /* Note: not used currently! */
	else {
		float tail_fac = 1.0f - head_fac;
		radius = radius_head * head_fac + radius_tail * tail_fac;
		ob_bone_origin = head * head_fac + tail * tail_fac;
	}
#endif

	/* Yep, since input pos is unit sphere coordinates, it's also our normal. */
	vec3 nor = pos.xyz;
	ob_pos = pos * radius * size;
	ob_pos.xyz = bone_mat * ob_pos.xyz;
	ob_pos.w = 1.0f;

	gl_Position = ViewProjectionMatrix * (ob_pos + ob_bone_origin);
	normal = normalize(nor_mat * nor);
	finalColor = color;
}