From 714038d0bce05c734d4e45289ec2bf1174463e4a Mon Sep 17 00:00:00 2001 From: rodri Date: Fri, 5 Jul 2024 18:16:49 +0000 Subject: create a new texture interface. --- color.c | 4 ++++ graphics.h | 30 +++++++++++++++++------- scene.c | 20 ++++++++-------- texture.c | 77 +++++++++++++++++++++++++++++++++++++++----------------------- 4 files changed, 86 insertions(+), 45 deletions(-) diff --git a/color.c b/color.c index cdd089f..6ba23e3 100644 --- a/color.c +++ b/color.c @@ -8,6 +8,10 @@ #include "graphics.h" #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": "")}' diff --git a/graphics.h b/graphics.h index 335b4b0..70eeb71 100644 --- a/graphics.h +++ b/graphics.h @@ -17,12 +17,18 @@ enum { LIGHT_SPOT, }; +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 @@ struct Color 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 @@ struct Material Color diffuse; Color specular; double shininess; - Memimage *diffusemap; - Memimage *normalmap; + Texture *diffusemap; + Texture *normalmap; }; struct Primitive @@ -135,7 +147,7 @@ struct Model { 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 @@ void addvattr(Vertex*, char*, int, void*); 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); diff --git a/scene.c b/scene.c index f003e83..c11588d 100644 --- a/scene.c +++ b/scene.c @@ -165,17 +165,19 @@ loadobjmodel(Model *m, OBJ *obj) 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 @@ delmodel(Model *m) 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); diff --git a/texture.c b/texture.c index d51076e..50ce200 100644 --- a/texture.c +++ b/texture.c @@ -22,10 +22,10 @@ enum { * 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,73 +41,92 @@ cbuf2col(uchar b[4]) } 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; } /* * 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)); } /* * 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(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) { - return sampler(i, uv); + freememimage(t->image); + free(t); } /* cubemap sampling */ @@ -116,6 +135,7 @@ Cubemap * readcubemap(char *paths[6]) { Cubemap *cm; + Memimage *i; char **p; int fd; @@ -127,9 +147,10 @@ readcubemap(char *paths[6]) 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 @@ freecubemap(Cubemap *cm) 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 @@ freecubemap(Cubemap *cm) * - “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; -- cgit v1.2.3