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;