src/ascension/shader.h

Fri, 13 Jun 2025 17:45:19 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 13 Jun 2025 17:45:19 +0200
changeset 147
4908cc6c2e01
parent 145
a3231310d66d
permissions
-rw-r--r--

compute frame time before syncing to avoid div-by-zero in first frame

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * Copyright 2023 Mike Becker. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ASCENSION_SHADER_H
#define ASCENSION_SHADER_H

#include "camera.h"

struct asc_shader_code_files_s {
    /**
     * File name of the vertex shader.
     */
    const char *vtx;
    /**
     * File name of the fragment shader.
     */
    const char *frag;
};

struct asc_shader_code_defines_s {
    /**
     * Preprocessor code that shall be prepended to the vertex shader.
     */
    const char *vtx;
    /**
     * Preprocessor code that shall be prepended to the fragment shader.
     */
    const char *frag;
};

typedef struct asc_shader_code_info_s {
    struct asc_shader_code_files_s files;
    struct asc_shader_code_defines_s defines;
} AscShaderCodeInfo;

typedef struct asc_shader_codes_s {
    char *vtx;
    char *frag;
    /**
     * Optional preprocessor code for the vertex shader.
     */
    const char *vtx_pp;
    /**
     * Optional preprocessor code for the fragment shader.
     */
    const char *frag_pp;
} AscShaderCodes;

typedef struct asc_shader_program_s {
    unsigned int id;
    unsigned int gl_id;
    int model;
    int view;
    int projection;
    cx_destructor_func destr_func;
} AscShaderProgram;

/**
 * The maximum ID for a user defined shader.
 *
 * The IDs above this number are reserved for the engine.
 */
#define ASC_SHADER_ID_USER_MAX  1'000'000'000u

typedef AscShaderProgram*(*asc_shader_create_func)(void);

/**
 * Loads shader codes from files.
 *
 * @param info the structure containing the file names and preprocessing info
 * @param codes the structure where to store the loaded codes
 * @return zero on success, non-zero on failure
 */
int asc_shader_load_code_files(AscShaderCodeInfo info, AscShaderCodes *codes);

/**
 * Deallocates the memory for the source codes.
 *
 * @param codes the structure containing pointers to the source codes
 */
void asc_shader_free_codes(AscShaderCodes codes);

/**
 * Creates a shader program.
 *
 * @note This function intentionally has an unspecified pointer return type
 * so that you can assign the return value to your shader struct pointer without casts.
 *
 * @param codes the (zero-terminated) source codes
 * @param mem_size the memory size required for the structure
 * @return the compiled and linked shader program with @c AscShaderProgram as base struct
 */
void *asc_shader_create(AscShaderCodes codes, size_t mem_size);

/**
 * Frees a shader program.
 *
 * @param program the program
 */
void asc_shader_free(AscShaderProgram *program);

/**
 * Activates a shader for use.
 *
 * Does nothing when the shader is already active.
 *
 * @param shader the shader program to use or @c NULL to deactivate any shader
 * @param camera the camera matrices (view/projection) to upload
 */
void asc_shader_use(const AscShaderProgram *shader, const AscCamera *camera);


/**
 * Registers a shader under a certain ID.
 *
 * @note This function intentionally has an unspecified pointer return type
 * so that you can assign the return value to your shader struct pointer without casts.
 * All shader structs must be based on @c AscShaderProgram.
 *
 * @param id the custom ID of the shader
 * @param create_func the function that creates the shader
 * @return the shader created by the @c create_func
 * @see asc_shader_lookup()
 */
const void *asc_shader_register(unsigned int id, asc_shader_create_func create_func);

/**
 * Looks up a shader by ID.
 *
 * @note This function intentionally has an unspecified pointer return type
 * so that you can assign the return value to your shader struct pointer without casts.
 * All shader structs must be based on @c AscShaderProgram.
 *
 * @param id the ID of the shader to look up
 * @return the shader or @c NULL if no shader with such ID exists
 * @see asc_shader_register()
 */
const void *asc_shader_lookup(unsigned int id);

/**
 * Looks up a shader by ID or registers a new one if no shader exists with the specified ID.
 *
 * This function can be used for lazy initialization of shaders.
 *
 * @note This function intentionally has an unspecified pointer return type
 * so that you can assign the return value to your shader struct pointer without casts.
 * All shader structs must be based on @c AscShaderProgram.
 *
 * @param id the custom ID of the shader
 * @param create_func the function to create the shader
 * @return the found shader or the newly created shader
 * @see asc_shader_lookup()
 * @see asc_shader_register()
 */
const void *asc_shader_lookup_or_create(unsigned int id, asc_shader_create_func create_func);


/**
 * Frees all registered shaders.
 *
 * Completely wipes all shaders.
 * Be careful with this function when shaders are needed that have been registered with @c asc_shader_register().
 * Those need to be registered again, or @a asc_shader_lookup() will fail.
 * Shaders that are used with @a asc_shader_lookup_or_create() will be re-created automatically.
 *
 * TODO: maybe we should add another function that only clears lazy-initialized shaders
 *       another alternative would be to keep the initialization info and lazy-initialize cleared shaders on lookup
 *
 * @see asc_shader_lookup_or_create()
 */
void asc_shader_clear_registry(void);

#endif //ASCENSION_SHADER_H

mercurial