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 "header/client.h"
#include "input/header/input.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; extern cvar_t *vid_renderer;
cvar_t *cin_force43; cvar_t *cin_force43;
@ -50,6 +64,7 @@ typedef struct
int width; int width;
int height; int height;
int color_bits;
byte *pic; byte *pic;
byte *pic_pending; byte *pic_pending;
@ -598,6 +613,12 @@ SCR_DrawCinematic(void)
if (Q_stricmp(vid_renderer->string, "soft") == 0) if (Q_stricmp(vid_renderer->string, "soft") == 0)
{ {
color = SCR_MinimalColor(); color = SCR_MinimalColor();
/* Soft render requires to reset palette before show RGBA image */
if (cin.color_bits == 32)
{
R_SetPalette(NULL);
}
} }
else else
{ {
@ -621,16 +642,51 @@ SCR_DrawCinematic(void)
Draw_Fill(x, y + h, w, viddef.height - (y + h), color); 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; 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 void
SCR_PlayCinematic(char *arg) SCR_PlayCinematic(char *arg)
{ {
int width, height; int width, height;
byte *palette; byte *palette = NULL;
char name[MAX_OSPATH], *dot; char name[MAX_OSPATH], *dot;
In_FlushQueue(); In_FlushQueue();
@ -645,11 +701,43 @@ SCR_PlayCinematic(char *arg)
/* static pcx image */ /* static pcx image */
if (dot && !strcmp(dot, ".pcx")) if (dot && !strcmp(dot, ".pcx"))
{ {
cvar_t *r_retexturing;
Com_sprintf(name, sizeof(name), "pics/%s", arg); 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.cinematicframe = -1;
cl.cinematictime = 1; cl.cinematictime = 1;
SCR_EndLoadingPlaque(); SCR_EndLoadingPlaque();
cls.state = ca_active; cls.state = ca_active;
if (!cin.pic) if (!cin.pic)
@ -657,7 +745,7 @@ SCR_PlayCinematic(char *arg)
Com_Printf("%s not found.\n", name); Com_Printf("%s not found.\n", name);
cl.cinematictime = 0; cl.cinematictime = 0;
} }
else else if (palette)
{ {
memcpy(cl.cinematicpalette, palette, sizeof(cl.cinematicpalette)); memcpy(cl.cinematicpalette, palette, sizeof(cl.cinematicpalette));
Z_Free(palette); Z_Free(palette);
@ -678,6 +766,7 @@ SCR_PlayCinematic(char *arg)
SCR_EndLoadingPlaque(); SCR_EndLoadingPlaque();
cin.color_bits = 8;
cls.state = ca_active; cls.state = ca_active;
FS_Read(&width, 4, cl.cinematic_file); FS_Read(&width, 4, cl.cinematic_file);

View file

@ -330,10 +330,9 @@ RDraw_FadeScreen(void)
} }
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]; GLfloat tex[8];
byte *source;
float hscale = 1.0f; float hscale = 1.0f;
int frac, fracstep; int frac, fracstep;
int i, j, trows; 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); R_Bind(0);
if(gl_config.npottextures || rows <= 256) if(gl_config.npottextures || rows <= 256 || bits == 32)
{ {
// X, X // X, X
tex[0] = 0; 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 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 */ 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. * pixels to fit into a 256x256 texture.
* This causes text in videos (which are 320x240) to not look broken anymore. * 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; 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++) for (i = 0; i < trows; i++)
{ {
const byte *source;
row = (int)(i * hscale); row = (int)(i * hscale);
if (row > rows) 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++) for (i = 0; i < trows; i++)
{ {
const byte *source;
row = (int)(i * hscale); row = (int)(i * hscale);
if (row > rows) 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_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_Fill(int x, int y, int w, int h, int c);
extern void RDraw_FadeScreen(void); 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 #endif

View file

@ -350,7 +350,7 @@ GL3_Draw_FadeScreen(void)
} }
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; 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; unsigned* img = image32;
if(cols*rows > 320*240) if (bits == 32)
{ {
/* in case there is a bigger video after all, img = (unsigned *)data;
* malloc enough space to hold the frame */
img = (unsigned*)malloc(cols*rows*4);
} }
else
for(i=0; i<rows; ++i)
{ {
int rowOffset = i*cols; if(cols*rows > 320*240)
for(j=0; j<cols; ++j)
{ {
byte palIdx = data[rowOffset+j]; /* in case there is a bigger video after all,
img[rowOffset+j] = gl3_rawpalette[palIdx]; * 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, glTexImage2D(GL_TEXTURE_2D, 0, gl3_tex_solid_format,
cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img); cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
if(img != image32) if(img != image32 && img != (unsigned *)data)
{ {
free(img); 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_Fill(int x, int y, int w, int h, int c);
extern void GL3_Draw_FadeScreen(void); 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_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 // 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_GetPicSize (int *w, int *h, char *name);
void RE_Draw_PicScaled (int x, int y, char *name, float scale); 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_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_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_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); 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); void R_FreeUnusedImages(void);
qboolean R_ImageHasFreeSpace(void); qboolean R_ImageHasFreeSpace(void);
pixel_t R_ApplyLight(pixel_t pix, const light3_t light); 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_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 ); 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 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; image_t pic;
byte *image_scaled; 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 // we have only one image size
pic.mip_levels = 1; 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)) 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 else
{ {
image_scaled = data; image_scaled = (byte *)data;
} }
pic.pixels[0] = image_scaled; 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 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, R_Convert32To8bit(const unsigned char* pic_in, pixel_t* pic_out, size_t size,
qboolean transparent) 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 *DrawFill) (int x, int y, int w, int h, int c);
void (EXPORT *DrawFadeScreen) (void); 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 ** 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_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_Fill(int x, int y, int w, int h, int c);
void Draw_FadeScreen(void); 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); //int R_Init(void *hinstance, void *hWnd);
//void R_Shutdown(void); //void R_Shutdown(void);
void R_SetPalette(const unsigned char *palette); void R_SetPalette(const unsigned char *palette);

View file

@ -735,11 +735,11 @@ Draw_FadeScreen(void)
} }
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) if (ref_active)
{ {
re.DrawStretchRaw(x, y, w, h, cols, rows, data); re.DrawStretchRaw(x, y, w, h, cols, rows, data, bits);
} }
} }