ref: 5b04bd5b3a152d0b2d5a8d8e1e25887b71c338d5
dir: /graphics.h/
#define HZ2MS(hz) (1000/(hz))
#define HZ2NS(hz) (1000000000ULL/(hz))
#define min(a, b) ((a)<(b)?(a):(b))
#define max(a, b) ((a)>(b)?(a):(b))
/* bootleg ripoffs for Xpeed */
#define _Xdotvec2(a,b) ((a).x*(b).x + (a).y*(b).y)
#define _Xdotvec3(a,b) ((a).x*(b).x + (a).y*(b).y + (a).z*(b).z)
enum {
/* projection types */
ORTHOGRAPHIC,
PERSPECTIVE,
/* culling modes */
CullNone = 0,
CullFront,
CullBack,
/* primitive types */
PPoint = 0,
PLine,
PTriangle,
/* light types */
LightPoint = 0,
LightDirectional,
LightSpot,
/* raster formats */
COLOR32 = 0, /* RGBA32 */
FLOAT32, /* F32 */
/* texture formats */
RAWTexture = 0, /* unmanaged */
sRGBTexture,
/* upscaling filters */
UFNone = 0, /* nearest neighbour */
UFScale2x,
UFScale3x,
UFScale4x,
/* render options */
ROBlend = 0x01,
RODepth = 0x02,
ROAbuff = 0x04,
/* vertex attribute types */
VAPoint = 0,
VANumber,
MAXVATTRS = 10, /* change this if your shaders require it */
/* itemarray */
NaI = ~0ULL, /* not an index */
};
typedef struct ItemArray ItemArray;
typedef struct Color Color;
typedef struct Texture Texture;
typedef struct Cubemap Cubemap;
typedef struct Vertexattr Vertexattr;
typedef struct Vertexattrs Vertexattrs;
typedef struct Vertex Vertex;
typedef struct BVertex BVertex;
typedef struct LightSource LightSource;
typedef struct Material Material;
typedef struct Primitive Primitive;
typedef struct Model Model;
typedef struct Entity Entity;
typedef struct Scene Scene;
typedef struct Shaderparams Shaderparams;
typedef struct Shadertab Shadertab;
typedef struct Rendertime Rendertime;
typedef struct Renderer Renderer;
typedef struct Renderjob Renderjob;
typedef struct Fragment Fragment;
typedef struct Astk Astk;
typedef struct Abuf Abuf;
typedef struct Raster Raster;
typedef struct Framebuf Framebuf;
typedef struct Framebufctl Framebufctl;
typedef struct Viewdrawctx Viewdrawctx;
typedef struct Viewport Viewport;
typedef struct Camera Camera;
struct ItemArray
{
void *items;
usize nitems;
usize itemsize;
};
struct Color
{
double r, g, b, a;
};
struct Texture
{
int type;
char *file;
Memimage *image;
};
struct Cubemap
{
char *name;
Texture *faces[6]; /* -x, +x, -y, +y, -z, +z */
};
/*
* a more general approach worth investigating.
* it could be made to handle types other than double.
*
* examples:
* double intens;
* addvattr(v, "intensity", 1, &intens);
*
* Point3 p;
* addvattr(v, "normal", 3, &p);
*
* Matrix3 m;
* addvattr(v, "proj", 4*4, m);
*/
//struct Vertexattr
//{
// char *id;
// int type;
// ulong len;
// double val[];
//};
struct Vertexattr
{
char *id;
int type;
union {
Point3 p;
double n;
};
};
struct Vertexattrs
{
Vertexattr attrs[MAXVATTRS];
ulong nattrs;
};
struct Vertex
{
usize p; /* position idx */
usize n; /* surface normal idx */
usize uv; /* texture coordinate idx */
usize c; /* shading color idx */
};
/*
* BVertex is only used internally in the rasterizer, but it's
* presented to the user by the Shaderparams so its definition must be
* publicly available.
*/
struct BVertex
{
Point3 p; /* position */
Point3 n; /* surface normal */
Point2 uv; /* texture coordinate */
Color c; /* shading color */
Point3 tangent; /* used for normal mapping */
Material *mtl;
Vertexattrs; /* attributes (varyings) */
};
struct LightSource
{
int type;
Point3 p;
Point3 dir;
Color c;
double cutoff; /* distance */
/* spotlights only */
double θu; /* umbra angle. anything beyond is unlit */
double θp; /* penumbra angle. anything within is fully lit */
LightSource *prev;
LightSource *next;
};
struct Material
{
char *name;
Color ambient;
Color diffuse;
Color specular;
double shininess;
Texture *diffusemap;
Texture *specularmap;
Texture *normalmap;
};
struct Primitive
{
int type;
usize v[3]; /* vertex indices */
usize tangent; /* tangent idx */
Material *mtl;
};
struct Model
{
char *name;
ItemArray *positions;
ItemArray *normals;
ItemArray *texcoords;
ItemArray *colors;
ItemArray *tangents;
ItemArray *verts;
ItemArray *prims;
Material *materials;
ulong nmaterials;
usize (*addposition)(Model*, Point3);
usize (*addnormal)(Model*, Point3);
usize (*addtexcoord)(Model*, Point2);
usize (*addcolor)(Model*, Color);
usize (*addtangent)(Model*, Point3);
usize (*addvert)(Model*, Vertex);
usize (*addprim)(Model*, Primitive);
int (*addmaterial)(Model*, Material);
Material* (*getmaterial)(Model*, char*);
};
struct Entity
{
RFrame3;
char *name;
Model *mdl;
Entity *prev;
Entity *next;
};
struct Scene
{
char *name;
Entity ents;
ulong nents;
LightSource lights;
ulong nlights;
Cubemap *skybox;
void (*addent)(Scene*, Entity*);
void (*delent)(Scene*, Entity*);
Entity* (*getent)(Scene*, char*);
void (*addlight)(Scene*, LightSource*);
};
struct Shaderparams
{
Framebuf *fb;
Shadertab *stab;
Camera *camera;
Entity *entity;
Scene *scene;
BVertex *v;
Point p; /* fragment position (fshader-only) */
uint idx; /* vertex index (vshader-only) */
Vertexattr* (*getuniform)(Shaderparams*, char*);
Vertexattr* (*getattr)(Shaderparams*, char*);
void (*setattr)(Shaderparams*, char*, int, void*);
void (*toraster)(Shaderparams*, char*, void*);
};
struct Shadertab
{
char *name;
Point3 (*vs)(Shaderparams*); /* vertex shader */
Color (*fs)(Shaderparams*); /* fragment shader */
Vertexattrs; /* uniforms */
};
struct Rendertime
{
uvlong t0, t1;
};
struct Renderer
{
Channel *jobq;
ulong nprocs;
int doprof; /* enable profiling */
};
struct Renderjob
{
Ref;
uvlong id;
Renderer *rctl;
Framebuf *fb;
Camera *camera;
Shadertab *shaders;
Channel *donec;
Rectangle *cliprects; /* one per rasterizer */
int ncliprects;
Renderjob *next;
struct {
Rendertime R; /* renderer */
Rendertime E; /* entityproc */
Rendertime *Tn; /* tilers */
Rendertime *Rn; /* rasterizers */
} times;
};
struct Fragment
{
Color c;
float z;
};
struct Astk
{
Point p;
Fragment *items;
ulong size;
};
struct Abuf
{
QLock;
Astk *stk; /* framebuffer fragment stacks */
Astk **act; /* active fragment stacks */
ulong nact;
};
struct Raster
{
char name[32];
Rectangle r;
ulong chan;
Raster *next;
ulong data[];
};
struct Framebuf
{
Rectangle r;
Rectangle clipr;
Raster *rasters; /* [0] color, [1] depth, [2..n] user-defined */
Abuf abuf; /* A-buffer */
int (*createraster)(Framebuf*, char*, ulong);
Raster* (*fetchraster)(Framebuf*, char*);
};
struct Framebufctl
{
QLock;
Framebuf *fb[2]; /* double buffer */
uint idx; /* front buffer index */
uint upfilter; /* upscaling filter */
void (*draw)(Framebufctl*, Image*, char*, Point, Point, Viewdrawctx*);
void (*memdraw)(Framebufctl*, Memimage*, char*, Point, Point, Viewdrawctx*);
void (*swap)(Framebufctl*);
void (*reset)(Framebufctl*);
int (*createraster)(Framebufctl*, char*, ulong);
Raster* (*fetchraster)(Framebufctl*, char*);
Framebuf* (*getfb)(Framebufctl*);
Framebuf* (*getbb)(Framebufctl*);
};
struct Viewdrawctx
{
/* draw */
Image *img;
/* upscaled (mem)?draw */
ulong *blk; /* upscaled scanline */
Rectangle blkr;
};
struct Viewport
{
RFrame;
Framebufctl *fbctl;
Rectangle r;
Viewdrawctx dctx;
struct {
uvlong min, avg, max, acc, n, v;
uvlong nframes;
} stats;
void (*draw)(Viewport*, Image*, char*);
void (*memdraw)(Viewport*, Memimage*, char*);
void (*setscale)(Viewport*, double, double);
void (*setscalefilter)(Viewport*, int);
Framebuf* (*getfb)(Viewport*);
int (*getwidth)(Viewport*);
int (*getheight)(Viewport*);
int (*createraster)(Viewport*, char*, ulong);
Raster* (*fetchraster)(Viewport*, char*);
};
struct Camera
{
RFrame3; /* VCS */
Viewport *view;
Scene *scene;
Renderer *rctl;
double fov; /* vertical FOV */
double znear;
double zfar;
int cullmode;
int rendopts;
int projtype;
Matrix3 proj; /* VCS to clip space xform */
Matrix3 invproj; /* clip space to VCS xform */
struct {
uvlong min, avg, max, acc, n, v;
uvlong nframes;
} stats;
};
extern Rectangle UR; /* unit rectangle */
/* camera */
Camera* Camv(Viewport*, Renderer*, int, double, double, double);
Camera* Cam(Rectangle, Renderer*, int, double, double, double);
Camera* newcamera(void);
void delcamera(Camera*);
void reloadcamera(Camera*);
void configcamera(Camera*, int, double, double, double);
void placecamera(Camera*, Scene*, Point3, Point3, Point3);
void movecamera(Camera*, Point3);
void rotatecamera(Camera*, Point3, double);
void aimcamera(Camera*, Point3);
void shootcamera(Camera*, Shadertab*);
/* viewport */
Viewport* mkviewport(Rectangle);
void rmviewport(Viewport*);
/* render */
Renderer* initgraphics(void);
void setuniform(Shadertab*, char*, int, void*);
/* xform */
Point3 model2world(Entity*, Point3);
Point3 world2vcs(Camera*, Point3);
Point3 vcs2clip(Camera*, Point3);
Point3 world2clip(Camera*, Point3);
Point3 clip2ndc(Point3);
Point3 ndc2viewport(Framebuf*, Point3);
Point3 viewport2ndc(Framebuf*, Point3);
Point3 ndc2vcs(Camera*, Point3);
Point3 viewport2vcs(Camera*, Point3);
Point3 vcs2world(Camera*, Point3);
Point3 viewport2world(Camera*, Point3);
Point3 world2model(Entity*, Point3);
void perspective(Matrix3, double, double, double, double);
void orthographic(Matrix3, double, double, double, double, double, double);
/* marshal */
Model* readmodel(int);
usize writemodel(int, Model*);
int exportmodel(char*, Model*);
/* scene */
LightSource* newpointlight(Point3, Color);
LightSource* newdireclight(Point3, Point3, Color);
LightSource* newspotlight(Point3, Point3, Color, double, double);
LightSource* duplight(LightSource*);
void dellight(LightSource*);
Entity* newentity(char*, Model*);
Entity* dupentity(Entity*);
void delentity(Entity*);
Scene* newscene(char*);
Scene* dupscene(Scene*);
void delscene(Scene*);
void clearscene(Scene*);
/* model */
Vertex mkvert(void);
Primitive mkprim(int);
Material* newmaterial(char*);
void delmaterial(Material*);
Model* newmodel(void);
Model* dupmodel(Model*);
void delmodel(Model*);
void compactmodel(Model*);
/* texture */
Texture* alloctexture(int, Memimage*);
Texture* duptexture(Texture*);
void freetexture(Texture*);
Color neartexsampler(Texture*, Point2);
Color bilitexsampler(Texture*, Point2);
Color sampletexture(Texture*, Point2, Color(*)(Texture*, Point2));
Cubemap* readcubemap(char*[6]);
Cubemap* dupcubemap(Cubemap*);
void freecubemap(Cubemap*);
Color samplecubemap(Cubemap*, Point3, Color(*)(Texture*, Point2));
/* util */
Point minpt(Point, Point);
Point maxpt(Point, Point);
Point2 modulapt2(Point2, Point2);
Point2 minpt2(Point2, Point2);
Point2 maxpt2(Point2, Point2);
int eqpt2(Point2, Point2);
Point3 modulapt3(Point3, Point3);
Point3 minpt3(Point3, Point3);
Point3 maxpt3(Point3, Point3);
int eqpt3(Point3, Point3);
Memimage* rgba(ulong);
Memimage* dupmemimage(Memimage*);
/* itemarray */
ItemArray* mkitemarray(usize);
usize itemarrayadd(ItemArray*, void*);
void* itemarrayget(ItemArray*, usize);
usize copyitemarray(ItemArray*, ItemArray*);
ItemArray* dupitemarray(ItemArray*);
void rmitemarray(ItemArray*);
/* color */
ulong col2ul(Color);
Color ul2col(ulong);
int hasalpha(ulong);
Color srgb2linear(Color);
Color linear2srgb(Color);
ulong srgb2linearul(ulong);
ulong linear2srgbul(ulong);
Color aces(Color);
Color aces2(Color);
/* shadeop */
double sign(double);
double step(double, double);
double smoothstep(double, double, double);
Color getlightcolor(LightSource*, Point3, Point3);
Color getscenecolor(Scene*, Point3, Point3);
/* nanosec */
uvlong nanosec(void);