cl_cin: Support of RGBA png/jpg image with r_retexturing as cinematic

This commit is contained in:
Denis Pauk 2023-07-01 23:30:41 +03:00
parent 86dd7e6d2d
commit 5c0883594f
10 changed files with 147 additions and 33 deletions

View File

@ -30,6 +30,20 @@
#include "header/client.h"
#include "input/header/input.h"
// don't need HDR stuff
#define STBI_NO_LINEAR
#define STBI_NO_HDR
// make sure STB_image uses standard malloc(), as we'll use standard free() to deallocate
#define STBI_MALLOC(sz) malloc(sz)
#define STBI_REALLOC(p,sz) realloc(p,sz)
#define STBI_FREE(p) free(p)
// Switch of the thread local stuff. Breaks mingw under Windows.
#define STBI_NO_THREAD_LOCALS
// include implementation part of stb_image into this file
#define STB_IMAGE_IMPLEMENTATION
#include "refresh/files/stb_image.h"
extern cvar_t *vid_renderer;
cvar_t *cin_force43;
@ -50,6 +64,7 @@ typedef struct
int width;
int height;
int color_bits;
byte *pic;
byte *pic_pending;
@ -598,6 +613,12 @@ SCR_DrawCinematic(void)
if (Q_stricmp(vid_renderer->string, "soft") == 0)
{
color = SCR_MinimalColor();
/* Soft render requires to reset palette before show RGBA image */
if (cin.color_bits == 32)
{
R_SetPalette(NULL);
}
}
else
{
@ -621,16 +642,51 @@ SCR_DrawCinematic(void)
Draw_Fill(x, y + h, w, viddef.height - (y + h), color);
}
Draw_StretchRaw(x, y, w, h, cin.width, cin.height, cin.pic);
Draw_StretchRaw(x, y, w, h, cin.width, cin.height, cin.pic, cin.color_bits);
return true;
}
byte *
SCR_LoadHiColor(const char* namewe, const char *ext, int *width, int *height)
{
char filename[256];
int bytesPerPixel;
byte *pic, *data = NULL;
void *rawdata;
size_t len;
Q_strlcpy(filename, namewe, sizeof(filename));
Q_strlcat(filename, ".", sizeof(filename));
Q_strlcat(filename, ext, sizeof(filename));
len = FS_LoadFile(filename, &rawdata);
if (!rawdata || len <=0)
{
return NULL;
}
data = stbi_load_from_memory(rawdata, len, width, height,
&bytesPerPixel, STBI_rgb_alpha);
if (data == NULL)
{
FS_FreeFile(rawdata);
return NULL;
}
pic = Z_Malloc(cin.height * cin.width * 4);
memcpy(pic, data, cin.height * cin.width * 4);
free(data);
return pic;
}
void
SCR_PlayCinematic(char *arg)
{
int width, height;
byte *palette;
byte *palette = NULL;
char name[MAX_OSPATH], *dot;
In_FlushQueue();
@ -645,11 +701,43 @@ SCR_PlayCinematic(char *arg)
/* static pcx image */
if (dot && !strcmp(dot, ".pcx"))
{
cvar_t *r_retexturing;
Com_sprintf(name, sizeof(name), "pics/%s", arg);
SCR_LoadPCX(name, &cin.pic, &palette, &cin.width, &cin.height);
r_retexturing = Cvar_Get("r_retexturing", "1", CVAR_ARCHIVE);
if (r_retexturing->value)
{
char namewe[256];
cin.color_bits = 32;
/* Remove the extension */
memset(namewe, 0, 256);
memcpy(namewe, name, strlen(name) - strlen(dot));
cin.pic = SCR_LoadHiColor(namewe, "tga", &cin.width, &cin.height);
if (!cin.pic)
{
cin.pic = SCR_LoadHiColor(namewe, "png", &cin.width, &cin.height);
}
if (!cin.pic)
{
cin.pic = SCR_LoadHiColor(namewe, "jpg", &cin.width, &cin.height);
}
}
if (!cin.pic)
{
SCR_LoadPCX(name, &cin.pic, &palette, &cin.width, &cin.height);
cin.color_bits = 8;
}
cl.cinematicframe = -1;
cl.cinematictime = 1;
SCR_EndLoadingPlaque();
cls.state = ca_active;
if (!cin.pic)
@ -657,7 +745,7 @@ SCR_PlayCinematic(char *arg)
Com_Printf("%s not found.\n", name);
cl.cinematictime = 0;
}
else
else if (palette)
{
memcpy(cl.cinematicpalette, palette, sizeof(cl.cinematicpalette));
Z_Free(palette);
@ -678,6 +766,7 @@ SCR_PlayCinematic(char *arg)
SCR_EndLoadingPlaque();
cin.color_bits = 8;
cls.state = ca_active;
FS_Read(&width, 4, cl.cinematic_file);

View File

@ -330,10 +330,9 @@ RDraw_FadeScreen(void)
}
void
RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
GLfloat tex[8];
byte *source;
float hscale = 1.0f;
int frac, fracstep;
int i, j, trows;
@ -341,7 +340,7 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
R_Bind(0);
if(gl_config.npottextures || rows <= 256)
if(gl_config.npottextures || rows <= 256 || bits == 32)
{
// X, X
tex[0] = 0;
@ -389,7 +388,7 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
x, y + h
};
if (!gl_config.palettedtexture)
if (!gl_config.palettedtexture || bits == 32)
{
unsigned image32[320*240]; /* was 256 * 256, but we want a bit more space */
@ -398,7 +397,13 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
* pixels to fit into a 256x256 texture.
* This causes text in videos (which are 320x240) to not look broken anymore.
*/
if(gl_config.npottextures || rows <= 256)
if (bits == 32)
{
glTexImage2D(GL_TEXTURE_2D, 0, gl_tex_solid_format,
cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE,
data);
}
else if(gl_config.npottextures || rows <= 256)
{
unsigned* img = image32;
@ -435,6 +440,8 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
for (i = 0; i < trows; i++)
{
const byte *source;
row = (int)(i * hscale);
if (row > rows)
@ -466,6 +473,8 @@ RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
for (i = 0; i < trows; i++)
{
const byte *source;
row = (int)(i * hscale);
if (row > rows)

View File

@ -407,6 +407,6 @@ extern void RDraw_CharScaled(int x, int y, int num, float scale);
extern void RDraw_TileClear(int x, int y, int w, int h, char *pic);
extern void RDraw_Fill(int x, int y, int w, int h, int c);
extern void RDraw_FadeScreen(void);
extern void RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
extern void RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
#endif

View File

@ -350,7 +350,7 @@ GL3_Draw_FadeScreen(void)
}
void
GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
int i, j;
@ -360,20 +360,27 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
unsigned* img = image32;
if(cols*rows > 320*240)
if (bits == 32)
{
/* in case there is a bigger video after all,
* malloc enough space to hold the frame */
img = (unsigned*)malloc(cols*rows*4);
img = (unsigned *)data;
}
for(i=0; i<rows; ++i)
else
{
int rowOffset = i*cols;
for(j=0; j<cols; ++j)
if(cols*rows > 320*240)
{
byte palIdx = data[rowOffset+j];
img[rowOffset+j] = gl3_rawpalette[palIdx];
/* in case there is a bigger video after all,
* malloc enough space to hold the frame */
img = (unsigned*)malloc(cols*rows*4);
}
for(i=0; i<rows; ++i)
{
int rowOffset = i*cols;
for(j=0; j<cols; ++j)
{
byte palIdx = data[rowOffset+j];
img[rowOffset+j] = gl3_rawpalette[palIdx];
}
}
}
@ -387,7 +394,7 @@ GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
glTexImage2D(GL_TEXTURE_2D, 0, gl3_tex_solid_format,
cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
if(img != image32)
if(img != image32 && img != (unsigned *)data)
{
free(img);
}

View File

@ -425,7 +425,7 @@ extern void GL3_DrawFrameBufferObject(int x, int y, int w, int h, GLuint fboText
extern void GL3_Draw_Fill(int x, int y, int w, int h, int c);
extern void GL3_Draw_FadeScreen(void);
extern void GL3_Draw_Flash(const float color[4], float x, float y, float w, float h);
extern void GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
extern void GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
// gl3_image.c

View File

@ -581,7 +581,7 @@ struct image_s *RE_Draw_FindPic (char *name);
void RE_Draw_GetPicSize (int *w, int *h, char *name);
void RE_Draw_PicScaled (int x, int y, char *name, float scale);
void RE_Draw_StretchPic (int x, int y, int w, int h, char *name);
void RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data);
void RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
void RE_Draw_CharScaled (int x, int y, int c, float scale);
void RE_Draw_TileClear (int x, int y, int w, int h, char *name);
void RE_Draw_Fill (int x, int y, int w, int h, int c);
@ -595,6 +595,7 @@ byte *Get_BestImageSize(const image_t *image, int *req_width, int *req_height);
void R_FreeUnusedImages(void);
qboolean R_ImageHasFreeSpace(void);
pixel_t R_ApplyLight(pixel_t pix, const light3_t light);
void R_Convert32To8bit(const unsigned char* pic_in, pixel_t* pic_out, size_t size, qboolean transparent);
void R_InitSkyBox(model_t *loadmodel);
void R_IMFlatShadedQuad( const vec3_t a, const vec3_t b, const vec3_t c, const vec3_t d, int color, float alpha );

View File

@ -321,7 +321,7 @@ RE_Draw_StretchRaw
=============
*/
void
RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
image_t pic;
byte *image_scaled;
@ -329,7 +329,12 @@ RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
// we have only one image size
pic.mip_levels = 1;
if (r_retexturing->value)
if (bits == 32)
{
image_scaled = malloc(cols * rows);
R_Convert32To8bit(data, image_scaled, cols * rows, false);
}
else if (r_retexturing->value)
{
if (cols < (w / 3) || rows < (h / 3))
{
@ -352,7 +357,7 @@ RE_Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
}
else
{
image_scaled = data;
image_scaled = (byte *)data;
}
pic.pixels[0] = image_scaled;

View File

@ -206,7 +206,7 @@ Get_BestImageSize(const image_t *image, int *req_width, int *req_height)
static byte *d_16to8table = NULL; // 16 to 8 bit conversion table
static void
void
R_Convert32To8bit(const unsigned char* pic_in, pixel_t* pic_out, size_t size,
qboolean transparent)
{

View File

@ -197,8 +197,11 @@ typedef struct
void (EXPORT *DrawFill) (int x, int y, int w, int h, int c);
void (EXPORT *DrawFadeScreen) (void);
// Draw images for cinematic rendering (which can have a different palette). Note that calls
void (EXPORT *DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, byte *data);
/*
* Draw images for cinematic rendering (which can have a different palette if bits equals to 8).
* Note that calls
*/
void (EXPORT *DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
/*
** video mode and refresh state management entry points
@ -278,7 +281,7 @@ void Draw_CharScaled(int x, int y, int num, float scale);
void Draw_TileClear(int x, int y, int w, int h, char *name);
void Draw_Fill(int x, int y, int w, int h, int c);
void Draw_FadeScreen(void);
void Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data);
void Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits);
//int R_Init(void *hinstance, void *hWnd);
//void R_Shutdown(void);
void R_SetPalette(const unsigned char *palette);

View File

@ -735,11 +735,11 @@ Draw_FadeScreen(void)
}
void
Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int bits)
{
if (ref_active)
{
re.DrawStretchRaw(x, y, w, h, cols, rows, data);
re.DrawStretchRaw(x, y, w, h, cols, rows, data, bits);
}
}