28 #include "../../shared/images.h"
29 #include "../cl_screen.h"
31 #define MAX_IMAGEHASH 256
34 #define IMAGE_ARRAY_SIZE 128
44 #define FOR_EACH_IMAGE(i, image, imageArray) \
45 for (i = 0, imageArray = &r_images, image = &imageArray->images[0]; i < r_numImages; i++, image++, \
46 (i % IMAGE_ARRAY_SIZE) ? 0 : (image = (imageArray = imageArray->next) ? &imageArray->images[0] : nullptr))
55 #define MAX_TEXTURE_SIZE 8192
102 switch (image->
type) {
141 Com_Printf(
"Total texel count (not counting mipmaps): %i\n", texels);
163 const size_t size = (surf->w * surf->h) * 4;
167 memcpy(*pic, surf->pixels, size);
168 SDL_FreeSurface(surf);
172 void R_ScaleTexture (
const unsigned* in,
int inwidth,
int inheight,
unsigned* out,
int outwidth,
int outheight)
176 const unsigned fracstep = inwidth * 0x10000 / outwidth;
180 unsigned frac = fracstep >> 2;
181 for (i = 0; i < outwidth; i++) {
182 p1[
i] = 4 * (frac >> 16);
185 frac = 3 * (fracstep >> 2);
186 for (i = 0; i < outwidth; i++) {
187 p2[
i] = 4 * (frac >> 16);
191 for (i = 0; i < outheight; i++, out += outwidth) {
192 const int index = inwidth * (
int) ((i + 0.25) * inheight / outheight);
193 const unsigned* inrow = in +
index;
194 const int index2 = inwidth * (
int) ((i + 0.75) * inheight / outheight);
195 const unsigned* inrow2 = in + index2;
197 assert(index < inwidth * inheight);
198 assert(index2 < inwidth * inheight);
200 for (
int j = 0; j < outwidth; j++) {
201 const byte* pix1 = (
const byte*) inrow + p1[j];
202 const byte* pix2 = (
const byte*) inrow + p2[j];
203 const byte* pix3 = (
const byte*) inrow2 + p1[j];
204 const byte* pix4 = (
const byte*) inrow2 + p2[j];
205 ((
byte*) (out + j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
206 ((
byte*) (out + j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
207 ((
byte*) (out + j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
208 ((
byte*) (out + j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
222 for (*scaledWidth = 1; *scaledWidth < width; *scaledWidth <<= 1) {}
223 for (*scaledHeight = 1; *scaledHeight < height; *scaledHeight <<= 1) {}
232 else if (*scaledWidth < 1)
237 else if (*scaledHeight < 1)
246 #ifdef GL_VERSION_ES_CM_1_0
247 inline static void R_StripAlpha (
const unsigned*
data,
unsigned* buffer,
const unsigned count)
250 memmove(((
byte*)buffer) +
i * 3, (
const byte*)data, 3);
266 #ifdef GL_VERSION_ES_CM_1_0
267 GLint texFormat = GL_RGB;
275 const int c = width * height;
277 for (i = 0, scan = ((
const byte*) data) + 3; i < c; ++
i, scan += 4) {
279 #ifdef GL_VERSION_ES_CM_1_0
289 int scaledWidth, scaledHeight;
295 unsigned* tmpBuff =
nullptr;
297 if (!mipmap && scaledWidth == width && scaledHeight == height) {
307 #ifdef GL_VERSION_ES_CM_1_0
309 if (texFormat == GL_RGB) {
310 const int count = scaledWidth * scaledHeight;
312 R_StripAlpha(data, tmpBuff, count);
314 GLenum bFormat = texFormat;
318 glTexImage2D(GL_TEXTURE_2D, 0, texFormat, scaledWidth, scaledHeight, 0, bFormat, GL_UNSIGNED_BYTE, tmpBuff ? tmpBuff : data);
324 if (scaledWidth != width || scaledHeight != height) {
326 R_ScaleTexture(data, width, height, tmpBuff, scaledWidth, scaledHeight);
329 #ifdef GL_VERSION_ES_CM_1_0
336 if (texFormat == GL_RGB) {
337 const int count = scaledWidth * scaledHeight;
340 R_StripAlpha(c == count ? data : tmpBuff, tmpBuff, count);
348 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
353 #ifndef GL_VERSION_ES_CM_1_0
355 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT,
r_texture_lod->
value);
361 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
376 #ifdef GL_VERSION_ES_CM_1_0
377 const GLenum bFormat = texFormat;
379 const GLenum bFormat = GL_RGBA;
381 glTexImage2D(GL_TEXTURE_2D, 0, texFormat, scaledWidth, scaledHeight, 0, bFormat, GL_UNSIGNED_BYTE, tmpBuff ? tmpBuff : data);
393 const int size = width * height * bpp;
398 Com_Error(
ERR_FATAL,
"R_SoftenTexture: failed on allocation of %i bytes", width * height * bpp);
400 memcpy(out, in, size);
402 for (
int i = 1;
i < height - 1;
i++) {
403 for (
int j = 1; j < width - 1; j++) {
404 const byte* src = in + ((
i * width) + j) * bpp;
406 const byte* u = (src - (width * bpp));
407 const byte* d = (src + (width * bpp));
408 const byte* l = (src - (1 * bpp));
409 const byte* r = (src + (1 * bpp));
411 byte*
dest = out + ((
i * width) + j) * bpp;
413 for (
int k = 0; k < bpp; k++)
414 dest[k] = (u[k] + d[k] + l[k] + r[k]) / 4;
419 memcpy(in, out, size);
427 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, image->
width, image->
height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, alphaData);
438 for (
image_t** anchor = &imageHash[hash]; *anchor; anchor = &(*anchor)->
hash_next) {
446 glDeleteTextures(1, &image->
texnum);
458 for (image = imageHash[hash]; image; image = image->
hash_next)
484 if (len >=
sizeof(image->
name))
493 Com_Printf(
"R_LoadImageData: image '%s' is already uploaded\n", name);
506 for (images = &r_images; images->
next;)
507 images = images->
next;
517 image->
width = width;
521 #ifdef COMPILE_UNITTESTS
523 static int texnum = 0;
532 if (len >= 4 && image->
name[len - 4] ==
'.') {
533 image->
name[len - 4] =
'\0';
534 Com_Printf(
"Image with extension: '%s'\n", name);
550 const bool dimensionDiffer = img !=
nullptr && img->
width != w && img->
height != h;
551 if (img ==
nullptr || dimensionDiffer) {
552 if (dimensionDiffer) {
561 #ifndef GL_VERSION_ES_CM_1_0
562 glReadBuffer(GL_BACK);
566 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, w, h, 0);
609 if (!pname || !pname[0])
619 Com_Printf(
"Warning: inconsistent usage of image %s (%i,%i)\n", image->
name, image->
type, type);
631 SDL_FreeSurface(surf);
688 Q_vsnprintf(filename,
sizeof(filename), pname, ap);
691 for (
int i = 0; types[
i];
i++) {
706 for (images = &r_images;
images; images = images->
next) {
708 return imagePtr - &images->
images[0];
726 images = images->
next;
728 return &images->
images[i];
738 if (!image || !image->
texnum)
822 Com_Printf(
"R_ReloadImageData: unable to load image %s\n", image->
name);
823 surf = SDL_CreateRGBSurface(0, image->
width, image->
height, 32,
824 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
825 SDL_FillRect(surf,
nullptr, 0x99ff33ff);
829 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
830 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
832 SDL_FreeSurface(surf);
842 glEnable(GL_TEXTURE_2D);
861 {
"GL_NEAREST", GL_NEAREST, GL_NEAREST},
862 {
"GL_LINEAR", GL_LINEAR, GL_LINEAR},
863 {
"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
864 {
"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
865 {
"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
866 {
"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
874 for (i = 0; i <
size; i++) {
875 mode = &gl_texture_modes[
i];
880 if (mode ==
nullptr) {
903 #ifdef GL_VERSION_ES_CM_1_0
917 {
"GL_RGBA", GL_RGBA},
918 {
"GL_RGBA8", GL_RGBA8},
919 {
"GL_RGB5_A1", GL_RGB5_A1},
920 {
"GL_RGBA4", GL_RGBA4},
921 {
"GL_RGBA2", GL_RGBA2},
922 {
"GL_LUMINANCE4_ALPHA4", GL_LUMINANCE4_ALPHA4},
923 {
"GL_LUMINANCE6_ALPHA2", GL_LUMINANCE6_ALPHA2},
924 {
"GL_LUMINANCE8_ALPHA8", GL_LUMINANCE8_ALPHA8},
925 {
"GL_LUMINANCE12_ALPHA4", GL_LUMINANCE12_ALPHA4},
926 {
"GL_LUMINANCE12_ALPHA12", GL_LUMINANCE12_ALPHA12},
927 {
"GL_LUMINANCE16_ALPHA16", GL_LUMINANCE16_ALPHA16}
935 for (
int i = 0;
i <
size;
i++) {
943 Com_Printf(
"bad alpha texture mode name (%s)\n",
string);
948 {
"GL_RGB8", GL_RGB8},
949 {
"GL_RGB5", GL_RGB5},
950 {
"GL_RGB4", GL_RGB4},
951 {
"GL_R3_G3_B2", GL_R3_G3_B2},
952 {
"GL_RGB2", GL_RGB2_EXT},
953 {
"GL_RGB4", GL_RGB4_EXT},
954 {
"GL_RGB5", GL_RGB5_EXT},
955 {
"GL_RGB8", GL_RGB8_EXT},
956 {
"GL_RGB10", GL_RGB10_EXT},
957 {
"GL_RGB12", GL_RGB12_EXT},
958 {
"GL_RGB16", GL_RGB16_EXT},
959 {
"GL_LUMINANCE", GL_LUMINANCE},
960 {
"GL_LUMINANCE4", GL_LUMINANCE4},
961 {
"GL_LUMINANCE8", GL_LUMINANCE8},
962 {
"GL_LUMINANCE12", GL_LUMINANCE12},
963 {
"GL_LUMINANCE16", GL_LUMINANCE16}
970 for (
int i = 0;
i <
size;
i++) {
978 Com_Printf(
"bad solid texture mode name (%s)\n",
string);
static void R_ChangeImageType(image_t *img, imagetype_t type)
Set up new image type and change texturemapping paramenters accordingly.
static void R_ReloadImageData(image_t *image)
bool Q_strnull(const char *string)
static const gltmode_t gl_solid_modes[]
image_t * R_RenderToTexture(const char *name, int x, int y, int w, int h)
static image_t * imageHash[MAX_IMAGEHASH]
struct imageArray_s * next
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
void R_SoftenTexture(byte *in, int width, int height, int bpp)
Applies blurring to a texture.
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
QGL_EXTERN GLint GLenum type
void R_LoadImage(const char *name, byte **pic, int *width, int *height)
Generic image-data loading fucntion.
#define HASH_Delete(anchor)
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
void SCR_DrawLoadingScreen(bool string, int percent)
Precache and loading screen at startup.
static bool R_IsClampedImageType(imagetype_t type)
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
const GLenum *typedef GLint
const image_t * R_FindPics(const char *name)
Searches for an image in the image array.
void R_ScaleTexture(const unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
image_t * R_LoadImageData(const char *name, const byte *pic, int width, int height, imagetype_t type)
Creates a new image from RGBA data. Stores it in the gltextures array and also uploads it...
local graphics definitions
void R_ShutdownImages(void)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
image_t * r_envmaptextures[MAX_ENVMAPTEXTURES]
const GLuint *typedef GLuint *typedef GLenum
void R_TextureMode(const char *string)
#define FOR_EACH_IMAGE(i, image, imageArray)
char const *const * Img_GetImageTypes(void)
static void R_DeleteImage(image_t *image)
void Com_Error(int code, const char *fmt,...)
void R_ImageList_f(void)
Shows all loaded images.
image_t * R_FindImage(const char *pname, imagetype_t type)
Finds or loads the given image.
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
image_t images[IMAGE_ARRAY_SIZE]
image_t * R_GetImageAtIndex(int i)
Returns an image pointer from the r_images linked list, as if r_images would be a plain contiguous ar...
void R_ImageClearMaterials(void)
Free previously loaded materials and their stages.
static const gltmode_t gl_alpha_modes[]
struct image_s * roughnessmap
struct imageArray_s imageArray_t
static wrapCache_t * hash[MAX_WRAP_HASH]
int R_GetImageIndex(image_t *imagePtr)
Returns an index of the image pointer in the r_images linked list, as if r_images would be a plain co...
void R_UploadAlpha(const image_t *image, const byte *alphaData)
#define MAX_ENVMAPTEXTURES
#define NUM_FLARETEXTURES
SDL_Surface * Img_LoadImage(char const *name)
Loads the specified image from the game filesystem and populates the provided SDL_Surface.
int gl_compressed_alpha_format
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels)
material_t defaultMaterial
#define Q_strcasecmp(a, b)
void R_TextureSolidMode(const char *string)
#define HASH_Add(hash, elem, index)
QGL_EXTERN GLenum GLuint * dest
struct image_s * specularmap
void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
#define Mem_PoolAllocTypeN(type, n, pool)
struct image_s * hash_next
void R_ReloadImages(void)
image_t * r_flaretextures[NUM_FLARETEXTURES]
QGL_EXTERN GLuint GLchar GLuint * len
static const glTextureMode_t gl_texture_modes[]
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
void R_TextureAlphaMode(const char *string)
void R_GetScaledTextureSize(int width, int height, int *scaledWidth, int *scaledHeight)
Calculates the texture size that should be used to upload the texture data.
unsigned int Com_HashKey(const char *name, int hashsize)
returns hash key for a string
void glGenTextures(GLsizei n, GLuint *textures)
void R_FreeWorldImages(void)
Any image that is a mesh or world texture will be removed here.
void R_FreeImage(image_t *image)
Free the image and its assigned maps (roughness, normal, specular, glow - if there are any) ...
memPool_t * vid_imagePool
#define Mem_AllocType(type)
GLsizei const GLvoid * data
struct image_s * normalmap
image_t * R_GetImage(const char *name)
void R_UploadTexture(const unsigned *data, int width, int height, image_t *image)
Uploads the opengl texture to the server.
#define R_BindTexture(tn)
bool R_ImageExists(const char *pname,...)
struct materialStage_s * next
int gl_compressed_solid_format
bool R_SelectTexture(gltexunit_t *texunit)
Returns false if the texunit is not supported.