Skip to content

Instantly share code, notes, and snippets.

@vaiorabbit
Created August 16, 2026 13:57
Show Gist options
  • Select an option

  • Save vaiorabbit/1e8f251656523e95e38d6dcaa375ba30 to your computer and use it in GitHub Desktop.

Select an option

Save vaiorabbit/1e8f251656523e95e38d6dcaa375ba30 to your computer and use it in GitHub Desktop.
// mruby のコードを読み込み→トップレベルの関数にアクセスするまでの手順
const char* script_path = "./code_nanovg.rb";
mrb_state* mrb;
mrb_value receiver;
mrb_sym app_update;
mrb_state* mrb = mrb_open();
FILE* fp = fopen(script_path, "rb");
mrbc_context* context = mrbc_context_new(mrb);
mrbc_filename(mrb, context, script_path);
mrb_load_file_cxt(mrb, fp, context);
mrb_value receiver = mrb_top_self(mrb);
mrb_sym app_update = mrb_intern_cstr(mrb, "app_update");
// NanoVG : NVGcontext は何度も使うのでmruby用にラップした形式で保持
NVGcontext* vg = nvgCreateGL3();
struct RClass* nvg_context_class = mrb_define_class(mrb, "NanoVGContext", mrb->object_class);
MRB_SET_INSTANCE_TT(nvg_context_class, MRB_TT_DATA);
mrb_value vg_value = mrb_obj_value(Data_Wrap_Struct(mrb, nvg_context_class, &nvg_context_data_type, vg));
mrb_gc_register(mrb, vg_value);
while (!WindowShouldClose()) {
// ...
// NanoVG の API 呼び出しを mruby に移譲
nvgBeginFrame(vg, window_w, window_h, pixel_ratio);
// code_nanovg.rb にある2引数の関数 app_update(vg. t) を呼び出す
mrb_value app_update_args[] = {
vg_value,
mrb_float_value(mrb, static_cast<mrb_float>(GetTime())),
};
mrb_funcall_argv(mrb, receiver, app_update, 2, app_update_args);
nvgEndFrame(vg);
// ...
}
fclose(fp);
mrbc_context_free(mrb, context);
mrb_gc_unregister(mrb, vg_value);
mrb_close(mrb);
# C++側から呼び出されるスクリプト
# vg : NVGcontext*
# t : float (raylib's GetTime())
def app_update(vg, t)
draw_graph(vg, 0.0, 400.0, 1280.0, 400.0, t)
end
def draw_graph(vg, x, y, w, h, t)
dx = w / 5.0
samples = [
(1.0 + Math.sin(t * 1.2345 + Math.cos(t * 0.33457) * 0.44)) * 0.5,
(1.0 + Math.sin(t * 0.68363 + Math.cos(t * 1.3) * 1.55)) * 0.5,
(1.0 + Math.sin(t * 1.1642 + Math.cos(t * 0.33457) * 1.24)) * 0.5,
(1.0 + Math.sin(t * 0.56345 + Math.cos(t * 1.63) * 0.14)) * 0.5,
(1.0 + Math.sin(t * 1.6245 + Math.cos(t * 0.254) * 0.3)) * 0.5,
(1.0 + Math.sin(t * 0.345 + Math.cos(t * 0.03) * 0.6)) * 0.5,
]
sx = []
sy = []
6.times do |i|
sx[i] = x + i * dx
sy[i] = y + h * samples[i] * 0.8
end
background = NanoVG.nvgLinearGradient(vg, x, y, x, y + h,
NanoVG.nvgRGBA(0, 160, 192, 0), NanoVG.nvgRGBA(0, 160, 192, 64))
NanoVG.nvgBeginPath(vg)
NanoVG.nvgMoveTo(vg, sx[0], sy[0])
(1...6).each do |i|
NanoVG.nvgBezierTo(vg, sx[i - 1] + dx * 0.5, sy[i - 1], sx[i] - dx * 0.5, sy[i], sx[i], sy[i])
end
NanoVG.nvgLineTo(vg, x + w, y + h)
NanoVG.nvgLineTo(vg, x, y + h)
NanoVG.nvgFillPaint(vg, background)
NanoVG.nvgFill(vg)
NanoVG.nvgBeginPath(vg)
NanoVG.nvgMoveTo(vg, sx[0], sy[0] + 2.0)
(1...6).each do |i|
NanoVG.nvgBezierTo(vg, sx[i - 1] + dx * 0.5, sy[i - 1] + 2.0, sx[i] - dx * 0.5, sy[i] + 2.0, sx[i], sy[i] + 2.0)
end
NanoVG.nvgStrokeColor(vg, NanoVG.nvgRGBA(0, 0, 0, 32))
NanoVG.nvgStrokeWidth(vg, 3.0)
NanoVG.nvgStroke(vg)
NanoVG.nvgBeginPath(vg)
NanoVG.nvgMoveTo(vg, sx[0], sy[0])
(1...6).each do |i|
NanoVG.nvgBezierTo(vg, sx[i - 1] + dx * 0.5, sy[i - 1], sx[i] - dx * 0.5, sy[i], sx[i], sy[i])
end
NanoVG.nvgStrokeColor(vg, NanoVG.nvgRGBA(0, 160, 192, 255))
NanoVG.nvgStrokeWidth(vg, 3.0)
NanoVG.nvgStroke(vg)
6.times do |i|
glow = NanoVG.nvgRadialGradient(vg, sx[i], sy[i] + 2.0, 3.0, 8.0,
NanoVG.nvgRGBA(0, 0, 0, 32), NanoVG.nvgRGBA(0, 0, 0, 0))
NanoVG.nvgBeginPath(vg)
NanoVG.nvgRect(vg, sx[i] - 10.0, sy[i] - 8.0, 20.0, 20.0)
NanoVG.nvgFillPaint(vg, glow)
NanoVG.nvgFill(vg)
end
NanoVG.nvgBeginPath(vg)
6.times { |i| NanoVG.nvgCircle(vg, sx[i], sy[i], 4.0) }
NanoVG.nvgFillColor(vg, NanoVG.nvgRGBA(0, 160, 192, 255))
NanoVG.nvgFill(vg)
NanoVG.nvgBeginPath(vg)
6.times { |i| NanoVG.nvgCircle(vg, sx[i], sy[i], 2.0) }
NanoVG.nvgFillColor(vg, NanoVG.nvgRGBA(220, 220, 220, 255))
NanoVG.nvgFill(vg)
NanoVG.nvgStrokeWidth(vg, 1.0)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment