diff --git a/output/posts/2024/09-09-gltest.html b/output/posts/2024/09-09-gltest.html index 225abf9..ab4b057 100644 --- a/output/posts/2024/09-09-gltest.html +++ b/output/posts/2024/09-09-gltest.html @@ -34,229 +34,229 @@

Related Listening<

These files are lifted directly from here

%% src/gl_const.erl
--module(gl_const).
--compile(nowarn_export_all).
--compile(export_all).
+-module(gl_const).
+-compile(nowarn_export_all).
+-compile(export_all).
 
--include_lib("wx/include/gl.hrl").
-
-gl_depth_test() -> ?GL_DEPTH_TEST.
-
-gl_lequal() -> ?GL_LEQUAL.
-gl_color_buffer_bit() -> ?GL_COLOR_BUFFER_BIT.
-
-gl_depth_buffer_bit() -> ?GL_DEPTH_BUFFER_BIT.
-
-gl_triangles() -> ?GL_TRIANGLES.
-gl_array_buffer() -> ?GL_ARRAY_BUFFER.
-gl_element_array_buffer() -> ?GL_ELEMENT_ARRAY_BUFFER.
-gl_static_draw() -> ?GL_STATIC_DRAW.
-
-gl_vertex_shader() -> ?GL_VERTEX_SHADER.
-gl_fragment_shader() -> ?GL_FRAGMENT_SHADER.
-
-gl_compile_status() -> ?GL_COMPILE_STATUS.
-gl_link_status() -> ?GL_LINK_STATUS.
-
-gl_float() -> ?GL_FLOAT.
-gl_false() -> ?GL_FALSE.
-gl_true() -> ?GL_TRUE.
-gl_unsigned_int() -> ?GL_UNSIGNED_INT.
-gl_unsigned_byte() -> ?GL_UNSIGNED_BYTE.
-
-gl_front_and_back() -> ?GL_FRONT_AND_BACK.
-gl_line() -> ?GL_LINE.
-gl_fill() -> ?GL_FILL.
-gl_debug_output() -> ?GL_DEBUG_OUTPUT.
-gl_texture_2d() -> ?GL_TEXTURE_2D.
-gl_texture_wrap_s() -> ?GL_TEXTURE_WRAP_S.
-gl_texture_wrap_t() -> ?GL_TEXTURE_WRAP_T.
-gl_texture_min_filter() -> ?GL_TEXTURE_MIN_FILTER.
-gl_texture_mag_filter() -> ?GL_TEXTURE_MAG_FILTER.
-gl_rgb() -> ?GL_RGB.
-gl_rgba() -> ?GL_RGBA.
-gl_multisample() -> ?GL_MULTISAMPLE.
-gl_luminance() -> ?GL_LUMINANCE.
-
-gl_texture0() -> ?GL_TEXTURE0.
-
-gl_cull_face() -> ?GL_CULL_FACE.
-gl_back() -> ?GL_BACK.
-gl_front() -> ?GL_FRONT.
-gl_ccw() -> ?GL_CCW.
-gl_cw() -> ?GL_CW.
-
-gl_info_log_length() -> ?GL_INFO_LOG_LENGTH.
-
-gl_blend() -> ?GL_BLEND.
-gl_src_alpha() -> ?GL_SRC_ALPHA.
-gl_one() -> ?GL_ONE.
-gl_one_minus_src_alpha() -> ?GL_ONE_MINUS_SRC_ALPHA.
-
-gl_repeat() -> ?GL_REPEAT.
-gl_linear() -> ?GL_LINEAR.
-gl_nearest() -> ?GL_NEAREST.
-
-gl_framebuffer() -> ?GL_FRAMEBUFFER.
-gl_renderbuffer() -> ?GL_RENDERBUFFER.
-gl_color_attachment0() -> ?GL_COLOR_ATTACHMENT0.
-gl_framebuffer_complete() -> ?GL_FRAMEBUFFER_COMPLETE.
-gl_read_framebuffer() -> ?GL_READ_FRAMEBUFFER.
-gl_draw_framebuffer() -> ?GL_DRAW_FRAMEBUFFER.
-
-gl_texture_env() -> ?GL_TEXTURE_ENV.
-gl_texture_env_mode() -> ?GL_TEXTURE_ENV_MODE.
-gl_replace() -> ?GL_REPLACE.
+-include_lib("wx/include/gl.hrl"). + +gl_depth_test() -> ?GL_DEPTH_TEST. + +gl_lequal() -> ?GL_LEQUAL. +gl_color_buffer_bit() -> ?GL_COLOR_BUFFER_BIT. + +gl_depth_buffer_bit() -> ?GL_DEPTH_BUFFER_BIT. + +gl_triangles() -> ?GL_TRIANGLES. +gl_array_buffer() -> ?GL_ARRAY_BUFFER. +gl_element_array_buffer() -> ?GL_ELEMENT_ARRAY_BUFFER. +gl_static_draw() -> ?GL_STATIC_DRAW. + +gl_vertex_shader() -> ?GL_VERTEX_SHADER. +gl_fragment_shader() -> ?GL_FRAGMENT_SHADER. + +gl_compile_status() -> ?GL_COMPILE_STATUS. +gl_link_status() -> ?GL_LINK_STATUS. + +gl_float() -> ?GL_FLOAT. +gl_false() -> ?GL_FALSE. +gl_true() -> ?GL_TRUE. +gl_unsigned_int() -> ?GL_UNSIGNED_INT. +gl_unsigned_byte() -> ?GL_UNSIGNED_BYTE. + +gl_front_and_back() -> ?GL_FRONT_AND_BACK. +gl_line() -> ?GL_LINE. +gl_fill() -> ?GL_FILL. +gl_debug_output() -> ?GL_DEBUG_OUTPUT. +gl_texture_2d() -> ?GL_TEXTURE_2D. +gl_texture_wrap_s() -> ?GL_TEXTURE_WRAP_S. +gl_texture_wrap_t() -> ?GL_TEXTURE_WRAP_T. +gl_texture_min_filter() -> ?GL_TEXTURE_MIN_FILTER. +gl_texture_mag_filter() -> ?GL_TEXTURE_MAG_FILTER. +gl_rgb() -> ?GL_RGB. +gl_rgba() -> ?GL_RGBA. +gl_multisample() -> ?GL_MULTISAMPLE. +gl_luminance() -> ?GL_LUMINANCE. + +gl_texture0() -> ?GL_TEXTURE0. + +gl_cull_face() -> ?GL_CULL_FACE. +gl_back() -> ?GL_BACK. +gl_front() -> ?GL_FRONT. +gl_ccw() -> ?GL_CCW. +gl_cw() -> ?GL_CW. + +gl_info_log_length() -> ?GL_INFO_LOG_LENGTH. + +gl_blend() -> ?GL_BLEND. +gl_src_alpha() -> ?GL_SRC_ALPHA. +gl_one() -> ?GL_ONE. +gl_one_minus_src_alpha() -> ?GL_ONE_MINUS_SRC_ALPHA. + +gl_repeat() -> ?GL_REPEAT. +gl_linear() -> ?GL_LINEAR. +gl_nearest() -> ?GL_NEAREST. + +gl_framebuffer() -> ?GL_FRAMEBUFFER. +gl_renderbuffer() -> ?GL_RENDERBUFFER. +gl_color_attachment0() -> ?GL_COLOR_ATTACHMENT0. +gl_framebuffer_complete() -> ?GL_FRAMEBUFFER_COMPLETE. +gl_read_framebuffer() -> ?GL_READ_FRAMEBUFFER. +gl_draw_framebuffer() -> ?GL_DRAW_FRAMEBUFFER. + +gl_texture_env() -> ?GL_TEXTURE_ENV. +gl_texture_env_mode() -> ?GL_TEXTURE_ENV_MODE. +gl_replace() -> ?GL_REPLACE.

 %% src/wx_const.erl
--module(wx_const).
--compile(nowarn_export_all).
--compile(export_all).
+-module(wx_const).
+-compile(nowarn_export_all).
+-compile(export_all).
 
--include_lib("wx/include/wx.hrl").
+-include_lib("wx/include/wx.hrl").
 
-wx_id_any() -> ?wxID_ANY.
-wx_gl_rgba() -> ?WX_GL_RGBA.
+wx_id_any() -> ?wxID_ANY.
+wx_gl_rgba() -> ?WX_GL_RGBA.
 
-wx_gl_doublebuffer() -> ?WX_GL_DOUBLEBUFFER.
-wx_gl_depth_size() -> ?WX_GL_DEPTH_SIZE.
-wx_gl_forward_compat() -> ?WX_GL_FORWARD_COMPAT.
+wx_gl_doublebuffer() -> ?WX_GL_DOUBLEBUFFER.
+wx_gl_depth_size() -> ?WX_GL_DEPTH_SIZE.
+wx_gl_forward_compat() -> ?WX_GL_FORWARD_COMPAT.
 
-wxk_left() -> ?WXK_LEFT.
-wxk_right() -> ?WXK_RIGHT.
-wxk_up() -> ?WXK_UP.
-wxk_down() -> ?WXK_DOWN.
-wxk_space() -> ?WXK_SPACE.
-wxk_raw_control() -> ?WXK_RAW_CONTROL.
+wxk_left() -> ?WXK_LEFT.
+wxk_right() -> ?WXK_RIGHT.
+wxk_up() -> ?WXK_UP.
+wxk_down() -> ?WXK_DOWN.
+wxk_space() -> ?WXK_SPACE.
+wxk_raw_control() -> ?WXK_RAW_CONTROL.
 
-wx_gl_major_version() -> ?WX_GL_MAJOR_VERSION.
+wx_gl_major_version() -> ?WX_GL_MAJOR_VERSION.
 
-wx_gl_minor_version() -> ?WX_GL_MINOR_VERSION.
+wx_gl_minor_version() -> ?WX_GL_MINOR_VERSION.
 
-wx_gl_core_profile() -> ?WX_GL_CORE_PROFILE.
-wx_gl_sample_buffers() -> ?WX_GL_SAMPLE_BUFFERS.
+wx_gl_core_profile() -> ?WX_GL_CORE_PROFILE.
+wx_gl_sample_buffers() -> ?WX_GL_SAMPLE_BUFFERS.
 
-wx_gl_samples() -> ?WX_GL_SAMPLES.
+wx_gl_samples() -> ?WX_GL_SAMPLES.
 
-wx_null_cursor() -> ?wxNullCursor.
-wx_cursor_blank() -> ?wxCURSOR_BLANK.
-wx_cursor_cross() -> ?wxCURSOR_CROSS.
+wx_null_cursor() -> ?wxNullCursor.
+wx_cursor_blank() -> ?wxCURSOR_BLANK.
+wx_cursor_cross() -> ?wxCURSOR_CROSS.
 
-wx_fontfamily_default() -> ?wxFONTFAMILY_DEFAULT.
-wx_fontfamily_teletype() -> ?wxFONTFAMILY_TELETYPE.
-wx_normal() -> ?wxNORMAL.
-wx_fontstyle_normal() -> ?wxFONTSTYLE_NORMAL.
-wx_fontweight_bold() -> ?wxFONTWEIGHT_BOLD.
-wx_fontweight_normal() -> ?wxFONTWEIGHT_NORMAL.
+wx_fontfamily_default() -> ?wxFONTFAMILY_DEFAULT. +wx_fontfamily_teletype() -> ?wxFONTFAMILY_TELETYPE. +wx_normal() -> ?wxNORMAL. +wx_fontstyle_normal() -> ?wxFONTSTYLE_NORMAL. +wx_fontweight_bold() -> ?wxFONTWEIGHT_BOLD. +wx_fontweight_normal() -> ?wxFONTWEIGHT_NORMAL.

Also add wx to extra_applications in mix.exs:

-
  def application do
-    [
-      extra_applications: [:logger, :wx]
-    ]
-  end
+
  def application do
+    [
+      extra_applications: [:logger, :wx]
+    ]
+  end

For reference, this is the link to the Erlang WX documentation: https://www.erlang.org/doc/apps/wx/chapter.html

Following along here with Ian’s Triangle post, we will also add the records from wx.hrl to our project:

-
defmodule WxRecords do
+
defmodule WxRecords do
   require Record
 
-  for {type, record} <- Record.extract_all(from_lib: "wx/include/wx.hrl") do
-    Record.defrecord(type, record)
-  end
-end
+
for {type, record} <- Record.extract_all(from_lib: "wx/include/wx.hrl") do + Record.defrecord(type, record) + end +end

Finally, we can add a module to render our window!

-
defmodule GlTest.Window do
+
defmodule GlTest.Window do
   import WxRecords
 
   @behaviour :wx_object
 
-  def start_link(_) do
-    :wx_object.start_link(__MODULE__, [], [])
-    {:ok, self()}
-  end
+  def start_link(_) do
+    :wx_object.start_link(__MODULE__, [], [])
+    {:ok, self()}
+  end
 
   @impl :wx_object
-  def init(_) do
-    opts = [size: {800, 600}]
-    wx = :wx.new()
-    frame = :wxFrame.new(wx, :wx_const.wx_id_any(), ~c"Hello", opts)
-    :wxWindow.connect(frame, :close_window)
-
-    :wxFrame.show(frame)
-
-    gl_attrib = [
-      attribList: [
-        :wx_const.wx_gl_core_profile(),
-        :wx_const.wx_gl_major_version(),
+  def init(_) do
+    opts = [size: {800, 600}]
+    wx = :wx.new()
+    frame = :wxFrame.new(wx, :wx_const.wx_id_any(), ~c"Hello", opts)
+    :wxWindow.connect(frame, :close_window)
+
+    :wxFrame.show(frame)
+
+    gl_attrib = [
+      attribList: [
+        :wx_const.wx_gl_core_profile(),
+        :wx_const.wx_gl_major_version(),
         3,
-        :wx_const.wx_gl_minor_version(),
+        :wx_const.wx_gl_minor_version(),
         3,
-        :wx_const.wx_gl_doublebuffer(),
+        :wx_const.wx_gl_doublebuffer(),
         0
-      ]
-    ]
+      ]
+    ]
 
-    canvas = :wxGLCanvas.new(frame, opts ++ gl_attrib)
-    ctx = :wxGLContext.new(canvas)
-    :wxGLCanvas.setCurrent(canvas, ctx)
+    canvas = :wxGLCanvas.new(frame, opts ++ gl_attrib)
+    ctx = :wxGLContext.new(canvas)
+    :wxGLCanvas.setCurrent(canvas, ctx)
 
-    send(self(), :update)
+    send(self(), :update)
 
-    {frame,
-     %{
+    {frame,
+     %{
        frame: frame,
        canvas: canvas
-     }}
-  end
+     }}
+  end
 
   @impl :wx_object
-  def handle_event(wx(event: wxClose()), state) do
-    {:stop, :normal, state}
-  end
+  def handle_event(wx(event: wxClose()), state) do
+    {:stop, :normal, state}
+  end
 
   @impl :wx_object
-  def handle_info(:stop, %{canvas: canvas} = state) do
-    :wxGLCanvas.destroy(canvas)
+  def handle_info(:stop, %{canvas: canvas} = state) do
+    :wxGLCanvas.destroy(canvas)
 
-    {:stop, :normal, state}
-  end
+    {:stop, :normal, state}
+  end
 
   @impl :wx_object
-  def handle_info(:update, state) do
-    render(state)
+  def handle_info(:update, state) do
+    render(state)
 
-    {:noreply, state}
-  end
+    {:noreply, state}
+  end
 
-  defp render(%{canvas: canvas} = state) do
-    draw(state)
-    :wxGLCanvas.swapBuffers(canvas)
-    send(self(), :update)
+  defp render(%{canvas: canvas} = state) do
+    draw(state)
+    :wxGLCanvas.swapBuffers(canvas)
+    send(self(), :update)
 
     :ok
-  end
+  end
 
-  defp draw(%{canvas: _canvas} = _state) do
-    :gl.clearColor(0.2, 0.1, 0.3, 1.0)
-    :gl.clear(:gl_const.gl_color_buffer_bit())
+  defp draw(%{canvas: _canvas} = _state) do
+    :gl.clearColor(0.2, 0.1, 0.3, 1.0)
+    :gl.clear(:gl_const.gl_color_buffer_bit())
 
     :ok
-  end
+  end
 
-  def child_spec(opts) do
-    %{
+  def child_spec(opts) do
+    %{
       id: __MODULE__,
-      start: {__MODULE__, :start_link, [opts]},
+      start: {__MODULE__, :start_link, [opts]},
       restart: :permanent
-    }
-  end
-end
+
} + end +end

And then we can add it to our application.ex and fire up iex -S mix:

-
defmodule Gltest.Application do
+
defmodule Gltest.Application do
   # See https://hexdocs.pm/elixir/Application.html
   # for more information on OTP Applications
   @moduledoc false
@@ -264,17 +264,17 @@ 

Related Listening< use Application @impl true - def start(_type, _args) do - children = [ + def start(_type, _args) do + children = [ GlTest.Window - ] + ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options - opts = [strategy: :one_for_one, name: Gltest.Supervisor] - Supervisor.start_link(children, opts) - end -end

+
opts = [strategy: :one_for_one, name: Gltest.Supervisor] + Supervisor.start_link(children, opts) + end +end

It’s important to note that we’re returning {:ok, self()} from start_link/1, because if you just return the value of :wx_object.start_link/3 the process will crash, because what that diff --git a/output/posts/2024/09-10-opengl-part-2.html b/output/posts/2024/09-10-opengl-part-2.html index 0a21eb8..dcb9190 100644 --- a/output/posts/2024/09-10-opengl-part-2.html +++ b/output/posts/2024/09-10-opengl-part-2.html @@ -29,53 +29,53 @@

Related Listening< The journey of a thousand triangles begins with a single triangle.

This post is basically porting the C++ from this learnopengl.com chapter to Elixir.

-
defmodule GlTest.Window do
+
defmodule GlTest.Window do
   import WxRecords
 
   @behaviour :wx_object
 
-  def start_link(_) do
-    :wx_object.start_link(__MODULE__, [], [])
-    {:ok, self()}
-  end
+  def start_link(_) do
+    :wx_object.start_link(__MODULE__, [], [])
+    {:ok, self()}
+  end
 
   @impl :wx_object
-  def init(_) do
-    opts = [size: {800, 600}]
-    wx = :wx.new()
-    frame = :wxFrame.new(wx, :wx_const.wx_id_any(), ~c"Hello", opts)
-    :wxWindow.connect(frame, :close_window)
-
-    :wxFrame.show(frame)
-
-    gl_attrib = [
-      attribList: [
-        :wx_const.wx_gl_core_profile(),
-        :wx_const.wx_gl_major_version(),
+  def init(_) do
+    opts = [size: {800, 600}]
+    wx = :wx.new()
+    frame = :wxFrame.new(wx, :wx_const.wx_id_any(), ~c"Hello", opts)
+    :wxWindow.connect(frame, :close_window)
+
+    :wxFrame.show(frame)
+
+    gl_attrib = [
+      attribList: [
+        :wx_const.wx_gl_core_profile(),
+        :wx_const.wx_gl_major_version(),
         3,
-        :wx_const.wx_gl_minor_version(),
+        :wx_const.wx_gl_minor_version(),
         3,
-        :wx_const.wx_gl_doublebuffer(),
+        :wx_const.wx_gl_doublebuffer(),
         0
-      ]
-    ]
+      ]
+    ]
 
-    canvas = :wxGLCanvas.new(frame, opts ++ gl_attrib)
-    ctx = :wxGLContext.new(canvas)
-    :wxGLCanvas.setCurrent(canvas, ctx)
+    canvas = :wxGLCanvas.new(frame, opts ++ gl_attrib)
+    ctx = :wxGLContext.new(canvas)
+    :wxGLCanvas.setCurrent(canvas, ctx)
 
-    {shader_program, vao} = init_opengl()
+    {shader_program, vao} = init_opengl()
 
-    send(self(), :update)
+    send(self(), :update)
 
-    {frame,
-     %{
+    {frame,
+     %{
        frame: frame,
        canvas: canvas,
        shader_program: shader_program,
        vao: vao
-     }}
-  end
+     }}
+  end
 
   @vertex_source """
                  #version 330 core
@@ -84,7 +84,7 @@ 

Related Listening< gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); }\0 """ - |> String.to_charlist() + |> String.to_charlist() @fragment_source """ #version 330 core @@ -93,27 +93,27 @@

Related Listening< FragColor = vec4(0.44f, 0.35f, 0.5f, 1.0f); }\0 """ - |> String.to_charlist() + |> String.to_charlist() - def init_opengl() do - vertex_shader = :gl.createShader(:gl_const.gl_vertex_shader()) - :gl.shaderSource(vertex_shader, [@vertex_source]) - :gl.compileShader(vertex_shader) + def init_opengl() do + vertex_shader = :gl.createShader(:gl_const.gl_vertex_shader()) + :gl.shaderSource(vertex_shader, [@vertex_source]) + :gl.compileShader(vertex_shader) - fragment_shader = :gl.createShader(:gl_const.gl_fragment_shader()) - :gl.shaderSource(fragment_shader, [@fragment_source]) - :gl.compileShader(fragment_shader) + fragment_shader = :gl.createShader(:gl_const.gl_fragment_shader()) + :gl.shaderSource(fragment_shader, [@fragment_source]) + :gl.compileShader(fragment_shader) - shader_program = :gl.createProgram() - :gl.attachShader(shader_program, vertex_shader) - :gl.attachShader(shader_program, fragment_shader) - :gl.linkProgram(shader_program) + shader_program = :gl.createProgram() + :gl.attachShader(shader_program, vertex_shader) + :gl.attachShader(shader_program, fragment_shader) + :gl.linkProgram(shader_program) - :gl.deleteShader(vertex_shader) - :gl.deleteShader(fragment_shader) + :gl.deleteShader(vertex_shader) + :gl.deleteShader(fragment_shader) vertices = - [ + [ -0.5, -0.5, 0.0, @@ -123,88 +123,88 @@

Related Listening< 0.0, 0.5, 0.0 - ] - |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) + ] + |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) - [vao] = :gl.genVertexArrays(1) - [vbo] = :gl.genBuffers(1) + [vao] = :gl.genVertexArrays(1) + [vbo] = :gl.genBuffers(1) - :gl.bindVertexArray(vao) + :gl.bindVertexArray(vao) - :gl.bindBuffer(:gl_const.gl_array_buffer(), vbo) + :gl.bindBuffer(:gl_const.gl_array_buffer(), vbo) - :gl.bufferData( - :gl_const.gl_array_buffer(), - byte_size(vertices), + :gl.bufferData( + :gl_const.gl_array_buffer(), + byte_size(vertices), vertices, - :gl_const.gl_static_draw() - ) + :gl_const.gl_static_draw() + ) - :gl.vertexAttribPointer( + :gl.vertexAttribPointer( 0, 3, - :gl_const.gl_float(), - :gl_const.gl_false(), - 3 * byte_size(<<0.0::float-size(32)>>), + :gl_const.gl_float(), + :gl_const.gl_false(), + 3 * byte_size(<<0.0::float-size(32)>>), 0 - ) + ) - :gl.enableVertexAttribArray(0) + :gl.enableVertexAttribArray(0) - :gl.bindBuffer(:gl_const.gl_array_buffer(), 0) + :gl.bindBuffer(:gl_const.gl_array_buffer(), 0) - :gl.bindVertexArray(0) + :gl.bindVertexArray(0) - {shader_program, vao} - end + {shader_program, vao} + end @impl :wx_object - def handle_event(wx(event: wxClose()), state) do - {:stop, :normal, state} - end + def handle_event(wx(event: wxClose()), state) do + {:stop, :normal, state} + end @impl :wx_object - def handle_info(:stop, %{canvas: canvas} = state) do - :wxGLCanvas.destroy(canvas) + def handle_info(:stop, %{canvas: canvas} = state) do + :wxGLCanvas.destroy(canvas) - {:stop, :normal, state} - end + {:stop, :normal, state} + end @impl :wx_object - def handle_info(:update, state) do - render(state) + def handle_info(:update, state) do + render(state) - {:noreply, state} - end + {:noreply, state} + end - defp render(%{canvas: canvas} = state) do - draw(state) - :wxGLCanvas.swapBuffers(canvas) - send(self(), :update) + defp render(%{canvas: canvas} = state) do + draw(state) + :wxGLCanvas.swapBuffers(canvas) + send(self(), :update) :ok - end + end - defp draw(%{canvas: _canvas} = state) do - :gl.clearColor(0.2, 0.1, 0.3, 1.0) - :gl.clear(:gl_const.gl_color_buffer_bit()) + defp draw(%{canvas: _canvas} = state) do + :gl.clearColor(0.2, 0.1, 0.3, 1.0) + :gl.clear(:gl_const.gl_color_buffer_bit()) - :gl.useProgram(state.shader_program) + :gl.useProgram(state.shader_program) - :gl.bindVertexArray(state.vao) - :gl.drawArrays(:gl_const.gl_triangles(), 0, 3) + :gl.bindVertexArray(state.vao) + :gl.drawArrays(:gl_const.gl_triangles(), 0, 3) :ok - end + end - def child_spec(opts) do - %{ + def child_spec(opts) do + %{ id: __MODULE__, - start: {__MODULE__, :start_link, [opts]}, + start: {__MODULE__, :start_link, [opts]}, restart: :permanent - } - end -end

+
} + end +end

Boy, that is a LOT just to render a dang ol triangle. OpenGL doesn’t let you get anything for cheap, huh. Regardless, it’s pretty cool that I can get this to render on my machine with no diff --git a/output/posts/2024/09-11-opengl-part-3.html b/output/posts/2024/09-11-opengl-part-3.html index 689038a..6388618 100644 --- a/output/posts/2024/09-11-opengl-part-3.html +++ b/output/posts/2024/09-11-opengl-part-3.html @@ -25,49 +25,49 @@

Related Listening<

Posted on 2024-09-11

Continuing on, I wanted to try the exercises at the bottom of this chapter, and this is what I came up with.

-
defmodule GlTest.Window do
+
defmodule GlTest.Window do
   import WxRecords
 
   @behaviour :wx_object
 
-  def start_link(_) do
-    :wx_object.start_link(__MODULE__, [], [])
-    {:ok, self()}
-  end
+  def start_link(_) do
+    :wx_object.start_link(__MODULE__, [], [])
+    {:ok, self()}
+  end
 
   @impl :wx_object
-  def init(_) do
-    opts = [size: {800, 600}]
-    wx = :wx.new()
-    frame = :wxFrame.new(wx, :wx_const.wx_id_any(), ~c"Hello", opts)
-
-    :wxWindow.connect(frame, :close_window)
-    :wxFrame.show(frame)
-
-    gl_attrib = [
-      attribList: [
-        :wx_const.wx_gl_core_profile(),
-        :wx_const.wx_gl_major_version(),
+  def init(_) do
+    opts = [size: {800, 600}]
+    wx = :wx.new()
+    frame = :wxFrame.new(wx, :wx_const.wx_id_any(), ~c"Hello", opts)
+
+    :wxWindow.connect(frame, :close_window)
+    :wxFrame.show(frame)
+
+    gl_attrib = [
+      attribList: [
+        :wx_const.wx_gl_core_profile(),
+        :wx_const.wx_gl_major_version(),
         3,
-        :wx_const.wx_gl_minor_version(),
+        :wx_const.wx_gl_minor_version(),
         3,
-        :wx_const.wx_gl_doublebuffer(),
+        :wx_const.wx_gl_doublebuffer(),
         0
-      ]
-    ]
+      ]
+    ]
 
-    canvas = :wxGLCanvas.new(frame, opts ++ gl_attrib)
-    ctx = :wxGLContext.new(canvas)
-    :wxGLCanvas.setCurrent(canvas, ctx)
+    canvas = :wxGLCanvas.new(frame, opts ++ gl_attrib)
+    ctx = :wxGLContext.new(canvas)
+    :wxGLCanvas.setCurrent(canvas, ctx)
 
-    {shader_program, vao1, vao2, rect_vao} = init_opengl()
-    frame_counter = :counters.new(1, [:atomics])
+    {shader_program, vao1, vao2, rect_vao} = init_opengl()
+    frame_counter = :counters.new(1, [:atomics])
 
-    send(self(), :update)
-    now = System.monotonic_time(:millisecond)
+    send(self(), :update)
+    now = System.monotonic_time(:millisecond)
 
-    {frame,
-     %{
+    {frame,
+     %{
        last_time: now,
        frame: frame,
        frame_counter: frame_counter,
@@ -77,8 +77,8 @@ 

Related Listening< vao1: vao1, vao2: vao2, rect_vao: rect_vao - }} - end + }} + end @vertex_source """ #version 330 core @@ -87,7 +87,7 @@

Related Listening< gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); }\0 """ - |> String.to_charlist() + |> String.to_charlist() @fragment_source """ #version 330 core @@ -96,216 +96,216 @@

Related Listening< FragColor = vec4(0.44f, 0.35f, 0.5f, 1.0f); }\0 """ - |> String.to_charlist() + |> String.to_charlist() - def init_opengl() do - vertex_shader = :gl.createShader(:gl_const.gl_vertex_shader()) - :gl.shaderSource(vertex_shader, [@vertex_source]) - :gl.compileShader(vertex_shader) + def init_opengl() do + vertex_shader = :gl.createShader(:gl_const.gl_vertex_shader()) + :gl.shaderSource(vertex_shader, [@vertex_source]) + :gl.compileShader(vertex_shader) - fragment_shader = :gl.createShader(:gl_const.gl_fragment_shader()) - :gl.shaderSource(fragment_shader, [@fragment_source]) - :gl.compileShader(fragment_shader) + fragment_shader = :gl.createShader(:gl_const.gl_fragment_shader()) + :gl.shaderSource(fragment_shader, [@fragment_source]) + :gl.compileShader(fragment_shader) - shader_program = :gl.createProgram() - :gl.attachShader(shader_program, vertex_shader) - :gl.attachShader(shader_program, fragment_shader) - :gl.linkProgram(shader_program) + shader_program = :gl.createProgram() + :gl.attachShader(shader_program, vertex_shader) + :gl.attachShader(shader_program, fragment_shader) + :gl.linkProgram(shader_program) - :gl.deleteShader(vertex_shader) - :gl.deleteShader(fragment_shader) + :gl.deleteShader(vertex_shader) + :gl.deleteShader(fragment_shader) - vertices = triangle_vertices() - vertices_2 = triangle_vertices_2() + vertices = triangle_vertices() + vertices_2 = triangle_vertices_2() - [vao1, vao2, rect_vao] = :gl.genVertexArrays(3) - [vbo1, vbo2, rect_vbo, ebo] = :gl.genBuffers(4) + [vao1, vao2, rect_vao] = :gl.genVertexArrays(3) + [vbo1, vbo2, rect_vbo, ebo] = :gl.genBuffers(4) - for {vertex_array, vertex_buffer, vertices} <- [ - {vao1, vbo1, vertices}, - {vao2, vbo2, vertices_2} - ] do - :gl.bindVertexArray(vertex_array) + for {vertex_array, vertex_buffer, vertices} <- [ + {vao1, vbo1, vertices}, + {vao2, vbo2, vertices_2} + ] do + :gl.bindVertexArray(vertex_array) - :gl.bindBuffer(:gl_const.gl_array_buffer(), vertex_buffer) + :gl.bindBuffer(:gl_const.gl_array_buffer(), vertex_buffer) - :gl.bufferData( - :gl_const.gl_array_buffer(), - byte_size(vertices), + :gl.bufferData( + :gl_const.gl_array_buffer(), + byte_size(vertices), vertices, - :gl_const.gl_static_draw() - ) + :gl_const.gl_static_draw() + ) - :gl.vertexAttribPointer( + :gl.vertexAttribPointer( 0, 3, - :gl_const.gl_float(), - :gl_const.gl_false(), - 3 * byte_size(<<0.0::float-size(32)>>), + :gl_const.gl_float(), + :gl_const.gl_false(), + 3 * byte_size(<<0.0::float-size(32)>>), 0 - ) + ) - :gl.enableVertexAttribArray(0) + :gl.enableVertexAttribArray(0) - :gl.bindBuffer(:gl_const.gl_array_buffer(), 0) + :gl.bindBuffer(:gl_const.gl_array_buffer(), 0) - :gl.bindVertexArray(0) - end + :gl.bindVertexArray(0) + end - rect_vertices = rectangle_vertices() - rect_indices = rectangle_indices() + rect_vertices = rectangle_vertices() + rect_indices = rectangle_indices() - :gl.bindVertexArray(rect_vao) - :gl.bindBuffer(:gl_const.gl_array_buffer(), rect_vbo) + :gl.bindVertexArray(rect_vao) + :gl.bindBuffer(:gl_const.gl_array_buffer(), rect_vbo) - :gl.bufferData( - :gl_const.gl_array_buffer(), - byte_size(rect_vertices), + :gl.bufferData( + :gl_const.gl_array_buffer(), + byte_size(rect_vertices), rect_vertices, - :gl_const.gl_static_draw() - ) + :gl_const.gl_static_draw() + ) - :gl.bindBuffer(:gl_const.gl_element_array_buffer(), ebo) + :gl.bindBuffer(:gl_const.gl_element_array_buffer(), ebo) - :gl.bufferData( - :gl_const.gl_element_array_buffer(), - byte_size(rect_indices), + :gl.bufferData( + :gl_const.gl_element_array_buffer(), + byte_size(rect_indices), rect_indices, - :gl_const.gl_static_draw() - ) + :gl_const.gl_static_draw() + ) - :gl.vertexAttribPointer( + :gl.vertexAttribPointer( 0, 3, - :gl_const.gl_float(), - :gl_const.gl_false(), - 3 * byte_size(<<0.0::float-size(32)>>), + :gl_const.gl_float(), + :gl_const.gl_false(), + 3 * byte_size(<<0.0::float-size(32)>>), 0 - ) - - :gl.enableVertexAttribArray(0) - {shader_program, vao1, vao2, rect_vao} - end - - @triangle_vertices [ - [0.0, 1.0, 0.0], - [1.0, 0.0, 0.0], - [1.0, 1.0, 0.0] - ] - |> List.flatten() - |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) - def triangle_vertices do + ) + + :gl.enableVertexAttribArray(0) + {shader_program, vao1, vao2, rect_vao} + end + + @triangle_vertices [ + [0.0, 1.0, 0.0], + [1.0, 0.0, 0.0], + [1.0, 1.0, 0.0] + ] + |> List.flatten() + |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) + def triangle_vertices do @triangle_vertices - end - - @triangle_vertices_2 [ - [-0.5, -0.5, 0.0], - [0.5, -0.5, 0.0], - [0.0, 0.5, 0.0] - ] - |> List.flatten() - |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) - def triangle_vertices_2 do + end + + @triangle_vertices_2 [ + [-0.5, -0.5, 0.0], + [0.5, -0.5, 0.0], + [0.0, 0.5, 0.0] + ] + |> List.flatten() + |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) + def triangle_vertices_2 do @triangle_vertices_2 - end - - @rectangle_vertices [ - [0.5, 0.5, 0.0], - [0.5, -0.5, 0.0], - [-0.5, -0.5, 0.0], - [-0.5, 0.5, 0.0] - ] - |> List.flatten() - |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) - - def rectangle_vertices do + end + + @rectangle_vertices [ + [0.5, 0.5, 0.0], + [0.5, -0.5, 0.0], + [-0.5, -0.5, 0.0], + [-0.5, 0.5, 0.0] + ] + |> List.flatten() + |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::float-native-size(32)>> end) + + def rectangle_vertices do @rectangle_vertices - end + end - @rectangle_indices [[0, 1, 3], [1, 2, 3]] - |> List.flatten() - |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::native-size(32)>> end) - def rectangle_indices do + @rectangle_indices [[0, 1, 3], [1, 2, 3]] + |> List.flatten() + |> Enum.reduce(<<>>, fn el, acc -> acc <> <<el::native-size(32)>> end) + def rectangle_indices do @rectangle_indices - end + end @impl :wx_object - def handle_event(wx(event: wxClose()), state) do - {:stop, :normal, state} - end + def handle_event(wx(event: wxClose()), state) do + {:stop, :normal, state} + end @impl :wx_object - def handle_info(:stop, %{canvas: canvas, fps_counter_label: fps_counter_label} = state) do - :wxGLCanvas.destroy(canvas) - :wxStaticText.destroy(fps_counter_label) + def handle_info(:stop, %{canvas: canvas, fps_counter_label: fps_counter_label} = state) do + :wxGLCanvas.destroy(canvas) + :wxStaticText.destroy(fps_counter_label) - {:stop, :normal, state} - end + {:stop, :normal, state} + end @impl :wx_object - def handle_info(:update, state) do - state = render(state) + def handle_info(:update, state) do + state = render(state) - {:noreply, state} - end + {:noreply, state} + end - defp render(%{canvas: canvas} = state) do + defp render(%{canvas: canvas} = state) do state = state - |> update_frame_counter() - |> draw() + |> update_frame_counter() + |> draw() - :wxGLCanvas.swapBuffers(canvas) - send(self(), :update) + :wxGLCanvas.swapBuffers(canvas) + send(self(), :update) state - end + end - defp draw(%{frame: frame} = state) do - :gl.clearColor(0.2, 0.1, 0.3, 1.0) - :gl.clear(:gl_const.gl_color_buffer_bit()) + defp draw(%{frame: frame} = state) do + :gl.clearColor(0.2, 0.1, 0.3, 1.0) + :gl.clear(:gl_const.gl_color_buffer_bit()) - :gl.useProgram(state.shader_program) + :gl.useProgram(state.shader_program) - :gl.bindVertexArray(state.vao1) - :gl.drawArrays(:gl_const.gl_triangles(), 0, 3) + :gl.bindVertexArray(state.vao1) + :gl.drawArrays(:gl_const.gl_triangles(), 0, 3) - :gl.bindVertexArray(state.vao2) - :gl.drawArrays(:gl_const.gl_triangles(), 0, 3) + :gl.bindVertexArray(state.vao2) + :gl.drawArrays(:gl_const.gl_triangles(), 0, 3) - :gl.polygonMode(:gl_const.gl_front_and_back(), :gl_const.gl_line()) - :gl.bindVertexArray(state.rect_vao) - :gl.drawElements(:gl_const.gl_triangles(), 6, :gl_const.gl_unsigned_int(), 0) - :gl.polygonMode(:gl_const.gl_front_and_back(), :gl_const.gl_fill()) + :gl.polygonMode(:gl_const.gl_front_and_back(), :gl_const.gl_line()) + :gl.bindVertexArray(state.rect_vao) + :gl.drawElements(:gl_const.gl_triangles(), 6, :gl_const.gl_unsigned_int(), 0) + :gl.polygonMode(:gl_const.gl_front_and_back(), :gl_const.gl_fill()) - :wxWindow.setLabel(frame, ~c"FPS: #{state.fps}") + :wxWindow.setLabel(frame, ~c"FPS: #{state.fps}") state - end + end - def update_frame_counter(%{last_time: last_time, frame_counter: frame_counter} = state) do - now = System.monotonic_time(:millisecond) + def update_frame_counter(%{last_time: last_time, frame_counter: frame_counter} = state) do + now = System.monotonic_time(:millisecond) elapsed = now - last_time - if elapsed > 100 do - frames = :counters.get(frame_counter, 1) - fps = (frames / elapsed * 1000) |> round() - :counters.put(frame_counter, 1, 0) - Map.merge(state, %{fps: fps, last_time: now}) - else - :counters.add(frame_counter, 1, 1) + if elapsed > 100 do + frames = :counters.get(frame_counter, 1) + fps = (frames / elapsed * 1000) |> round() + :counters.put(frame_counter, 1, 0) + Map.merge(state, %{fps: fps, last_time: now}) + else + :counters.add(frame_counter, 1, 1) state - end - end + end + end - def child_spec(opts) do - %{ + def child_spec(opts) do + %{ id: __MODULE__, - start: {__MODULE__, :start_link, [opts]}, + start: {__MODULE__, :start_link, [opts]}, restart: :permanent - } - end -end

+
} + end +end

I was reading some of the related links and I saw this article with a bit about adding a FPS counter, and I thought that would be a fun exercise to try.

diff --git a/output/posts/2024/11-15-how-to-do-a-preload-good.html b/output/posts/2024/11-15-how-to-do-a-preload-good.html index 19094d2..bec44a9 100644 --- a/output/posts/2024/11-15-how-to-do-a-preload-good.html +++ b/output/posts/2024/11-15-how-to-do-a-preload-good.html @@ -36,44 +36,44 @@

How do you solve it? More functions!

The Solution

-
def get_thing(id, opts \\ []) do
-  from(t in Thing, where: t.id == ^id)
-  |> preload(opts[:preload])
-  |> Repo.one()
-end
+
def get_thing(id, opts \\ []) do
+  from(t in Thing, where: t.id == ^id)
+  |> preload(opts[:preload])
+  |> Repo.one()
+end
 
-defp preload(query), do: preload(query, true)
-defp preload(query, nil), do: query
+defp preload(query), do: preload(query, true)
+defp preload(query, nil), do: query
 
-defp preload(query, true) do
+defp preload(query, true) do
   from q in query, 
-    left_join: t in assoc(q, :thing),
-    left_join: s in assoc(t, :sub_thing),
-    preload: [
-      thing: {t, [sub_thing: s]}
-    ],
-    order_by: [asc: t.index]
+    left_join: t in assoc(q, :thing),
+    left_join: s in assoc(t, :sub_thing),
+    preload: [
+      thing: {t, [sub_thing: s]}
+    ],
+    order_by: [asc: t.index]
 ]
-end
+end
 
-defp preload(query, preloads) do
+defp preload(query, preloads) do
   from q in query, preload: ^preloads
-end
+
end

Edit: I made a mistake here originally. Thanks to @AtomKirk for pointing it out!

What I had originally was:

-
def preload(query, true) do
-  from q in query, preload: [
+
def preload(query, true) do
+  from q in query, preload: [
     :association,
-    other_assoc: [:sub_assoc]
-  ]
-end
+
other_assoc: [:sub_assoc] + ] +end

However, this is incorrect. The correct way to do this is to use the left_join with assoc functions.

What I described originally was how Ash does it. In Ash, you’d do something like:

-
Ash.get!(Thing, id, load: [:association, other_assoc: [:sub_assoc]])
+
Ash.get!(Thing, id, load: [:association, other_assoc: [:sub_assoc]])

For a more explicit example, check out this code here

diff --git a/output/posts/2024/12-30-adding-rss-to-a-static-site.html b/output/posts/2024/12-30-adding-rss-to-a-static-site.html index 39d2e83..51ff531 100644 --- a/output/posts/2024/12-30-adding-rss-to-a-static-site.html +++ b/output/posts/2024/12-30-adding-rss-to-a-static-site.html @@ -35,7 +35,6 @@

Related Listening< I’m going to push what I have so far and close the issue, but I’ll be back with another post about getting fancy with the XML generation.

Check out the PR here to see what the code looks like.

-
diff --git a/posts/2024/12-30-adding-rss-to-a-static-site.md b/posts/2024/12-30-adding-rss-to-a-static-site.md index dcb064a..9713b84 100644 --- a/posts/2024/12-30-adding-rss-to-a-static-site.md +++ b/posts/2024/12-30-adding-rss-to-a-static-site.md @@ -18,5 +18,3 @@ I think it will also be the time I finally get around to having a real dev serve I'm going to push what I have so far and close the issue, but I'll be back with another post about getting fancy with the XML generation. Check out the PR [here](https://github.com/andyleclair/andyleclair.github.io/pull/2) to see what the code looks like. -``` -