Implemented GL3_LoadPic() and related functions

so loading texture and uploading them to the GPU should work.
a pity there's no code to use them yet :P
This commit is contained in:
Daniel Gibson 2016-12-31 03:19:43 +01:00
parent 0787b75792
commit 26904949c2
5 changed files with 458 additions and 53 deletions

View file

@ -27,6 +27,8 @@
#include "header/local.h"
extern unsigned d_8to24table[256];
typedef struct
{
char *name;
@ -45,6 +47,15 @@ glmode_t modes[] = {
int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
int gl_filter_max = GL_LINEAR;
// TODO: do we need the following configurable?
static const int gl_solid_format = GL_RGB;
static const int gl_alpha_format = GL_RGBA;
static const int gl_tex_solid_format = GL_RGB;
static const int gl_tex_alpha_format = GL_RGBA;
gl3image_t gl3textures[MAX_GL3TEXTURES];
int numgl3textures;
void
GL3_TextureMode(char *string)
{
@ -86,31 +97,361 @@ GL3_TextureMode(char *string)
}
#if 0 // TODO!
image_t *glt;
gl3image_t *glt;
/* change all the existing mipmap texture objects */
for (i = 0, glt = gltextures; i < numgltextures; i++, glt++)
for (i = 0, glt = gl3textures; i < numgl3textures; i++, glt++)
{
if ((glt->type != it_pic) && (glt->type != it_sky))
{
R_Bind(glt->texnum);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
gl_filter_min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
gl_filter_max);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
/* Set anisotropic filter if supported and enabled */
if (gl_config.anisotropic && gl_anisotropic->value)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
gl_anisotropic->value);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropic->value);
}
}
}
#endif // 0
}
void
GL3_Bind(int texnum)
{
extern gl3image_t *draw_chars;
if (gl_nobind->value && draw_chars) /* performance evaluation option */
{
texnum = draw_chars->texnum;
}
if (gl3state.currenttexture == texnum)
{
return;
}
gl3state.currenttexture = texnum;
glBindTexture(GL_TEXTURE_2D, texnum);
}
/*
* Returns has_alpha
*/
qboolean
GL3_Upload32(unsigned *data, int width, int height, qboolean mipmap)
{
qboolean res;
int samples;
int i, c;
byte *scan;
int comp;
c = width * height;
scan = ((byte *)data) + 3;
samples = gl_solid_format;
comp = gl_tex_solid_format;
//upload_width = width; // TODO: remove, probably
//upload_height = height;
STUB_ONCE("TODO: something with gamma and intensity, somewhere");
// R_LightScaleTexture(data, upload_width, upload_height, !mipmap);
for (i = 0; i < c; i++, scan += 4)
{
if (*scan != 255)
{
samples = gl_alpha_format;
comp = gl_tex_alpha_format;
break;
}
}
// TODO: some hardware may require mipmapping disabled for NPOT textures!
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, mipmap);
glTexImage2D(GL_TEXTURE_2D, 0, comp, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, data);
//glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, false);
res = (samples == gl_alpha_format);
if (mipmap)
{
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
if (mipmap && gl3config.anisotropic && gl_anisotropic->value)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropic->value);
}
return res;
}
/*
* Returns has_alpha
*/
qboolean
GL3_Upload8(byte *data, int width, int height, qboolean mipmap, qboolean is_sky)
{
unsigned trans[512 * 256];
int i, s;
int p;
s = width * height;
if (s > sizeof(trans) / 4)
{
ri.Sys_Error(ERR_DROP, "GL3_Upload8: too large");
}
for (i = 0; i < s; i++)
{
p = data[i];
trans[i] = d_8to24table[p];
/* transparent, so scan around for
another color to avoid alpha fringes */
if (p == 255)
{
if ((i > width) && (data[i - width] != 255))
{
p = data[i - width];
}
else if ((i < s - width) && (data[i + width] != 255))
{
p = data[i + width];
}
else if ((i > 0) && (data[i - 1] != 255))
{
p = data[i - 1];
}
else if ((i < s - 1) && (data[i + 1] != 255))
{
p = data[i + 1];
}
else
{
p = 0;
}
/* copy rgb components */
((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
}
}
return GL3_Upload32(trans, width, height, mipmap);
}
/*
* This is also used as an entry point for the generated r_notexture
*/
gl3image_t *
GL3_LoadPic(char *name, byte *pic, int width, int realwidth,
int height, int realheight, imagetype_t type, int bits)
{
gl3image_t *image = NULL;
GLuint texNum=0;
int i;
qboolean nolerp = false;
if (gl_nolerp_list != NULL && gl_nolerp_list->string != NULL)
{
nolerp = strstr(gl_nolerp_list->string, name) != NULL;
}
/* find a free gl3image_t */
for (i = 0, image = gl3textures; i < numgl3textures; i++, image++)
{
if (image->texnum == 0)
{
break;
}
}
if (i == numgl3textures)
{
if (numgl3textures == MAX_GL3TEXTURES)
{
ri.Sys_Error(ERR_DROP, "MAX_GLTEXTURES");
}
numgl3textures++;
}
image = &gl3textures[i];
if (strlen(name) >= sizeof(image->name))
{
ri.Sys_Error(ERR_DROP, "GL3_LoadPic: \"%s\" is too long", name);
}
strcpy(image->name, name);
image->registration_sequence = registration_sequence;
image->width = width;
image->height = height;
image->type = type;
if ((type == it_skin) && (bits == 8))
{
//R_FloodFillSkin(pic, width, height);
STUB_ONCE("TODO: Implement and call GL3_FloodFillSkin()!");
}
image->scrap = false; // FIXME: not sure if we need scrap anymore..
glGenTextures(1, &texNum);
image->texnum = texNum;
GL3_Bind(texNum);
if (bits == 8)
{
image->has_alpha = GL3_Upload8(pic, width, height,
(image->type != it_pic && image->type != it_sky),
image->type == it_sky);
}
else
{
image->has_alpha = GL3_Upload32((unsigned *)pic, width, height,
(image->type != it_pic && image->type != it_sky));
}
// TODO: I don't think we even need image->upload_*
image->upload_width = width; // upload_width; /* after power of 2 and scales */
image->upload_height = height; // upload_height;
//image->paletted = uploaded_paletted;
if (realwidth && realheight)
{
if ((realwidth <= image->width) && (realheight <= image->height))
{
image->width = realwidth;
image->height = realheight;
}
else
{
R_Printf(PRINT_DEVELOPER,
"Warning, image '%s' has hi-res replacement smaller than the original! (%d x %d) < (%d x %d)\n",
name, image->width, image->height, realwidth, realheight);
}
}
image->sl = 0;
image->sh = 1;
image->tl = 0;
image->th = 1;
if (nolerp)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
#if 0 // TODO: do we need the scrap? (probably not)
/* load little pics into the scrap */
if (!nolerp && (image->type == it_pic) && (bits == 8) &&
(image->width < 64) && (image->height < 64))
{
int x, y;
int i, j, k;
int texnum;
texnum = Scrap_AllocBlock(image->width, image->height, &x, &y);
if (texnum == -1)
{
goto nonscrap;
}
scrap_dirty = true;
/* copy the texels into the scrap block */
k = 0;
for (i = 0; i < image->height; i++)
{
for (j = 0; j < image->width; j++, k++)
{
scrap_texels[texnum][(y + i) * BLOCK_WIDTH + x + j] = pic[k];
}
}
image->texnum = TEXNUM_SCRAPS + texnum;
image->scrap = true;
image->has_alpha = true;
image->sl = (x + 0.01) / (float)BLOCK_WIDTH;
image->sh = (x + image->width - 0.01) / (float)BLOCK_WIDTH;
image->tl = (y + 0.01) / (float)BLOCK_WIDTH;
image->th = (y + image->height - 0.01) / (float)BLOCK_WIDTH;
}
else
{
nonscrap:
image->scrap = false;
image->texnum = TEXNUM_IMAGES + (image - gltextures);
R_Bind(image->texnum);
if (bits == 8)
{
image->has_alpha = R_Upload8(pic, width, height,
(image->type != it_pic && image->type != it_sky),
image->type == it_sky);
}
else
{
image->has_alpha = R_Upload32((unsigned *)pic, width, height,
(image->type != it_pic && image->type != it_sky));
}
image->upload_width = upload_width; /* after power of 2 and scales */
image->upload_height = upload_height;
image->paletted = uploaded_paletted;
if (realwidth && realheight)
{
if ((realwidth <= image->width) && (realheight <= image->height))
{
image->width = realwidth;
image->height = realheight;
}
else
{
R_Printf(PRINT_DEVELOPER,
"Warning, image '%s' has hi-res replacement smaller than the original! (%d x %d) < (%d x %d)\n",
name, image->width, image->height, realwidth, realheight);
}
}
image->sl = 0;
image->sh = 1;
image->tl = 0;
image->th = 1;
if (nolerp)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
}
#endif // 0
return image;
}
static gl3image_t *
LoadWal(char *origname)
{
@ -152,10 +493,9 @@ LoadWal(char *origname)
gl3image_t *
GL3_FindImage(char *name, imagetype_t type)
{
#if 0
gl3image_t *image;
int i, len;
byte *pic, *palette;
byte *pic;
int width, height;
char *ptr;
char namewe[256];
@ -192,7 +532,7 @@ GL3_FindImage(char *name, imagetype_t type)
}
/* look for it */
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
for (i = 0, image = gl3textures; i < numgl3textures; i++, image++)
{
if (!strcmp(name, image->name))
{
@ -203,7 +543,6 @@ GL3_FindImage(char *name, imagetype_t type)
/* load the pic from disk */
pic = NULL;
palette = NULL;
if (strcmp(ext, "pcx") == 0)
{
@ -222,13 +561,13 @@ GL3_FindImage(char *name, imagetype_t type)
|| LoadSTB(namewe, "jpg", &pic, &width, &height) )
{
/* upload tga or png or jpg */
image = R_LoadPic(name, pic, width, realwidth, height,
image = GL3_LoadPic(name, pic, width, realwidth, height,
realheight, type, 32);
}
else
{
/* PCX if no TGA/PNG/JPEG available (exists always) */
LoadPCX(name, &pic, &palette, &width, &height);
LoadPCX(name, &pic, NULL, &width, &height);
if (!pic)
{
@ -237,19 +576,19 @@ GL3_FindImage(char *name, imagetype_t type)
}
/* Upload the PCX */
image = R_LoadPic(name, pic, width, 0, height, 0, type, 8);
image = GL3_LoadPic(name, pic, width, 0, height, 0, type, 8);
}
}
else /* gl_retexture is not set */
{
LoadPCX(name, &pic, &palette, &width, &height);
LoadPCX(name, &pic, NULL, &width, &height);
if (!pic)
{
return NULL;
}
image = R_LoadPic(name, pic, width, 0, height, 0, type, 8);
image = GL3_LoadPic(name, pic, width, 0, height, 0, type, 8);
}
}
else if (strcmp(ext, "wal") == 0)
@ -270,8 +609,7 @@ GL3_FindImage(char *name, imagetype_t type)
|| LoadSTB(namewe, "jpg", &pic, &width, &height) )
{
/* upload tga or png or jpg */
image = R_LoadPic(name, pic, width, realwidth, height,
realheight, type, 32);
image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32);
}
else
{
@ -321,7 +659,7 @@ GL3_FindImage(char *name, imagetype_t type)
if(LoadSTB(name, ext, &pic, &width, &height))
{
image = R_LoadPic(name, pic, width, realwidth, height, realheight, type, 32);
image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32);
}
}
else
@ -334,14 +672,7 @@ GL3_FindImage(char *name, imagetype_t type)
free(pic);
}
if (palette)
{
free(palette);
}
return image;
#endif // 0
return NULL;
}
gl3image_t *
@ -356,21 +687,21 @@ void
GL3_ImageList_f(void)
{
R_Printf(PRINT_ALL, "TODO: Implement R_ImageList_f()\n");
#if 0 // TODO!
int i;
image_t *image;
gl3image_t *image;
int texels;
const char *palstrings[2] = {
"RGB",
"PAL"
const char *formatstrings[2] = {
"RGB ",
"RGBA"
};
R_Printf(PRINT_ALL, "------------------\n");
texels = 0;
for (i = 0, image = gltextures; i < numgltextures; i++, image++)
for (i = 0, image = gl3textures; i < numgl3textures; i++, image++)
{
if (image->texnum <= 0)
if (image->texnum == 0)
{
continue;
}
@ -397,10 +728,9 @@ GL3_ImageList_f(void)
}
R_Printf(PRINT_ALL, " %3i %3i %s: %s\n",
image->upload_width, image->upload_height,
palstrings[image->paletted], image->name);
image->upload_width, image->upload_height,
formatstrings[image->has_alpha], image->name);
}
R_Printf(PRINT_ALL, "Total texel count (not counting mipmaps): %i\n", texels);
#endif
}

View file

@ -38,9 +38,6 @@ gl3state_t gl3state;
viddef_t vid;
gl3image_t *gl3_notexture; /* use for bad textures */
gl3image_t *gl3_particletexture; /* little dot for particles */
cvar_t *gl_msaa_samples;
cvar_t *gl_swapinterval;
cvar_t *gl_retexturing;
@ -52,6 +49,7 @@ cvar_t *vid_gamma;
cvar_t *gl_anisotropic;
cvar_t *gl_nolerp_list;
cvar_t *gl_nobind;
cvar_t *gl3_debugcontext;
@ -87,6 +85,7 @@ GL3_Register(void)
/* don't bilerp characters and crosshairs */
gl_nolerp_list = ri.Cvar_Get("gl_nolerp_list", "pics/conchars.pcx pics/ch1.pcx pics/ch2.pcx pics/ch3.pcx", 0);
gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
gl_anisotropic = ri.Cvar_Get("gl_anisotropic", "0", CVAR_ARCHIVE);
@ -121,7 +120,7 @@ GL3_Register(void)
gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
gl_stencilshadow = ri.Cvar_Get("gl_stencilshadow", "0", CVAR_ARCHIVE);
gl_dynamic = ri.Cvar_Get("gl_dynamic", "1", 0);
gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
//gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
gl_round_down = ri.Cvar_Get("gl_round_down", "1", 0);
gl_picmip = ri.Cvar_Get("gl_picmip", "0", 0);
gl_showtris = ri.Cvar_Get("gl_showtris", "0", 0);
@ -377,19 +376,20 @@ GL3_Init(void)
GL3_SetDefaultState();
STUB("TODO: Some intensity and gamma stuff that was in R_InitImages()");
registration_sequence = 1; // also from R_InitImages()
#if 0
//R_InitImages(); - most of the things in R_InitImages() shouldn't be needed anymore
Mod_Init();
R_InitParticleTexture();
#endif // 0
GL3_InitParticleTexture();
GL3_Draw_InitLocal();
R_Printf(PRINT_ALL, "\n");
return true; // -1 is error, other values don't matter. FIXME: mabe make this return bool..
return true;
return false;
}
void
@ -426,10 +426,11 @@ GetRefAPI(refimport_t imp)
re.PrepareForWindow = GL3_PrepareForWindow;
re.InitContext = GL3_InitContext;
re.ShutdownWindow = GL3_ShutdownWindow;
#if 0 // TODO!
re.BeginRegistration = RI_BeginRegistration;
re.RegisterModel = RI_RegisterModel;
re.RegisterSkin = RI_RegisterSkin;
re.RegisterSkin = GL3_RegisterSkin;
re.SetSky = RI_SetSky;
re.EndRegistration = RI_EndRegistration;

View file

@ -27,6 +27,9 @@
#include "header/local.h"
gl3image_t *gl3_notexture; /* use for bad textures */
gl3image_t *gl3_particletexture; /* little dot for particles */
void
GL3_SetDefaultState(void)
{
@ -93,6 +96,54 @@ GL3_SetDefaultState(void)
}
}
static byte dottexture[8][8] = {
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 0, 0, 0},
{0, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
};
void
GL3_InitParticleTexture(void)
{
int x, y;
byte data[8][8][4];
/* particle texture */
for (x = 0; x < 8; x++)
{
for (y = 0; y < 8; y++)
{
data[y][x][0] = 255;
data[y][x][1] = 255;
data[y][x][2] = 255;
data[y][x][3] = dottexture[x][y] * 255;
}
}
gl3_particletexture = GL3_LoadPic("***particle***", (byte *)data,
8, 0, 8, 0, it_sprite, 32);
/* also use this for bad textures, but without alpha */
for (x = 0; x < 8; x++)
{
for (y = 0; y < 8; y++)
{
data[y][x][0] = dottexture[x & 3][y & 3] * 255;
data[y][x][1] = 0;
data[y][x][2] = 0;
data[y][x][3] = 255;
}
}
gl3_notexture = GL3_LoadPic("***r_notexture***", (byte *)data,
8, 0, 8, 0, it_wall, 32);
}
void
GL3_ScreenShot(void)
{

View file

@ -26,6 +26,8 @@
#include "header/local.h"
int registration_sequence;
void
GL3_Mod_Modellist_f(void)
{

View file

@ -46,6 +46,14 @@
#define STUB(msg) \
R_Printf(PRINT_ALL, "STUB: %s() %s\n", __FUNCTION__, msg )
#define STUB_ONCE(msg) do {\
static int show=1; \
if(show) { \
show = 0; \
R_Printf(PRINT_ALL, "STUB: %s() %s\n", __FUNCTION__, msg ); \
} \
} while(0);
typedef struct
{
const char *renderer_string;
@ -79,8 +87,9 @@ typedef struct
int lightmap_textures;
int currenttextures[2];
int currenttmu;
//int currenttextures[2];
GLuint currenttexture;
//int currenttmu;
//GLenum currenttarget;
//float camera_separation;
@ -94,8 +103,12 @@ extern gl3state_t gl3state;
extern viddef_t vid;
typedef struct gl3image_s
/* NOTE: struct image_s* is what re.RegisterSkin() etc return so no gl3image_s!
* (I think the client only passes the pointer around and doesn't know the
* definition of this struct, so this being different from struct image_s
* in ref_gl should be ok)
*/
typedef struct image_s
{
// TODO: what of this is actually needed?
char name[MAX_QPATH]; /* game path, including extension */
@ -104,17 +117,18 @@ typedef struct gl3image_s
int upload_width, upload_height; /* after power of two and picmip */
int registration_sequence; /* 0 = free */
struct msurface_s *texturechain; /* for sort-by-texture world drawing */
int texnum; /* gl texture binding */
GLuint texnum; /* gl texture binding */
float sl, tl, sh, th; /* 0,0 - 1,1 unless part of the scrap */
qboolean scrap;
qboolean has_alpha;
qboolean paletted;
//qboolean paletted;
} gl3image_t;
enum {MAX_GL3TEXTURES = 1024};
extern gl3image_t *gl3_notexture;
extern gl3image_t *gl3_notexture; /* use for bad textures */
extern gl3image_t *gl3_particletexture; /* little dot for particles */
extern int gl_filter_min;
@ -125,15 +139,21 @@ extern int GL3_InitContext(void* win);
extern void GL3_EndFrame(void);
extern void GL3_ShutdownWindow(qboolean contextOnly);
extern void GL3_InitParticleTexture(void);
extern void GL3_ScreenShot(void);
extern void GL3_SetDefaultState(void);
extern int registration_sequence;
extern void GL3_Mod_Modellist_f(void);
extern void GL3_Draw_InitLocal(void);
extern int GL3_Draw_GetPalette(void);
extern gl3image_t * GL3_FindImage(char *name, imagetype_t type);
extern void GL3_Bind(int texnum);
extern gl3image_t *GL3_LoadPic(char *name, byte *pic, int width, int realwidth,
int height, int realheight, imagetype_t type, int bits);
extern gl3image_t *GL3_FindImage(char *name, imagetype_t type);
extern gl3image_t *GL3_RegisterSkin(char *name);
extern void GL3_TextureMode(char *string);
extern void GL3_ImageList_f(void);
@ -146,6 +166,7 @@ extern cvar_t *gl_customwidth;
extern cvar_t *gl_customheight;
extern cvar_t *gl_nolerp_list;
extern cvar_t *gl_nobind;
extern cvar_t *vid_gamma;
extern cvar_t *gl_anisotropic;