#include "renderer.h" #include "../Core/logger.h" #include #include static void fill_constant_buffer(float* cb, const Mat4* world, const Mat4* wvp, Vec3 light_dir, Vec4 light_color, Vec4 ambient_color, int use_texture, Vec4 diffuse_color) { memcpy(cb + 0, world->m, sizeof(float) * 16); memcpy(cb + 16, wvp->m, sizeof(float) * 16); cb[32] = light_dir.x; cb[33] = light_dir.y; cb[34] = light_dir.z; cb[35] = 0.0f; cb[36] = light_color.x; cb[37] = light_color.y; cb[38] = light_color.z; cb[39] = light_color.w; cb[40] = ambient_color.x; cb[41] = ambient_color.y; cb[42] = ambient_color.z; cb[43] = ambient_color.w; cb[44] = use_texture ? 1.0f : 0.0f; cb[45] = 0.0f; cb[46] = 0.0f; cb[47] = 0.0f; cb[48] = diffuse_color.x; cb[49] = diffuse_color.y; cb[50] = diffuse_color.z; cb[51] = diffuse_color.w; } Renderer* renderer_create(GraphicsDevice* device) { Renderer* r = (Renderer*)calloc(1, sizeof(Renderer)); r->device = device; mat4_identity(&r->view); mat4_identity(&r->projection); r->light_dir = (Vec3){0.5f, -1.0f, 0.3f}; r->light_color = (Vec4){1,1,1,1}; r->ambient_color = (Vec4){0.2f,0.2f,0.3f,1}; r->clear_color[0] = 0.1f; r->clear_color[1] = 0.1f; r->clear_color[2] = 0.15f; r->clear_color[3] = 1.0f; return r; } void renderer_destroy(Renderer* r) { free(r); } void renderer_begin_frame(Renderer* r) { ID3D11DeviceContext* ctx = r->device->context; graphics_device_clear(r->device, r->clear_color[0], r->clear_color[1], r->clear_color[2], r->clear_color[3]); D3D11_VIEWPORT vp = {0}; vp.Width = (float)r->device->width; vp.Height = (float)r->device->height; vp.MaxDepth = 1.0f; ctx->lpVtbl->RSSetViewports(ctx, 1, &vp); ctx->lpVtbl->IASetPrimitiveTopology(ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } void renderer_end_frame(Renderer* r) { graphics_device_present(r->device); } void renderer_draw_mesh(Renderer* r, Mesh* m) { if (!r || !m || m->icount == 0) return; if (!m->vb) { LOG_ERROR("renderer_draw_mesh: null vertex buffer"); return; } if (!m->ib) { LOG_ERROR("renderer_draw_mesh: null index buffer"); return; } ID3D11DeviceContext* ctx = r->device->context; UINT stride = sizeof(Vertex); UINT offset = 0; ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &m->vb, &stride, &offset); ctx->lpVtbl->IASetIndexBuffer(ctx, m->ib, DXGI_FORMAT_R32_UINT, 0); ctx->lpVtbl->DrawIndexed(ctx, m->icount, 0, 0); } void renderer_draw_mesh_with_shader(Renderer* r, Mesh* m, Shader* s, const Mat4* world, Texture* t) { if (!m || !s || !r) return; ID3D11DeviceContext* ctx = r->device->context; shader_bind(s, ctx); Mat4 wvp; mat4_multiply(world, &r->view, &wvp); mat4_multiply(&wvp, &r->projection, &wvp); float cb[64]; memset(cb, 0, sizeof(cb)); fill_constant_buffer(cb, world, &wvp, r->light_dir, r->light_color, r->ambient_color, t ? 1 : 0, (Vec4){1,1,1,1}); shader_set_matrix(s, ctx, cb); if (t) texture_bind(t, ctx, 0); renderer_draw_mesh(r, m); } void renderer_draw_mesh_with_material(Renderer* r, Mesh* m, Material* mat, const Mat4* world) { if (!m || !mat || !mat->shader || !r) return; ID3D11DeviceContext* ctx = r->device->context; shader_bind(mat->shader, ctx); Mat4 wvp; mat4_multiply(world, &r->view, &wvp); mat4_multiply(&wvp, &r->projection, &wvp); float cb[64]; memset(cb, 0, sizeof(cb)); fill_constant_buffer(cb, world, &wvp, r->light_dir, r->light_color, r->ambient_color, mat->use_texture, mat->color); shader_set_matrix(mat->shader, ctx, cb); if (mat->use_texture && mat->texture) texture_bind(mat->texture, ctx, 0); renderer_draw_mesh(r, m); } void renderer_set_view(Renderer* r, const Mat4* v) { r->view = *v; } void renderer_set_projection(Renderer* r, const Mat4* p) { r->projection = *p; } void renderer_set_light(Renderer* r, Vec3 d, Vec4 c, Vec4 a) { r->light_dir=d; r->light_color=c; r->ambient_color=a; } void renderer_set_clear_color(Renderer* r, float rc, float g, float b, float a) { if (!r) return; r->clear_color[0] = rc; r->clear_color[1] = g; r->clear_color[2] = b; r->clear_color[3] = a; } GraphicsDevice* renderer_get_device(Renderer* r) { return r ? r->device : NULL; } void renderer_get_view_projection(const Renderer* r, Mat4* out) { if (!r || !out) return; mat4_multiply(&r->view, &r->projection, out); } void renderer_resize(Renderer* r, int width, int height) { if (r && r->device && width > 0 && height > 0) { graphics_device_resize(r->device, width, height); } }