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 @@
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 @@
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 @@
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 @@
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 @@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.
-```
-