162 lines
4.2 KiB
GLSL
162 lines
4.2 KiB
GLSL
#version 330
|
|
|
|
layout(triangles) in;
|
|
layout(triangle_strip, max_vertices = 3) out;
|
|
|
|
uniform vec3 light_position;
|
|
uniform mat4 proj, model, view;
|
|
uniform float scale, inv_scale;
|
|
uniform float show_uvs;
|
|
uniform vec3 camera_local;
|
|
|
|
in vData {
|
|
vec3 normal;
|
|
vec3 normal_data;
|
|
vec3 tangent;
|
|
vec3 uv;
|
|
vec4 color;
|
|
} vertices[];
|
|
|
|
out fData {
|
|
vec3 to_eye;
|
|
vec3 to_light;
|
|
vec3 normal;
|
|
vec2 texcoord;
|
|
vec4 color;
|
|
} frag;
|
|
|
|
#if ROSY == 2
|
|
vec3 compat_orientation(vec3 q, vec3 ref, vec3 n) {
|
|
return q * sign(dot(q, ref));
|
|
}
|
|
#elif ROSY == 4
|
|
vec3 compat_orientation(vec3 q, vec3 ref, vec3 n) {
|
|
vec3 t = cross(n, q);
|
|
float dp0 = dot(q, ref), dp1 = dot(t, ref);
|
|
if (abs(dp0) > abs(dp1))
|
|
return q * sign(dp0);
|
|
else
|
|
return t * sign(dp1);
|
|
}
|
|
#else
|
|
vec3 rotate60(vec3 d, vec3 n) { return 0.8660254037 * cross(n, d) + 0.5 * (d + n * dot(n, d)); }
|
|
|
|
vec3 compat_orientation(vec3 q, vec3 ref, vec3 n) {
|
|
vec3 t[3] = vec3[](rotate60(q, -n), q, rotate60(q, n));
|
|
float dp[3] = float[](dot(t[0], ref), dot(t[1], ref), dot(t[2], ref));
|
|
float abs_dp[3] = float[](abs(dp[0]), abs(dp[1]), abs(dp[2]));
|
|
|
|
if (abs_dp[0] >= abs_dp[1] && abs_dp[0] >= abs_dp[2])
|
|
return t[0] * sign(dp[0]);
|
|
else if (abs_dp[1] >= abs_dp[0] && abs_dp[1] >= abs_dp[2])
|
|
return t[1] * sign(dp[1]);
|
|
else
|
|
return t[2] * sign(dp[2]);
|
|
}
|
|
#endif
|
|
|
|
#if POSY == 4
|
|
vec3 compat_position(vec3 o, vec3 ref, vec3 q, vec3 t, vec3 n) {
|
|
vec3 d = ref - o;
|
|
return o +
|
|
q * round(dot(q, d) * inv_scale) * scale +
|
|
t * round(dot(t, d) * inv_scale) * scale;
|
|
}
|
|
#else
|
|
vec3 compat_position(vec3 o, vec3 ref, vec3 q, in vec3 t, vec3 n) {
|
|
vec3 d = ref - o;
|
|
t = rotate60(q, n);
|
|
|
|
float dpq = dot(q, d), dpt = dot(t, d);
|
|
float u = floor(( 4*dpq - 2*dpt) * (1.0f / 3.0f) * inv_scale);
|
|
float v = floor((-2*dpq + 4*dpt) * (1.0f / 3.0f) * inv_scale);
|
|
|
|
q *= scale; t *= scale;
|
|
o = o + q*u + t*v - ref;
|
|
|
|
vec3 candidates[] = vec3[4](o, o+q, o+t, o+q+t);
|
|
|
|
float best_length = 1e20;
|
|
int best_index = -1;
|
|
for (int i=0; i<4; ++i) {
|
|
float length = dot(candidates[i], candidates[i]);
|
|
if (length < best_length) {
|
|
best_length = length;
|
|
best_index = i;
|
|
}
|
|
}
|
|
return candidates[best_index] + ref;
|
|
}
|
|
#endif
|
|
|
|
void main() {
|
|
vec3 face_normal = normalize(cross(
|
|
gl_in[1].gl_Position.xyz-gl_in[0].gl_Position.xyz,
|
|
gl_in[2].gl_Position.xyz-gl_in[0].gl_Position.xyz));
|
|
|
|
if (dot(gl_in[0].gl_Position.xyz - camera_local, face_normal) > 0.0)
|
|
return;
|
|
|
|
vec2 texcoord[3];
|
|
if (show_uvs == 1.0) {
|
|
/* Step 1: Rotate everthing into the triangle plane */
|
|
vec3 tangents[3], uv[3];
|
|
for (int i=0; i<3; ++i) {
|
|
float cosTheta = dot(vertices[i].normal_data, face_normal);
|
|
|
|
if (cosTheta < 0.9999f) {
|
|
vec3 axis = cross(vertices[i].normal_data, face_normal);
|
|
float sinTheta2 = dot(axis, axis),
|
|
factor = (1.0 - cosTheta) / sinTheta2;
|
|
|
|
vec3 v_tangent = vertices[i].tangent;
|
|
tangents[i] = v_tangent * cosTheta + cross(axis, v_tangent)
|
|
+ axis * dot(axis, v_tangent) * factor;
|
|
|
|
vec3 v_uv = vertices[i].uv - gl_in[i].gl_Position.xyz;
|
|
uv[i] = v_uv * cosTheta + cross(axis, v_uv)
|
|
+ axis * dot(axis, v_uv) * factor + gl_in[i].gl_Position.xyz;
|
|
} else {
|
|
tangents[i] = vertices[i].tangent;
|
|
uv[i] = vertices[i].uv;
|
|
}
|
|
}
|
|
|
|
/* Step 2: search orientation field quotient space */
|
|
for (int i=1; i<3; ++i)
|
|
tangents[i] = compat_orientation(tangents[i], tangents[0], face_normal);
|
|
|
|
vec3 bitangents[3];
|
|
for (int i=0; i<3; ++i)
|
|
bitangents[i] = cross(face_normal, tangents[i]);
|
|
|
|
/* Step 3: search position field quotient space */
|
|
for (int i=1; i<3; ++i)
|
|
uv[i] = compat_position(uv[i], uv[0], tangents[i], bitangents[i], face_normal);
|
|
|
|
/* Step 4: compute uv coordinates */
|
|
for (int i=0; i<3; ++i) {
|
|
vec3 rel = gl_in[i].gl_Position.xyz - uv[i];
|
|
texcoord[i] = vec2(
|
|
dot(rel, tangents[i]) * inv_scale,
|
|
dot(rel, bitangents[i]) * inv_scale
|
|
);
|
|
}
|
|
}
|
|
|
|
for (int i=0; i<3; ++i) {
|
|
vec4 pos_camera = view * (model * gl_in[i].gl_Position);
|
|
vec3 vn = vertices[i].normal;
|
|
|
|
gl_Position = proj * pos_camera;
|
|
frag.to_light = (view * vec4(light_position, 1.0)).xyz - pos_camera.xyz;
|
|
frag.to_eye = -pos_camera.xyz;
|
|
frag.normal = (model * (view * vec4(vn, 0.0))).xyz;
|
|
frag.texcoord = texcoord[i];
|
|
frag.color = vertices[i].color;
|
|
|
|
EmitVertex();
|
|
}
|
|
EndPrimitive();
|
|
}
|