taisei/src/renderer/api.h

1018 lines
38 KiB
C

/*
* This software is licensed under the terms of the MIT License.
* See COPYING for further information.
* ---
* Copyright (c) 2011-2024, Lukas Weber <laochailan@web.de>.
* Copyright (c) 2012-2024, Andrei Alexeyev <akari@taisei-project.org>.
*/
#pragma once
#include "taisei.h"
#include "color.h"
#include "pixmap/pixmap.h"
#include "renderer/common/shaderlib/shaderlib.h"
#include "resource/resource.h"
#include "resource/shader_program.h"
#include "resource/texture.h"
typedef struct Texture Texture;
typedef struct Framebuffer Framebuffer;
typedef struct VertexBuffer VertexBuffer;
typedef struct VertexArray VertexArray;
typedef struct IndexBuffer IndexBuffer;
typedef struct ShaderObject ShaderObject;
typedef struct ShaderProgram ShaderProgram;
typedef struct Sprite Sprite;
typedef struct Model Model;
enum {
R_DEBUG_LABEL_SIZE = 128,
R_NUM_SPRITE_AUX_TEXTURES = 3,
};
typedef enum RendererFeature {
RFEAT_DRAW_INSTANCED,
RFEAT_DRAW_INSTANCED_BASE_INSTANCE,
RFEAT_DEPTH_TEXTURE,
RFEAT_FRAMEBUFFER_MULTIPLE_OUTPUTS,
RFEAT_TEXTURE_BOTTOMLEFT_ORIGIN,
RFEAT_TEXTURE_SWIZZLE,
RFEAT_PARTIAL_MIPMAPS,
NUM_RFEATS,
} RendererFeature;
typedef uint_fast8_t r_feature_bits_t;
typedef enum RendererCapability {
RCAP_DEPTH_TEST,
RCAP_DEPTH_WRITE,
RCAP_CULL_FACE,
NUM_RCAPS
} RendererCapability;
typedef uint_fast8_t r_capability_bits_t;
enum {
TEX_TYPE_COMPRESSED_BIT = 0x8000,
};
#define TEX_TYPES_UNCOMPRESSED(X, ...) \
/* NOTE: whichever is placed first here is considered the "default" where applicable. */ \
X(RGBA_8, __VA_ARGS__) \
X(RGB_8, __VA_ARGS__) \
X(RG_8, __VA_ARGS__) \
X(R_8, __VA_ARGS__) \
X(RGBA_16, __VA_ARGS__) \
X(RGB_16, __VA_ARGS__) \
X(RG_16, __VA_ARGS__) \
X(R_16, __VA_ARGS__) \
X(RGBA_16_FLOAT, __VA_ARGS__) \
X(RGB_16_FLOAT, __VA_ARGS__) \
X(RG_16_FLOAT, __VA_ARGS__) \
X(R_16_FLOAT, __VA_ARGS__) \
X(RGBA_32_FLOAT, __VA_ARGS__) \
X(RGB_32_FLOAT, __VA_ARGS__) \
X(RG_32_FLOAT, __VA_ARGS__) \
X(R_32_FLOAT, __VA_ARGS__) \
X(DEPTH_8, __VA_ARGS__) \
X(DEPTH_16, __VA_ARGS__) \
X(DEPTH_24, __VA_ARGS__) \
X(DEPTH_32, __VA_ARGS__) \
X(DEPTH_16_FLOAT, __VA_ARGS__) \
X(DEPTH_32_FLOAT, __VA_ARGS__) \
#define TEX_TYPES_HANDLE_COMPRESSED(comp, layout, X, ...) \
X(COMPRESSED_##comp, __VA_ARGS__)
#define TEX_TYPES_COMPRESSED(X, ...) \
PIXMAP_COMPRESSION_FORMATS(TEX_TYPES_HANDLE_COMPRESSED, X, __VA_ARGS__)
#define TEX_TYPES(X, ...) \
TEX_TYPES_UNCOMPRESSED(X, __VA_ARGS__) \
TEX_TYPES_COMPRESSED(X, __VA_ARGS__) \
typedef enum TextureType {
TEX_TYPE_INVALID = -1,
#define DECLARE_TEX_UNCOMPRESSED_TYPE(type, ...) \
TEX_TYPE_##type,
TEX_TYPES_UNCOMPRESSED(DECLARE_TEX_UNCOMPRESSED_TYPE,)
#undef DECLARE_TEX_UNCOMPRESSED_TYPE
#define DECLARE_TEX_COMPRESSED_TYPE(fmt, ...) \
TEX_TYPE_COMPRESSED_##fmt = PIXMAP_COMPRESSION_##fmt | TEX_TYPE_COMPRESSED_BIT,
PIXMAP_COMPRESSION_FORMATS(DECLARE_TEX_COMPRESSED_TYPE,)
#undef DECLARE_TEX_COMPRESSED_TYPE
TEX_TYPE_R = TEX_TYPE_R_8,
TEX_TYPE_RG = TEX_TYPE_RG_8,
TEX_TYPE_RGB = TEX_TYPE_RGB_8,
TEX_TYPE_RGBA = TEX_TYPE_RGBA_8,
TEX_TYPE_DEPTH = TEX_TYPE_DEPTH_24,
} TextureType;
#define TEX_TYPE_IS_COMPRESSED(type) ((bool)((type) & TEX_TYPE_COMPRESSED_BIT))
#define TEX_TYPE_TO_COMPRESSION_FORMAT(type) ((PixmapCompression)((type) & ~TEX_TYPE_COMPRESSED_BIT))
#define COMPRESSION_FORMAT_TO_TEX_TYPE(cfmt) ((TextureType)((cfmt) | TEX_TYPE_COMPRESSED_BIT))
#define TEX_TYPE_IS_DEPTH(type) ((type) >= TEX_TYPE_DEPTH_8 && (type) <= TEX_TYPE_DEPTH_32_FLOAT)
typedef enum TextureClass {
// NOTE: whichever is placed first here is considered the "default" where applicable.
TEXTURE_CLASS_2D,
TEXTURE_CLASS_CUBEMAP,
NUM_TEXTURE_CLASSES,
} TextureClass;
typedef enum TextureFilterMode {
// NOTE: whichever is placed first here is considered the "default" where applicable.
TEX_FILTER_LINEAR,
TEX_FILTER_LINEAR_MIPMAP_NEAREST,
TEX_FILTER_LINEAR_MIPMAP_LINEAR,
TEX_FILTER_NEAREST,
TEX_FILTER_NEAREST_MIPMAP_NEAREST,
TEX_FILTER_NEAREST_MIPMAP_LINEAR,
} TextureFilterMode;
typedef enum TextureWrapMode {
// NOTE: whichever is placed first here is considered the "default" where applicable.
TEX_WRAP_REPEAT,
TEX_WRAP_MIRROR,
TEX_WRAP_CLAMP,
} TextureWrapMode;
typedef enum TextureMipmapMode {
TEX_MIPMAP_MANUAL,
TEX_MIPMAP_AUTO,
} TextureMipmapMode;
typedef enum TextureFlags {
// NOTE: this can be later expanded to include intended usage flags, e.g. "render target", "filterable", etc.
TEX_FLAG_SRGB = (1 << 0),
TEX_FLAG_STREAM = (1 << 1),
} TextureFlags;
enum {
TEX_ANISOTROPY_DEFAULT = 1,
// TEX_MIPMAPS_MAX = ((uint)(-1)),
// pedantic out-of-range warning
#define TEX_MIPMAPS_MAX ((uint)(-1))
};
typedef enum CubemapFace {
CUBEMAP_FACE_POS_X,
CUBEMAP_FACE_NEG_X,
CUBEMAP_FACE_POS_Y,
CUBEMAP_FACE_NEG_Y,
CUBEMAP_FACE_POS_Z,
CUBEMAP_FACE_NEG_Z,
} CubemapFace;
typedef struct TextureParams {
uint width;
uint height;
uint layers;
TextureType type;
TextureClass class;
struct {
TextureFilterMode mag;
TextureFilterMode min;
} filter;
struct {
TextureWrapMode s;
TextureWrapMode t;
} wrap;
SwizzleMask swizzle;
uint anisotropy;
uint mipmaps;
TextureMipmapMode mipmap_mode;
TextureFlags flags;
} attr_designated_init TextureParams;
typedef struct TextureTypeQueryResult {
PixmapFormat optimal_pixmap_format;
PixmapOrigin optimal_pixmap_origin;
bool supplied_pixmap_format_supported;
bool supplied_pixmap_origin_supported;
} TextureTypeQueryResult;
typedef enum FramebufferAttachment {
FRAMEBUFFER_ATTACH_DEPTH,
FRAMEBUFFER_ATTACH_COLOR0,
FRAMEBUFFER_ATTACH_COLOR1,
FRAMEBUFFER_ATTACH_COLOR2,
FRAMEBUFFER_ATTACH_COLOR3,
FRAMEBUFFER_MAX_COLOR_ATTACHMENTS = 4,
FRAMEBUFFER_MAX_ATTACHMENTS = FRAMEBUFFER_ATTACH_COLOR0 + FRAMEBUFFER_MAX_COLOR_ATTACHMENTS,
FRAMEBUFFER_ATTACH_NONE = -1,
} FramebufferAttachment;
enum {
FRAMEBUFFER_MAX_OUTPUTS = FRAMEBUFFER_MAX_COLOR_ATTACHMENTS,
};
typedef void (*FramebufferReadAsyncCallback)(const Pixmap *pixmap, void *userdata);
typedef enum Primitive {
PRIM_POINTS,
PRIM_LINE_STRIP,
PRIM_LINES,
PRIM_TRIANGLE_STRIP,
PRIM_TRIANGLES,
} Primitive;
struct Model {
VertexArray *vertex_array;
size_t num_vertices;
size_t num_indices;
size_t offset;
Primitive primitive;
};
typedef enum VertexAttribType {
VA_FLOAT,
VA_BYTE,
VA_UBYTE,
VA_SHORT,
VA_USHORT,
VA_INT,
VA_UINT,
} VertexAttribType;
typedef struct VertexAttribTypeInfo {
size_t size;
size_t alignment;
} VertexAttribTypeInfo;
typedef enum VertexAttribConversion {
VA_CONVERT_FLOAT,
VA_CONVERT_FLOAT_NORMALIZED,
VA_CONVERT_INT,
} VertexAttribConversion;
typedef struct VertexAttribSpec {
uint8_t elements;
VertexAttribType type;
VertexAttribConversion coversion;
uint divisor;
} VertexAttribSpec;
typedef struct VertexAttribFormat {
VertexAttribSpec spec;
size_t stride;
size_t offset;
uint attachment;
} VertexAttribFormat;
typedef struct GenericModelVertex {
float position[3];
float uv[2];
float normal[3];
float tangent[4]; // NOTE: bitangent = cross(normal, tangent) * tangent[3]
} GenericModelVertex;
typedef enum UniformType {
UNIFORM_FLOAT,
UNIFORM_VEC2,
UNIFORM_VEC3,
UNIFORM_VEC4,
UNIFORM_INT,
UNIFORM_IVEC2,
UNIFORM_IVEC3,
UNIFORM_IVEC4,
UNIFORM_SAMPLER_2D,
UNIFORM_SAMPLER_CUBE,
UNIFORM_MAT3,
UNIFORM_MAT4,
UNIFORM_UNKNOWN,
} UniformType;
#define UNIFORM_TYPE_IS_SAMPLER(ut) \
((ut) == UNIFORM_SAMPLER_2D || (ut) == UNIFORM_SAMPLER_CUBE)
typedef struct UniformTypeInfo {
// Refers to vector elements, not array elements.
uint8_t elements;
uint8_t element_size;
} UniformTypeInfo;
typedef struct Uniform Uniform;
typedef enum BufferKindFlags {
BUFFER_COLOR = (1 << 0),
BUFFER_DEPTH = (1 << 1),
BUFFER_ALL = BUFFER_COLOR | BUFFER_DEPTH,
CLEAR_COLOR attr_deprecated("Use BUFFER_COLOR instead") = BUFFER_COLOR,
CLEAR_DEPTH attr_deprecated("Use BUFFER_DEPTH instead") = BUFFER_DEPTH,
CLEAR_ALL attr_deprecated("Use BUFFER_ALL instead") = BUFFER_ALL,
} BufferKindFlags;
typedef BufferKindFlags ClearBufferFlags
attr_deprecated("Use BufferKindFlags instead");
// Blend modes API based on the SDL one.
typedef enum BlendModeComponent {
BLENDCOMP_COLOR_OP = 0x00,
BLENDCOMP_SRC_COLOR = 0x04,
BLENDCOMP_DST_COLOR = 0x08,
BLENDCOMP_ALPHA_OP = 0x10,
BLENDCOMP_SRC_ALPHA = 0x14,
BLENDCOMP_DST_ALPHA = 0x18,
} BlendModeComponent;
#define BLENDMODE_COMPOSE(src_color, dst_color, color_op, src_alpha, dst_alpha, alpha_op) \
( \
((uint32_t) color_op << BLENDCOMP_COLOR_OP ) | \
((uint32_t) src_color << BLENDCOMP_SRC_COLOR) | \
((uint32_t) dst_color << BLENDCOMP_DST_COLOR) | \
((uint32_t) alpha_op << BLENDCOMP_ALPHA_OP ) | \
((uint32_t) src_alpha << BLENDCOMP_SRC_ALPHA) | \
((uint32_t) dst_alpha << BLENDCOMP_DST_ALPHA) \
)
#define BLENDMODE_COMPONENT(mode, comp) \
(((uint32_t) mode >> (uint32_t) comp) & 0xF)
typedef enum BlendOp {
BLENDOP_ADD = 0x1, // dst + src
BLENDOP_SUB = 0x2, // dst - src
BLENDOP_REV_SUB = 0x3, // src - dst
BLENDOP_MIN = 0x4, // min(dst, src)
BLENDOP_MAX = 0x5, // max(dst, src)
} BlendOp;
typedef enum BlendFactor {
BLENDFACTOR_ZERO = 0x1, // 0, 0, 0, 0
BLENDFACTOR_ONE = 0x2, // 1, 1, 1, 1
BLENDFACTOR_SRC_COLOR = 0x3, // srcR, srcG, srcB, srcA
BLENDFACTOR_INV_SRC_COLOR = 0x4, // 1-srcR, 1-srcG, 1-srcB, 1-srcA
BLENDFACTOR_SRC_ALPHA = 0x5, // srcA, srcA, srcA, srcA
BLENDFACTOR_INV_SRC_ALPHA = 0x6, // 1-srcA, 1-srcA, 1-srcA, 1-srcA
BLENDFACTOR_DST_COLOR = 0x7, // dstR, dstG, dstB, dstA
BLENDFACTOR_INV_DST_COLOR = 0x8, // 1-dstR, 1-dstG, 1-dstB, 1-dstA
BLENDFACTOR_DST_ALPHA = 0x9, // dstA, dstA, dstA, dstA
BLENDFACTOR_INV_DST_ALPHA = 0xA, // 1-dstA, 1-dstA, 1-dstA, 1-dstA
} BlendFactor;
typedef enum BlendMode {
BLEND_NONE = BLENDMODE_COMPOSE(
BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDOP_ADD,
BLENDFACTOR_ONE, BLENDFACTOR_ZERO, BLENDOP_ADD
),
BLEND_ALPHA = BLENDMODE_COMPOSE(
BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_INV_SRC_ALPHA, BLENDOP_ADD,
BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA, BLENDOP_ADD
),
BLEND_PREMUL_ALPHA = BLENDMODE_COMPOSE(
BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA, BLENDOP_ADD,
BLENDFACTOR_ONE, BLENDFACTOR_INV_SRC_ALPHA, BLENDOP_ADD
),
_BLEND_ADD = BLENDMODE_COMPOSE(
BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE, BLENDOP_ADD,
BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDOP_ADD
),
BLEND_SUB = BLENDMODE_COMPOSE(
BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE, BLENDOP_REV_SUB,
BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDOP_REV_SUB
),
BLEND_MOD = BLENDMODE_COMPOSE(
BLENDFACTOR_ZERO, BLENDFACTOR_SRC_COLOR, BLENDOP_ADD,
BLENDFACTOR_ZERO, BLENDFACTOR_ONE, BLENDOP_ADD
),
} BlendMode;
attr_deprecated("Use BLEND_PREMUL_ALPHA and a color with alpha == 0 instead")
static const BlendMode BLEND_ADD = _BLEND_ADD;
typedef struct UnpackedBlendModePart {
BlendOp op;
BlendFactor src;
BlendFactor dst;
} UnpackedBlendModePart;
typedef struct UnpackedBlendMode {
UnpackedBlendModePart color;
UnpackedBlendModePart alpha;
} UnpackedBlendMode;
typedef enum CullFaceMode {
CULL_FRONT = 0x1,
CULL_BACK = 0x2,
CULL_BOTH = CULL_FRONT | CULL_BACK,
} CullFaceMode;
typedef enum DepthTestFunc {
DEPTH_NEVER,
DEPTH_ALWAYS,
DEPTH_EQUAL,
DEPTH_NOTEQUAL,
DEPTH_LESS,
DEPTH_LEQUAL,
DEPTH_GREATER,
DEPTH_GEQUAL,
} DepthTestFunc;
typedef enum VsyncMode {
VSYNC_NONE,
VSYNC_NORMAL,
VSYNC_ADAPTIVE,
} VsyncMode;
typedef union ShaderCustomParams {
float vector[4];
Color color;
} ShaderCustomParams;
typedef struct SpriteStateParams {
ShaderProgram *shader;
Texture *primary_texture;
Texture *aux_textures[R_NUM_SPRITE_AUX_TEXTURES];
BlendMode blend;
} SpriteStateParams;
typedef union SpriteScaleParams {
struct {
union {
float x;
float both;
};
float y;
};
cmplxf as_cmplx;
} SpriteScaleParams;
typedef struct SpriteRotationParams {
vec3 vector;
float angle;
} SpriteRotationParams;
typedef struct SpriteFlipParams {
bool x;
bool y;
} SpriteFlipParams;
typedef struct SpriteParams {
Sprite *sprite_ptr;
ShaderProgram *shader_ptr;
Texture *aux_textures[R_NUM_SPRITE_AUX_TEXTURES];
// TODO: maybe embed these by value and get rid of SpriteParamsBuffer?
const Color *color;
const ShaderCustomParams *shader_params;
BlendMode blend;
FloatOffset pos;
SpriteScaleParams scale;
SpriteRotationParams rotation;
SpriteFlipParams flip;
} SpriteParams;
typedef struct SpriteParamsBuffer {
Color color;
ShaderCustomParams shader_params;
} SpriteParamsBuffer;
// Matches vertex buffer layout
typedef struct SpriteInstanceAttribs {
mat4 mv_transform;
mat4 tex_transform;
union {
FloatRect texrect;
vec4 texrect_vec4;
};
Color rgba;
FloatExtent sprite_size;
ShaderCustomParams custom;
// offsetof(end_of_fields) == size without padding.
char end_of_fields;
} SpriteInstanceAttribs;
/*
* Creates an SDL window with proper flags, and, if needed, sets up a rendering context associated with it.
* Must be called before anything else.
*/
SDL_Window* r_create_window(const char *title, int x, int y, int w, int h, uint32_t flags)
attr_nonnull(1) attr_nodiscard;
/*
* TODO: Document these, and put them in an order that makes a little bit of sense.
*/
void r_init(void);
void r_post_init(void);
void r_release_resources(void);
void r_shutdown(void);
const char *r_backend_name(void);
void r_unclaim_window(SDL_Window *window);
r_feature_bits_t r_features(void);
r_capability_bits_t r_capabilities_current(void);
void r_capabilities(r_capability_bits_t newcaps);
void r_capability(RendererCapability cap, bool value);
bool r_capability_current(RendererCapability cap);
void r_color4(float r, float g, float b, float a);
const Color* r_color_current(void);
void r_blend(BlendMode mode);
BlendMode r_blend_current(void);
void r_cull(CullFaceMode mode);
CullFaceMode r_cull_current(void);
void r_depth_func(DepthTestFunc func);
DepthTestFunc r_depth_func_current(void);
bool r_shader_language_supported(const ShaderLangInfo *lang, ShaderLangInfo *out_alternative) attr_nonnull(1);
ShaderObject* r_shader_object_compile(ShaderSource *source) attr_nonnull(1);
void r_shader_object_destroy(ShaderObject *shobj) attr_nonnull(1);
void r_shader_object_set_debug_label(ShaderObject *shobj, const char *label) attr_nonnull(1);
const char* r_shader_object_get_debug_label(ShaderObject *shobj) attr_nonnull(1);
bool r_shader_object_transfer(ShaderObject *dst, ShaderObject *src) attr_nonnull_all;
ShaderProgram* r_shader_program_link(uint num_objects, ShaderObject *shobjs[num_objects]) attr_nonnull(2);
void r_shader_program_destroy(ShaderProgram *prog);
void r_shader_program_set_debug_label(ShaderProgram *prog, const char *label) attr_nonnull(1);
const char* r_shader_program_get_debug_label(ShaderProgram *prog) attr_nonnull(1);
bool r_shader_program_transfer(ShaderProgram *dst, ShaderProgram *src) attr_nonnull_all;
void r_shader_ptr(ShaderProgram *prog) attr_nonnull(1);
ShaderProgram* r_shader_current(void) attr_returns_nonnull;
Uniform* _r_shader_uniform(ShaderProgram *prog, const char *uniform_name, hash_t uniform_name_hash) attr_nonnull(1, 2);
UniformType r_uniform_type(Uniform *uniform);
void r_uniform_ptr_unsafe(Uniform *uniform, uint offset, uint count, void *data);
#define _R_UNIFORM_GENERIC(suffix, uniform, ...) (_Generic((uniform), \
char* : _r_uniform_##suffix, \
const char* : _r_uniform_##suffix, \
Uniform* : _r_uniform_ptr_##suffix \
))(uniform, __VA_ARGS__)
void _r_uniform_ptr_float(Uniform *uniform, float value);
void _r_uniform_float(const char *uniform, float value) attr_nonnull(1);
#define r_uniform_float(uniform, ...) _R_UNIFORM_GENERIC(float, uniform, __VA_ARGS__)
void _r_uniform_ptr_float_array(Uniform *uniform, uint offset, uint count, float elements[count]) attr_nonnull(4);
void _r_uniform_float_array(const char *uniform, uint offset, uint count, float elements[count]) attr_nonnull(1, 4);
#define r_uniform_float_array(uniform, ...) _R_UNIFORM_GENERIC(float_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec2(Uniform *uniform, float x, float y);
void _r_uniform_vec2(const char *uniform, float x, float y) attr_nonnull(1);
#define r_uniform_vec2(uniform, ...) _R_UNIFORM_GENERIC(vec2, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec2_vec(Uniform *uniform, vec2_noalign value) attr_nonnull(2);
void _r_uniform_vec2_vec(const char *uniform, vec2_noalign value) attr_nonnull(1, 2);
#define r_uniform_vec2_vec(uniform, ...) _R_UNIFORM_GENERIC(vec2_vec, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec2_complex(Uniform *uniform, cmplx value);
void _r_uniform_vec2_complex(const char *uniform, cmplx value) attr_nonnull(1);
#define r_uniform_vec2_complex(uniform, ...) _R_UNIFORM_GENERIC(vec2_complex, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec2_array(Uniform *uniform, uint offset, uint count, vec2_noalign elements[count]) attr_nonnull(4);
void _r_uniform_vec2_array(const char *uniform, uint offset, uint count, vec2_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_vec2_array(uniform, ...) _R_UNIFORM_GENERIC(vec2_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec2_array_complex(Uniform *uniform, uint offset, uint count, cmplx elements[count]) attr_nonnull(4);
void _r_uniform_vec2_array_complex(const char *uniform, uint offset, uint count, cmplx elements[count]) attr_nonnull(1, 4);
#define r_uniform_vec2_array_complex(uniform, ...) _R_UNIFORM_GENERIC(vec2_array_complex, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec3(Uniform *uniform, float x, float y, float z);
void _r_uniform_vec3(const char *uniform, float x, float y, float z) attr_nonnull(1);
#define r_uniform_vec3(uniform, ...) _R_UNIFORM_GENERIC(vec3, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec3_vec(Uniform *uniform, vec3_noalign value) attr_nonnull(2);
void _r_uniform_vec3_vec(const char *uniform, vec3_noalign value) attr_nonnull(1, 2);
#define r_uniform_vec3_vec(uniform, ...) _R_UNIFORM_GENERIC(vec3_vec, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec3_rgb(Uniform *uniform, const Color *rgb) attr_nonnull(2);
void _r_uniform_vec3_rgb(const char *uniform, const Color *rgb) attr_nonnull(1, 2);
#define r_uniform_vec3_rgb(uniform, ...) _R_UNIFORM_GENERIC(vec3_rgb, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec3_array(Uniform *uniform, uint offset, uint count, vec3_noalign elements[count]) attr_nonnull(4);
void _r_uniform_vec3_array(const char *uniform, uint offset, uint count, vec3_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_vec3_array(uniform, ...) _R_UNIFORM_GENERIC(vec3_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec4(Uniform *uniform, float x, float y, float z, float w);
void _r_uniform_vec4(const char *uniform, float x, float y, float z, float w) attr_nonnull(1);
#define r_uniform_vec4(uniform, ...) _R_UNIFORM_GENERIC(vec4, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec4_vec(Uniform *uniform, vec4_noalign value) attr_nonnull(2);
void _r_uniform_vec4_vec(const char *uniform, vec4_noalign value) attr_nonnull(1, 2);
#define r_uniform_vec4_vec(uniform, ...) _R_UNIFORM_GENERIC(vec4_vec, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec4_rgba(Uniform *uniform, const Color *rgba) attr_nonnull(2);
void _r_uniform_vec4_rgba(const char *uniform, const Color *rgba) attr_nonnull(1, 2);
#define r_uniform_vec4_rgba(uniform, ...) _R_UNIFORM_GENERIC(vec4_rgba, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec4_array(Uniform *uniform, uint offset, uint count, vec4_noalign elements[count]) attr_nonnull(4);
void _r_uniform_vec4_array(const char *uniform, uint offset, uint count, vec4_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_vec4_array(uniform, ...) _R_UNIFORM_GENERIC(vec4_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_mat3(Uniform *uniform, mat3_noalign value) attr_nonnull(2);
void _r_uniform_mat3(const char *uniform, mat3_noalign value) attr_nonnull(1, 2);
#define r_uniform_mat3(uniform, ...) _R_UNIFORM_GENERIC(mat3, uniform, __VA_ARGS__)
void _r_uniform_ptr_mat3_array(Uniform *uniform, uint offset, uint count, mat3_noalign elements[count]) attr_nonnull(4);
void _r_uniform_mat3_array(const char *uniform, uint offset, uint count, mat3_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_mat3_array(uniform, ...) _R_UNIFORM_GENERIC(mat3_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_mat4(Uniform *uniform, mat4_noalign value) attr_nonnull(2);
void _r_uniform_mat4(const char *uniform, mat4_noalign value) attr_nonnull(1, 2);
#define r_uniform_mat4(uniform, ...) _R_UNIFORM_GENERIC(mat4, uniform, __VA_ARGS__)
void _r_uniform_ptr_mat4_array(Uniform *uniform, uint offset, uint count, mat4_noalign elements[count]) attr_nonnull(4);
void _r_uniform_mat4_array(const char *uniform, uint offset, uint count, mat4_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_mat4_array(uniform, ...) _R_UNIFORM_GENERIC(mat4_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_int(Uniform *uniform, int value);
void _r_uniform_int(const char *uniform, int value) attr_nonnull(1);
#define r_uniform_int(uniform, ...) _R_UNIFORM_GENERIC(int, uniform, __VA_ARGS__)
void _r_uniform_ptr_int_array(Uniform *uniform, uint offset, uint count, int elements[count]) attr_nonnull(4);
void _r_uniform_int_array(const char *uniform, uint offset, uint count, int elements[count]) attr_nonnull(1, 4);
#define r_uniform_int_array(uniform, ...) _R_UNIFORM_GENERIC(int_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec2(Uniform *uniform, int x, int y);
void _r_uniform_ivec2(const char *uniform, int x, int y) attr_nonnull(1);
#define r_uniform_ivec2(uniform, ...) _R_UNIFORM_GENERIC(ivec2, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec2_vec(Uniform *uniform, ivec2_noalign value) attr_nonnull(2);
void _r_uniform_ivec2_vec(const char *uniform, ivec2_noalign value) attr_nonnull(1, 2);
#define r_uniform_ivec2_vec(uniform, ...) _R_UNIFORM_GENERIC(ivec2_vec, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec2_array(Uniform *uniform, uint offset, uint count, ivec2_noalign elements[count]) attr_nonnull(4);
void _r_uniform_ivec2_array(const char *uniform, uint offset, uint count, ivec2_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_ivec2_array(uniform, ...) _R_UNIFORM_GENERIC(ivec2_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec3(Uniform *uniform, int x, int y, int z);
void _r_uniform_ivec3(const char *uniform, int x, int y, int z) attr_nonnull(1);
#define r_uniform_ivec3(uniform, ...) _R_UNIFORM_GENERIC(ivec3, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec3_vec(Uniform *uniform, ivec3_noalign value) attr_nonnull(2);
void _r_uniform_ivec3_vec(const char *uniform, ivec3_noalign value) attr_nonnull(1, 2);
#define r_uniform_ivec3_vec(uniform, ...) _R_UNIFORM_GENERIC(ivec3_vec, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec3_array(Uniform *uniform, uint offset, uint count, ivec3_noalign elements[count]) attr_nonnull(4);
void _r_uniform_ivec3_array(const char *uniform, uint offset, uint count, ivec3_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_ivec3_array(uniform, ...) _R_UNIFORM_GENERIC(ivec3_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec4(Uniform *uniform, int x, int y, int z, int w);
void _r_uniform_ivec4(const char *uniform, int x, int y, int z, int w) attr_nonnull(1);
#define r_uniform_ivec4(uniform, ...) _R_UNIFORM_GENERIC(ivec4, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec4_vec(Uniform *uniform, ivec4_noalign value) attr_nonnull(2);
void _r_uniform_ivec4_vec(const char *uniform, ivec4_noalign value) attr_nonnull(1, 2);
#define r_uniform_ivec4_vec(uniform, ...) _R_UNIFORM_GENERIC(ivec4_vec, uniform, __VA_ARGS__)
void _r_uniform_ptr_ivec4_array(Uniform *uniform, uint offset, uint count, ivec4_noalign elements[count]) attr_nonnull(4);
void _r_uniform_ivec4_array(const char *uniform, uint offset, uint count, ivec4_noalign elements[count]) attr_nonnull(1, 4);
#define r_uniform_ivec4_array(uniform, ...) _R_UNIFORM_GENERIC(ivec4_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_sampler_ptr(Uniform *uniform, Texture *tex) attr_nonnull(2);
void _r_uniform_sampler_ptr(const char *uniform, Texture *tex) attr_nonnull(1, 2);
void _r_uniform_ptr_sampler(Uniform *uniform, const char *tex) attr_nonnull(2);
void _r_uniform_sampler(const char *uniform, const char *tex) attr_nonnull(1, 2);
#define r_uniform_sampler(uniform, tex) (_Generic((uniform), \
char* : _Generic((tex), \
char* : _r_uniform_sampler, \
const char* : _r_uniform_sampler, \
Texture* : _r_uniform_sampler_ptr \
), \
const char* : _Generic((tex), \
char* : _r_uniform_sampler, \
const char* : _r_uniform_sampler, \
Texture* : _r_uniform_sampler_ptr \
), \
Uniform* : _Generic((tex), \
char* : _r_uniform_ptr_sampler, \
const char* : _r_uniform_ptr_sampler, \
Texture* : _r_uniform_ptr_sampler_ptr \
) \
))(uniform, tex)
void _r_uniform_ptr_sampler_array_ptr(Uniform *uniform, uint offset, uint count, Texture *values[count]) attr_nonnull(4);
void _r_uniform_sampler_array_ptr(const char *uniform, uint offset, uint count, Texture *values[count]) attr_nonnull(1, 4);
void _r_uniform_ptr_sampler_array(Uniform *uniform, uint offset, uint count, const char *values[count]) attr_nonnull(4);
void _r_uniform_sampler_array(const char *uniform, uint offset, uint count, const char *values[count]) attr_nonnull(4);
#define r_uniform_sampler_array(uniform, offset, count, values) (_Generic(uniform, \
char* : _Generic((values), \
char** : _r_uniform_sampler_array, \
Texture** : _r_uniform_sampler_array_ptr \
), \
const char* : _Generic((values), \
char** : _r_uniform_sampler_array, \
Texture** : _r_uniform_sampler_array_ptr \
), \
Uniform* : _Generic((values), \
char** : _r_uniform_ptr_sampler_array, \
Texture** : _r_uniform_ptr_sampler_array_ptr \
) \
))(uniform, offset, count, values)
void r_draw(VertexArray *varr, Primitive prim, uint firstvert, uint count, uint instances, uint base_instance);
void r_draw_indexed(VertexArray *varr, Primitive prim, uint firstidx, uint count, uint instances, uint base_instance);
Texture* r_texture_create(const TextureParams *params) attr_nonnull(1);
void r_texture_get_size(Texture *tex, uint mipmap, uint *width, uint *height) attr_nonnull(1);
uint r_texture_get_width(Texture *tex, uint mipmap) attr_nonnull(1);
uint r_texture_get_height(Texture *tex, uint mipmap) attr_nonnull(1);
void r_texture_get_params(Texture *tex, TextureParams *params) attr_nonnull(1, 2);
const char* r_texture_get_debug_label(Texture *tex) attr_nonnull(1);
void r_texture_set_debug_label(Texture *tex, const char *label) attr_nonnull(1);
void r_texture_set_filter(Texture *tex, TextureFilterMode fmin, TextureFilterMode fmag) attr_nonnull(1);
void r_texture_set_wrap(Texture *tex, TextureWrapMode ws, TextureWrapMode wt) attr_nonnull(1);
void r_texture_fill(Texture *tex, uint mipmap, uint layer, const Pixmap *image_data) attr_nonnull(1, 4);
void r_texture_fill_region(Texture *tex, uint mipmap, uint layer, uint x, uint y, const Pixmap *image_data) attr_nonnull(1, 6);
bool r_texture_dump(Texture *tex, uint mipmap, uint layer, Pixmap *dst) attr_nonnull(1, 4);
void r_texture_invalidate(Texture *tex) attr_nonnull(1);
void r_texture_clear(Texture *tex, const Color *clr) attr_nonnull(1, 2);
void r_texture_destroy(Texture *tex) attr_nonnull(1);
bool r_texture_transfer(Texture *dst, Texture *src) attr_nonnull(1);
bool r_texture_type_query(TextureType type, TextureFlags flags, PixmapFormat pxfmt, PixmapOrigin pxorigin, TextureTypeQueryResult *result) attr_nodiscard;
const char *r_texture_type_name(TextureType type);
TextureType r_texture_type_from_pixmap_format(PixmapFormat fmt);
uint r_texture_util_max_num_miplevels(uint width, uint height);
Framebuffer* r_framebuffer_create(void);
const char* r_framebuffer_get_debug_label(Framebuffer *fb) attr_nonnull(1);
void r_framebuffer_set_debug_label(Framebuffer *fb, const char* label) attr_nonnull(1);
void r_framebuffer_attach(Framebuffer *fb, Texture *tex, uint mipmap, FramebufferAttachment attachment) attr_nonnull(1);
Texture* r_framebuffer_get_attachment(Framebuffer *fb, FramebufferAttachment attachment) attr_nonnull(1);
uint r_framebuffer_get_attachment_mipmap(Framebuffer *fb, FramebufferAttachment attachment) attr_nonnull(1);
void r_framebuffer_set_output_attachment(Framebuffer *fb, uint output, FramebufferAttachment attachment);
FramebufferAttachment r_framebuffer_get_output_attachment(Framebuffer *fb, uint output);
void r_framebuffer_set_output_attachments(Framebuffer *fb, const FramebufferAttachment config[FRAMEBUFFER_MAX_OUTPUTS]);
void r_framebuffer_get_output_attachments(Framebuffer *fb, FramebufferAttachment config[FRAMEBUFFER_MAX_OUTPUTS]);
void r_framebuffer_viewport(Framebuffer *fb, float x, float y, float w, float h);
void r_framebuffer_viewport_rect(Framebuffer *fb, FloatRect viewport);
void r_framebuffer_viewport_current(Framebuffer *fb, FloatRect *viewport) attr_nonnull(2);
void r_framebuffer_destroy(Framebuffer *fb) attr_nonnull(1);
void r_framebuffer_clear(Framebuffer *fb, BufferKindFlags flags, const Color *colorval, float depthval);
void r_framebuffer_copy(Framebuffer *dst, Framebuffer *src, BufferKindFlags flags) attr_nonnull_all;
IntExtent r_framebuffer_get_size(Framebuffer *fb);
void r_framebuffer_read_async(Framebuffer *framebuffer, FramebufferAttachment attachment, IntRect region, void *userdata, FramebufferReadAsyncCallback callback);
void r_framebuffer_read_viewport_async(Framebuffer *framebuffer, FramebufferAttachment attachment, void *userdata, FramebufferReadAsyncCallback callback);
void r_framebuffer(Framebuffer *fb);
Framebuffer* r_framebuffer_current(void);
VertexBuffer* r_vertex_buffer_create(size_t capacity, void *data);
const char* r_vertex_buffer_get_debug_label(VertexBuffer *vbuf) attr_nonnull(1);
void r_vertex_buffer_set_debug_label(VertexBuffer *vbuf, const char* label) attr_nonnull(1);
void r_vertex_buffer_destroy(VertexBuffer *vbuf) attr_nonnull(1);
void r_vertex_buffer_invalidate(VertexBuffer *vbuf) attr_nonnull(1);
SDL_RWops* r_vertex_buffer_get_stream(VertexBuffer *vbuf) attr_nonnull(1);
IndexBuffer* r_index_buffer_create(uint index_size, size_t max_elements);
size_t r_index_buffer_get_capacity(IndexBuffer *ibuf) attr_nonnull(1);
uint r_index_buffer_get_index_size(IndexBuffer *ibuf) attr_nonnull(1);
const char* r_index_buffer_get_debug_label(IndexBuffer *ibuf) attr_nonnull(1);
void r_index_buffer_set_debug_label(IndexBuffer *ibuf, const char *label) attr_nonnull(1);
void r_index_buffer_set_offset(IndexBuffer *ibuf, size_t offset) attr_nonnull(1);
size_t r_index_buffer_get_offset(IndexBuffer *ibuf) attr_nonnull(1);
void r_index_buffer_add_indices_u16(IndexBuffer *ibuf, uint16_t index_ofs, size_t num_elements, uint16_t indices[num_elements]) attr_nonnull(1, 4);
void r_index_buffer_add_indices_u32(IndexBuffer *ibuf, uint32_t index_ofs, size_t num_elements, uint32_t indices[num_elements]) attr_nonnull(1, 4);
void r_index_buffer_invalidate(IndexBuffer *ibuf) attr_nonnull(1);
void r_index_buffer_destroy(IndexBuffer *ibuf) attr_nonnull(1);
VertexArray* r_vertex_array_create(void);
const char* r_vertex_array_get_debug_label(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_set_debug_label(VertexArray *varr, const char* label) attr_nonnull(1);
void r_vertex_array_destroy(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_attach_vertex_buffer(VertexArray *varr, VertexBuffer *vbuf, uint attachment) attr_nonnull(1, 2);
VertexBuffer* r_vertex_array_get_vertex_attachment(VertexArray *varr, uint attachment) attr_nonnull(1);
void r_vertex_array_attach_index_buffer(VertexArray *varr, IndexBuffer *ibuf) attr_nonnull(1);
IndexBuffer* r_vertex_array_get_index_attachment(VertexArray *varr) attr_nonnull(1);
void r_vertex_array_layout(VertexArray *varr, uint nattribs, VertexAttribFormat attribs[nattribs]) attr_nonnull(1, 3);
// NOTE: setting all parameters to 0 disables the scissor test
void r_scissor(int x, int y, int w, int h);
void r_scissor_rect(IntRect scissor);
void r_scissor_current(IntRect *scissor) attr_nonnull(1);
void r_model_add_static(Model *out_mdl, Primitive prim, size_t num_vertices, GenericModelVertex vertices[num_vertices], size_t num_indices, uint32_t indices[num_indices]);
const Model *r_model_get_quad(void) attr_returns_nonnull;
void r_vsync(VsyncMode mode);
VsyncMode r_vsync_current(void);
void r_swap(SDL_Window *window);
void r_mat_mv_push(void);
void r_mat_mv_push_premade(mat4 mat);
void r_mat_mv_push_identity(void);
void r_mat_mv_pop(void);
void r_mat_mv(mat4 mat);
void r_mat_mv_current(mat4 out_mat);
mat4 *r_mat_mv_current_ptr(void);
void r_mat_mv_identity(void);
void r_mat_mv_translate_v(vec3 v);
void r_mat_mv_rotate_v(float angle, vec3 v);
void r_mat_mv_scale_v(vec3 v);
void r_mat_proj_push(void);
void r_mat_proj_push_premade(mat4 mat);
void r_mat_proj_push_identity(void);
void r_mat_proj_push_ortho_ex(float left, float right, float bottom, float top, float near, float far);
void r_mat_proj_push_ortho(float width, float height);
void r_mat_proj_push_perspective(float angle, float aspect, float near, float far);
void r_mat_proj_pop(void);
void r_mat_proj(mat4 mat);
void r_mat_proj_current(mat4 out_mat);
mat4 *r_mat_proj_current_ptr(void);
void r_mat_proj_identity(void);
void r_mat_proj_translate_v(vec3 v);
void r_mat_proj_rotate_v(float angle, vec3 v);
void r_mat_proj_scale_v(vec3 v);
void r_mat_proj_ortho(float left, float right, float bottom, float top, float near, float far);
void r_mat_proj_perspective(float angle, float aspect, float near, float far);
void r_mat_tex_push(void);
void r_mat_tex_push_premade(mat4 mat);
void r_mat_tex_push_identity(void);
void r_mat_tex_pop(void);
void r_mat_tex(mat4 mat);
void r_mat_tex_current(mat4 out_mat);
mat4 *r_mat_tex_current_ptr(void);
void r_mat_tex_identity(void);
void r_mat_tex_translate_v(vec3 v);
void r_mat_tex_rotate_v(float angle, vec3 v);
void r_mat_tex_scale_v(vec3 v);
void r_shader_standard(void);
void r_shader_standard_notex(void);
VertexBuffer* r_vertex_buffer_static_models(void) attr_returns_nonnull;
VertexArray* r_vertex_array_static_models(void) attr_returns_nonnull;
void r_state_push(void);
void r_state_pop(void);
void r_draw_quad(void);
void r_draw_quad_instanced(uint instances);
void r_draw_model_ptr(const Model *model, uint instances, uint base_instance) attr_nonnull(1);
void r_draw_sprite(const SpriteParams *params) attr_nonnull(1);
void r_sprite_batch_prepare_state(const SpriteStateParams *stp);
void r_sprite_batch_add_instance(const SpriteInstanceAttribs *attribs);
void r_flush_sprites(void);
BlendMode r_blend_compose(
BlendFactor src_color, BlendFactor dst_color, BlendOp color_op,
BlendFactor src_alpha, BlendFactor dst_alpha, BlendOp alpha_op
);
uint32_t r_blend_component(BlendMode mode, BlendModeComponent component);
void r_blend_unpack(BlendMode mode, UnpackedBlendMode *dest) attr_nonnull(2);
const UniformTypeInfo* r_uniform_type_info(UniformType type) attr_returns_nonnull;
const VertexAttribTypeInfo* r_vertex_attrib_type_info(VertexAttribType type);
VertexAttribFormat* r_vertex_attrib_format_interleaved(
size_t nattribs,
VertexAttribSpec specs[nattribs],
VertexAttribFormat formats[nattribs],
uint attachment
) attr_nonnull(2, 3);
/*
* Small convenience wrappers
*/
INLINE
void r_enable(RendererCapability cap) {
r_capability(cap, true);
}
INLINE
void r_disable(RendererCapability cap) {
r_capability(cap, false);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
/*
* FIXME: These sometimes trip false positives in ASan (stack use after scope) with clang;
* possibly only in unoptimized builds.
*/
#if 0
INLINE void r_mat_mv_translate(float x, float y, float z) { r_mat_mv_translate_v((vec3) { x, y, z }); }
INLINE void r_mat_proj_translate(float x, float y, float z) { r_mat_proj_translate_v((vec3) { x, y, z }); }
INLINE void r_mat_tex_translate(float x, float y, float z) { r_mat_tex_translate_v((vec3) { x, y, z }); }
INLINE void r_mat_mv_rotate(float angle, float nx, float ny, float nz) { r_mat_mv_rotate_v(angle, (vec3) { nx, ny, nz }); }
INLINE void r_mat_proj_rotate(float angle, float nx, float ny, float nz) { r_mat_proj_rotate_v(angle, (vec3) { nx, ny, nz }); }
INLINE void r_mat_tex_rotate(float angle, float nx, float ny, float nz) { r_mat_tex_rotate_v(angle, (vec3) { nx, ny, nz }); }
INLINE void r_mat_mv_scale(float sx, float sy, float sz) { r_mat_mv_scale_v((vec3) { sx, sy, sz }); }
INLINE void r_mat_proj_scale(float sx, float sy, float sz) { r_mat_proj_scale_v((vec3) { sx, sy, sz }); }
INLINE void r_mat_tex_scale(float sx, float sy, float sz) { r_mat_tex_scale_v((vec3) { sx, sy, sz }); }
#else
#define r_mat_mv_translate(x, y, z) r_mat_mv_translate_v((vec3) { (x), (y), (z) })
#define r_mat_proj_translate(x, y, z) r_mat_proj_translate_v((vec3) { (x), (y), (z) })
#define r_mat_tex_translate(x, y, z) r_mat_tex_translate_v((vec3) { (x), (y), (z) })
#define r_mat_mv_scale(x, y, z) r_mat_mv_scale_v((vec3) { (x), (y), (z) })
#define r_mat_proj_scale(x, y, z) r_mat_proj_scale_v((vec3) { (x), (y), (z) })
#define r_mat_tex_scale(x, y, z) r_mat_tex_scale_v((vec3) { (x), (y), (z) })
#define r_mat_mv_rotate(a, x, y, z) r_mat_mv_rotate_v((a), (vec3) { (x), (y), (z) })
#define r_mat_proj_rotate(a, x, y, z) r_mat_proj_rotate_v((a), (vec3) { (x), (y), (z) })
#define r_mat_tex_rotate(a, x, y, z) r_mat_tex_rotate_v((a), (vec3) { (x), (y), (z) })
#endif
#pragma GCC diagnostic pop
INLINE
void r_color(const Color *c) {
r_color4(c->r, c->g, c->b, c->a);
}
INLINE
void r_color3(float r, float g, float b) {
r_color4(r, g, b, 1.0);
}
INLINE attr_nonnull(1)
void r_shader(const char *prog) {
r_shader_ptr(res_shader(prog));
}
INLINE
Uniform* r_shader_uniform(ShaderProgram *prog, const char *name) {
return _r_shader_uniform(prog, name, ht_str2ptr_hash(name));
}
INLINE
Uniform* r_shader_current_uniform(const char *name) {
return r_shader_uniform(r_shader_current(), name);
}
INLINE
void r_clear(BufferKindFlags flags, const Color *colorval, float depthval) {
r_framebuffer_clear(r_framebuffer_current(), flags, colorval, depthval);
}
INLINE attr_nonnull(1)
void r_draw_model(const char *model) {
r_draw_model_ptr(res_get_data(RES_MODEL, model, RESF_DEFAULT), 0, 0);
}
INLINE attr_nonnull(1)
void r_draw_model_instanced(const char *model, uint instances, uint base_instance) {
r_draw_model_ptr(res_get_data(RES_MODEL, model, RESF_DEFAULT), instances, base_instance);
}
INLINE
r_capability_bits_t r_capability_bit(RendererCapability cap) {
r_capability_bits_t idx = cap;
assert(idx < NUM_RCAPS);
return (1 << idx);
}
INLINE
r_feature_bits_t r_feature_bit(RendererFeature feat) {
r_feature_bits_t idx = feat;
assert(idx < NUM_RFEATS);
return (1 << idx);
}
INLINE
bool r_supports(RendererFeature feature) {
return r_features() & r_feature_bit(feature);
}