Skip to content

Commit

Permalink
Merge pull request #74 from MrTanoshii/shader-comments
Browse files Browse the repository at this point in the history
Added comments for shader file and a bit for pathfinding algorithm
  • Loading branch information
Jeb4dev committed Apr 1, 2023
2 parents d99fb4b + c9a0d33 commit d781478
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 13 deletions.
62 changes: 51 additions & 11 deletions src/assets/shaders/lights.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,41 @@ uniform int obstaclesCount;

bool segmentsIntersection(vec2 first, vec2 second, vec2 third, vec2 fourth)
{
vec3 r = vec3(second - first, 0.0);
vec3 s = vec3(fourth - third, 0.0);
vec3 first_third = vec3(third - first, 0.0);
/*
Checks if two segments intersect
vec2 first: x, y of the first end of the first segment
vec2 second: x, y of the second end of the first segment
vec2 third: x, y of the first end of the second segment
vec2 fourth: x, y of the second end of the second segment
float t_numerator = cross(first_third, s).z;
float u_numerator = cross(first_third, r).z;
float denominator = cross(r, s).z;
return bool: true if segments intersect, false if not
if (abs(denominator) <= 1e-8)
return false;
to get familiar with what's going on here, you can read the following article on wikipedia:
https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line_segment
*/

vec3 r = vec3(second - first, 0.0); // the same as (x2 - x1, y2 - y1) in the article
vec3 s = vec3(fourth - third, 0.0); // the same as (x4 - x3, y4 - y3) in the article
vec3 first_third = vec3(third - first, 0.0); // the same as (x3 - x1, y3 - y1) in the article

// these three vectors are three-dimensional, because I decided to find determinant using cross-product
// of two two-dimensional vectors

float t_numerator = cross(first_third, s).z; // numerator of t from the article
float u_numerator = cross(first_third, r).z; // numerator of u from the article
float denominator = cross(r, s).z; // denominator from the article (t and u have the same denominator)

if (abs(denominator) <= 1e-8) // if determinant is zero (or approximately equal to), then
return false; // the segments are parallel therefore do not intersect

// then we should test if t and u are in the interval [0, 1], if they are then segments intersecting
// but division is time-consuming operation, doing some math, we can avoid division
// that is what's going on in the lines below

// if both numerator and denominator are positive
if (0.0 <= t_numerator && t_numerator <= denominator && 0.0 <= u_numerator && u_numerator <= denominator)
return true;
// if both numerator and denominator are negative
else if (denominator <= t_numerator && t_numerator <= 0.0 && denominator <= u_numerator && u_numerator <= 0.0)
return true;
else
Expand All @@ -35,6 +57,17 @@ bool segmentsIntersection(vec2 first, vec2 second, vec2 third, vec2 fourth)

bool segmentRectangleIntersection(vec4 segment, vec4 rectangle)
{
/*
Checks if given segment intersects given rectangle
vec4 segment: x, y of the first end of the segment and x, y of the second end of the segment
vec4 rectangle x, y of the top left vertex of the rectangle and x, y of the bottom right vertex
return bool: true if a segment intersects rectangle else false
if a line intersects a rectangle, then it intersects at least one of it's diagonal,
hence instead of checking four sides, we can check for intersection only diagonals
the game draws obstacles after calculating the lights, hence in the end we obtain a nice picture
*/
vec4 firstDiagonal = rectangle;
vec4 secondDiagonal = vec4(rectangle.z, rectangle.y, rectangle.x, rectangle.w);

Expand All @@ -49,11 +82,18 @@ bool segmentRectangleIntersection(vec4 segment, vec4 rectangle)

float computeLight(vec3 light, vec2 pixelPosition)
{
/*
Calculates how much light is in given point
vec3 light: x, y, radius of a light
vec2 pixelPosition: x, y of a pixel that we are checking
return float: number in interval [0, 1] that tells us how much light in the pixel
*/
float _distance = length(light.xy - pixelPosition);

vec4 segment = vec4(light.xy, pixelPosition);


// Check every rectangle (obstacle) on a game plane
for (int i = 0; i < obstaclesCount; ++i)
if (segmentRectangleIntersection(segment, obstacles[i].xyzw))
return 0.0;
Expand All @@ -70,8 +110,8 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord )
for (int i = 0; i < lightCount; ++i)
{
float lightAmount = computeLight(lightSources[i].xyz, fragCoord);
vec4 color = mix(blackColor, LIGHT_COLOR, lightAmount);
preFragColor = mix(preFragColor, color, lightAmount);
vec4 color = mix(blackColor, LIGHT_COLOR, lightAmount); // mix obtained light amount with light color
preFragColor = mix(preFragColor, color, lightAmount); // mix obtained color with color of texture
}

fragColor = preFragColor;
Expand Down
5 changes: 3 additions & 2 deletions src/classes/world.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,16 @@ def tile_to_screen(self, tile_x: int, tile_y: int) -> tuple[int, int]:
@lru_cache()
def pathfinding(self, start: tuple[int, int], destination: tuple[int, int]) -> list[tuple[int, int]] | None:
"""
A* algorithm realization
Uses manhattan distance as heuristics
:param start: tuple of absolute coordinates of start position
:param destination: tuple of absolute coordinates of destination position
:return: list of absolute coordinates or None if path not found
"""

start_tile = self.screen_to_tile(*start)
destination_tile = self.screen_to_tile(*destination)
print(self.grid[destination_tile])
print(destination_tile)

lengths = np.full((int(self.map.width), int(self.map.height)), -1)
lengths[start_tile] = 0
Expand Down

0 comments on commit d781478

Please sign in to comment.