pascalabcnet/InstallerSamples/StandardUnits/OpenGL и OpenCL/OpenGLABC/Точки на поле/Сумма расстояний.frag

87 lines
2.6 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#version 460 core
noperspective in vec2 logic_pos;
layout(location = 0) uniform int point_count;
layout(binding = 0) buffer points_in {
dvec2 data[];
} points;
layout(location = 1) uniform double camera_aspect_ratio;
layout(location = 2) uniform double camera_scale;
layout(location = 3) uniform dvec2 camera_pos;
/**
layout(binding = 1) buffer temp_otp {
dvec2 data[3];
} temp;
/**/
out vec3 color;
// Радиус красной точки
const float point_r = 5;
// Скорость затемнения при отдалении от точки
const float fall_speed = 0.6;
const bool fall_range_debug = false;
void main() {
// В идеале это надо считать в геометрическом шейдере,
// или даже на CPU... Но для этого надо менять код, общий с другими примерами
float min_r_sum = 0;
dvec2 d_center = {0,0};
for (int i=0; i<point_count; ++i) d_center += points.data[i];
d_center /= point_count;
vec2 center = vec2( d_center );
for (int i=0; i<point_count; ++i)
min_r_sum += distance(center, vec2(points.data[i]));
// Считаем в фрагментном шейдере, потому что интерполяция
// 64-битного logic_pos (с типом dvec2) в OpenGL запрещена
dvec2 pos = { logic_pos.x*camera_aspect_ratio, logic_pos.y };
pos *= camera_scale;
pos += camera_pos;
if (fall_range_debug && distance(pos, d_center)<point_r) {
color = vec3(0, 0, 0.7);
return;
}
float r_sum = 0;
for (int i=0; i<point_count; ++i) {
dvec2 dp = pos - points.data[i];
float r = sqrt(float(dot(dp, dp)));
if (r<point_r) {
color = vec3(0.7, 0, 0);
return;
}
r_sum += r;
}
// Функция формы y=1/x, но маштабированная чтобы y(min_r_sum)=1
double d_fall = min_r_sum/r_sum;
float fall = pow(float(d_fall), fall_speed);
// Ступеньки из оттенков серого
if (true) {
int color_count = 64;
fall = round(fall*color_count) / color_count;
}
// center всё же не всегда имеет наименьшую сумму расстояний
// Поэтому min_r_sum может считаться неправильно и fall оказываться >1
// Наверное, нужен итерационный алгоритм на стороне CPU, чтобы адекватно это сделать
// Напишите если есть идеи лучше
if (fall_range_debug && fall>1) {
color = vec3(0.8, 0, 0.8);
return;
}
color = vec3( fall );
}