shithub: libgraphics

Download patch

ref: 714038d0bce05c734d4e45289ec2bf1174463e4a
parent: 6d8fbc2953c6ae29ee5162ca04920d6cef85d0ce
author: rodri <rgl@antares-labs.eu>
date: Fri Jul 5 14:16:49 EDT 2024

create a new texture interface.

--- a/color.c
+++ b/color.c
@@ -9,6 +9,10 @@
 #include "internal.h"
 
 /*
+ * see also “The Importance of Being Linear”, Gritz and d'Eon, GPU Gems 3, Ch. 24, December 2007
+ */
+
+/*
  * generated with:
  * 	% seq 0 255 | awk '{$0 = $0/255; if($0 > 0.04045) $0 = (($0+0.055)/1.055)^2.4; else $0 = $0/12.92; printf("\t0x%02X,%s", int($0*255+0.5), NR%8 == 0? "\n": "")}'
  */
--- a/graphics.h
+++ b/graphics.h
@@ -18,11 +18,17 @@
 };
 
 enum {
+	RAWTexture,
+	sRGBTexture,
+};
+
+enum {
 	VAPoint,
 	VANumber,
 };
 
 typedef struct Color Color;
+typedef struct Texture Texture;
 typedef struct Cubemap Cubemap;
 typedef struct Vertexattr Vertexattr;
 typedef struct Vertex Vertex;
@@ -49,10 +55,16 @@
 	double r, g, b, a;
 };
 
+struct Texture
+{
+	Memimage *image;
+	int type;
+};
+
 struct Cubemap
 {
 	char *name;
-	Memimage *faces[6];
+	Texture *faces[6];
 };
 
 /*
@@ -119,8 +131,8 @@
 	Color diffuse;
 	Color specular;
 	double shininess;
-	Memimage *diffusemap;
-	Memimage *normalmap;
+	Texture *diffusemap;
+	Texture *normalmap;
 };
 
 struct Primitive
@@ -135,7 +147,7 @@
 {
 	Primitive *prims;
 	ulong nprims;
-	Memimage *tex;		/* texture map (TODO get rid of it, use materials) */
+	Texture *tex;		/* texture map (TODO get rid of it, use materials) */
 	Material *materials;
 	ulong nmaterials;
 };
@@ -325,12 +337,14 @@
 Vertexattr *getvattr(Vertex*, char*);
 
 /* texture */
-Color neartexsampler(Memimage*, Point2);
-Color bilitexsampler(Memimage*, Point2);
-Color texture(Memimage*, Point2, Color(*)(Memimage*, Point2));
+Texture *alloctexture(int, Memimage*);
+void freetexture(Texture*);
+Color neartexsampler(Texture*, Point2);
+Color bilitexsampler(Texture*, Point2);
+Color texture(Texture*, Point2, Color(*)(Texture*, Point2));
 Cubemap *readcubemap(char*[6]);
 void freecubemap(Cubemap*);
-Color cubemaptexture(Cubemap*, Point3, Color(*)(Memimage*, Point2));
+Color cubemaptexture(Cubemap*, Point3, Color(*)(Texture*, Point2));
 
 /* util */
 double fmin(double, double);
--- a/scene.c
+++ b/scene.c
@@ -165,17 +165,19 @@
 			mtl->shininess = objmtl->Ns;
 
 			if(objmtl->map_Kd != nil){
-				mtl->diffusemap = allocmemimaged(objmtl->map_Kd->r, objmtl->map_Kd->chan, objmtl->map_Kd->data);
-				if(mtl->diffusemap == nil)
+				mtl->diffusemap = alloctexture(sRGBTexture, nil);
+				mtl->diffusemap->image = allocmemimaged(objmtl->map_Kd->r, objmtl->map_Kd->chan, objmtl->map_Kd->data);
+				if(mtl->diffusemap->image == nil)
 					sysfatal("allocmemimaged: %r");
-				mtl->diffusemap->data->ref++;
+				mtl->diffusemap->image->data->ref++;
 			}
 
 			if(objmtl->norm != nil){
-				mtl->normalmap = allocmemimaged(objmtl->norm->r, objmtl->norm->chan, objmtl->norm->data);
-				if(mtl->normalmap == nil)
+				mtl->normalmap = alloctexture(RAWTexture, nil);
+				mtl->normalmap->image = allocmemimaged(objmtl->norm->r, objmtl->norm->chan, objmtl->norm->data);
+				if(mtl->normalmap->image == nil)
 					sysfatal("allocmemimaged: %r");
-				mtl->normalmap->data->ref++;
+				mtl->normalmap->image->data->ref++;
 			}
 
 			addmtlmap(&mtlmap, objmtl, m->nmaterials-1);
@@ -323,11 +325,11 @@
 	if(m == nil)
 		return;
 	if(m->tex != nil)
-		freememimage(m->tex);
+		freetexture(m->tex);
 	if(m->nmaterials > 0){
 		while(m->nmaterials--){
-			freememimage(m->materials[m->nmaterials].diffusemap);
-			freememimage(m->materials[m->nmaterials].normalmap);
+			freetexture(m->materials[m->nmaterials].diffusemap);
+			freetexture(m->materials[m->nmaterials].normalmap);
 			free(m->materials[m->nmaterials].name);
 		}
 		free(m->materials);
--- a/texture.c
+++ b/texture.c
@@ -22,10 +22,10 @@
  * hence the need to reverse the v coord.
  */
 static Point
-uv2tp(Point2 uv, Memimage *i)
+uv2tp(Point2 uv, Texture *t)
 {
 	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));
+	return Pt(uv.x*Dx(t->image->r), (1 - uv.y)*Dy(t->image->r));
 }
 
 static Color
@@ -41,30 +41,31 @@
 }
 
 static Color
-_memreadcolor(Memimage *i, Point sp)
+_memreadcolor(Texture *t, Point sp)
 {
+	Color c;
 	uchar cbuf[4];
 
-	switch(i->chan){
+	switch(t->image->chan){
 	case RGB24:
-		unloadmemimage(i, rectaddpt(UR, sp), cbuf+1, sizeof cbuf - 1);
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf+1, sizeof cbuf - 1);
 		cbuf[0] = 0xFF;
 		break;
 	case RGBA32:
-		unloadmemimage(i, rectaddpt(UR, sp), cbuf, sizeof cbuf);
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf, sizeof cbuf);
 		break;
 	case XRGB32:
-		unloadmemimage(i, rectaddpt(UR, sp), cbuf, sizeof cbuf);
+		unloadmemimage(t->image, rectaddpt(UR, sp), cbuf, sizeof cbuf);
 		memmove(cbuf+1, cbuf, 3);
 		cbuf[0] = 0xFF;
 		break;
 	}
 
-	/* TODO
-	 * not all textures require color space conversion. implement a better
-	 * interface to let the user decide.
-	 */
-	return srgb2linear(cbuf2col(cbuf));
+	c = cbuf2col(cbuf);
+	switch(t->type){
+	case sRGBTexture: c = srgb2linear(c); break;
+	}
+	return c;
 }
 
 /*
@@ -71,9 +72,9 @@
  * nearest-neighbour sampler
  */
 Color
-neartexsampler(Memimage *i, Point2 uv)
+neartexsampler(Texture *t, Point2 uv)
 {
-	return _memreadcolor(i, uv2tp(uv, i));
+	return _memreadcolor(t, uv2tp(uv, t));
 }
 
 /*
@@ -80,36 +81,54 @@
  * bilinear sampler
  */
 Color
-bilitexsampler(Memimage *i, Point2 uv)
+bilitexsampler(Texture *t, Point2 uv)
 {
 	Rectangle r;
 	Color c1, c2;
 
-	r = rectaddpt(UR, uv2tp(uv, i));
-	if(r.min.x < i->r.min.x){
+	r = rectaddpt(UR, uv2tp(uv, t));
+	if(r.min.x < t->image->r.min.x){
 		r.min.x++;
 		r.max.x++;
-	}if(r.min.y < i->r.min.y){
+	}if(r.min.y < t->image->r.min.y){
 		r.min.y++;
 		r.max.y++;
-	}if(r.max.x >= i->r.max.x){
+	}if(r.max.x >= t->image->r.max.x){
 		r.min.x--;
 		r.max.x--;
-	}if(r.max.y >= i->r.max.y){
+	}if(r.max.y >= t->image->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);
+	c1 = lerp3(_memreadcolor(t, r.min), _memreadcolor(t, Pt(r.max.x, r.min.y)), 0.5);
+	c2 = lerp3(_memreadcolor(t, Pt(r.min.x, r.max.y)), _memreadcolor(t, r.max), 0.5);
 	return lerp3(c1, c2, 0.5);
 }
 
 Color
-texture(Memimage *i, Point2 uv, Color(*sampler)(Memimage*,Point2))
+texture(Texture *t, Point2 uv, Color(*sampler)(Texture*,Point2))
 {
-	return sampler(i, uv);
+	return sampler(t, uv);
 }
 
+Texture *
+alloctexture(int type, Memimage *i)
+{
+	Texture *t;
+
+	t = emalloc(sizeof *t);
+	t->image = i;
+	t->type = type;
+	return t;
+}
+
+void
+freetexture(Texture *t)
+{
+	freememimage(t->image);
+	free(t);
+}
+
 /* cubemap sampling */
 
 Cubemap *
@@ -116,6 +135,7 @@
 readcubemap(char *paths[6])
 {
 	Cubemap *cm;
+	Memimage *i;
 	char **p;
 	int fd;
 
@@ -127,9 +147,10 @@
 		fd = open(*p, OREAD);
 		if(fd < 0)
 			sysfatal("open: %r");
-		cm->faces[p-paths] = readmemimage(fd);
-		if(cm->faces[p-paths] == nil)
+		i = readmemimage(fd);
+		if(i == nil)
 			sysfatal("readmemimage: %r");
+		cm->faces[p-paths] = alloctexture(sRGBTexture, i);
 		close(fd);
 	}
 	return cm;
@@ -141,7 +162,7 @@
 	int i;
 
 	for(i = 0; i < 6; i++)
-		freememimage(cm->faces[i]);
+		freetexture(cm->faces[i]);
 	free(cm->name);
 	free(cm);
 }
@@ -152,7 +173,7 @@
  * 	- “Cubemap Texture Selection”, OpenGL ES 2.0 § 3.7.5, November 2010
  */
 Color
-cubemaptexture(Cubemap *cm, Point3 d, Color(*sampler)(Memimage*,Point2))
+cubemaptexture(Cubemap *cm, Point3 d, Color(*sampler)(Texture*,Point2))
 {
 	Point2 uv;
 	double ax, ay, az, ma, sc, tc;