#version 460 layout (lines) in; layout (triangle_strip, max_vertices = 5) out; uniform mat4 transform; uniform vec3 lightPositionAndSize; in vec2 originalPos[]; out vec4 penumbras; mat2 adjugate(mat2 m) { return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]); } void workWithSegmentForward(float x) { vec2 endpoint_a = originalPos[0]; vec2 endpoint_b = originalPos[1]; vec2 endpoint = mix(endpoint_a, endpoint_b, x); float light_radius = lightPositionAndSize.z; // Deltas from the segment to the light center. vec2 delta_a = endpoint_a - lightPositionAndSize.xy; vec2 delta_b = endpoint_b - lightPositionAndSize.xy; vec2 delta = endpoint - lightPositionAndSize.xy; // Offsets from the light center to the edge of the light volume. vec2 offset_a = vec2(-light_radius, light_radius) * normalize(delta_a).xy; vec2 offset_b = vec2( light_radius, -light_radius) * normalize(delta_b).xy; vec2 offset = mix(offset_a, offset_b, x); vec2 penumbra_a = adjugate(mat2( offset_a, -delta_a))*(delta - mix(offset, delta_a, 0)); vec2 penumbra_b = adjugate(mat2(-offset_b, delta_b))*(delta - mix(offset, delta_b, 0)); // Vertex projection. gl_Position = transform * vec4(delta - offset, 0.0, 1.0); EmitVertex(); } void main() { vec4 a = gl_in[0].gl_Position; vec4 b = gl_in[1].gl_Position; vec2 aInv = originalPos[0]; vec2 bInv = originalPos[1]; vec2 lightPosition = lightPositionAndSize.xy; float lightSize = lightPositionAndSize.z; gl_Position = b; EmitVertex(); gl_Position = a; EmitVertex(); workWithSegmentForward(0); workWithSegmentForward(1); EndPrimitive(); // hard shadow geometry (umbra) //gl_Position = transform * vec4(aInv + (aInv - lightPositionAndSize.xy) * 10000, 0, 1); //EmitVertex(); //gl_Position = transform * vec4(bInv + (bInv - lightPositionAndSize.xy) * 10000, 0, 1); //EmitVertex(); // находим направления к вершинам линии /*vec2 deltaA = normalize(aInv - lightPosition); vec2 deltaB = normalize(bInv - lightPosition); // находим наклон прямых из центра float degA = acos(deltaA.x); float degB = acos(deltaB.x); // корректируем угол в зависимости, находимся ли мы в отрицательном Y if (deltaA.y < 0) { degA = -degA; } if (deltaB.y < 0) { degB = -degB; } /*if (degA < 0) { degA = 360 + degA; } if (degB < 0) { degB = 360 + degB; } // определяем, находимся ли мы "сзади" if (degA < degB) { vec2 temp = aInv; aInv = bInv; bInv = temp; // находим направления к вершинам линии deltaA = normalize(aInv - lightPosition); deltaB = normalize(bInv - lightPosition); // находим наклон прямых из центра degA = acos(deltaA.x); degB = acos(deltaB.x); // корректируем угол в зависимости, находимся ли мы в отрицательном Y if (deltaA.y < 0) { degA = -degA; } if (deltaB.y < 0) { degB = -degB; } if (degA < 0) { degA = 360 + degA; } if (degB < 0) { degB = 360 + degB; } }*/ // поворачиваем наши углы на 90 градусов /*degA -= 1.57079632; degB += 1.57079632; // Теперь для каждой вершины вычисляем касательную точку на окружности vec2 pointA = vec2(cos(degA), sin(degA)) * lightSize + lightPosition; vec2 pointB = vec2(cos(degB), sin(degB)) * lightSize + lightPosition; // мы нашли касательные точки, теперь просто надо провести прямые начиная от вершин // это у нас "hard shadows" gl_Position = transform * vec4(aInv + (aInv - pointA) * 10000, 0, 1); EmitVertex(); gl_Position = transform * vec4(bInv + (bInv - pointB) * 10000, 0, 1); EmitVertex(); gl_Position = b; EmitVertex(); EndPrimitive();*/ }