shithub: libgraphics

ref: 930e09a2ea12275cf2e04577a170a2be342db045
dir: /texture.c/

View raw version
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include <memdraw.h>
#include <geometry.h>
#include "libobj/obj.h"
#include "graphics.h"
#include "internal.h"

/*
 * uv-coords belong to the 1st quadrant (v grows bottom-up),
 * hence the need to reverse the v coord.
 */
static Point
uv2tp(Point2 uv, Memimage *i)
{
	assert(uv.x >= 0 && uv.x <= 1 && uv.y >= 0 && uv.y <= 1);
	return Pt(uv.x*Dx(i->r), (1 - uv.y)*Dy(i->r));
}

static Color
ul2col(ulong l)
{
	Color c;

	c.a = (l     & 0xff)/255.0;
	c.b = (l>>8  & 0xff)/255.0;
	c.g = (l>>16 & 0xff)/255.0;
	c.r = (l>>24 & 0xff)/255.0;
	return c;
}

static Color
cbuf2col(uchar b[4])
{
	Color c;

	c.a = b[0] / 255.0;
	c.b = b[1] / 255.0;
	c.g = b[2] / 255.0;
	c.r = b[3] / 255.0;
	return c;
}

static Color
_memreadcolor(Memimage *i, Point sp)
{
	uchar cbuf[4];

	switch(i->chan){
	case RGB24:
		unloadmemimage(i, rectaddpt(UR, sp), cbuf+1, sizeof cbuf - 1);
		cbuf[0] = 0xFF;
		break;
	case RGBA32:
		unloadmemimage(i, rectaddpt(UR, sp), cbuf, sizeof cbuf);
		break;
	case XRGB32:
		unloadmemimage(i, rectaddpt(UR, sp), cbuf, sizeof cbuf);
		memmove(cbuf+1, cbuf, 3);
		cbuf[0] = 0xFF;
		break;
	}

	return cbuf2col(cbuf);
}

/*
 * nearest-neighbour sampler
 */
Color
neartexsampler(Memimage *i, Point2 uv)
{
	return _memreadcolor(i, uv2tp(uv, i));
}

/*
 * bilinear sampler
 */
Color
bilitexsampler(Memimage *i, Point2 uv)
{
	Rectangle r;
	Color c1, c2;

	r = rectaddpt(UR, uv2tp(uv, i));
	if(r.min.x < i->r.min.x){
		r.min.x++;
		r.max.x++;
	}if(r.min.y < i->r.min.y){
		r.min.y++;
		r.max.y++;
	}if(r.max.x >= i->r.max.x){
		r.min.x--;
		r.max.x--;
	}if(r.max.y >= i->r.max.y){
		r.min.y--;
		r.max.y--;
	}
	c1 = lerp3(_memreadcolor(i, r.min), _memreadcolor(i, Pt(r.max.x, r.min.y)), 0.5);
	c2 = lerp3(_memreadcolor(i, Pt(r.min.x, r.max.y)), _memreadcolor(i, r.max), 0.5);
	return lerp3(c1, c2, 0.5);
}

Color
texture(Memimage *i, Point2 uv, Color(*sampler)(Memimage*,Point2))
{
	return sampler(i, uv);
}