Compare commits

...

2 Commits

Author SHA1 Message Date
e375dc02aa git commit 2025-09-27 19:04:04 +03:00
6e5241c4cb work on some water 2025-09-27 09:32:37 +03:00
16 changed files with 13621 additions and 3314 deletions

View File

@ -1,8 +1,13 @@
#scope_file
char_pos : Vector3 = .{0.0, 1.5, 0.0};
rotation : float = 0.0;
cam : Camera = .{
far = 2000.0,
near = 1.0
near = 1.0,
target = .{0.0, 0.0, 0.0},
position = .{0.0, 0.0, 0.0}
};
#scope_export
@ -10,11 +15,25 @@ game_init :: () {
}
game_tick :: () {
cam.position += Vector3.{0.01, 0.0, 0.0};
cam.target += Vector3.{0.01, 0.0, 0.0};
speed := 0.1;
forward := Vector3.{1.0, 0.0, 0.0};
char_pos += speed * forward;
cam.position = char_pos;
cam.target = char_pos + forward;
}
game_draw :: () {
if is_in_reflection_pass {
cam.position.y *= -1;
cam.target.y *= -1;
}
draw_sky(*cam);
draw_ground_plane(*cam);
if !is_in_reflection_pass then draw_ground_plane(*cam);
if is_in_reflection_pass {
cam.position.y *= -1;
cam.target.y *= -1;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,12 @@ get_level_editor_camera :: () -> Camera {
camera.position = camera.target;
camera.position += cameraDir * cameraDist;
if is_in_reflection_pass {
camera.position.y *= -1;
camera.target.y *= -1;
}
return camera;
}
@ -275,11 +281,8 @@ tick_level_editor :: () {
}
}
draw_level_editor :: () {
draw_sky(*get_level_editor_camera(), *world.conf);
draw_ground_plane(*get_level_editor_camera(), *world.conf);
cam := get_level_editor_camera();
mvp := create_viewproj(*cam);
draw_world_triles :: (cam: *Camera, world: *World) {
mvp := create_viewproj(cam);
vs_params : Trile_Vs_Params;
vs_params.mvp = mvp.floats;
@ -321,31 +324,14 @@ draw_level_editor :: () {
sg_apply_uniforms(UB_trile_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, cast(s32) trilegfx.vertex_count, idx);
}
}
if show_trile_preview && !trile_preview_disabled {
positions : [1]Vector4;
trilegfx := get_trile_gfx(editor_current_trile.name);
positions[0] = .{xx trile_preview_x, xx trile_preview_y, xx trile_preview_z, 0.0};
offset := sg_append_buffer(gPipelines.trile.bind.vertex_buffers[3], *(sg_range.{
ptr = positions.data,
size = size_of(type_of(positions)),
}));
bindings : sg_bindings;
bindings.vertex_buffers[0] = trilegfx.vertex_buffer;
bindings.vertex_buffers[1] = trilegfx.normal_buffer;
bindings.vertex_buffers[2] = trilegfx.centre_buffer;
bindings.vertex_buffers[3] = gPipelines.trile.bind.vertex_buffers[3];
bindings.vertex_buffer_offsets[3] = offset;
bindings.samplers[0] = gPipelines.trile.bind.samplers[0];
bindings.images[0] = trilegfx.trixel_colors;
sg_apply_bindings(*bindings);
sg_apply_uniforms(UB_trile_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params))}));
sg_apply_uniforms(UB_trile_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, cast(s32) trilegfx.vertex_count, 1);
}
draw_level_editor :: () {
cam := get_level_editor_camera();
update_image_from_ground(*world, *gPipelines.plane.bind.images[2]);
draw_sky(*get_level_editor_camera(), *world.conf);
if !is_in_reflection_pass then draw_ground_plane(*get_level_editor_camera(), *world.conf);
draw_world_triles(*cam, *world);
}
draw_level_editor_ui :: (theme: *GR.Overall_Theme) {

View File

@ -116,6 +116,8 @@ init_after_asset_pack :: () {
game_init();
}
is_in_reflection_pass : bool = false;
frame :: () {
delta_time = get_time() - last_frame_time;
last_frame_time = get_time();
@ -143,10 +145,23 @@ frame :: () {
sgl_matrix_mode_projection();
sgl_ortho(0.0, sapp_widthf(), sapp_heightf(), 0.0, -1.0, +1.0);
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
tick_ui();
sg_begin_pass(*(sg_pass.{ action = gPipelines.plane.pass_action, attachments = gPipelines.plane.attachments}));
is_in_reflection_pass = true;
draw_editor();
if !in_editor_view then game_draw();
is_in_reflection_pass = false;
sg_end_pass();
sg_begin_pass(*(sg_pass.{ action = state.pass_action_clear, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
draw_editor();
uiTex := Ui_Texture.{*gPipelines.plane.bind.images[2]};
set_shader_for_images(*uiTex);
r := GR.get_rect(500,500,300,300);
immediate_quad(.{r.x, r.y}, .{r.x + r.w, r.y}, .{r.x + r.w, r.y + r.h}, .{r.x, r.y + r.h});
set_shader_for_color();
if !in_editor_view then game_draw();
ui_pass();
sg_end_pass();
sg_commit();

View File

@ -1,6 +1,8 @@
Pipeline_Binding :: struct {
pipeline : sg_pipeline;
bind : sg_bindings;
pipeline : sg_pipeline;
bind : sg_bindings;
attachments : sg_attachments;
pass_action : sg_pass_action;
}
g_specular_lut : sg_image;
@ -281,12 +283,28 @@ create_sky_pipeline :: () {
gPipelines.sky.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
}
// @ToDo: This needs to be redone when the window is resized;
create_plane_pipeline_reflection_image :: (binding: *sg_bindings) {
reflection_img := sg_alloc_image();
w, h := get_window_size();
img_desc := sg_image_desc.{
width = w,
height = h,
pixel_format = .RGBA8,
render_target = true,
sample_count = 1,
};
binding.images[0] = sg_make_image(*img_desc);
binding.images[1] = sg_make_image(*img_desc);
}
create_plane_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := plane_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.buffers[0].stride = 4*3;
pipeline.layout.attrs[ATTR_plane_position] = .{ format = .FLOAT3, buffer_index = 0 };
pipeline.index_type = .UINT16;
pipeline.depth = .{
@ -325,6 +343,41 @@ create_plane_pipeline :: () {
gPipelines.plane.bind.index_buffer = sg_make_buffer(*ibuffer);
gPipelines.plane.bind.vertex_buffers[0] = sg_make_buffer(*vbuffer);
create_plane_pipeline_reflection_image(*gPipelines.plane.bind);
attachmentsDesc := sg_attachments_desc.{
colors[0].image = gPipelines.plane.bind.images[0],
depth_stencil.image = gPipelines.plane.bind.images[1],
};
gPipelines.plane.attachments = sg_make_attachments(*attachmentsDesc);
gPipelines.plane.pass_action = .{
colors[0] = .{ load_action = .CLEAR, clear_value = .{ 0.25, 0.25, 0.25, 1.0 } },
};
gPipelines.plane.bind.samplers[0] = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
materialdata : [1000*1000*4]u8;
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{materialdata.data, materialdata.count};
ground_img_desc := sg_image_desc.{
width = 1000,
height = 1000,
pixel_format = .RGBA8,
render_target = false,
sample_count = 1,
data = imgdata
};
gPipelines.plane.bind.images[2] = sg_make_image(*ground_img_desc);
}
create_arbtri_pipeline :: () {
@ -358,4 +411,5 @@ create_arbtri_pipeline :: () {
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}

View File

@ -14,5 +14,5 @@ log_content :: (format_string: string, args: .. Any, loc := #caller_location, fl
} @PrintLike
logger :: (message: string, data: *void, info: Log_Info) {
print("%\n", message);
print("% % %\n", message, data, info);
}

View File

@ -3,6 +3,12 @@ draw_ground_plane :: (cam: *Camera, worldConfig: *World_Config = null) {
vs_params : Plane_Vs_Params;
world_conf : Plane_World_Config;
plane_data : Plane_Data;
w, h := get_window_size();
plane_data.screen_w = w;
plane_data.screen_h = h;
plane_data.is_reflection_pass = xx ifx is_in_reflection_pass then 1 else 0;
wc : *World_Config = ifx worldConfig == null then *(World_Config.{}) else worldConfig;
@ -13,5 +19,11 @@ draw_ground_plane :: (cam: *Camera, worldConfig: *World_Config = null) {
sg_apply_bindings(*gPipelines.plane.bind);
sg_apply_uniforms(UB_plane_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_apply_uniforms(UB_plane_world_config, *(sg_range.{ptr = *world_conf, size = size_of(type_of(world_conf))}));
sg_draw(0, 6, 128);
sg_apply_uniforms(UB_plane_data, *(sg_range.{ptr = *plane_data, size = size_of(type_of(plane_data))}));
if wc.planeType == 1 {
sg_draw(0, 6, 1);
} else {
sg_draw(0, 6, 128);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ out flat int idx;
void main() {
vec3 multisize = vec3(position.xyz * 1000.0);
gl_Position = mvp * (vec4(multisize.x, 0.0 + float(gl_InstanceIndex) * 0.003, multisize.z, 1.0));
pos = position;
gl_Position = mvp * (vec4(multisize.x, 0.0 + float(gl_InstanceIndex) * 0.006, multisize.z, 1.0));
pos = vec4(multisize, 1.0);
idx = gl_InstanceIndex;
}
@end
@ -57,8 +57,20 @@ layout(binding=1) uniform plane_world_config {
int planeType;
float time;
float grassDensity;
};
layout(binding=2) uniform plane_data {
int screen_w;
int screen_h;
int is_reflection_pass;
};
layout(binding = 0) uniform texture2D reftex;
layout(binding = 2) uniform texture2D groundtex;
layout(binding = 0) uniform sampler refsmp;
#define hash(p) fract(sin(dot(p, vec2(11.9898, 78.233))) * 43758.5453)
float B(vec2 U) {
@ -96,45 +108,135 @@ float noise (vec2 st) {
(d - b) * u.x * u.y;
}
vec3 wave(vec4 wave, vec3 p, inout vec3 tangent, inout vec3 binormal) {
float steepness = wave.z;
float wavelength = wave.w;
float k = 2.0 * 3.141 / wavelength;
float c = 2.0;
vec2 d = normalize(vec2(wave.x, wave.y));
float f = k * (dot(d, p.xz) - c * (time * 0.1));
float a = steepness / k;
tangent += vec3(
-d.x * d.x * (steepness * sin(f)),
d.x * (steepness * cos(f)),
-d.x * d.y * (steepness * sin(f))
);
binormal += vec3(
-d.x * d.y * (steepness * sin(f)),
d.y * (steepness * cos(f)),
-d.y * d.y * (steepness * sin(f))
);
return vec3(
d.x * (a * cos(f)),
a * sin(f),
d.y * (a * cos(f))
);
}
void main() {
if(planeType == 1) {
frag_color = vec4(0.0, 0.0, 1.0, 1.0);
vec4 reflection = texelFetch(sampler2D(reftex, refsmp), ivec2(gl_FragCoord.x, screen_h - gl_FragCoord.y), 0);
frag_color = reflection * vec4(0.9, 0.9, 1.0, 1.0);
} else {
float density = 80000.0;
float density = grassDensity;
vec2 densifiedCoordinate = pos.xz * density;
densifiedCoordinate.x += sin(densifiedCoordinate.y);
densifiedCoordinate.y += sin(densifiedCoordinate.x);
densifiedCoordinate.x += sin(densifiedCoordinate.y) * 0.5;
densifiedCoordinate.y += sin(densifiedCoordinate.x) * 0.5;
vec2 ruohokeskus = round(densifiedCoordinate);
float noiseval_fine = noise(densifiedCoordinate / 50.0);
float noiseval_coarse = noise(densifiedCoordinate / 500.0);
float h = (1.0 / 128.0) * idx;
float rand = (B(ruohokeskus) + sin(pos.x) * 0.4) * 0.5;
rand += noiseval_coarse * 0.4 + noiseval_fine * 0.1;
ruohokeskus.x += sin(time * 1.2) * 0.6 * h;
float distanceFromCenter = length(ruohokeskus - (densifiedCoordinate));
if(idx > 0 && rand < 0.2) {
discard;
float noiseval_plantti = noise(densifiedCoordinate / 500.0);
if(noiseval_plantti < 0.9) {
noiseval_plantti = 0.0;
} else {
noiseval_plantti = (noiseval_plantti - 0.9) * 10.0;
}
float noiseval_vesi = noise(densifiedCoordinate.yx / 700.0);
int is_water = 0;
float is_water_coast = 1.0;
float coast_multiplier = 0.0;
if(noiseval_vesi > 0.9) {
is_water = 1;
if(noiseval_vesi < 0.93) {
is_water_coast = (noiseval_vesi - 0.9) * 33.333;
}
}
if(noiseval_vesi > 0.8) {
coast_multiplier = (noiseval_vesi - 0.8) * 10;
}
float thickness = 0.5;
float rand = (hash12(ruohokeskus)) - 0.4;
rand += 0.4 * noiseval_coarse;
vec2 sandDensifiedCoordinate = round(pos.xz * density * 10.0);
float sand_rand = (hash12(sandDensifiedCoordinate));
vec4 sandcolor = vec4(mix(0.8, 1.0, sand_rand) * vec3(0.8, 0.7, 0.5), 1.0);
if(is_water == 1) {
vec3 tangent = vec3(1.0, 0.0, 0.0);
vec3 binormal = vec3(0.0, 0.0, 1.0);
vec3 p = vec3(0.0);
p += wave(vec4(1.0, 0.5, 0.1, 0.9), pos.xyz, tangent, binormal);
vec3 normal = normalize(cross(normalize(binormal), normalize(tangent)));
vec2 rippleOffset = normal.xz * 0.005;
rippleOffset.x = clamp(rippleOffset.x, -0.01, 0.01);
rippleOffset.y = clamp(rippleOffset.y, -0.01, 0.01);
vec3 light = normalize(sunPosition);
float lightfactor = max(dot(light, normal),0.0);
lightfactor = min(max(lightfactor, 0.1), 1.0);
// float spec = max(dot(normalize(light + normalize(cv - fragWorldPos)), normal), 0.0);
// spec -= 0.9;
// spec = max(spec, 0.0);
// spec *= 4.0;
// vec3 specLight = spec * sunIntensity * sunColor.xyz;
vec3 diffLight = lightfactor * sunIntensity * sunLightColor.xyz * 0.1;
// vec3 totalLight = (specLight + diffLight);
if(idx > 0 && (rand - h) * thickness < distanceFromCenter) {
discard;
} else {
frag_color = vec4(noiseval_coarse * 0.5, min(1.0, h + 0.2) + noiseval_fine * 0.2, 0.0, 1.0);
if(idx > 0 || is_reflection_pass == 1) discard;
vec4 reflection = texelFetch(sampler2D(reftex, refsmp), ivec2(gl_FragCoord.x + int(rippleOffset.x * screen_w), screen_h + int(rippleOffset.y * screen_h) - gl_FragCoord.y), 0);
frag_color = vec4(min(vec3(1.0), vec3(mix(1.0, 0.8, smoothstep(0.0, 0.9, is_water_coast))) + diffLight), 1.0) * mix(sandcolor, reflection, smoothstep(0.0, 0.9, is_water_coast));
// frag_color = reflection;
} else {
float h = (1.0 / 128.0) * idx;
rand -= mix(0.0, 1.0, coast_multiplier);
rand = max(0.0, rand);
ruohokeskus.x += sin(time * 1.2) * 0.2 * h;
float distanceFromCenter = length(ruohokeskus - (densifiedCoordinate));
if(idx > 0 && rand < 0.2) {
discard;
}
float thickness = 0.5;
if(idx > 0 && (rand - h) * thickness < distanceFromCenter) {
discard;
} else {
if(idx == 0) {
frag_color = mix(vec4(noiseval_coarse * 0.5, 0.2 + noiseval_fine * 0.2, 0.1, 1.0),sandcolor,coast_multiplier);
} else {
vec4 grass_color = vec4(noiseval_coarse * 0.5, min(1.0, h + 0.2) + noiseval_fine * 0.2, 0.1, 1.0);
vec4 plantti_color = vec4(h, h * 0.3, 0.0, 1.0);
vec4 normal_ground_color = mix(grass_color, plantti_color, noiseval_plantti);
frag_color = mix(normal_ground_color, vec4(h * 2.0 + 0.4, h * 2.0 + 0.4, 0.0, 1.0), coast_multiplier);
}
}
}
}
}
@end

View File

@ -17,6 +17,7 @@ void main() {
@end
@fs fs_sky
layout(binding=1) uniform sky_world_config {
vec3 skyBase;
vec3 skyTop;
@ -35,6 +36,8 @@ layout(binding=1) uniform sky_world_config {
int planeType;
float time;
float grassDensity;
};
in vec4 pos;

View File

@ -46,6 +46,8 @@ layout(binding=1) uniform trile_world_config {
int planeType;
float time;
float grassDensity;
};
in vec3 cam;

View File

@ -45,6 +45,8 @@ layout(binding=1) uniform trixel_world_config {
int planeType;
float time;
float grassDensity;
};
in vec4 color;

View File

@ -14,7 +14,9 @@ World_Config :: struct {
hasPlane : s32 = 0; @Slider,0,1,1
planeHeight : float = 0.0; @Slider,-100,100,1
planeType : s32 = 0; @Slider,0,2,1
planeType : s32 = 0; @Slider,0,1,1
grassDensity : float = 30; @Slider,10,100,1
}
// Copies over all the fields of our world config into a given shader type.
@ -38,8 +40,42 @@ TrilePositions :: struct {
positions: [..]Vector4;
}
Ground_Tile :: enum {
WATER;
GRASS;
}
World :: struct {
// @ToDo: Add a pool into here so we allocate all of the world stuff in it's own pool.
conf : World_Config;
positions : [..]TrilePositions;
ground : [1000][1000]Ground_Tile;
}
update_image_from_ground :: (world: *World, img: *sg_image) {
materialdata : [1000*1000*4]u8;
counter : int = 0;
for x: 0..1000 {
for y: 0..1000 {
if world.ground[x][y] == .GRASS {
materialdata[counter + 0] = 0;
materialdata[counter + 1] = 255;
materialdata[counter + 2] = 0;
materialdata[counter + 3] = 255;
}
if world.ground[x][y] == .WATER {
materialdata[counter + 0] = 0;
materialdata[counter + 1] = 0;
materialdata[counter + 2] = 255;
materialdata[counter + 3] = 255;
}
counter += 4;
}
}
imgdata : sg_image_data;
imgdata.subimage[0][0] = .{materialdata.data, materialdata.count};
sg_update_image(img, *imgdata);
}