src/ascension/shader.h

Mon, 30 Jun 2025 23:59:30 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 30 Jun 2025 23:59:30 +0200
changeset 171
7748713bb604
parent 169
6e6717d9c776
permissions
-rw-r--r--

create prototype for creating ellipsis

/*
 * 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_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;
    /**
     * A list of flag-based preprocessor code for the vertex shader.
     * Each code must end with a new-line.
     */
    const char * const *vtx_list;
    /**
     * A list of flag-based preprocessor code for the fragment shader.
     * Each code must end with a new-line.
     */
    const char * const *frag_list;
    /**
     * Selection flags for the list of codes for the vertex shader.
     */
    unsigned short vtx_list_select;
    /**
     * Selection flags for the list of codes for the fragment shader.
     */
    unsigned short frag_list_select;
};

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;
    const char * const *vtx_pp_list;
    const char * const *frag_pp_list;
    unsigned short vtx_pp_list_select;
    unsigned short frag_pp_list_select;
} 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.
 * This is only allowed to return @c NULL when loading the code
 * files from disk fails. In all other cases, this must
 * at least return a valid pointer to a program for which
 * asc_shader_invalid() returns @c true.
 */
typedef AscShaderProgram*(*asc_shader_create_func)(int);

/**
 * 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);

/**
 * Checks if the shader received a correct Open GL ID.
 *
 * If it did not, there is something wrong (compilation or linking failed).
 *
 * @param program the program
 * @return true if the shader was not created successfully
 */
bool asc_shader_invalid(const AscShaderProgram *program);

/**
 * Creates a shader program.
 *
 * @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
 */
AscShaderProgram *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 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);


/**
 * Registers a shader under a certain ID.
 *
 * @param id the custom ID of the shader
 * @param create_func the function that creates the shader
 * @param create_flags flags passed to create_func
 * @return the shader created by the @c create_func or @c NULL when shader compilation failed
 * @see asc_shader_lookup()
 */
const AscShaderProgram *asc_shader_register(unsigned int id, asc_shader_create_func create_func, int create_flags);

/**
 * Looks up a shader by ID.
 *
 * @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 AscShaderProgram *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.
 *
 * @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
 * @see asc_shader_lookup()
 * @see asc_shader_register()
 */
const AscShaderProgram *asc_shader_lookup_or_create(unsigned int id, asc_shader_create_func create_func, int create_flags);


/**
 * 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);

asc_uniform_loc asc_shader_get_uniform_loc(const AscShaderProgram *shader, const char *name);

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

void asc_shader_upload_col4f(int uniform_id, asc_col4f color);

static inline void asc_shader_upload_col4i(int uniform_id, asc_col4i color) {
    asc_shader_upload_col4f(uniform_id, asc_col_itof(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