shithub: libgraphics

ref: 5b04bd5b3a152d0b2d5a8d8e1e25887b71c338d5
dir: /graphics.h/

View raw version
#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);