From 4ccbac5f245ba6b6da4c0a1ffd368514de3533f7 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 6 Apr 2024 20:15:16 +0300 Subject: [PATCH] textures --- src/gfx.h | 28 ++++++++ src/gl/gfx_gl.h | 8 +++ src/gl/tex_gl.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nexus3d.c | 18 +++++ src/nexus3d.h | 11 +++ 5 files changed, 275 insertions(+) create mode 100644 src/gl/tex_gl.c diff --git a/src/gfx.h b/src/gfx.h index fc9816a..cf3887c 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -43,6 +43,17 @@ enum nex_cube_face { NEX_CUBE_PZ, NEX_CUBE_NZ }; +enum nex_pixfmt { + NEX_GREY8, + NEX_RGB24, + NEX_RGBA32, + NEX_SRGB, + NEX_SRGBA, + NEX_GREYF, + NEX_RGBF, + NEX_RGBAF +}; + typedef struct nex_buffer nex_buffer; typedef struct nex_geometry nex_geometry; typedef struct nex_shader nex_shader; @@ -104,4 +115,21 @@ nex_sdrprog *nex_load_sdrprog(const char *vpath, const char *ppath); nex_texture *nex_alloc_texture(enum nex_tex_type type); void nex_free_texture(nex_texture *tex); +void nex_tex_storage1d(nex_texture *tex, int sz, enum nex_pixfmt fmt); +void nex_tex_storage2d(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt); +void nex_tex_storage3d(nex_texture *tex, int xsz, int ysz, int zsz, enum nex_pixfmt fmt); +void nex_tex_storagecube(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt); + +void nex_tex_update1d(nex_texture *tex, int lvl, int x, int width, + enum nex_pixfmt pixfmt, void *data, long pitch); +void nex_tex_update2d(nex_texture *tex, int lvl, int x, int y, int width, int height, + enum nex_pixfmt pixfmt, void *data, long pitch); +void nex_tex_update3d(nex_texture *tex, int lvl, int x, int y, int z, int width, + int height, int depth, enum nex_pixfmt pixfmt, void *data, long pitch); +void nex_tex_updatecube(nex_texture *tex, int lvl, enum nex_cube_face face, + int x, int y, int width, int height, enum nex_pixfmt pixfmt, void *data, + long pitch); + +void bind_texture(int tunit, nex_texture *tex); + #endif /* NEXUS3D_GFX_H_ */ diff --git a/src/gl/gfx_gl.h b/src/gl/gfx_gl.h index 01fa5c8..2ed2e77 100644 --- a/src/gl/gfx_gl.h +++ b/src/gl/gfx_gl.h @@ -47,4 +47,12 @@ struct nex_sdrprog { int num_sdr; }; + +struct nex_texture { + unsigned int tex; + int xsz, ysz, zsz; + enum nex_tex_type type; + enum nex_pixfmt pixfmt; +}; + #endif /* NEXUS3D_GFX_GL_H_ */ diff --git a/src/gl/tex_gl.c b/src/gl/tex_gl.c new file mode 100644 index 0000000..6369a5c --- /dev/null +++ b/src/gl/tex_gl.c @@ -0,0 +1,210 @@ +#include "nexus3d_impl.h" +#include "gfx_gl.h" +#include "opengl.h" + +static unsigned int gltextype(enum nex_tex_type type); +static unsigned int glpixfmt(enum nex_pixfmt fmt); +static unsigned int glformat(enum nex_pixfmt fmt); +static unsigned int gltype(enum nex_pixfmt fmt); +/*static unsigned int glcubeface(enum nex_cube_face face);*/ +static unsigned int miplevels(int x, int y, int z); + +nex_texture *nex_alloc_texture(enum nex_tex_type type) +{ + nex_texture *tex; + + if(!(tex = calloc(1, sizeof *tex))) { + return 0; + } + tex->type = type; + glCreateTextures(gltextype(type), 1, &tex->tex); + return tex; +} + +void nex_free_texture(nex_texture *tex) +{ + if(!tex) return; + + glDeleteTextures(1, &tex->tex); + free(tex); +} + + +void nex_tex_storage1d(nex_texture *tex, int sz, enum nex_pixfmt fmt) +{ + glTextureStorage1D(tex->tex, miplevels(sz, 0, 0), glpixfmt(fmt), sz); +} + +void nex_tex_storage2d(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt) +{ + int levels = miplevels(xsz, ysz, 0); + glTextureStorage2D(tex->tex, levels, glpixfmt(fmt), xsz, ysz); +} + +void nex_tex_storage3d(nex_texture *tex, int xsz, int ysz, int zsz, enum nex_pixfmt fmt) +{ + int levels = miplevels(xsz, ysz, zsz); + glTextureStorage3D(tex->tex, levels, glpixfmt(fmt), xsz, ysz, zsz); +} + +void nex_tex_storagecube(nex_texture *tex, int xsz, int ysz, enum nex_pixfmt fmt) +{ + nex_tex_storage2d(tex, xsz, ysz, fmt); +} + + +void nex_tex_update1d(nex_texture *tex, int lvl, int x, int width, + enum nex_pixfmt pixfmt, void *data, long pitch) +{ + int fmt = glformat(pixfmt); + int type = gltype(pixfmt); + glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch); + glTextureSubImage1D(tex->tex, lvl, x, width, fmt, type, data); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + +void nex_tex_update2d(nex_texture *tex, int lvl, int x, int y, int width, int height, + enum nex_pixfmt pixfmt, void *data, long pitch) +{ + int fmt = glformat(pixfmt); + int type = gltype(pixfmt); + glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch); + glTextureSubImage2D(tex->tex, lvl, x, y, width, height, fmt, type, data); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + +void nex_tex_update3d(nex_texture *tex, int lvl, int x, int y, int z, int width, + int height, int depth, enum nex_pixfmt pixfmt, void *data, long pitch) +{ + int fmt = glformat(pixfmt); + int type = gltype(pixfmt); + glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch); + glTextureSubImage3D(tex->tex, lvl, x, y, z, width, height, depth, fmt, type, + data); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + + +void nex_tex_updatecube(nex_texture *tex, int lvl, enum nex_cube_face face, + int x, int y, int width, int height, enum nex_pixfmt pixfmt, void *data, + long pitch) +{ + int fmt = glformat(pixfmt); + int type = gltype(pixfmt); + glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch); + glTextureSubImage3D(tex->tex, lvl, x, y, face, width, height, 1, fmt, type, + data); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + +void bind_texture(int tunit, nex_texture *tex) +{ + glBindTextureUnit(tunit, tex->tex); +} + + +static unsigned int gltextype(enum nex_tex_type type) +{ + switch(type) { + case NEX_TEX1D: + return GL_TEXTURE_1D; + case NEX_TEX2D: + return GL_TEXTURE_2D; + case NEX_TEX3D: + return GL_TEXTURE_3D; + case NEX_TEXCUBE: + return GL_TEXTURE_CUBE_MAP; + default: + break; + } + return 0; +} + +static unsigned int glpixfmt(enum nex_pixfmt fmt) +{ + switch(fmt) { + case NEX_GREY8: + return GL_LUMINANCE; + case NEX_RGB24: + return GL_RGB; + case NEX_RGBA32: + return GL_RGBA; + case NEX_SRGB: + return GL_SRGB; + case NEX_SRGBA: + return GL_SRGB_ALPHA; + case NEX_GREYF: + return GL_LUMINANCE16F_ARB; + case NEX_RGBF: + return GL_RGB16F; + case NEX_RGBAF: + return GL_RGBA16F; + default: + break; + } + return 0; +} + +/* +static unsigned int glcubeface(enum nex_cube_face face) +{ + switch(face) { + case NEX_CUBE_PX: + return GL_TEXTURE_CUBE_MAP_POSITIVE_X; + case NEX_CUBE_NX: + return GL_TEXTURE_CUBE_MAP_NEGATIVE_X; + case NEX_CUBE_PY: + return GL_TEXTURE_CUBE_MAP_POSITIVE_Y; + case NEX_CUBE_NY: + return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; + case NEX_CUBE_PZ: + return GL_TEXTURE_CUBE_MAP_POSITIVE_Z; + case NEX_CUBE_NZ: + return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; + default: + break; + } + return 0; +} +*/ + +static unsigned int glformat(enum nex_pixfmt fmt) +{ + switch(fmt) { + case NEX_GREY8: + case NEX_GREYF: + return GL_LUMINANCE; + case NEX_RGB24: + case NEX_SRGB: + case NEX_RGBF: + return GL_RGB; + case NEX_RGBA32: + case NEX_SRGBA: + case NEX_RGBAF: + return GL_RGBA; + default: + break; + } + return 0; +} + +static unsigned int gltype(enum nex_pixfmt fmt) +{ + if(fmt == NEX_GREYF || fmt == NEX_RGBF || fmt == NEX_RGBAF) { + return GL_FLOAT; + } + return GL_UNSIGNED_BYTE; +} + +static unsigned int miplevels(int x, int y, int z) +{ + int lvl = 0; + if(y > x) x = y; + if(z > x) x = z; + + while(x > 0) { + lvl++; + x >>= 1; + } + return lvl; +} diff --git a/src/nexus3d.c b/src/nexus3d.c index a4e8f1e..340967c 100644 --- a/src/nexus3d.c +++ b/src/nexus3d.c @@ -11,3 +11,21 @@ void nex_gfxapi_opengl(int vmaj, int vmin, enum nex_apiflags_gl flags) nex_apicfg.gl.ver_minor = vmin; nex_apicfg.gl.flags = flags; } + +struct nex_span nex_span(int x, int len) +{ + struct nex_span s; + s.start = x; + s.len = len; + return s; +} + +struct nex_rect nex_rect(int x, int y, int w, int h) +{ + struct nex_rect r; + r.x = x; + r.y = y; + r.width = w; + r.height = h; + return r; +} diff --git a/src/nexus3d.h b/src/nexus3d.h index f1ad71b..b2e67f6 100644 --- a/src/nexus3d.h +++ b/src/nexus3d.h @@ -5,6 +5,14 @@ #include "wsys/wsys.h" #include "cgmath2/cgmath2.h" +struct nex_span { + int start, len; +}; + +struct nex_rect { + int x, y, width, height; +}; + enum nex_apiflags_gl { NEX_OPENGL_COMPAT = 1, NEX_OPENGL_DEBUG = 2 @@ -12,4 +20,7 @@ enum nex_apiflags_gl { void nex_gfxapi_opengl(int vmaj, int vmin, enum nex_apiflags_gl flags); +struct nex_span nex_span(int x, int len); +struct nex_rect nex_rect(int x, int y, int w, int h); + #endif /* NEXUS3D_H_ */ -- 1.7.10.4