Nimbin2git.christianimmanuel.de / Games / strichmaennchen / renderer.c

strichmaennchen git · main

git clone https://git.christianimmanuel.de/games/strichmaennchen.gitwget https://git.christianimmanuel.de/games/strichmaennchen/archive/strichmaennchen.tar.gz
renderer.c 3.7 KB · 114 lines raw
#include <SDL3/SDL.h>
#include <SDL3/SDL_video.h>
#include <stdio.h>
#include <stdlib.h>


#include "renderer.h"
#include "mesh.h"
#include "shader.h"
#include "glfuncs.h"
#include "platform.h"

Renderer* Renderer_create(int width, int height) {
    Renderer* renderer = calloc(1, sizeof(Renderer));
    printf("sizeof(Renderer) = %zu\n", sizeof(Renderer));
    if (!renderer) {
        SDL_Log("Renderer allocation failed.");
        return NULL;
    }

    if (!Platform_init(renderer)) {
        SDL_Log("Renderer Platform_init failed.");
        return NULL;
    }

    if (!Renderer_init(renderer, width, height)) {
        SDL_Log("Renderer init failed");
        Platform_shutdown(renderer);
        return NULL;
    }
    return renderer;
}

bool Renderer_init(Renderer* renderer, int width, int height) {
    renderer->width = width;
    renderer->height = height;

    char* vertSrc = readFile("shaders/basic.vert");
    char* fragSrc = readFile("shaders/basic.frag");
    if (!vertSrc || !fragSrc) {
        fprintf(stderr, "Failed to load shader files\n");
        free(vertSrc); free(fragSrc);
        return false;
    }

    renderer->shaderProgram = createShaderProgram(vertSrc, fragSrc);
    free(vertSrc);
    free(fragSrc);

    if (!renderer->shaderProgram) return false;

    // Initialize shadow shader
    char* shadowVert = readFile("shaders/simple.vert");
    char* shadowFrag = readFile("shaders/simple.frag");
    if (!shadowVert || !shadowFrag) {
        fprintf(stderr, "Failed to load shadow shader files\n");
        free(shadowVert); free(shadowFrag);
        return false;
    }

    renderer->shadowShader = createShaderProgram(shadowVert, shadowFrag);
    free(shadowVert); free(shadowFrag);

    if (!renderer->shadowShader) return false;

    // Initialize shadow map
    renderer->shadowMapWidth = 4096; // Increased resolution for sharper shadows
    renderer->shadowMapHeight = 4096;

    glGenTextures(1, &renderer->shadowMap);
    glBindTexture(GL_TEXTURE_2D, renderer->shadowMap);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, renderer->shadowMapWidth, renderer->shadowMapHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // For PCF
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    float borderColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

    glGenFramebuffers(1, &renderer->shadowFramebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, renderer->shadowFramebuffer);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderer->shadowMap, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        fprintf(stderr, "Shadow framebuffer incomplete!\n");
        return false;
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glEnable(GL_DEPTH_TEST);
    glClearColor(0.1f,0.1f,0.1f,1.0f);

    return true;
}

void Renderer_resize(Renderer* renderer) {
    SDL_GetWindowSize(renderer->window, &renderer->width, &renderer->height);
    glViewport(0, 0, renderer->width, renderer->height);
}

void Renderer_clear(float r, float g, float b, float a) {
    glClearColor(r, g, b, a);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void Renderer_shutdown(Renderer* renderer) {
    if (renderer->shaderProgram) glDeleteProgram(renderer->shaderProgram);
    if (renderer->shadowShader) glDeleteProgram(renderer->shadowShader);
    glDeleteFramebuffers(1, &renderer->shadowFramebuffer);
    glDeleteTextures(1, &renderer->shadowMap);
}