src/ascension/shader.h

Tue, 19 Aug 2025 18:51:46 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 19 Aug 2025 18:51:46 +0200
changeset 270
3031d1bb5957
parent 269
f40054d711b3
permissions
-rw-r--r--

further improve names and docu of the uniform location init functions

/*
 * 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 <cx/allocator.h>

#include "camera.h"

typedef struct asc_scene_node_s AscSceneNode; // avoids full include of scene_node.h

typedef int asc_uniform_loc;

struct asc_shader_code_s {
    /**
     * File name of the shader.
     * Set to @c NULL if the specific type of shader is not used in the program.
     */
    const char *source_file;
    /**
     * An array of code segments, usually preprocessor defines.
     *
     * The maximum number of elements in this array is 64.
     * The preamble_code_flags integer decides which elements of this array shall be prepended to
     * the shader code before compilation.
     */
    const char * const *preamble_code;
    /**
     * Flags for deciding which code segments shall be added to the preamble of the shader.
     */
    uint64_t preamble_code_flags;
};

typedef struct asc_shader_codes_s {
    struct asc_shader_code_s vtx;
    struct asc_shader_code_s frag;
} 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

/**
 * A function to create a shader program.
 * Should return @c NULL when creation fails.
 *
 * Usually this function calls asc_shader_create() with
 * a configuration that depends on the flags passed as parameter.
 *
 * @see asc_shader_create()
 */
typedef AscShaderProgram*(*asc_shader_create_func)(int);

/**
 * Initialization function for a shader.
 *
 * This usually gets all uniform locations and stores them as integers in the struct.
 *
 * To be used with asc_shader_create().
 * @see asc_shader_create()
 * @see asc_shader_set_uniform_loc()
 */
typedef void(*asc_shader_init_func)(AscShaderProgram*, int);

/**
 * Creates a shader program.
 *
 * @param code_info the information about the code that should be loaded
 * @param mem_size the memory size required for the target structure
 * @param init_func the initialization function
 * @param flags the creation flags
 * @return the compiled and linked shader program as a structure of size @p mem_size
 * that contains @c AscShaderProgram as base struct
 */
AscShaderProgram *asc_shader_create(AscShaderCodes code_info,
    size_t mem_size, asc_shader_init_func init_func, int flags);

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

/**
 * Activates a shader for use.
 *
 * Does nothing and immediately returns zero 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
 * @retval zero when the shader is now active
 * @retval non-zero when the shader that was supposed to be activated is invalid
 */
int asc_shader_use(const AscShaderProgram *shader, const AscCamera *camera);

/**
 * Looks up a shader by ID or registers a new one if no shader exists with the specified ID.
 *
 * @param id the custom ID of the shader
 * @param create_func the function to create the shader
 * @param create_flags flags passed to create_func
 * @return the found shader or the newly created shader or @c NULL when shader compilation failed
 */
const AscShaderProgram *asc_shader_lookup(unsigned int id, asc_shader_create_func create_func, int create_flags);


/**
 * Frees all registered shaders.
 *
 * The still required shaders are re-created when they are used next.
 *
 * @see asc_shader_lookup()
 */
void asc_shader_clear_registry(void);

/**
 * Gets the location of a uniform as an integer.
 *
 * Usually you will not need this function. Instead, it is recommended to create a custom
 * shader program struct which uses AscShaderProgram as the base struct and then add the uniform locations
 * as fields to that struct.
 * Then you can use asc_shader_set_uniform_loc_by_name() to initialize all uniform locations.
 *
 * @param shader a pointer to the shader struct
 * @param name the name of the uniform
 * @return the uniform's location
 */
asc_uniform_loc asc_shader_get_uniform_loc(const AscShaderProgram *shader, const char *name);

/**
 * Gets the location of a uniform as an integer and stores it directly in the struct.
 *
 * @param shader a pointer to the shader struct
 * @param mem_offset the offset of the @c asc_uniform_loc field in the shader program struct
 * @param name the name of the uniform
 */
void asc_shader_set_uniform_loc(AscShaderProgram *shader, off_t mem_offset, const char *name);

/**
 * Gets the location of a uniform as an integer and stores it in the struct.
 *
 * Use this macro for asc_shader_set_uniform_loc() when the name in your struct is identical to the uniform's name.
 *
 * @param shader a pointer to the shader struct
 * @param type_name the type name of the shader struct
 * @param field_name the field name which must match the uniform's name
 */
#define asc_shader_set_uniform_loc_by_name(shader, type_name, field_name) \
    asc_shader_set_uniform_loc(shader, offsetof(type_name, field_name), #field_name)

void asc_shader_upload_model_matrix(const AscShaderProgram *shader, const AscSceneNode *node);

void asc_shader_upload_color(int uniform_id, asc_color color);

void asc_shader_upload_float(int uniform_id, float value);

void asc_shader_upload_vec2f(int uniform_id, asc_vec2f value);

#endif //ASCENSION_SHADER_H

mercurial