У меня есть TileSet
, и я пытаюсь применить пользовательские Shader
и ShaderMaterial
к одной из моих плиток. Однако он не затеняет нужную область. Я новичок как в Godot, так и в разработке игр, но все, что я прочитал, похоже, указывает на то, что мой код правильный.
shader_type canvas_item;
uniform vec2 points[3]; // Polygon points
uniform vec2 atlas_id; // atlas position within the TileSet
uniform vec2 tile_size = vec2(32.0, 32.0);
uniform vec4 modulate_color : source_color;
// code generated by Copilot
bool point_in_triangle(vec2 p, vec2 p0, vec2 p1, vec2 p2) {
vec2 v0 = p2 - p0;
vec2 v1 = p1 - p0;
vec2 v2 = p - p0;
float dot00 = dot(v0, v0);
float dot01 = dot(v0, v1);
float dot02 = dot(v0, v2);
float dot11 = dot(v1, v1);
float dot12 = dot(v1, v2);
float invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
return (u >= 0.0) && (v >= 0.0) && (u + v < 1.0);
}
void fragment() {
vec2 top_left_px = atlas_id * tile_size;
vec2 pixel_coordinate = UV / TEXTURE_PIXEL_SIZE;
pixel_coordinate[0] = mod(pixel_coordinate[0], tile_size[0]);
vec2 relative_coord = pixel_coordinate - top_left_px;
// Check if the current fragment is inside the triangle
if (point_in_triangle(relative_coord, points[0], points[1], points[2])) {
COLOR *= modulate_color;
}
}
Текстура моего TileSet имеет размер 256x256 с плитками 32x32.
Я пытаюсь заштриховать треугольники в третьем ряду с помощью шейдера. Это результат приведенного выше кода.
Хоть убей, я не могу понять, что я делаю не так. Если бы мне пришлось угадывать, то это расчет vec2 pixel_coordinate = UV / TEXTURE_PIXEL_SIZE;
. Я просто не понимаю почему и не нашел хорошего способа отладки шейдера без отладчика или printf.
Когда я жестко запрограммировал размер текстуры, он работает отлично.
vec2 pixel_coordinate = UV * vec2(256.0, 256.0);
Это вряд ли идеально. Я сделал его однородным, но это по-прежнему означает, что если я когда-нибудь изменю размер текстуры, мне придется обновить каждое место, где я использую этот шейдер. Мне все же хотелось бы общего ответа.
Я почти уверен, что это не код обнаружения треугольника. Я заменил код простой проверкой, находится ли он в прямоугольнике, содержащем треугольник, и позиции по-прежнему отклоняются от тех же полей.
Просто отключите заполнение текстуры в конфигурации TileSet, шейдер применяется к исходной текстуре и не учитывает заполнение, отсюда и странное масштабирование.
У меня не было времени полностью продумать логику
point_in_triangle
, ноdot01 * dot01
кажется мне странным. Поскольку остальная часть функции очень симметрична, я ожидаю, что одна из них будетdot10
.