using simp
This commit is contained in:
parent
f07013ad8a
commit
bc4d8bb0e1
715
module.jai
715
module.jai
@ -169,13 +169,13 @@ draw_plot :: (key: string, size: Vector2, xdata: []float64, yarrays: [][]float64
|
|||||||
plot.x = xx child_pos.x;
|
plot.x = xx child_pos.x;
|
||||||
plot.y = xx child_pos.y;
|
plot.y = xx child_pos.y;
|
||||||
|
|
||||||
//plot_size = .{plot_size.x, min(260.0, plot_size.y / workspace.f64_arrays.count)};
|
|
||||||
|
|
||||||
if plot.width < 0 || plot.height < 0 {
|
if plot.width < 0 || plot.height < 0 {
|
||||||
log("[Warning] The plot has dimensions lower than 0.");
|
log("[Warning] The plot has dimensions lower than 0.");
|
||||||
} else {
|
} else {
|
||||||
if plot.width != cast(s32) size.x || plot.height != cast(s32) size.y {
|
if plot.width != cast(s32) size.x || plot.height != cast(s32) size.y {
|
||||||
plot_resize(plot, xx size.x, xx size.y);
|
plot.width = xx size.x;
|
||||||
|
plot.height = xx size.y;
|
||||||
|
Simp.texture_resize_render_target(plot.texture, xx size.x, xx size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
ar : float = cast(float) plot.width / cast(float) plot.height;
|
ar : float = cast(float) plot.width / cast(float) plot.height;
|
||||||
@ -197,19 +197,25 @@ draw_plot :: (key: string, size: Vector2, xdata: []float64, yarrays: [][]float64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, plot.fbo);
|
reset_fbo : GLint;
|
||||||
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, *reset_fbo);
|
||||||
|
defer glBindFramebuffer(GL_FRAMEBUFFER, xx reset_fbo);
|
||||||
|
|
||||||
glViewport(xx plot.left_bearing, xx plot.bottom_bearing,
|
reset_program : GLint;
|
||||||
xx (plot.width - plot.left_bearing), xx (plot.height - plot.bottom_bearing));
|
glGetIntegerv(GL_CURRENT_PROGRAM, *reset_program);
|
||||||
|
defer glUseProgram(xx reset_program);
|
||||||
|
|
||||||
glClearColor(colors.background.x, colors.background.y, colors.background.z, 0.0);
|
Simp.set_render_target(plot.texture);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
Simp.clear_render_target(colors.background.x, colors.background.y, colors.background.z, 1.0);
|
||||||
|
|
||||||
draw_axis(plot, plot.plot_style, colors);
|
draw_axis(plot, plot.plot_style, colors);
|
||||||
|
|
||||||
if plot.plot_style == .SCALE_MARKER
|
if plot.plot_style == .SCALE_MARKER
|
||||||
draw_scale(plot, colors);
|
draw_scale(plot, colors);
|
||||||
|
|
||||||
|
glUseProgram(data_shader);
|
||||||
|
|
||||||
glViewport(xx plot.left_bearing, xx plot.bottom_bearing,
|
glViewport(xx plot.left_bearing, xx plot.bottom_bearing,
|
||||||
xx (plot.width - plot.left_bearing), xx (plot.height - plot.bottom_bearing));
|
xx (plot.width - plot.left_bearing), xx (plot.height - plot.bottom_bearing));
|
||||||
|
|
||||||
@ -222,8 +228,6 @@ draw_plot :: (key: string, size: Vector2, xdata: []float64, yarrays: [][]float64
|
|||||||
|
|
||||||
for yfloat : plot.yfloats {
|
for yfloat : plot.yfloats {
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, plot.fbo);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, plot.yvbo);
|
glBindBuffer(GL_ARRAY_BUFFER, plot.yvbo);
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
glBufferData(GL_ARRAY_BUFFER, yfloat.count * size_of(float), yfloat.data, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, yfloat.count * size_of(float), yfloat.data, GL_DYNAMIC_DRAW);
|
||||||
@ -242,8 +246,6 @@ draw_plot :: (key: string, size: Vector2, xdata: []float64, yarrays: [][]float64
|
|||||||
(plot.ymin),
|
(plot.ymin),
|
||||||
(plot.ymax), -1.0, 1.0);
|
(plot.ymax), -1.0, 1.0);
|
||||||
|
|
||||||
glUseProgram(data_shader);
|
|
||||||
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(data_shader, "model"), 1, GL_TRUE, xx *model);
|
glUniformMatrix4fv(glGetUniformLocation(data_shader, "model"), 1, GL_TRUE, xx *model);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(data_shader, "proj"), 1, GL_TRUE, xx *proj);
|
glUniformMatrix4fv(glGetUniformLocation(data_shader, "proj"), 1, GL_TRUE, xx *proj);
|
||||||
|
|
||||||
@ -253,15 +255,10 @@ draw_plot :: (key: string, size: Vector2, xdata: []float64, yarrays: [][]float64
|
|||||||
|
|
||||||
glDrawArrays(GL_LINE_STRIP, 0, xx (plot.xfloat.count));
|
glDrawArrays(GL_LINE_STRIP, 0, xx (plot.xfloat.count));
|
||||||
primitives_rendered_this_frame += plot.xfloat.count - 1;
|
primitives_rendered_this_frame += plot.xfloat.count - 1;
|
||||||
|
|
||||||
//glBindFramebuffer(GL_READ_FRAMEBUFFER, plot.msfbo);
|
|
||||||
//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, plot.fbo);
|
|
||||||
//glBlitFramebuffer(0, 0, plot.width, plot.height, 0, 0, plot.width, plot.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Image(cast(ImGui.ImTextureID) plot.texture, size, .{0.0, 1.0}, .{1.0, 0.0});
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
ImGui.Image(cast(ImGui.ImTextureID) plot.texture.gl_handle, size, .{0.0, 1.0}, .{1.0, 0.0});
|
||||||
|
|
||||||
plot.last_frame = frame;
|
plot.last_frame = frame;
|
||||||
}
|
}
|
||||||
@ -287,24 +284,17 @@ free_old_plots :: () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init :: (_win_width: s32, _win_height: s32, _mouse_wheel_zoom : bool) {
|
init :: (_window: Window_Type, _win_width: s32, _win_height: s32, _mouse_wheel_zoom : bool) {
|
||||||
|
window = _window;
|
||||||
win_width = _win_width;
|
win_width = _win_width;
|
||||||
win_height = _win_height;
|
win_height = _win_height;
|
||||||
mouse_wheel_zoom = _mouse_wheel_zoom;
|
mouse_wheel_zoom = _mouse_wheel_zoom;
|
||||||
|
|
||||||
error := FT_Init_FreeType(*ftlib);
|
JetBrainsMonoRegular = Simp.get_font_at_size("fonts", "JetBrainsMono-Regular.ttf", 14);
|
||||||
if error {
|
assert(JetBrainsMonoRegular != null);
|
||||||
log("[Error] FreeType could not initialise. That is very bad!");
|
|
||||||
log(" with error code %.", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
data_shader = make_shader(data_vertex_shader_text, data_fragment_shader_text);
|
data_shader = make_shader(data_vertex_shader_text, data_fragment_shader_text);
|
||||||
line_shader = make_shader(line_vertex_shader_text, line_fragment_shader_text);
|
line_shader = make_shader(line_vertex_shader_text, line_fragment_shader_text);
|
||||||
text_shader = make_shader(text_vertex_shader_text, text_fragment_shader_text);
|
|
||||||
|
|
||||||
window_projection_matrix = orthographic_projection_matrix(0.0, xx win_width, xx win_height, 0.0, -1.0, 1.0);
|
|
||||||
|
|
||||||
init_font(*JetBrainsMonoRegular, "JetBrainsMono-Regular.ttf", 12);
|
|
||||||
|
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
||||||
@ -316,23 +306,97 @@ window_resize :: (_win_width: s32, _win_height: s32) {
|
|||||||
win_width = _win_width;
|
win_width = _win_width;
|
||||||
win_height = _win_height;
|
win_height = _win_height;
|
||||||
|
|
||||||
window_projection_matrix = orthographic_projection_matrix(0.0, xx win_width, xx win_height, 0.0, -1.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_frame :: (_mouse: Vector2, _mouse_delta: Vector2, _mouse_wheel_delta: float, _mouse_left: bool) {
|
new_frame :: () {
|
||||||
frame += 1;
|
frame += 1;
|
||||||
mouse = _mouse;
|
|
||||||
mouse_delta = _mouse_delta;
|
|
||||||
mouse_wheel_delta = _mouse_wheel_delta;
|
|
||||||
mouse_left = _mouse_left;
|
|
||||||
|
|
||||||
primitives_rendered_this_frame = 0;
|
primitives_rendered_this_frame = 0;
|
||||||
|
|
||||||
|
mouse_delta = .{};
|
||||||
|
mouse_wheel_delta = 0;
|
||||||
|
|
||||||
|
x, y := get_mouse_pointer_position(window, false);
|
||||||
|
mouse = .{cast(float, x), cast(float, y)};
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_input :: (events: []Input.Event) {
|
||||||
|
// @Hack Input module for android treats touch inputs as mouse button left, but you need to set the "mouse"
|
||||||
|
// position to something valid before triggering the click so update it here.
|
||||||
|
// @TODO(Charles): This can now be updated as modules/Input has touch! :ImGuiAndroidInput
|
||||||
|
#if OS == .ANDROID {
|
||||||
|
WC :: #import "Window_Creation";
|
||||||
|
Math :: #import "Math";
|
||||||
|
touch_x, touch_y, success := WC.get_mouse_pointer_position(true);
|
||||||
|
touch_x_f := cast(float) touch_x;
|
||||||
|
touch_y_f := cast(float) touch_y;
|
||||||
|
if !success {
|
||||||
|
// ImGui wants -FLT_MAX, -FLT_MAX to indicate no mouse.
|
||||||
|
FLT_MAX :: Math.FLOAT32_MAX;
|
||||||
|
touch_x_f = -FLT_MAX;
|
||||||
|
touch_y_f = -FLT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Hack when releasing screen, need to have the mouse position set to where we released.
|
||||||
|
touch_on_release := mouse;
|
||||||
|
|
||||||
|
mouse = .{touch_x_f, touch_y_f};
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(Charles): On windows mouse position is handled in ImGui_ImplWin32_NewFrame with GetCusorPos on tick. The
|
||||||
|
// Imgui examples also respond to WM_MOUSEMOVE, but it's not clear why?
|
||||||
|
// modules/Input "doesn't have mouse move events yet", it only gives us the delta.
|
||||||
|
|
||||||
|
for event: events {
|
||||||
|
// :Win32InputMissing AddFocusEvent, could be done by checking Input.input_application_has_focus for change.
|
||||||
|
if event.type == {
|
||||||
|
case .KEYBOARD;
|
||||||
|
if event.key_code == {
|
||||||
|
// :Win32InputMissing mouse extra buttons, SetCapturing?, Mouse source
|
||||||
|
// case .MOUSE_BUTTON_LEFT; io.AddMouseButtonEvent(io, xx ImGui.MouseButton.Left , xx event.key_pressed);
|
||||||
|
|
||||||
|
case .MOUSE_BUTTON_LEFT;
|
||||||
|
// @Hack
|
||||||
|
#if OS == .ANDROID {
|
||||||
|
if !event.key_pressed {
|
||||||
|
mouse = .{touch_on_release.x, touch_on_release.y};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if event.key_pressed
|
||||||
|
mouse_left = true;
|
||||||
|
else
|
||||||
|
mouse_left = false;
|
||||||
|
|
||||||
|
case .MOUSE_BUTTON_RIGHT;
|
||||||
|
//io.AddMouseButtonEvent(io, xx ImGui.MouseButton.Right , xx event.key_pressed);
|
||||||
|
|
||||||
|
case .MOUSE_BUTTON_MIDDLE;
|
||||||
|
//io.AddMouseButtonEvent(io, xx ImGui.MouseButton.Middle, xx event.key_pressed);
|
||||||
|
|
||||||
|
case;
|
||||||
|
//imgui_key := to_imgui_key(event.key_code);
|
||||||
|
//// :Win32InputMissing Input only gives us single ctrl, shift, alt, not left/right. ImGui example sends
|
||||||
|
//// one event for either, then an extra for left right.
|
||||||
|
//if imgui_key != .None {
|
||||||
|
// // :Win32InputMissing SetKeyEventNativeData gets called for some legacy reason?
|
||||||
|
// io.AddKeyEvent(io, imgui_key, xx event.key_pressed);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
case .MOUSE_WHEEL;
|
||||||
|
mouse_wheel_delta += event.wheel_delta / cast(float, event.typical_wheel_delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse_delta += .{cast(float, Input.mouse_delta_x), cast(float, Input.mouse_delta_y)};
|
||||||
}
|
}
|
||||||
|
|
||||||
get_primitives_rendered :: () -> int {
|
get_primitives_rendered :: () -> int {
|
||||||
return primitives_rendered_this_frame;
|
return primitives_rendered_this_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JetBrainsMonoRegular : *Simp.Dynamic_Font;
|
||||||
|
|
||||||
#scope_file
|
#scope_file
|
||||||
|
|
||||||
#import "Basic";
|
#import "Basic";
|
||||||
@ -340,7 +404,14 @@ get_primitives_rendered :: () -> int {
|
|||||||
#import "Hash_Table";
|
#import "Hash_Table";
|
||||||
#import "Math";
|
#import "Math";
|
||||||
ImGui :: #import,dir "../imgui-lib";
|
ImGui :: #import,dir "../imgui-lib";
|
||||||
|
Simp :: #import "Simp";
|
||||||
|
#import "stb_rect_pack";
|
||||||
|
#import "File";
|
||||||
|
Input :: #import "Input";
|
||||||
|
#import "Window_Creation";
|
||||||
|
|
||||||
|
|
||||||
|
window : Window_Type;
|
||||||
frame : s64;
|
frame : s64;
|
||||||
mouse : Vector2;
|
mouse : Vector2;
|
||||||
mouse_delta : Vector2;
|
mouse_delta : Vector2;
|
||||||
@ -365,10 +436,7 @@ Plot :: struct {
|
|||||||
|
|
||||||
plot_style : PLOT_STYLE;
|
plot_style : PLOT_STYLE;
|
||||||
|
|
||||||
msfbo : GLuint;
|
texture: *Simp.Texture;
|
||||||
mstexture : GLuint;
|
|
||||||
fbo : GLuint;
|
|
||||||
texture : GLuint;
|
|
||||||
|
|
||||||
vao : GLuint;
|
vao : GLuint;
|
||||||
xvbo : GLuint;
|
xvbo : GLuint;
|
||||||
@ -410,10 +478,6 @@ data_colors := Vector4.[
|
|||||||
];
|
];
|
||||||
|
|
||||||
free_plot :: (plot: *Plot) {
|
free_plot :: (plot: *Plot) {
|
||||||
glDeleteTextures(1, *plot.texture);
|
|
||||||
glDeleteTextures(1, *plot.mstexture);
|
|
||||||
glDeleteFramebuffers(1, *plot.fbo);
|
|
||||||
glDeleteFramebuffers(1, *plot.msfbo);
|
|
||||||
glDeleteVertexArrays(1, *plot.vao);
|
glDeleteVertexArrays(1, *plot.vao);
|
||||||
glDeleteBuffers(1, *plot.xvbo);
|
glDeleteBuffers(1, *plot.xvbo);
|
||||||
glDeleteBuffers(1, *plot.yvbo);
|
glDeleteBuffers(1, *plot.yvbo);
|
||||||
@ -429,63 +493,16 @@ init_plot :: (plot: *Plot, key: string, width: s32, height: s32) {
|
|||||||
plot.width = 1024;
|
plot.width = 1024;
|
||||||
plot.height = 1024;
|
plot.height = 1024;
|
||||||
|
|
||||||
glGenFramebuffers(1, *plot.fbo);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, plot.fbo);
|
|
||||||
|
|
||||||
glGenTextures(1, *plot.texture);
|
plot.texture = Simp.texture_create_render_target(width, height, .RGBA8, .sRGB);
|
||||||
glBindTexture(GL_TEXTURE_2D, plot.texture);
|
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, xx plot.width, xx plot.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
|
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, plot.texture, 0);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE {
|
|
||||||
log("[ERROR] FRAMEBUFFER: Framebuffer is not complete!");
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
glGenFramebuffers(1, *plot.msfbo);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, plot.msfbo);
|
|
||||||
|
|
||||||
glGenTextures(1, *plot.mstexture);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, plot.mstexture);
|
|
||||||
|
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_SRGB8_ALPHA8, xx plot.width, xx plot.height, GL_TRUE);
|
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, plot.mstexture, 0);
|
|
||||||
|
|
||||||
if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE {
|
|
||||||
log("[ERROR] FRAMEBUFFER: Framebuffer is not complete!");
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenVertexArrays(1, *plot.vao);
|
glGenVertexArrays(1, *plot.vao);
|
||||||
glBindVertexArray(plot.vao);
|
glBindVertexArray(plot.vao);
|
||||||
|
|
||||||
glGenBuffers(1, *plot.xvbo);
|
glGenBuffers(1, *plot.xvbo);
|
||||||
glGenBuffers(1, *plot.yvbo);
|
glGenBuffers(1, *plot.yvbo);
|
||||||
}
|
|
||||||
|
|
||||||
plot_resize :: (plot: *Plot, width: s32, height: s32) {
|
|
||||||
plot.width = width;
|
|
||||||
plot.height = height;
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, plot.texture);
|
|
||||||
|
|
||||||
if width > 0 && height > 0 {
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, xx plot.width, xx plot.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, plot.mstexture);
|
|
||||||
|
|
||||||
if width > 0 && height > 0 {
|
|
||||||
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_SRGB8_ALPHA8, xx plot.width, xx plot.height, GL_TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
truncate :: (x: float, n: s32) -> float {
|
truncate :: (x: float, n: s32) -> float {
|
||||||
@ -534,13 +551,15 @@ draw_axis :: (using plot: Plot, style: PLOT_STYLE, colors: PlotColors) {
|
|||||||
array_add(*positions, .{cast(float) xpos, 0.0});
|
array_add(*positions, .{cast(float) xpos, 0.0});
|
||||||
array_add(*positions, .{cast(float) xpos, cast(float) (content_height )});
|
array_add(*positions, .{cast(float) xpos, cast(float) (content_height )});
|
||||||
|
|
||||||
to_render := tprint("%", formatFloat(cast(float) xxx, trailing_width = 1, zero_removal = .NO));
|
label_width := Simp.prepare_text(JetBrainsMonoRegular, tprint("%", formatFloat(cast(float) xxx,
|
||||||
label_size := calculate_string_draw_size(*JetBrainsMonoRegular, to_render);
|
trailing_width = 1, zero_removal = .NO)));
|
||||||
|
|
||||||
if style == .TICK_MARKS {
|
if style == .TICK_MARKS {
|
||||||
render_string(*JetBrainsMonoRegular, to_render,
|
|
||||||
.{xpos + left_bearing - (label_size.x / 2.0), xx (plot.height - bottom_bearing + 4.0)},
|
Simp.draw_prepared_text(JetBrainsMonoRegular,
|
||||||
colors.text, plot.width, plot.height);
|
xx (xpos + left_bearing - (label_width / 2.0)),
|
||||||
|
xx (4.0),
|
||||||
|
.{1, 1, 1, 1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,17 +567,19 @@ draw_axis :: (using plot: Plot, style: PLOT_STYLE, colors: PlotColors) {
|
|||||||
for 0..y_ticks {
|
for 0..y_ticks {
|
||||||
ypos : s64 = cast(s64) (cast(float) it / cast(float) y_ticks * (content_height ));
|
ypos : s64 = cast(s64) (cast(float) it / cast(float) y_ticks * (content_height ));
|
||||||
yyy := ((0.5) - cast(float) it / cast(float) y_ticks) / zoom + 0.5;
|
yyy := ((0.5) - cast(float) it / cast(float) y_ticks) / zoom + 0.5;
|
||||||
yyy = yyy * (ymax - pos.y) + (1 - yyy) * (ymin - pos.y);
|
yyy = yyy * (ymin - pos.y) + (1 - yyy) * (ymax - pos.y);
|
||||||
array_add(*positions, .{0.0, cast(float) ypos});
|
array_add(*positions, .{0.0, cast(float) ypos});
|
||||||
array_add(*positions, .{cast(float) (content_width ), cast(float) ypos});
|
array_add(*positions, .{cast(float) (content_width ), cast(float) ypos});
|
||||||
|
|
||||||
to_render := tprint("%", formatFloat(cast(float) yyy, trailing_width = 1, zero_removal = .NO));
|
label_width := Simp.prepare_text(JetBrainsMonoRegular, tprint("%", formatFloat(cast(float) yyy, trailing_width = 1,
|
||||||
label_size := calculate_string_draw_size(*JetBrainsMonoRegular, to_render);
|
zero_removal = .NO)));
|
||||||
|
|
||||||
if style == .TICK_MARKS {
|
if style == .TICK_MARKS {
|
||||||
render_string(*JetBrainsMonoRegular, to_render,
|
|
||||||
.{xx cast(s64) (left_bearing - label_size.x - 4.0), xx cast(s64) (ypos - label_size.y / 2.0)},
|
Simp.draw_prepared_text(JetBrainsMonoRegular,
|
||||||
colors.text, plot.width, plot.height);
|
xx (xx cast(s64) (left_bearing - label_width - 4.0)),
|
||||||
|
xx (cast(s64) (ypos + JetBrainsMonoRegular.character_height)),
|
||||||
|
.{1, 1, 1, 1});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -607,38 +628,35 @@ draw_scale :: (using plot: Plot, colors: PlotColors) {
|
|||||||
|
|
||||||
positions : [..]Vector2;
|
positions : [..]Vector2;
|
||||||
defer array_reset(*positions);
|
defer array_reset(*positions);
|
||||||
// array_add(*positions, .{0.0, 0.0});
|
|
||||||
// array_add(*positions, .{xx width, 0.0});
|
|
||||||
|
|
||||||
// array_add(*positions, .{xx width, 0.0});
|
|
||||||
// array_add(*positions, .{xx width, xx height});
|
|
||||||
|
|
||||||
// array_add(*positions, .{xx width, xx height});
|
|
||||||
// array_add(*positions, .{0.0, xx height});
|
|
||||||
|
|
||||||
// array_add(*positions, .{0.0, xx height});
|
|
||||||
// array_add(*positions, .{0.0, 0.0});
|
|
||||||
|
|
||||||
|
|
||||||
array_add(*positions, .{5.0, 5.0});
|
array_add(*positions, .{1.0, 1.0});
|
||||||
array_add(*positions, .{5.0 + content_width / 10.0, 5.0});
|
array_add(*positions, .{1.0 + content_width / 10.0, 1.0});
|
||||||
|
|
||||||
to_render := tprint("%", formatFloat(cast(float) extent_x / zoom / 10.0, trailing_width = 1, zero_removal = .NO));
|
glViewport(0, 0, xx width, xx (height));
|
||||||
label_size := calculate_string_draw_size(*JetBrainsMonoRegular, to_render);
|
|
||||||
render_string(*JetBrainsMonoRegular, to_render,
|
|
||||||
.{xx cast(s64) (5.0 + content_width / 10.0), xx height - label_size.y - 5.0},
|
|
||||||
colors.text, plot.width, plot.height);
|
|
||||||
|
|
||||||
array_add(*positions, .{5.0, 5.0});
|
label_width := Simp.prepare_text(JetBrainsMonoRegular, tprint("%", formatFloat(cast(float) extent_x / zoom / 10.0,
|
||||||
array_add(*positions, .{5.0, 5.0 + content_height / 10.0});
|
trailing_width = 1, zero_removal = .NO)));
|
||||||
|
|
||||||
to_render = tprint("%", formatFloat(cast(float) extent_y / zoom / 10.0, trailing_width = 1, zero_removal = .NO));
|
Simp.draw_prepared_text(JetBrainsMonoRegular,
|
||||||
label_size = calculate_string_draw_size(*JetBrainsMonoRegular, to_render);
|
xx (5.0 + content_width / 10.0),
|
||||||
render_string(*JetBrainsMonoRegular, to_render,
|
xx (0),
|
||||||
.{xx cast(s64) (5.0), height - 5.0 - content_height / 10.0 - label_size.y},
|
.{1, 1, 1, 1});
|
||||||
colors.text, plot.width, plot.height);
|
|
||||||
|
|
||||||
glViewport(0, 0, xx width, xx height);
|
array_add(*positions, .{1.0, 1.0});
|
||||||
|
array_add(*positions, .{1.0, 1.0 + content_height / 10.0});
|
||||||
|
|
||||||
|
label_width = Simp.prepare_text(JetBrainsMonoRegular, tprint("%", formatFloat(cast(float) extent_y / zoom / 10.0,
|
||||||
|
trailing_width = 1, zero_removal = .NO)));
|
||||||
|
|
||||||
|
|
||||||
|
Simp.draw_prepared_text(JetBrainsMonoRegular,
|
||||||
|
xx (0),
|
||||||
|
xx (5.0 + content_height / 10.0),
|
||||||
|
.{1, 1, 1, 1});
|
||||||
|
|
||||||
|
|
||||||
|
//glViewport(xx left_bearing, xx bottom_bearing, xx (width - left_bearing), xx (height - bottom_bearing));
|
||||||
|
|
||||||
scale_vao : GLuint;
|
scale_vao : GLuint;
|
||||||
glGenVertexArrays(1, *scale_vao);
|
glGenVertexArrays(1, *scale_vao);
|
||||||
@ -653,7 +671,6 @@ draw_scale :: (using plot: Plot, colors: PlotColors) {
|
|||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, size_of(Vector2), null);
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, size_of(Vector2), null);
|
||||||
|
|
||||||
proj := orthographic_projection_matrix(0.0, cast(float) (width), 0.0, cast(float) (height), -1.0, 1.0);
|
proj := orthographic_projection_matrix(0.0, cast(float) (width), 0.0, cast(float) (height), -1.0, 1.0);
|
||||||
//proj := orthographic_projection_matrix(xmin * zoom, xmax * zoom, ymin * zoom, ymax * zoom, -1.0, 1.0);
|
|
||||||
|
|
||||||
glUseProgram(line_shader);
|
glUseProgram(line_shader);
|
||||||
|
|
||||||
@ -682,362 +699,8 @@ is_in_rect :: (pos: Vector2, size: Vector2, test: Vector2) -> bool {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FONTS
|
|
||||||
|
|
||||||
#import "freetype-2.12.1";
|
|
||||||
#import "harfbuzz";
|
|
||||||
#import "stb_rect_pack";
|
|
||||||
#import "File";
|
|
||||||
|
|
||||||
ftlib : FT_Library;
|
|
||||||
|
|
||||||
ATLAS_SIZE :: 2048;
|
|
||||||
|
|
||||||
JetBrainsMonoRegular: Font;
|
|
||||||
|
|
||||||
JetBrainsMonoRegular_text :: #run read_entire_file(tprint("%/JetBrainsMono-Regular.ttf", #filepath));
|
|
||||||
|
|
||||||
Glyph :: struct {
|
|
||||||
utf32 : u32;
|
|
||||||
index : u32;
|
|
||||||
|
|
||||||
x, y : s16;
|
|
||||||
width, height : u32;
|
|
||||||
|
|
||||||
bearing_x, bearing_y : s16;
|
|
||||||
|
|
||||||
y_max, y_min : s16;
|
|
||||||
|
|
||||||
ascent : s16;
|
|
||||||
advance : s16;
|
|
||||||
|
|
||||||
uv0, uv1 : Vector2;
|
|
||||||
|
|
||||||
bitmap : *u8;
|
|
||||||
}
|
|
||||||
|
|
||||||
Font :: struct {
|
|
||||||
face : FT_Face;
|
|
||||||
|
|
||||||
glyphs : Table(u32, Glyph);
|
|
||||||
|
|
||||||
graphics_font : GraphicsFont;
|
|
||||||
|
|
||||||
hb : *hb_font_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_font :: (using font: *Font, filename: string, size: s32) {
|
|
||||||
|
|
||||||
pixel_size := size * 96.0 / 72.0;
|
|
||||||
//pixel_size := size;
|
|
||||||
|
|
||||||
//FT_New_Face(ftlib, filename.data, 0, *face);
|
|
||||||
|
|
||||||
FT_New_Memory_Face(ftlib, JetBrainsMonoRegular_text.data, JetBrainsMonoRegular_text.count, 0, *face);
|
|
||||||
|
|
||||||
//error := FT_Set_Pixel_Sizes(face, 0, xx size);
|
|
||||||
error := FT_Set_Char_Size(face, 0, size * 64, 0, 96);
|
|
||||||
if error
|
|
||||||
log("%", to_string(FT_Error_String(error)));
|
|
||||||
|
|
||||||
rects : [..] stbrp_rect;
|
|
||||||
defer array_free(rects);
|
|
||||||
|
|
||||||
nodes : [ATLAS_SIZE] stbrp_node;
|
|
||||||
|
|
||||||
stbrpcontext : stbrp_context;
|
|
||||||
stbrp_init_target(*stbrpcontext, ATLAS_SIZE, ATLAS_SIZE, nodes.data, nodes.count);
|
|
||||||
|
|
||||||
atlas : *u8 = alloc(ATLAS_SIZE * ATLAS_SIZE);
|
|
||||||
defer free(atlas);
|
|
||||||
|
|
||||||
|
|
||||||
for 0..face.num_glyphs {
|
|
||||||
error = FT_Load_Glyph(face, cast(u32) it, FT_LOAD_RENDER);
|
|
||||||
if error
|
|
||||||
log("%", to_string(FT_Error_String(error)));
|
|
||||||
|
|
||||||
array_add(*rects, stbrp_rect.{cast(s32) face.glyph.glyph_index, cast(s32) face.glyph.bitmap.width,
|
|
||||||
cast(s32) face.glyph.bitmap.rows, 0, 0, 0});
|
|
||||||
|
|
||||||
glyph : Glyph;
|
|
||||||
glyph.utf32 = cast(u32) it;
|
|
||||||
glyph.index = face.glyph.glyph_index;
|
|
||||||
glyph.bearing_x = cast,trunc(s16) face.glyph.bitmap_left;
|
|
||||||
glyph.bearing_y = cast,trunc(s16) face.glyph.bitmap_top;
|
|
||||||
glyph.width = face.glyph.bitmap.width;
|
|
||||||
glyph.height = face.glyph.bitmap.rows;
|
|
||||||
glyph.advance = cast(s16) face.glyph.advance.x >> 6;
|
|
||||||
glyph.bitmap = alloc(glyph.height * glyph.width);
|
|
||||||
memcpy(glyph.bitmap, face.glyph.bitmap.buffer, glyph.height * glyph.width);
|
|
||||||
|
|
||||||
table_set(*font.glyphs, glyph.index, glyph);
|
|
||||||
}
|
|
||||||
|
|
||||||
stbrp_pack_rects(*stbrpcontext, rects.data, cast(s32) rects.count);
|
|
||||||
|
|
||||||
|
|
||||||
copybitmaptoatlas :: (bitmap : *u8, width: s32, height: s32, atlas: *u8, destx: s32, desty: s32) {
|
|
||||||
if (destx >= ATLAS_SIZE)
|
|
||||||
destx = ATLAS_SIZE - 1;
|
|
||||||
|
|
||||||
if (desty >= ATLAS_SIZE)
|
|
||||||
desty = ATLAS_SIZE - 1;
|
|
||||||
|
|
||||||
for j: 0..height - 1 {
|
|
||||||
for i: 0..width - 1 {
|
|
||||||
atlas[(desty + j) * ATLAS_SIZE + (destx + i)] = bitmap[j * width + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for rect : rects {
|
|
||||||
glyph : *Glyph = table_find_pointer(*font.glyphs, cast(u32) rect.id);
|
|
||||||
if (glyph.bitmap) {
|
|
||||||
glyph.x = cast,trunc(s16) rect.x;
|
|
||||||
glyph.y = cast,trunc(s16) rect.y;
|
|
||||||
copybitmaptoatlas(glyph.bitmap, cast(s32) glyph.width, cast(s32) glyph.height, atlas, cast(s32) rect.x, cast(s32) rect.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics_init_font(*font.graphics_font, atlas);
|
|
||||||
|
|
||||||
blob : *hb_blob_t = hb_blob_create(JetBrainsMonoRegular_text.data, JetBrainsMonoRegular_text.count, .HB_MEMORY_MODE_READONLY, null, null);
|
|
||||||
|
|
||||||
hb_face : *hb_face_t = hb_face_create(blob, 0);
|
|
||||||
hb = hb_font_create(hb_face);
|
|
||||||
hb_font_set_ppem(hb, xx pixel_size, xx pixel_size);
|
|
||||||
hb_font_set_scale(hb, cast(s32) pixel_size * 64, cast(s32) pixel_size * 64);
|
|
||||||
}
|
|
||||||
|
|
||||||
render_string :: (font: *Font, text: string, pos: Vector2, colour: Vector3 = .{1.0, 1.0, 1.0}, fb_width: s32, fb_height: s32,
|
|
||||||
nicebackground := false) {
|
|
||||||
if !text
|
|
||||||
return;
|
|
||||||
|
|
||||||
if nicebackground {
|
|
||||||
render_string(font, text, pos + .{3.0, 3.0}, xyz(0.0), fb_width, fb_height, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf : *hb_buffer_t = hb_buffer_create();
|
|
||||||
hb_buffer_add_utf8(buf, text.data, xx text.count, 0, -1);
|
|
||||||
|
|
||||||
hb_buffer_set_direction(buf, hb_direction_t.LTR);
|
|
||||||
hb_buffer_set_script(buf, hb_script_t.HB_SCRIPT_LATIN);
|
|
||||||
hb_buffer_set_language(buf, hb_language_from_string("en", -1));
|
|
||||||
|
|
||||||
features : [1]hb_feature_t;
|
|
||||||
//features[0].tag = HB_TAG(#char "c", #char "a", #char "l", #char "t");
|
|
||||||
//features[0].value = 1;
|
|
||||||
//features[0].start = HB_FEATURE_GLOBAL_START;
|
|
||||||
//features[0].end = HB_FEATURE_GLOBAL_END;
|
|
||||||
|
|
||||||
hb_shape(font.hb, buf, features.data, features.count);
|
|
||||||
|
|
||||||
glyph_count : u32;
|
|
||||||
glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count);
|
|
||||||
glyph_pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count);
|
|
||||||
|
|
||||||
vertices : [..] Vector2;
|
|
||||||
tex : [..] Vector2;
|
|
||||||
|
|
||||||
defer array_reset(*vertices);
|
|
||||||
defer array_reset(*tex);
|
|
||||||
|
|
||||||
render_pos := pos;
|
|
||||||
|
|
||||||
draw_size := calculate_string_draw_size(font, text);
|
|
||||||
|
|
||||||
for i : 0..glyph_count - 1 {
|
|
||||||
glyphid : hb_codepoint_t = glyph_info[i].codepoint;
|
|
||||||
x_offset : hb_position_t = glyph_pos[i].x_offset;
|
|
||||||
y_offset : hb_position_t = glyph_pos[i].y_offset;
|
|
||||||
x_advance : hb_position_t = glyph_pos[i].x_advance;
|
|
||||||
y_advance : hb_position_t = glyph_pos[i].y_advance;
|
|
||||||
|
|
||||||
glyph : *Glyph = table_find_pointer(*font.glyphs, glyphid);
|
|
||||||
|
|
||||||
//v0 := render_pos + xy(xx glyph.bearing_x, xx -glyph.bearing_y + draw_size.y);
|
|
||||||
v0 := render_pos + xy(cast(float) x_offset + cast(float) glyph.bearing_x,
|
|
||||||
cast(float) y_offset - cast(float) glyph.bearing_y + draw_size.y);
|
|
||||||
#if Y_IS_UP {
|
|
||||||
t0 := xy(cast(float) (glyph.x) / ATLAS_SIZE, (ATLAS_SIZE - (cast(float) (glyph.y))) / ATLAS_SIZE);
|
|
||||||
} else {
|
|
||||||
t0 := xy(cast(float) glyph.x / ATLAS_SIZE, cast(float) glyph.y / ATLAS_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if Y_IS_UP {
|
|
||||||
array_add(*vertices, v0);
|
|
||||||
array_add(*vertices, v0 + xy(0.0, cast(float) glyph.height));
|
|
||||||
array_add(*vertices, v0 + xy(cast(float) glyph.width, 0.0));
|
|
||||||
|
|
||||||
array_add(*vertices, v0 + xy(cast(float) glyph.width, 0.0));
|
|
||||||
array_add(*vertices, v0 + xy(0.0, cast(float) glyph.height));
|
|
||||||
array_add(*vertices, v0 + xy(cast(float) glyph.width, cast(float) glyph.height));
|
|
||||||
|
|
||||||
array_add(*tex, t0);
|
|
||||||
array_add(*tex, t0 + xy(0.0, -cast(float) (glyph.height) / ATLAS_SIZE));
|
|
||||||
array_add(*tex, t0 + xy(cast(float) (glyph.width) / ATLAS_SIZE, 0.0));
|
|
||||||
|
|
||||||
array_add(*tex, t0 + xy(cast(float) (glyph.width) / ATLAS_SIZE, 0.0));
|
|
||||||
array_add(*tex, t0 + xy(0.0, -cast(float) (glyph.height) / ATLAS_SIZE));
|
|
||||||
array_add(*tex, t0 + xy(cast(float) (glyph.width) / ATLAS_SIZE, -cast(float) (glyph.height) / ATLAS_SIZE));
|
|
||||||
} else {
|
|
||||||
array_add(*vertices, v0);
|
|
||||||
array_add(*vertices, v0 + xy(cast(float) glyph.width, 0.0));
|
|
||||||
array_add(*vertices, v0 + xy(0.0, cast(float) glyph.height));
|
|
||||||
|
|
||||||
array_add(*vertices, v0 + xy(cast(float) glyph.width, 0.0));
|
|
||||||
array_add(*vertices, v0 + xy(cast(float) glyph.width, cast(float) glyph.height));
|
|
||||||
array_add(*vertices, v0 + xy(0.0, cast(float) glyph.height));
|
|
||||||
|
|
||||||
array_add(*tex, t0);
|
|
||||||
array_add(*tex, t0 + xy(0.0, cast(float) glyph.height / ATLAS_SIZE));
|
|
||||||
array_add(*tex, t0 + xy(cast(float) glyph.width / ATLAS_SIZE, cast(float) glyph.height / ATLAS_SIZE));
|
|
||||||
|
|
||||||
array_add(*tex, t0 + xy(cast(float) glyph.width / ATLAS_SIZE, cast(float) glyph.height / ATLAS_SIZE));
|
|
||||||
array_add(*tex, t0 + xy(cast(float) glyph.width / ATLAS_SIZE, 0.0));
|
|
||||||
array_add(*tex, t0);
|
|
||||||
}
|
|
||||||
|
|
||||||
render_pos += xy(xx x_advance / 64.0, xx y_advance / 64.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics_render_font(*font.graphics_font, vertices, tex, colour, fb_width, fb_height);
|
|
||||||
|
|
||||||
hb_buffer_destroy(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
HB_TAG :: (c1: u8, c2: u8, c3: u8, c4: u8) -> hb_tag_t #expand {
|
|
||||||
return cast(hb_tag_t)(((cast(u32)(c1)&0xFF)<<24)|((cast(u32)(c2)&0xFF)<<16)|((cast(u32)(c3)&0xFF)<<8)|(cast(u32)(c4)&0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
HB_FEATURE_GLOBAL_END :: cast,no_check(u32) -1;
|
|
||||||
|
|
||||||
calculate_string_draw_size :: (font: *Font, text: string) -> Vector2 {
|
|
||||||
if !text
|
|
||||||
return .{};
|
|
||||||
|
|
||||||
buf : *hb_buffer_t = hb_buffer_create();
|
|
||||||
hb_buffer_add_utf8(buf, text.data, xx text.count, 0, -1);
|
|
||||||
|
|
||||||
hb_buffer_set_direction(buf, hb_direction_t.LTR);
|
|
||||||
hb_buffer_set_script(buf, hb_script_t.HB_SCRIPT_LATIN);
|
|
||||||
hb_buffer_set_language(buf, hb_language_from_string("en", -1));
|
|
||||||
|
|
||||||
features : [1]hb_feature_t;
|
|
||||||
features[0].tag = HB_TAG(#char "c", #char "a", #char "l", #char "t");
|
|
||||||
features[0].value = 1;
|
|
||||||
features[0].start = HB_FEATURE_GLOBAL_START;
|
|
||||||
features[0].end = HB_FEATURE_GLOBAL_END;
|
|
||||||
|
|
||||||
hb_shape(font.hb, buf, features.data, features.count);
|
|
||||||
glyph_count_u : u32;
|
|
||||||
glyph_info : *hb_glyph_info_t = hb_buffer_get_glyph_infos(buf, *glyph_count_u);
|
|
||||||
glyph_pos : *hb_glyph_position_t = hb_buffer_get_glyph_positions(buf, *glyph_count_u);
|
|
||||||
|
|
||||||
glyph_count : s32 = xx glyph_count_u;
|
|
||||||
|
|
||||||
size : Vector2;
|
|
||||||
|
|
||||||
for i : 0..glyph_count - 1 {
|
|
||||||
glyphid : hb_codepoint_t = glyph_info[i].codepoint;
|
|
||||||
x_offset : hb_position_t = glyph_pos[i].x_offset;
|
|
||||||
y_offset : hb_position_t = glyph_pos[i].y_offset;
|
|
||||||
x_advance : hb_position_t = glyph_pos[i].x_advance;
|
|
||||||
y_advance : hb_position_t = glyph_pos[i].y_advance;
|
|
||||||
|
|
||||||
glyph : *Glyph = table_find_pointer(*font.glyphs, glyphid);
|
|
||||||
|
|
||||||
size.y = max(size.y, xx glyph.height);
|
|
||||||
size.x += x_advance / 64.0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_buffer_destroy(buf);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RENDERING
|
|
||||||
|
|
||||||
data_shader : GLuint;
|
data_shader : GLuint;
|
||||||
line_shader : GLuint;
|
line_shader : GLuint;
|
||||||
text_shader : GLuint;
|
|
||||||
|
|
||||||
Y_IS_UP :: true;
|
|
||||||
|
|
||||||
window_projection_matrix : Matrix4;
|
|
||||||
|
|
||||||
GraphicsFont :: struct {
|
|
||||||
atlasid : GLuint;
|
|
||||||
|
|
||||||
vao: GLuint;
|
|
||||||
vbo : GLuint;
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics_init_font :: (graphics_font: *GraphicsFont, atlas: *u8) {
|
|
||||||
glGenTextures(1, *graphics_font.atlasid);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, graphics_font.atlasid);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, ATLAS_SIZE, ATLAS_SIZE, 0, GL_RED, GL_UNSIGNED_BYTE, atlas);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics_render_font :: (graphics_font: *GraphicsFont, vertices: []Vector2, tex: []Vector2, color: Vector3,
|
|
||||||
fb_width: s32, fb_height: s32) {
|
|
||||||
vao : GLuint;
|
|
||||||
glGenVertexArrays(1, *vao);
|
|
||||||
|
|
||||||
glViewport(0, 0, xx fb_width, xx fb_height);
|
|
||||||
|
|
||||||
glBindVertexArray(vao);
|
|
||||||
|
|
||||||
posvbo : GLuint;
|
|
||||||
glGenBuffers(1, *posvbo);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, posvbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, size_of(Vector2) * vertices.count, vertices.data, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, size_of(Vector2), null);
|
|
||||||
|
|
||||||
texvbo : GLuint;
|
|
||||||
glGenBuffers(1, *texvbo);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, texvbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, size_of(Vector2) * tex.count, tex.data, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, size_of(Vector2), null);
|
|
||||||
|
|
||||||
|
|
||||||
proj: Matrix4 = orthographic_projection_matrix(0.0, xx fb_width, xx fb_height, 0.0, -1.0, 1.0);
|
|
||||||
|
|
||||||
view : Matrix4 = identity_of(Matrix4);
|
|
||||||
|
|
||||||
model : Matrix4 = identity_of(Matrix4);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, graphics_font.atlasid);
|
|
||||||
|
|
||||||
glUseProgram(text_shader);
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(text_shader, "proj"), 1, GL_TRUE, cast(*float) *proj);
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(text_shader, "view"), 1, GL_TRUE, cast(*float) *view);
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(text_shader, "model"), 1, GL_TRUE, cast(*float) *model);
|
|
||||||
glUniform3fv(glGetUniformLocation(text_shader, "data_color"), 1, *color.x);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, cast(u32) vertices.count);
|
|
||||||
primitives_rendered_this_frame += vertices.count / 3;
|
|
||||||
|
|
||||||
glDeleteBuffers(1, *posvbo);
|
|
||||||
glDeleteBuffers(1, *texvbo);
|
|
||||||
glDeleteVertexArrays(1, *vao);
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
make_shader :: (vertex_shader_text: string, fragment_shader_text: string) -> GLuint {
|
make_shader :: (vertex_shader_text: string, fragment_shader_text: string) -> GLuint {
|
||||||
success : s32;
|
success : s32;
|
||||||
@ -1153,87 +816,3 @@ void main() {
|
|||||||
color = vec4(data_color.rgb, float_to_srgb(data_color.a));
|
color = vec4(data_color.rgb, float_to_srgb(data_color.a));
|
||||||
}
|
}
|
||||||
DONE
|
DONE
|
||||||
|
|
||||||
////////////////////////
|
|
||||||
// shader to render text
|
|
||||||
////////////////////////
|
|
||||||
|
|
||||||
text_vertex_shader_text : string = #string DONE
|
|
||||||
#version 330 core
|
|
||||||
|
|
||||||
in vec2 data_pos;
|
|
||||||
in vec2 data_tex;
|
|
||||||
|
|
||||||
out vec2 tex;
|
|
||||||
|
|
||||||
uniform mat4 proj;
|
|
||||||
uniform mat4 view;
|
|
||||||
uniform mat4 model;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = proj * view * model * vec4(data_pos, 0.0, 1.0);
|
|
||||||
tex = vec2(data_tex.x, 1.0 - data_tex.y);
|
|
||||||
}
|
|
||||||
DONE
|
|
||||||
|
|
||||||
text_fragment_shader_text : string = #string DONE
|
|
||||||
#version 330 core
|
|
||||||
|
|
||||||
in vec2 tex;
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
|
|
||||||
uniform sampler2D sampler;
|
|
||||||
uniform vec3 data_color;
|
|
||||||
|
|
||||||
float float_to_srgb(float l) {
|
|
||||||
if (l < 0.0031308) {
|
|
||||||
return l * 12.92;
|
|
||||||
} else {
|
|
||||||
return 1.055 * pow(l, 0.41666) - 0.055;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 linear_to_srgb(vec4 linear) {
|
|
||||||
vec4 srgb;
|
|
||||||
|
|
||||||
if (linear.x < 0.0031308) {
|
|
||||||
srgb.x = linear.x * 12.92;
|
|
||||||
} else {
|
|
||||||
srgb.x = 1.055 * pow(linear.x, 0.41666) - 0.055;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linear.y < 0.0031308) {
|
|
||||||
srgb.y = linear.y * 12.92;
|
|
||||||
} else {
|
|
||||||
srgb.y = 1.055 * pow(linear.y, 0.41666) - 0.055;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linear.z < 0.0031308) {
|
|
||||||
srgb.z = linear.z * 12.92;
|
|
||||||
} else {
|
|
||||||
srgb.z = 1.055 * pow(linear.z, 0.41666) - 0.055;
|
|
||||||
}
|
|
||||||
|
|
||||||
srgb.w = linear.w;
|
|
||||||
|
|
||||||
return srgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
float float_to_linear(float s) {
|
|
||||||
if (s <= 0.04045) {
|
|
||||||
return s / 12.92;
|
|
||||||
} else {
|
|
||||||
return pow((s + 0.055) / 1.055, 2.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 srgb_to_linear(vec4 srgb) {
|
|
||||||
return vec4(float_to_linear(srgb.r), float_to_linear(srgb.g), float_to_linear(srgb.b), srgb.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float sampled = texture(sampler, tex).r;
|
|
||||||
color = vec4(data_color, float_to_srgb(sampled));
|
|
||||||
}
|
|
||||||
DONE
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user