49 if (!strcmp(
"Renderer.vert.metal", name)) {
50 data = $(alloc(Data), initWithConstMemory, Renderer_vert_metal, Renderer_vert_metal_len);
51 }
else if (!strcmp(
"Renderer.frag.metal", name)) {
52 data = $(alloc(Data), initWithConstMemory, Renderer_frag_metal, Renderer_frag_metal_len);
53 }
else if (!strcmp(
"Renderer.vert.spv", name)) {
54 data = $(alloc(Data), initWithConstMemory, Renderer_vert_spv, Renderer_vert_spv_len);
55 }
else if (!strcmp(
"Renderer.frag.spv", name)) {
56 data = $(alloc(Data), initWithConstMemory, Renderer_frag_spv, Renderer_frag_spv_len);
125static void drawLines(
const Renderer *self,
const SDL_Point *points,
size_t count,
const SDL_Color *color) {
134 const size_t segCount = count - 1;
138 for (
size_t i = 0; i < segCount; i++) {
139 const float ax = (float) points[i].x, ay = (
float) points[i].y;
140 const float bx = (float) points[i+1].x, by = (
float) points[i+1].y;
142 const float dx = bx - ax, dy = by - ay;
143 const float len = sqrtf(dx * dx + dy * dy);
145 float nx = 0.0f, ny = 0.0f;
147 nx = (-dy / len) * 0.5f;
148 ny = ( dx / len) * 0.5f;
152 v[0] = (
MVC_Vertex) { { { ax - nx, ay - ny } }, { { 0.0f, 0.0f } }, { 0 } };
153 v[1] = (
MVC_Vertex) { { { ax + nx, ay + ny } }, { { 0.0f, 0.0f } }, { 0 } };
154 v[2] = (
MVC_Vertex) { { { bx - nx, by - ny } }, { { 0.0f, 0.0f } }, { 0 } };
155 v[3] = (
MVC_Vertex) { { { ax + nx, ay + ny } }, { { 0.0f, 0.0f } }, { 0 } };
156 v[4] = (
MVC_Vertex) { { { bx + nx, by + ny } }, { { 0.0f, 0.0f } }, { 0 } };
157 v[5] = (
MVC_Vertex) { { { bx - nx, by - ny } }, { { 0.0f, 0.0f } }, { 0 } };
192 const float x1 = (float) rect->x, y1 = (
float) rect->y;
193 const float x2 = (float) rect->x + rect->w, y2 = (
float) rect->y + rect->h;
196 { { { x1, y1 } }, { { 0.0f, 0.0f } }, { 0 } },
197 { { { x2, y1 } }, { { 0.0f, 0.0f } }, { 0 } },
198 { { { x1, y2 } }, { { 0.0f, 0.0f } }, { 0 } },
199 { { { x2, y1 } }, { { 0.0f, 0.0f } }, { 0 } },
200 { { { x2, y2 } }, { { 0.0f, 0.0f } }, { 0 } },
201 { { { x1, y2 } }, { { 0.0f, 0.0f } }, { 0 } },
211static void drawTexture(
const Renderer *self, Texture *texture,
const SDL_Rect *rect,
const SDL_Color *color) {
215 const float x1 = (float) rect->x, y1 = (
float) rect->y;
216 const float x2 = (float) rect->x + rect->w, y2 = (
float) rect->y + rect->h;
219 { { { x1, y1 } }, { { 0.0f, 0.0f } }, { 0 } },
220 { { { x2, y1 } }, { { 1.0f, 0.0f } }, { 0 } },
221 { { { x1, y2 } }, { { 0.0f, 1.0f } }, { 0 } },
222 { { { x2, y1 } }, { { 1.0f, 0.0f } }, { 0 } },
223 { { { x2, y2 } }, { { 1.0f, 1.0f } }, { 0 } },
224 { { { x1, y2 } }, { { 0.0f, 1.0f } }, { 0 } },
251 Framebuffer *framebuffer = self->framebuffer;
254 const SDL_GPUColorTargetInfo colorTarget = $(framebuffer, colorTargetInfo, 0, SDL_GPU_LOADOP_LOAD, SDL_GPU_STOREOP_STORE, NULL);
256 const size_t vtxCount = self->vertices->count;
258 CopyPass *copyPass = $(self->commands, beginCopyPass);
261 const Uint32 vtxSize = (Uint32) (vtxCount *
sizeof(
MVC_Vertex));
263 if (vtxCount > self->vertexBufferCapacity) {
264 release(self->vertexBuffer);
265 const SDL_GPUBufferCreateInfo info = { .usage = SDL_GPU_BUFFERUSAGE_VERTEX, .size = vtxSize };
266 self->vertexBuffer = $(self->
device, createBuffer, &info);
267 self->vertexBufferCapacity = (Uint32) vtxCount;
270 $(copyPass, uploadData, self->vertexBuffer->buffer, self->vertices->elements, vtxSize, 0,
true);
275 RenderPass *renderPass = $(self->commands, beginRenderPass, &colorTarget, 1, NULL);
277 $(renderPass, setViewport, &(SDL_GPUViewport){
278 .x = 0.0f, .y = 0.0f,
279 .w = (float) framebuffer->size.w, .h = (
float) framebuffer->size.h,
280 .min_depth = 0.0f, .max_depth = 1.0f,
284 SDL_GetWindowSize(self->
device->window, &winW, &winH);
285 const mat4 projection = mat4_ortho(0.f, (
float) winW, (
float) winH, 0.f, -1.f, 1.f);
286 $(self->commands, pushVertexUniformData, 0, projection.f,
sizeof(projection));
288 $(renderPass, bindPipeline, self->pipeline);
289 $(renderPass, bindVertexBuffers, 0, &(SDL_GPUBufferBinding) { .buffer = self->vertexBuffer->buffer }, 1);
291 for (
size_t i = 0; i < self->drawArrays->count; i++) {
292 const MVC_DrawArrays *
draw = VectorElement(self->drawArrays, MVC_DrawArrays, i);
294 $(renderPass, setScissor, &
draw->scissor);
296 $(renderPass, bindFragmentSamplers, 0, &(SDL_GPUTextureSamplerBinding) {
297 .texture =
draw->texture->texture, .sampler = self->sampler->sampler,
300 $(renderPass, drawPrimitives,
draw->vertexCount, 1,
draw->firstVertex, 0);
305 self->commands = NULL;
306 self->framebuffer = NULL;
361 Shader *vertexShader = $(self->
device, loadShader,
"Renderer.vert", &(SDL_GPUShaderCreateInfo) {
362 .stage = SDL_GPU_SHADERSTAGE_VERTEX,
363 .num_uniform_buffers = 1,
366 Shader *fragmentShader = $(self->
device, loadShader,
"Renderer.frag", &(SDL_GPUShaderCreateInfo) {
367 .stage = SDL_GPU_SHADERSTAGE_FRAGMENT,
371 const SDL_GPUVertexBufferDescription vertexBufferInfo = {
374 .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
375 .instance_step_rate = 0,
378 const SDL_GPUColorTargetDescription colorTarget = {
379 .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
381 .enable_blend =
true,
382 .color_blend_op = SDL_GPU_BLENDOP_ADD,
383 .alpha_blend_op = SDL_GPU_BLENDOP_ADD,
384 .src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
385 .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
386 .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE,
387 .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
391 const SDL_GPUGraphicsPipelineCreateInfo pipelineInfo = {
392 .vertex_shader = vertexShader->shader,
393 .fragment_shader = fragmentShader->shader,
394 .vertex_input_state = {
395 .vertex_buffer_descriptions = &vertexBufferInfo,
396 .num_vertex_buffers = 1,
397 .vertex_attributes = (SDL_GPUVertexAttribute[]) {
401 .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
407 .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
413 .format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM,
417 .num_vertex_attributes = 3,
419 .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
420 .rasterizer_state = {
421 .fill_mode = SDL_GPU_FILLMODE_FILL,
422 .cull_mode = SDL_GPU_CULLMODE_NONE,
423 .front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE,
426 .color_target_descriptions = &colorTarget,
427 .num_color_targets = 1,
431 self->pipeline = $(self->
device, createGraphicsPipeline, &pipelineInfo);
433 release(vertexShader);
434 release(fragmentShader);
436 self->sampler = $(self->
device, createSampler, &(
const SDL_GPUSamplerCreateInfo) {
437 .min_filter = SDL_GPU_FILTER_LINEAR,
438 .mag_filter = SDL_GPU_FILTER_LINEAR,
439 .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR,
440 .address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
441 .address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
442 .address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE,
445 const Uint8 white[4] = { 255, 255, 255, 255 };
447 self->white = $(self->
device, createTexture, &(
const SDL_GPUTextureCreateInfo) {
448 .type = SDL_GPU_TEXTURETYPE_2D,
449 .format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
450 .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER,
453 .layer_count_or_depth = 1,
498 ((ObjectInterface *) clazz->interface)->dealloc =
dealloc;
500 ((RendererInterface *) clazz->interface)->beginFrame =
beginFrame;
501 ((RendererInterface *) clazz->interface)->beginFrameWith =
beginFrameWith;
502 ((RendererInterface *) clazz->interface)->drawLine =
drawLine;
503 ((RendererInterface *) clazz->interface)->drawLines =
drawLines;
504 ((RendererInterface *) clazz->interface)->drawRect =
drawRect;
505 ((RendererInterface *) clazz->interface)->drawRectFilled =
drawRectFilled;
506 ((RendererInterface *) clazz->interface)->drawTexture =
drawTexture;
507 ((RendererInterface *) clazz->interface)->drawView =
drawView;
508 ((RendererInterface *) clazz->interface)->endFrame =
endFrame;
509 ((RendererInterface *) clazz->interface)->initWithDevice =
initWithDevice;
513 ((RendererInterface *) clazz->interface)->setClippingFrame =
setClippingFrame;