#include "asset.hpp" #include "camera.hpp" #include "debugdraw.hpp" #include "video.hpp" extern "C" { #include "plat.h" } void Line_Renderer::init(Device* dev, Asset_Arena* assets) { vb.init( dev, "Line Renderer mesh", max_lines * sizeof(Vertex) * 2, Buffer_Flags::vertex_buffer ); cb.init( dev, "Line Renderer cbuffer", sizeof(CBuffer), Buffer_Flags::constant_buffer ); shader = (Shader*)assets->load("debug.csh"); vert_binding = shader->binding_index("verts"); cbuffer_binding = shader->descriptor_binding("cbuf"); assert(vert_binding >= 0); assert(cbuffer_binding >= 0); verts = (Vertex*)vb.map(dev); cur = 0; } void Line_Renderer::destroy(Device* dev) { vb.unmap(dev); vb.destroy(dev); cb.destroy(dev); } void Line_Renderer::begin(int wi, int he) { cur = 0; w = wi; h = he; cur_col = v3f(1.0f, 1.0f, 1.0f); } void Line_Renderer::colour(const v3f& c) { cur_col = c; } void Line_Renderer::add_line(const v3f& s, const v3f& e) { if (cur >= max_lines) { assert(0); return; } Vertex& a = verts[cur * 2]; Vertex& b = verts[cur * 2 + 1]; a.x = s.x; a.y = s.y; a.z = s.z; b.x = e.x; b.y = e.y; b.z = e.z; a.r = cur_col.x; a.g = cur_col.y; a.b = cur_col.z; b.r = cur_col.x; b.g = cur_col.y; b.b = cur_col.z; cur++; } void Line_Renderer::add_arrow(const v3f& s, const v3f& e) { v3f tang(0.0f, 1.0f, 0.0f); v3f dir = v3f::normalised(e - s); v4f dir4 = v4f(dir, 0.0f); float d = v3f::dot(tang, dir); if (d > 0.999f || d < -0.999f) tang = v3f(1.0f, 0.0f, 0.0f); tang = v3f::cross(tang, dir); const m4f a = m4f::rotate(m4f::identity(), 2.8f, tang); const m4f b = m4f::rotate(m4f::identity(), 3.5f, tang); add_line(s, e); add_line(e, e + (a * dir4).xyz() * 0.1f); add_line(e, e + (b * dir4).xyz() * 0.1f); } void Line_Renderer::add_box(const AABB& b) { add_line(v3f(b.max.x, b.max.y, b.max.z), v3f(b.max.x, b.max.y, b.min.z)); add_line(v3f(b.max.x, b.max.y, b.max.z), v3f(b.max.x, b.min.y, b.max.z)); add_line(v3f(b.max.x, b.max.y, b.max.z), v3f(b.min.x, b.max.y, b.max.z)); add_line(v3f(b.max.x, b.min.y, b.min.z), v3f(b.max.x, b.max.y, b.min.z)); add_line(v3f(b.max.x, b.min.y, b.min.z), v3f(b.max.x, b.min.y, b.max.z)); add_line(v3f(b.min.x, b.max.y, b.max.z), v3f(b.min.x, b.min.y, b.max.z)); add_line(v3f(b.min.x, b.max.y, b.min.z), v3f(b.max.x, b.max.y, b.min.z)); add_line(v3f(b.min.x, b.max.y, b.min.z), v3f(b.min.x, b.max.y, b.max.z)); add_line(v3f(b.min.x, b.min.y, b.max.z), v3f(b.max.x, b.min.y, b.max.z)); add_line(v3f(b.min.x, b.min.y, b.min.z), v3f(b.max.x, b.min.y, b.min.z)); add_line(v3f(b.min.x, b.min.y, b.min.z), v3f(b.min.x, b.max.y, b.min.z)); add_line(v3f(b.min.x, b.min.y, b.min.z), v3f(b.min.x, b.min.y, b.max.z)); } void Line_Renderer::flush( const Camera& cam, Device* dev, Arena* a, Render_Pass& rp ) { if (!cur) return; CBuffer* c = (CBuffer*)cb.map(dev); c->vp = cam.get_proj() * cam.get_view(); cb.unmap(dev); Pipeline_Builder pb(a, dev); Context& ctx = dev->get_ctx(); cb.update(ctx); vb.update(ctx); pb.begin(); pb.shader(shader->id); pb.cbuffer(cbuffer_binding, cb.gpuonly); pb.vertex_format(shader->vf); pb.geo(Geo_Type::lines); if (rp.depth.id) pb.depth(true, false, Depth_Mode::less); Pipeline& pip = pb.build(); Vertex_Buffer_Binding binding[] = {{ .id = vb.gpuonly, .offset = 0, .target = vert_binding }, {}}; Draw d{}; d.verts = binding; d.vertex_count = cur * 2; d.instance_count = 1; ctx.submit(d, pip, rp); cur = 0; }