в вашем коде
float ld = length(p - pos);
Вычисляет ваше расстояние от света равномерно во всех направлениях (евклидово расстояние). Если вы хотите другое затенение, измените уравнение ...
Например, вы можете вычислить минимальное перпендикулярное расстояние до многоугольного источника света следующим образом:
Вершина:
// Vertex
#version 420 core
layout(location=0) in vec2 pos; // glVertex2f <-1,+1>
layout(location=8) in vec2 txr; // glTexCoord2f Unit0 <0,1>
out smooth vec2 t1; // fragment position <0,1>
void main()
{
t1=txr;
gl_Position=vec4(pos,0.0,1.0);
}
Фрагмент:
// Fragment
#version 420 core
uniform sampler2D txrmap; // texture unit
uniform vec2 t0; // mouse position <0,1>
in smooth vec2 t1; // fragment position <0,1>
out vec4 col;
// light shape
const int n=3;
const float ldepth=0.25; // distance to full disipation of light
const vec2 lpolygon[n]= // vertexes CCW
{
vec2(-0.05,-0.05),
vec2(+0.05,-0.05),
vec2( 0.00,+0.05),
};
void main()
{
int i;
float l;
vec2 p0,p1,p,n01;
// compute perpendicular distance to edges of polygon
for (p1=vec2(lpolygon[n-1]),l=0.0,i=0;i<n;i++)
{
p0=p1; p1=lpolygon[i]; // p0,p1 = edge of polygon
p=p1-p0; // edge direction
n01=normalize(vec2(+p.y,-p.x)); // edge normal CCW
// n01=normalize(vec2(-p.y,+p.x)); // edge normal CW
l=max(dot(n01,t1-t0-p0),l);
}
// convert to light strength
l = max(ldepth-l,0.0)/ldepth;
l=l*l*l;
// render
// col=l*texture2D(txrmap,t1);
col = l*vec4(1.0,1.0,1.0,0.0);
}
Я использовал подобный код Как реализовать эффект 2D лучевого освещения в GLSL в качестве отправной точки, следовательно, немного отличается имена переменных.
Идея состоит в том, чтобы вычислить перпендикулярное расстояние фрагмента до всех краев вашей формы света и выбрать самый большой, так как остальные обращены не на ту сторону.
lpolygon[n]
- это форма света относительно положения света t0
, а t1
- это положение фрагмента. Он должен быть в обмотке CCW, иначе вам нужно будет отменить нормальное вычисление (мое представление перевернуто, чтобы оно могло выглядеть как CW, а не как). Я использовал диапазон <0,1>
, так как вы можете использовать его в качестве координаты текстуры напрямую ...
Вот скриншот:
Вот некоторые объяснения:
Для аналитической формы вам необходимо использовать аналитическое вычисление расстояния ...