mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-01-19 15:01:13 +00:00
vulkan: rewrote render target stuff so bloom, r_projection, fxaa, should now be working.
gl: fix r_projection when using vid_restart. hdr: fixed iris stuff to work in more renderers. ircclient: don't disconnect instantly. that's just stupid. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5010 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
b14854ae04
commit
151bd6d0b1
25 changed files with 11954 additions and 8109 deletions
|
@ -1944,6 +1944,6 @@ INSTALL ?= install
|
|||
INSTALL_PROGRAM ?= $(INSTALL)
|
||||
INSTALL_DATA ?= ${INSTALL} -m 644
|
||||
install: sv-rel gl-rel mingl-rel qcc-rel
|
||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqw $(DESTDIR)$(bindir)/fteqw
|
||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqwsv $(DESTDIR)$(bindir)/fteqwsv
|
||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)fteqcc $(DESTDIR)$(bindir)/fteqcc
|
||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqw $(DESTDIR)$(bindir)/fteqw
|
||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqwsv $(DESTDIR)$(bindir)/fteqwsv
|
||||
$(INSTALL_PROGRAM) $(RELEASE_DIR)/fteqcc $(DESTDIR)$(bindir)/fteqcc
|
||||
|
|
|
@ -726,7 +726,7 @@ static void Stats_LoadFragFile(char *name)
|
|||
}
|
||||
|
||||
|
||||
static int qm_strcmp(char *s1, char *s2)//not like strcmp at all...
|
||||
static int qm_strcmp(const char *s1, const char *s2)//not like strcmp at all...
|
||||
{
|
||||
while(*s1)
|
||||
{
|
||||
|
@ -757,7 +757,7 @@ static int qm_stricmp(char *s1, char *s2)//not like strcmp at all...
|
|||
}
|
||||
*/
|
||||
|
||||
static int Stats_ExtractName(char **line)
|
||||
static int Stats_ExtractName(const char **line)
|
||||
{
|
||||
int i;
|
||||
int bm;
|
||||
|
@ -801,7 +801,7 @@ qboolean Stats_ParsePrintLine(const char *line)
|
|||
statmessage_t *ms;
|
||||
int p1;
|
||||
int p2;
|
||||
char *m2;
|
||||
const char *m2;
|
||||
|
||||
p1 = Stats_ExtractName(&line);
|
||||
if (p1<0) //reject it.
|
||||
|
|
|
@ -128,28 +128,28 @@ cvar_t r_floorcolour = CVARAF ("r_floorcolour", "64 64 128",
|
|||
// CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
|
||||
cvar_t r_fullbright = CVARFD ("r_fullbright", "0",
|
||||
CVAR_CHEAT|CVAR_SHADERSYSTEM, "Ignore world lightmaps, drawing everything fully lit.");
|
||||
cvar_t r_fullbrightSkins = SCVARF ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/
|
||||
cvar_t r_fullbrightSkins = CVARF ("r_fullbrightSkins", "0.8", /*don't default to 1, as it looks a little ugly (too bright), but don't default to 0 either because then you're handicapped in the dark*/
|
||||
CVAR_SEMICHEAT|CVAR_SHADERSYSTEM);
|
||||
cvar_t r_lightmap_saturation = SCVAR ("r_lightmap_saturation", "1");
|
||||
cvar_t r_lightstylesmooth = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_lightstylesmooth_limit = SCVAR ("r_lightstylesmooth_limit", "2");
|
||||
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10");
|
||||
cvar_t r_lightstylescale = SCVAR ("r_lightstylescale", "1");
|
||||
cvar_t r_hdr_irisadaptation = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2");
|
||||
cvar_t r_hdr_irisadaptation_minvalue = CVAR ("r_hdr_irisadaptation_minvalue", "0.5");
|
||||
cvar_t r_hdr_irisadaptation_maxvalue = CVAR ("r_hdr_irisadaptation_maxvalue", "4");
|
||||
cvar_t r_hdr_irisadaptation_fade_down = CVAR ("r_hdr_irisadaptation_fade_down", "0.5");
|
||||
cvar_t r_hdr_irisadaptation_fade_up = CVAR ("r_hdr_irisadaptation_fade_up", "0.1");
|
||||
cvar_t r_loadlits = CVARF ("r_loadlit", "1", CVAR_ARCHIVE);
|
||||
cvar_t r_menutint = SCVARF ("r_menutint", "0.68 0.4 0.13",
|
||||
cvar_t r_lightmap_saturation = SCVAR ("r_lightmap_saturation", "1");
|
||||
cvar_t r_lightstylesmooth = CVARF ("r_lightstylesmooth", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_lightstylesmooth_limit = SCVAR ("r_lightstylesmooth_limit", "2");
|
||||
cvar_t r_lightstylespeed = SCVAR ("r_lightstylespeed", "10");
|
||||
cvar_t r_lightstylescale = SCVAR ("r_lightstylescale", "1");
|
||||
cvar_t r_hdr_irisadaptation = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2");
|
||||
cvar_t r_hdr_irisadaptation_minvalue = CVAR ("r_hdr_irisadaptation_minvalue", "0.5");
|
||||
cvar_t r_hdr_irisadaptation_maxvalue = CVAR ("r_hdr_irisadaptation_maxvalue", "4");
|
||||
cvar_t r_hdr_irisadaptation_fade_down = CVAR ("r_hdr_irisadaptation_fade_down", "0.5");
|
||||
cvar_t r_hdr_irisadaptation_fade_up = CVAR ("r_hdr_irisadaptation_fade_up", "0.1");
|
||||
cvar_t r_loadlits = CVARF ("r_loadlit", "1", CVAR_ARCHIVE);
|
||||
cvar_t r_menutint = CVARF ("r_menutint", "0.68 0.4 0.13",
|
||||
CVAR_RENDERERCALLBACK);
|
||||
cvar_t r_netgraph = SCVAR ("r_netgraph", "0");
|
||||
cvar_t r_netgraph = CVAR ("r_netgraph", "0");
|
||||
extern cvar_t r_lerpmuzzlehack;
|
||||
cvar_t r_nolerp = CVARF ("r_nolerp", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_noframegrouplerp = CVARF ("r_noframegrouplerp", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_nolightdir = CVARF ("r_nolightdir", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_novis = CVARF ("r_novis", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_nolerp = CVARF ("r_nolerp", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_noframegrouplerp = CVARF ("r_noframegrouplerp", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_nolightdir = CVARF ("r_nolightdir", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_novis = CVARF ("r_novis", "0", CVAR_ARCHIVE);
|
||||
cvar_t r_part_rain = CVARFD ("r_part_rain", "0",
|
||||
CVAR_ARCHIVE,
|
||||
"Enable particle effects to emit off of surfaces. Mainly used for weather or lava/slime effects.");
|
||||
|
@ -523,8 +523,6 @@ void GLRenderer_Init(void)
|
|||
|
||||
Cvar_Register (&gl_lightmap_nearest, GLRENDEREROPTIONS);
|
||||
Cvar_Register (&gl_lightmap_average, GLRENDEREROPTIONS);
|
||||
|
||||
R_BloomRegister();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -634,6 +632,10 @@ void Renderer_Init(void)
|
|||
GLRenderer_Init();
|
||||
#endif
|
||||
|
||||
#if defined(GLQUAKE) || defined(VKQUAKE)
|
||||
R_BloomRegister();
|
||||
#endif
|
||||
|
||||
#ifdef SWQUAKE
|
||||
{
|
||||
extern cvar_t sw_interlace;
|
||||
|
|
|
@ -5069,7 +5069,7 @@ static int COM_WorkerThread(void *arg)
|
|||
static void Sys_ErrorThread(void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
//posted to main thread from a worker.
|
||||
Sys_Error(data);
|
||||
Sys_Error("%s", data);
|
||||
}
|
||||
void COM_WorkerAbort(char *message)
|
||||
{
|
||||
|
|
|
@ -3578,6 +3578,7 @@ void D3D11BE_DrawWorld (batch_t **worldbatches, qbyte *vis)
|
|||
else
|
||||
#endif
|
||||
shaderstate.identitylighting = 1;
|
||||
shaderstate.identitylighting *= r_refdef.hdr_value;
|
||||
// shaderstate.identitylightmap = shaderstate.identitylighting / (1<<gl_overbright.ival);
|
||||
|
||||
BE_SelectMode(BEM_STANDARD);
|
||||
|
|
|
@ -41,7 +41,7 @@ http://prideout.net/archive/bloom/ contains some sample code
|
|||
|
||||
#include "quakedef.h"
|
||||
|
||||
#ifdef GLQUAKE
|
||||
#if defined(GLQUAKE) || defined(VKQUAKE)
|
||||
#include "shader.h"
|
||||
#include "glquake.h"
|
||||
#include "gl_draw.h"
|
||||
|
@ -173,16 +173,130 @@ qboolean R_CanBloom(void)
|
|||
{
|
||||
if (!r_bloom.value)
|
||||
return false;
|
||||
if (!gl_config.ext_framebuffer_objects)
|
||||
return false;
|
||||
if (!gl_config.arb_shader_objects)
|
||||
return false;
|
||||
if (!sh_config.texture_non_power_of_two_pic)
|
||||
switch(qrenderer)
|
||||
{
|
||||
#ifdef GLQUAKE
|
||||
case QR_OPENGL:
|
||||
if (!gl_config.ext_framebuffer_objects)
|
||||
return false;
|
||||
if (!gl_config.arb_shader_objects)
|
||||
return false;
|
||||
if (!sh_config.texture_non_power_of_two_pic)
|
||||
return false;
|
||||
break;
|
||||
#endif
|
||||
#ifdef VKQUAKE
|
||||
case QR_VULKAN:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef VKQUAKE
|
||||
#include "../vk/vkrenderer.h"
|
||||
struct vk_rendertarg vk_rt_bloom[2][MAXLEVELS], vk_rt_filter;
|
||||
void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
|
||||
{
|
||||
int i;
|
||||
struct vk_rendertarg *oldfbo = vk.rendertarg;
|
||||
texid_t intex;
|
||||
int pixels = 1;
|
||||
int targetpixels = r_bloom_size.value * vid.pixelwidth / 320;
|
||||
|
||||
targetpixels *= r_bloom_initialscale.value;
|
||||
|
||||
/*whu?*/
|
||||
if (!w || !h)
|
||||
return;
|
||||
|
||||
/*update textures if we need to resize them*/
|
||||
R_SetupBloomTextures(w, h);
|
||||
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
#if 1
|
||||
/*filter the screen into a downscaled image*/
|
||||
VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false);
|
||||
VKBE_RT_Begin(&vk_rt_filter);
|
||||
vk.sourcecolour = source;
|
||||
R2D_ScalePic(0, 0, vid.width, vid.height, bloomfilter);
|
||||
R2D_Flush();
|
||||
intex = &vk_rt_filter.q_colour;
|
||||
#else
|
||||
intex = source;
|
||||
#endif
|
||||
|
||||
for (pixels = 1, i = 0; pixels < targetpixels && i < MAXLEVELS; i++, pixels <<= 1)
|
||||
{
|
||||
//downsize the blur, for added accuracy
|
||||
/*if (i > 0 && r_bloom_downsize.ival)
|
||||
{
|
||||
//simple downscale that multiple times
|
||||
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false);
|
||||
VKBE_RT_Begin(&vk_rt_bloom[0][i]);
|
||||
vk.sourcecolour = source;
|
||||
|
||||
R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale);
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
intex = &vk_rt_bloom[0][i];
|
||||
r_worldentity.glowmod[0] = 1.0 / intex->width;
|
||||
}
|
||||
else*/
|
||||
r_worldentity.glowmod[0] = 2.0 / intex->width;
|
||||
|
||||
r_worldentity.glowmod[1] = 0;
|
||||
|
||||
VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false);
|
||||
VKBE_RT_Begin(&vk_rt_bloom[1][i]);
|
||||
vk.sourcecolour = intex;
|
||||
BE_SelectEntity(&r_worldentity);
|
||||
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
|
||||
R2D_Flush();
|
||||
|
||||
r_worldentity.glowmod[0] = 0;
|
||||
r_worldentity.glowmod[1] = 1.0 / texheight[i];
|
||||
|
||||
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false);
|
||||
VKBE_RT_Begin(&vk_rt_bloom[0][i]);
|
||||
vk.sourcecolour = &vk_rt_bloom[1][i].q_colour;
|
||||
BE_SelectEntity(&r_worldentity);
|
||||
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
|
||||
R2D_Flush();
|
||||
|
||||
intex = &vk_rt_bloom[0][i].q_colour;
|
||||
}
|
||||
r_worldentity.glowmod[0] = 0;
|
||||
r_worldentity.glowmod[1] = 0;
|
||||
VKBE_RT_Begin(oldfbo);
|
||||
//go back to the screen fbo
|
||||
|
||||
/*combine them onto the screen*/
|
||||
bloomfinal->defaulttextures->base = intex;
|
||||
bloomfinal->defaulttextures->loweroverlay = (i >= 2)?&vk_rt_bloom[0][i-2].q_colour:0;
|
||||
bloomfinal->defaulttextures->upperoverlay = (i >= 3)?&vk_rt_bloom[0][i-3].q_colour:0;
|
||||
vk.sourcecolour = source;
|
||||
R2D_ScalePic(x, y, w, h, bloomfinal);
|
||||
R2D_Flush();
|
||||
}
|
||||
void VK_R_BloomShutdown(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAXLEVELS; i++)
|
||||
{
|
||||
VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false);
|
||||
VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false);
|
||||
}
|
||||
VKBE_RT_Gen(&vk_rt_filter, 0, 0, false);
|
||||
|
||||
R_InitBloomTextures();
|
||||
}
|
||||
#endif
|
||||
#ifdef GLQUAKE
|
||||
void R_BloomBlend (texid_t source, int x, int y, int w, int h)
|
||||
{
|
||||
int i;
|
||||
|
@ -298,5 +412,6 @@ void R_BloomShutdown(void)
|
|||
|
||||
R_InitBloomTextures();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -99,6 +99,7 @@ int scenepp_postproc_cube_size;
|
|||
|
||||
fbostate_t fbo_gameview;
|
||||
fbostate_t fbo_postproc;
|
||||
fbostate_t fbo_postproc_cube;
|
||||
|
||||
// KrimZon - init post processing - called in GL_CheckExtensions, when they're called
|
||||
// I put it here so that only this file need be changed when messing with the post
|
||||
|
@ -131,6 +132,7 @@ void GL_ShutdownPostProcessing(void)
|
|||
{
|
||||
GLBE_FBO_Destroy(&fbo_gameview);
|
||||
GLBE_FBO_Destroy(&fbo_postproc);
|
||||
GLBE_FBO_Destroy(&fbo_postproc_cube);
|
||||
R_BloomShutdown();
|
||||
}
|
||||
|
||||
|
@ -1418,7 +1420,6 @@ qboolean R_RenderScene_Cubemap(void)
|
|||
extern cvar_t r_projection;
|
||||
int oldfbo = -1;
|
||||
qboolean usefbo = true; //this appears to be a 20% speedup in my tests.
|
||||
static fbostate_t fbostate; //FIXME
|
||||
qboolean fboreset = false;
|
||||
int osm = r_refdef.stereomethod;
|
||||
|
||||
|
@ -1629,7 +1630,7 @@ qboolean R_RenderScene_Cubemap(void)
|
|||
|
||||
if (usefbo)
|
||||
{
|
||||
int r = GLBE_FBO_Update(&fbostate, FBO_RB_DEPTH|(fboreset?FBO_RESET:0), &scenepp_postproc_cube, 1, r_nulltex, cmapsize, cmapsize, i);
|
||||
int r = GLBE_FBO_Update(&fbo_postproc_cube, FBO_RB_DEPTH|(fboreset?FBO_RESET:0), &scenepp_postproc_cube, 1, r_nulltex, cmapsize, cmapsize, i);
|
||||
fboreset = false;
|
||||
if (oldfbo < 0)
|
||||
oldfbo = r;
|
||||
|
|
12165
engine/gl/r_bishaders.h
12165
engine/gl/r_bishaders.h
File diff suppressed because it is too large
Load diff
33
engine/shaders/Makefile
Normal file
33
engine/shaders/Makefile
Normal file
|
@ -0,0 +1,33 @@
|
|||
CC=i686-pc-mingw32-gcc
|
||||
|
||||
all:
|
||||
|
||||
NAMES= fixedemu altwater bloom_blur bloom_filter bloom_final colourtint crepuscular_opaque crepuscular_rays crepuscular_sky depthonly default2d defaultadditivesprite defaultskin defaultsky defaultfill defaultsprite defaultwall defaultwarp defaultgammacb drawflat_wall lpp_depthnorm lpp_light lpp_wall postproc_fisheye postproc_panorama postproc_laea postproc_stereographic postproc_equirectangular fxaa underwaterwarp menutint terrain rtlight
|
||||
|
||||
|
||||
ALLNAMES+=$(foreach v,$(NAMES),glsl/$v.glsl)
|
||||
ALLNAMES+=$(foreach v,$(NAMES),hlsl9/$v.hlsl)
|
||||
ALLNAMES+=$(foreach v,$(NAMES),hlsl11/$v.hlsl)
|
||||
ALLNAMES:=$(realpath $(ALLNAMES))
|
||||
|
||||
VKNAMES=$(realpath $(foreach v,$(NAMES),vulkan/$v.glsl))
|
||||
VKNAMES+=postproc_fisheye
|
||||
VKNAMES:=$(foreach v,$(VKNAMES),vulkanblobs/$(notdir $(basename $v)).fvb)
|
||||
ALLNAMES+=$(VKNAMES)
|
||||
|
||||
generatebuiltinsl: generatebuiltinsl.c
|
||||
$(CC) $< -o $@
|
||||
|
||||
makevulkanblob: makevulkanblob.c
|
||||
$(CC) $< -o $@
|
||||
|
||||
vulkanblobs/%.fvb: vulkan/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
|
||||
./makevulkanblob $< $@
|
||||
|
||||
vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
|
||||
./makevulkanblob $< $@
|
||||
|
||||
|
||||
all: generatebuiltinsl $(ALLNAMES)
|
||||
which glslangValidator
|
||||
./generatebuiltinsl
|
|
@ -76,12 +76,19 @@ void dumpprogstring(FILE *out, FILE *src)
|
|||
}
|
||||
fflush(out);
|
||||
}
|
||||
void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
|
||||
void dumpprogblob(FILE *out, FILE *src)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned int size;
|
||||
fseek(src, 0, SEEK_END);
|
||||
size = ftell(src);
|
||||
fseek(src, 0, SEEK_SET);
|
||||
buf = malloc(size);
|
||||
fread(buf, size, 1, src);
|
||||
|
||||
size_t totallen, i, linelen;
|
||||
totallen = 0;
|
||||
linelen = 32;
|
||||
fflush(out);
|
||||
fprintf(out, "\"");
|
||||
for (i=0;i<size;i++)
|
||||
{
|
||||
|
@ -90,408 +97,22 @@ void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
|
|||
fprintf(out, "\"\n\"");
|
||||
}
|
||||
fprintf(out, "\"");
|
||||
fflush(out);
|
||||
}
|
||||
|
||||
struct blobheader
|
||||
{
|
||||
unsigned char blobmagic[4]; //\xffSPV
|
||||
unsigned int blobversion;
|
||||
unsigned int defaulttextures; //s_diffuse etc flags
|
||||
unsigned int numtextures; //s_t0 count
|
||||
unsigned int permutations; //
|
||||
|
||||
unsigned int cvarsoffset; //double-null terminated string. I,XYZW prefixes
|
||||
unsigned int cvarslength;
|
||||
|
||||
unsigned int vertoffset;
|
||||
unsigned int vertlength;
|
||||
unsigned int fragoffset;
|
||||
unsigned int fraglength;
|
||||
};
|
||||
void generateprogsblob(struct blobheader *prototype, FILE *out, FILE *vert, FILE *frag)
|
||||
{
|
||||
struct blobheader *blob;
|
||||
int fraglen, vertlen, blobsize, cvarlen;
|
||||
cvarlen = prototype->cvarslength;
|
||||
cvarlen = (cvarlen + 3) & ~3; //round up for padding.
|
||||
fseek(vert, 0, SEEK_END);
|
||||
fseek(frag, 0, SEEK_END);
|
||||
vertlen = ftell(vert);
|
||||
fraglen = ftell(frag);
|
||||
fseek(vert, 0, SEEK_SET);
|
||||
fseek(frag, 0, SEEK_SET);
|
||||
blobsize = sizeof(*blob) + cvarlen + fraglen + vertlen;
|
||||
blob = malloc(blobsize);
|
||||
*blob = *prototype;
|
||||
blob->cvarsoffset = sizeof(*blob);
|
||||
blob->cvarslength = prototype->cvarslength; //unpadded length
|
||||
blob->vertoffset = blob->cvarsoffset+cvarlen;
|
||||
blob->vertlength = vertlen;
|
||||
blob->fragoffset = blob->vertoffset+vertlen;
|
||||
blob->fraglength = fraglen;
|
||||
memcpy((char*)blob+blob->cvarsoffset, (char*)prototype+prototype->cvarsoffset, prototype->cvarslength);
|
||||
fread((char*)blob+blob->vertoffset, blob->vertlength, 1, vert);
|
||||
fread((char*)blob+blob->fragoffset, blob->fraglength, 1, frag);
|
||||
dumpprogblob(out, (unsigned char*)blob, blobsize);
|
||||
free(blob);
|
||||
}
|
||||
|
||||
|
||||
int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, char *fname)
|
||||
{
|
||||
char command[1024];
|
||||
char glslname[256];
|
||||
char tempname[256];
|
||||
int inheader = 1;
|
||||
int i;
|
||||
unsigned short constid = 256; //first few are reserved.
|
||||
|
||||
const char *permutationnames[] =
|
||||
{
|
||||
"BUMP",
|
||||
"FULLBRIGHT",
|
||||
"UPPERLOWER",
|
||||
"REFLECTCUBEMASK",
|
||||
"SKELETAL",
|
||||
"FOG",
|
||||
"FRAMEBLEND",
|
||||
"LIGHTSTYLED",
|
||||
NULL
|
||||
};
|
||||
|
||||
snprintf(glslname, sizeof(glslname), "vulkan/%s.glsl", fname);
|
||||
snprintf(tempname, sizeof(tempname), "vulkan/%s.tmp", fname);
|
||||
// snprintf(vertname, sizeof(vertname), "vulkan/%s.vert", fname);
|
||||
// snprintf(fragname, sizeof(fragname), "vulkan/%s.frag", fname);
|
||||
|
||||
memcpy(blob->blobmagic, "\xffSPV", 4);
|
||||
blob->blobversion = 1;
|
||||
blob->defaulttextures = 0;
|
||||
blob->numtextures = 0;
|
||||
blob->permutations = 0;
|
||||
blob->cvarsoffset = sizeof(*blob);
|
||||
blob->cvarslength = 0;
|
||||
|
||||
FILE *glsl = fopen(glslname, "rt");
|
||||
if (!glsl)
|
||||
return 0;
|
||||
FILE *temp = fopen(tempname, "wt");
|
||||
while(fgets(command, sizeof(command), glsl))
|
||||
{
|
||||
if (inheader && !strncmp(command, "!!", 2))
|
||||
{
|
||||
if (!strncmp(command, "!!cvar", 6) || !strncmp(command, "!!arg", 5))
|
||||
{
|
||||
unsigned int type;
|
||||
unsigned int size;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
unsigned int u;
|
||||
} u[4];
|
||||
char *arg;
|
||||
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength;
|
||||
|
||||
if (command[2] == 'a')
|
||||
{
|
||||
type = command[5] == 'i' || command[5] == 'f' || command[5] == 'b';
|
||||
size = type?1:(command[5]-'0');
|
||||
arg = strtok(command+7, " ,=\n");
|
||||
type = command[6-type] - 'a' + 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
type = command[6] == 'i' || command[6] == 'f' || command[6] == 'b';
|
||||
size = type?1:(command[6]-'0');
|
||||
arg = strtok(command+8, " ,=\n");
|
||||
type = command[7-type];
|
||||
}
|
||||
|
||||
cb[0] = (constid>>8)&0xff;
|
||||
cb[1] = (constid>>0)&0xff;
|
||||
cb[2] = type;
|
||||
cb[3] = size + '0';
|
||||
cb += 4;
|
||||
while(*arg)
|
||||
*cb++ = *arg++;
|
||||
*cb++ = 0;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
arg = strtok(NULL, " ,=\n");
|
||||
if (type == 'f' || type == 'F')
|
||||
u[i].f = atof(arg);
|
||||
else
|
||||
u[i].u = atoi(arg);
|
||||
}
|
||||
else
|
||||
u[i].u = 0;
|
||||
*cb++ = (u[i].u>>24)&0xff;
|
||||
*cb++ = (u[i].u>>16)&0xff;
|
||||
*cb++ = (u[i].u>>8)&0xff;
|
||||
*cb++ = (u[i].u>>0)&0xff;
|
||||
}
|
||||
blob->cvarslength = cb - ((unsigned char*)blob + blob->cvarsoffset);
|
||||
constid += size;
|
||||
}
|
||||
else if (!strncmp(command, "!!permu", 7))
|
||||
{
|
||||
char *arg = strtok(command+7, " ,\n");
|
||||
for (i = 0; permutationnames[i]; i++)
|
||||
{
|
||||
if (!strcmp(arg, permutationnames[i]))
|
||||
{
|
||||
blob->permutations |= 1u<<i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!permutationnames[i])
|
||||
printf("Unknown permutation: \"%s\"\n", arg);
|
||||
}
|
||||
else if (!strncmp(command, "!!samps", 7))
|
||||
{
|
||||
char *arg = strtok(command+7, " ,\n");
|
||||
do
|
||||
{
|
||||
//light
|
||||
if (!strcasecmp(arg, "shadowmap"))
|
||||
blob->defaulttextures |= 1u<<0;
|
||||
else if (!strcasecmp(arg, "projectionmap"))
|
||||
blob->defaulttextures |= 1u<<1;
|
||||
|
||||
//material
|
||||
else if (!strcasecmp(arg, "diffuse"))
|
||||
blob->defaulttextures |= 1u<<2;
|
||||
else if (!strcasecmp(arg, "normalmap"))
|
||||
blob->defaulttextures |= 1u<<3;
|
||||
else if (!strcasecmp(arg, "specular"))
|
||||
blob->defaulttextures |= 1u<<4;
|
||||
else if (!strcasecmp(arg, "upper"))
|
||||
blob->defaulttextures |= 1u<<5;
|
||||
else if (!strcasecmp(arg, "lower"))
|
||||
blob->defaulttextures |= 1u<<6;
|
||||
else if (!strcasecmp(arg, "fullbright"))
|
||||
blob->defaulttextures |= 1u<<7;
|
||||
else if (!strcasecmp(arg, "paletted"))
|
||||
blob->defaulttextures |= 1u<<8;
|
||||
else if (!strcasecmp(arg, "reflectcube"))
|
||||
blob->defaulttextures |= 1u<<9;
|
||||
else if (!strcasecmp(arg, "reflectmask"))
|
||||
blob->defaulttextures |= 1u<<10;
|
||||
|
||||
//batch
|
||||
else if (!strcasecmp(arg, "lightmap"))
|
||||
blob->defaulttextures |= 1u<<11;
|
||||
else if (!strcasecmp(arg, "deluxmap"))
|
||||
blob->defaulttextures |= 1u<<12;
|
||||
else if (!strcasecmp(arg, "lightmaps"))
|
||||
blob->defaulttextures |= 1u<<11 | 1u<<13 | 1u<<14 | 1u<<15;
|
||||
else if (!strcasecmp(arg, "deluxmaps"))
|
||||
blob->defaulttextures |= 1u<<12 | 1u<<16 | 1u<<17 | 1u<<18;
|
||||
|
||||
//shader pass
|
||||
else if (atoi(arg))
|
||||
blob->numtextures = atoi(arg);
|
||||
else
|
||||
printf("Unknown texture: \"%s\"\n", arg);
|
||||
} while((arg = strtok(NULL, " ,\n")));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (inheader && !strncmp(command, "//", 2))
|
||||
continue;
|
||||
else if (inheader)
|
||||
{
|
||||
const char *specialnames[] =
|
||||
{
|
||||
//light
|
||||
"uniform sampler2DShadow s_shadowmap;\n",
|
||||
"uniform samplerCube s_projectionmap;\n",
|
||||
|
||||
//material
|
||||
"uniform sampler2D s_diffuse;\n",
|
||||
"uniform sampler2D s_normalmap;\n",
|
||||
"uniform sampler2D s_specular;\n",
|
||||
"uniform sampler2D s_upper;\n",
|
||||
"uniform sampler2D s_lower;\n",
|
||||
"uniform sampler2D s_fullbright;\n",
|
||||
"uniform sampler2D s_paletted;\n",
|
||||
"uniform samplerCube s_reflectcube;\n",
|
||||
"uniform sampler2D s_reflectmask;\n",
|
||||
|
||||
//batch
|
||||
"uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n",
|
||||
"uniform sampler2D s_deluxmap;\n#define s_deluxmap0 s_deluxmap\n",
|
||||
"uniform sampler2D s_lightmap1;\n",
|
||||
"uniform sampler2D s_lightmap2;\n",
|
||||
"uniform sampler2D s_lightmap3;\n",
|
||||
"uniform sampler2D s_deluxmap1;\n",
|
||||
"uniform sampler2D s_deluxmap2;\n",
|
||||
"uniform sampler2D s_deluxmap3;\n"
|
||||
};
|
||||
int binding = 2;
|
||||
inheader = 0;
|
||||
fprintf(temp, "#define OFFSETMAPPING (cvar_r_glsl_offsetmapping>0)\n");
|
||||
fprintf(temp, "#define SPECULAR (cvar_gl_specular>0)\n");
|
||||
fprintf(temp, "#ifdef FRAGMENT_SHADER\n");
|
||||
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
|
||||
{
|
||||
if (blob->defaulttextures & (1u<<i))
|
||||
fprintf(temp, "layout(set=0, binding=%u) %s", binding++, specialnames[i]);
|
||||
}
|
||||
for (i = 0; i < blob->numtextures; i++)
|
||||
{
|
||||
fprintf(temp, "layout(set=0, binding=%u) uniform sampler2D s_t%u;\n", binding++, i);
|
||||
}
|
||||
fprintf(temp, "#endif\n");
|
||||
|
||||
//cvar specialisation constants
|
||||
{
|
||||
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset;
|
||||
while (cb < (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength)
|
||||
{
|
||||
union
|
||||
{
|
||||
float f;
|
||||
unsigned int u;
|
||||
} u[4];
|
||||
unsigned short id;
|
||||
unsigned char type;
|
||||
unsigned char size;
|
||||
char *name;
|
||||
id = *cb++<<8;
|
||||
id |= *cb++;
|
||||
type = *cb++;
|
||||
size = (*cb++)-'0';
|
||||
name = cb;
|
||||
cb += strlen(name)+1;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
u[i].u = (cb[0]<<24)|(cb[1]<<16)|(cb[2]<<8)|(cb[3]<<0);
|
||||
cb+=4;
|
||||
}
|
||||
#if 0 //all is well
|
||||
if (size == 1 && type == 'b')
|
||||
fprintf(temp, "layout(constant_id=%u) const bool cvar_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
|
||||
else if (size == 1 && type == 'i')
|
||||
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, (int)u[0].u);
|
||||
else if (size == 1 && type == 'f')
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %f;\n", id, name, u[0].f);
|
||||
else if (size == 3 && type == 'f')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %f;\n", id+0, name, u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %f;\n", id+1, name, u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %f;\n", id+2, name, u[2].f);
|
||||
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'B')
|
||||
fprintf(temp, "layout(constant_id=%u) const bool arg_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
|
||||
else if (size == 1 && type == 'I')
|
||||
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, (int)u[0].u);
|
||||
else if (size == 1 && type == 'F')
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, u[0].f);
|
||||
else if (size == 3 && type == 'F')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %f;\n", id+0, name, u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %f;\n", id+1, name, u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %f;\n", id+2, name, u[2].f);
|
||||
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
#else
|
||||
//these initialised values are fucked up because glslangvalidator's spirv generator is fucked up and folds specialisation constants.
|
||||
//we get around this by ensuring that all such constants are given unique values to prevent them being folded, with the engine overriding everything explicitly.
|
||||
if (size == 1 && type == 'b')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const int _cvar_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
|
||||
fprintf(temp, "#define cvar_%s (_cvar_%s!=0)\n", name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'i')
|
||||
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, id);//(int)u[0].u);
|
||||
else if (size == 1 && type == 'f')
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %i;\n", id, name, id);//u[0].f);
|
||||
else if (size == 3 && type == 'f')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
|
||||
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'B')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const int _arg_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
|
||||
fprintf(temp, "#define arg_%s (_arg_%s!=0)\n", name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'I')
|
||||
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, id);//(int)u[0].u);
|
||||
else if (size == 1 && type == 'F')
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, id);//u[0].f);
|
||||
else if (size == 3 && type == 'F')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
|
||||
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//permutation stuff
|
||||
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
|
||||
{
|
||||
if (blob->permutations & (1<<i))
|
||||
{
|
||||
#if 0 //all is well
|
||||
fprintf(temp, "layout(constant_id=%u) const bool %s = %s;\n", 16+i, permutationnames[i], "false");
|
||||
#else
|
||||
fprintf(temp, "layout(constant_id=%u) const int _%s = %i;\n", 16+i, permutationnames[i], 16+i);
|
||||
fprintf(temp, "#define %s (_%s!=0)\n", permutationnames[i], permutationnames[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
fputs(command, temp);
|
||||
}
|
||||
fclose(temp);
|
||||
fclose(glsl);
|
||||
|
||||
snprintf(command, sizeof(command),
|
||||
/*preprocess the vertex shader*/
|
||||
"echo #version 450 core > vulkan/%s.vert && "
|
||||
"cpp vulkan/%s.tmp -DVULKAN -DVERTEX_SHADER -P >> vulkan/%s.vert && "
|
||||
|
||||
/*preprocess the fragment shader*/
|
||||
"echo #version 450 core > vulkan/%s.frag && "
|
||||
"cpp vulkan/%s.tmp -DVULKAN -DFRAGMENT_SHADER -P >> vulkan/%s.frag && "
|
||||
|
||||
/*convert to spir-v (annoyingly we have no control over the output file names*/
|
||||
"glslangValidator -V -l -d vulkan/%s.vert vulkan/%s.frag"
|
||||
|
||||
/*strip stuff out, so drivers don't glitch out from stuff that we don't use*/
|
||||
" && spirv-remap -i vert.spv frag.spv -o vulkan/remap"
|
||||
|
||||
,fname, fname, fname, fname, fname, fname, fname, fname);
|
||||
|
||||
system(command);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct shadertype_s
|
||||
{
|
||||
char *abrv;
|
||||
char *filepattern;
|
||||
char *preprocessor;
|
||||
char *rendererapi;
|
||||
int apiversion;
|
||||
int apiversion; //-1 is a binary blob.
|
||||
} shadertype[] =
|
||||
{
|
||||
{"glsl/%s.glsl", "GLQUAKE", "QR_OPENGL", 110}, //gl2+
|
||||
//{"gles/%s.glsl", "GLQUAKE", "QR_OPENGL", 100}, //gles
|
||||
{"hlsl9/%s.hlsl", "D3D9QUAKE", "QR_DIRECT3D9", 9}, //d3d9
|
||||
{"hlsl11/%s.hlsl", "D3D11QUAKE", "QR_DIRECT3D11", 11}, //d3d11
|
||||
{"vulkan/remap/%s.spv", "VKQUAKE", "QR_VULKAN", -1}, //vulkan
|
||||
{"GL", "glsl/%s.glsl", "GLQUAKE", "QR_OPENGL", 110}, //gl2+
|
||||
//{"ES","gles/%s.glsl", "GLQUAKE", "QR_OPENGL", 100}, //gles
|
||||
{"VK", "vulkanblobs/%s.fvb", "VKQUAKE", "QR_VULKAN", -1}, //vulkan
|
||||
{"D9", "hlsl9/%s.hlsl", "D3D9QUAKE", "QR_DIRECT3D9", 9}, //d3d9
|
||||
{"D11","hlsl11/%s.hlsl", "D3D11QUAKE", "QR_DIRECT3D11", 11}, //d3d11
|
||||
};
|
||||
//tbh we should precompile the d3d shaders.
|
||||
|
||||
|
@ -512,49 +133,33 @@ int main(void)
|
|||
|
||||
for (i = 0; *shaders[i]; i++)
|
||||
{
|
||||
printf("%25s: ", shaders[i]);
|
||||
for (a = 0; a < sizeof(shadertype)/sizeof(shadertype[0]); a++)
|
||||
{
|
||||
sprintf(line, shadertype[a].filepattern, shaders[i]);
|
||||
if (shadertype[a].apiversion == -1)
|
||||
{
|
||||
FILE *v, *f;
|
||||
char proto[8192];
|
||||
if (!generatevulkanblobs((struct blobheader*)proto, sizeof(proto), shaders[i]))
|
||||
continue;
|
||||
sprintf(line, shadertype[a].filepattern, "vert");
|
||||
v = fopen(line, "rb");
|
||||
sprintf(line, shadertype[a].filepattern, "frag");
|
||||
f = fopen(line, "rb");
|
||||
if (f && v)
|
||||
{
|
||||
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
|
||||
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
|
||||
generateprogsblob((struct blobheader*)proto, c, v, f);
|
||||
fputs("},\n", c);
|
||||
fprintf(c, "#endif\n");
|
||||
}
|
||||
fclose(f);
|
||||
fclose(v);
|
||||
}
|
||||
s = fopen(line, "rb");
|
||||
else
|
||||
{
|
||||
sprintf(line, shadertype[a].filepattern, shaders[i]);
|
||||
s = fopen(line, "rt");
|
||||
if (!s)
|
||||
{
|
||||
printf("unable to open %s\n", line);
|
||||
continue;
|
||||
}
|
||||
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
|
||||
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
|
||||
|
||||
dumpprogstring(c, s);
|
||||
|
||||
fputs("},\n", c);
|
||||
fprintf(c, "#endif\n");
|
||||
fclose(s);
|
||||
if (!s)
|
||||
{
|
||||
printf("%4s", "");
|
||||
continue;
|
||||
}
|
||||
fprintf(c, "#ifdef %s\n", shadertype[a].preprocessor);
|
||||
fprintf(c, "{%s, %i, \"%s\",\n", shadertype[a].rendererapi, shadertype[a].apiversion, shaders[i]);
|
||||
if (shadertype[a].apiversion == -1)
|
||||
dumpprogblob(c,s);
|
||||
else
|
||||
dumpprogstring(c, s);
|
||||
fputs("},\n", c);
|
||||
fprintf(c, "#endif\n");
|
||||
fclose(s);
|
||||
fflush(c);
|
||||
|
||||
printf("%4s", shadertype[a].abrv);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
fclose(c);
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
!!samps 1
|
||||
#include "sys/defs.h"
|
||||
//
|
||||
//This shader implements super-sampled anti-aliasing.
|
||||
//
|
||||
|
@ -5,7 +7,6 @@
|
|||
varying vec2 texcoord;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
attribute vec2 v_texcoord;
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
|
@ -14,7 +15,6 @@ void main()
|
|||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
uniform sampler2D s_t0;
|
||||
uniform vec2 e_sourcesize;
|
||||
|
||||
void main( void )
|
||||
|
|
462
engine/shaders/makevulkanblob.c
Normal file
462
engine/shaders/makevulkanblob.c
Normal file
|
@ -0,0 +1,462 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
void dumpprogblob(FILE *out, unsigned char *buf, unsigned int size)
|
||||
{
|
||||
if (out)
|
||||
{
|
||||
fwrite(buf, 1, size, out);
|
||||
return;
|
||||
}
|
||||
else
|
||||
out = stdout;
|
||||
|
||||
size_t totallen, i, linelen;
|
||||
totallen = 0;
|
||||
linelen = 32;
|
||||
fflush(out);
|
||||
fprintf(out, "\"");
|
||||
for (i=0;i<size;i++)
|
||||
{
|
||||
fprintf(out, "\\x%02X",buf[i]);
|
||||
if (i % linelen == linelen - 1)
|
||||
fprintf(out, "\"\n\"");
|
||||
}
|
||||
fprintf(out, "\"");
|
||||
fflush(out);
|
||||
}
|
||||
|
||||
struct blobheader
|
||||
{
|
||||
unsigned char blobmagic[4]; //\xffSPV
|
||||
unsigned int blobversion;
|
||||
unsigned int defaulttextures; //s_diffuse etc flags
|
||||
unsigned int numtextures; //s_t0 count
|
||||
unsigned int permutations; //
|
||||
|
||||
unsigned int cvarsoffset; //double-null terminated string. I,XYZW prefixes
|
||||
unsigned int cvarslength;
|
||||
|
||||
unsigned int vertoffset;
|
||||
unsigned int vertlength;
|
||||
unsigned int fragoffset;
|
||||
unsigned int fraglength;
|
||||
};
|
||||
void generateprogsblob(struct blobheader *prototype, FILE *out, FILE *vert, FILE *frag)
|
||||
{
|
||||
struct blobheader *blob;
|
||||
int fraglen, vertlen, blobsize, cvarlen;
|
||||
cvarlen = prototype->cvarslength;
|
||||
cvarlen = (cvarlen + 3) & ~3; //round up for padding.
|
||||
fseek(vert, 0, SEEK_END);
|
||||
fseek(frag, 0, SEEK_END);
|
||||
vertlen = ftell(vert);
|
||||
fraglen = ftell(frag);
|
||||
fseek(vert, 0, SEEK_SET);
|
||||
fseek(frag, 0, SEEK_SET);
|
||||
blobsize = sizeof(*blob) + cvarlen + fraglen + vertlen;
|
||||
blob = malloc(blobsize);
|
||||
*blob = *prototype;
|
||||
blob->cvarsoffset = sizeof(*blob);
|
||||
blob->cvarslength = prototype->cvarslength; //unpadded length
|
||||
blob->vertoffset = blob->cvarsoffset+cvarlen;
|
||||
blob->vertlength = vertlen;
|
||||
blob->fragoffset = blob->vertoffset+vertlen;
|
||||
blob->fraglength = fraglen;
|
||||
memcpy((char*)blob+blob->cvarsoffset, (char*)prototype+prototype->cvarsoffset, prototype->cvarslength);
|
||||
fread((char*)blob+blob->vertoffset, blob->vertlength, 1, vert);
|
||||
fread((char*)blob+blob->fragoffset, blob->fraglength, 1, frag);
|
||||
dumpprogblob(out, (unsigned char*)blob, blobsize);
|
||||
free(blob);
|
||||
}
|
||||
|
||||
|
||||
int generatevulkanblobs(struct blobheader *blob, size_t maxblobsize, const char *glslname)
|
||||
{
|
||||
char command[1024];
|
||||
char tempname[256];
|
||||
char tempvert[256];
|
||||
char tempfrag[256];
|
||||
int inheader = 1;
|
||||
int i;
|
||||
unsigned short constid = 256; //first few are reserved.
|
||||
|
||||
const char *permutationnames[] =
|
||||
{
|
||||
"BUMP",
|
||||
"FULLBRIGHT",
|
||||
"UPPERLOWER",
|
||||
"REFLECTCUBEMASK",
|
||||
"SKELETAL",
|
||||
"FOG",
|
||||
"FRAMEBLEND",
|
||||
"LIGHTSTYLED",
|
||||
NULL
|
||||
};
|
||||
|
||||
snprintf(tempname, sizeof(tempname), "vulkan/temp.tmp");
|
||||
snprintf(tempvert, sizeof(tempvert), "vulkan/temp.vert");
|
||||
snprintf(tempfrag, sizeof(tempfrag), "vulkan/temp.frag");
|
||||
|
||||
memcpy(blob->blobmagic, "\xffSPV", 4);
|
||||
blob->blobversion = 1;
|
||||
blob->defaulttextures = 0;
|
||||
blob->numtextures = 0;
|
||||
blob->permutations = 0;
|
||||
blob->cvarsoffset = sizeof(*blob);
|
||||
blob->cvarslength = 0;
|
||||
|
||||
FILE *glsl = fopen(glslname, "rt");
|
||||
if (!glsl)
|
||||
return 0;
|
||||
FILE *temp = fopen(tempname, "wt");
|
||||
while(fgets(command, sizeof(command), glsl))
|
||||
{
|
||||
if (inheader && !strncmp(command, "!!", 2))
|
||||
{
|
||||
if (!strncmp(command, "!!cvar", 6) || !strncmp(command, "!!arg", 5))
|
||||
{
|
||||
unsigned int type;
|
||||
unsigned int size;
|
||||
union
|
||||
{
|
||||
float f;
|
||||
unsigned int u;
|
||||
} u[4];
|
||||
char *arg;
|
||||
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength;
|
||||
|
||||
if (command[2] == 'a')
|
||||
{
|
||||
type = command[5] == 'i' || command[5] == 'f' || command[5] == 'b';
|
||||
size = type?1:(command[5]-'0');
|
||||
arg = strtok(command+7, " ,=\n");
|
||||
type = command[6-type] - 'a' + 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
type = command[6] == 'i' || command[6] == 'f' || command[6] == 'b';
|
||||
size = type?1:(command[6]-'0');
|
||||
arg = strtok(command+8, " ,=\n");
|
||||
type = command[7-type];
|
||||
}
|
||||
|
||||
cb[0] = (constid>>8)&0xff;
|
||||
cb[1] = (constid>>0)&0xff;
|
||||
cb[2] = type;
|
||||
cb[3] = size + '0';
|
||||
cb += 4;
|
||||
while(*arg)
|
||||
*cb++ = *arg++;
|
||||
*cb++ = 0;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (arg)
|
||||
{
|
||||
arg = strtok(NULL, " ,=\n");
|
||||
if (type == 'f' || type == 'F')
|
||||
u[i].f = atof(arg);
|
||||
else
|
||||
u[i].u = atoi(arg);
|
||||
}
|
||||
else
|
||||
u[i].u = 0;
|
||||
*cb++ = (u[i].u>>24)&0xff;
|
||||
*cb++ = (u[i].u>>16)&0xff;
|
||||
*cb++ = (u[i].u>>8)&0xff;
|
||||
*cb++ = (u[i].u>>0)&0xff;
|
||||
}
|
||||
blob->cvarslength = cb - ((unsigned char*)blob + blob->cvarsoffset);
|
||||
constid += size;
|
||||
}
|
||||
else if (!strncmp(command, "!!permu", 7))
|
||||
{
|
||||
char *arg = strtok(command+7, " ,\n");
|
||||
for (i = 0; permutationnames[i]; i++)
|
||||
{
|
||||
if (!strcmp(arg, permutationnames[i]))
|
||||
{
|
||||
blob->permutations |= 1u<<i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!permutationnames[i])
|
||||
{
|
||||
printf("Unknown permutation: \"%s\"\n", arg);
|
||||
for (i = 0; permutationnames[i]; i++)
|
||||
printf("%s ", permutationnames[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else if (!strncmp(command, "!!samps", 7))
|
||||
{
|
||||
char *arg = strtok(command+7, " ,\n");
|
||||
do
|
||||
{
|
||||
//light
|
||||
if (!strcasecmp(arg, "shadowmap"))
|
||||
blob->defaulttextures |= 1u<<0;
|
||||
else if (!strcasecmp(arg, "projectionmap"))
|
||||
blob->defaulttextures |= 1u<<1;
|
||||
|
||||
//material
|
||||
else if (!strcasecmp(arg, "diffuse"))
|
||||
blob->defaulttextures |= 1u<<2;
|
||||
else if (!strcasecmp(arg, "normalmap"))
|
||||
blob->defaulttextures |= 1u<<3;
|
||||
else if (!strcasecmp(arg, "specular"))
|
||||
blob->defaulttextures |= 1u<<4;
|
||||
else if (!strcasecmp(arg, "upper"))
|
||||
blob->defaulttextures |= 1u<<5;
|
||||
else if (!strcasecmp(arg, "lower"))
|
||||
blob->defaulttextures |= 1u<<6;
|
||||
else if (!strcasecmp(arg, "fullbright"))
|
||||
blob->defaulttextures |= 1u<<7;
|
||||
else if (!strcasecmp(arg, "paletted"))
|
||||
blob->defaulttextures |= 1u<<8;
|
||||
else if (!strcasecmp(arg, "reflectcube"))
|
||||
blob->defaulttextures |= 1u<<9;
|
||||
else if (!strcasecmp(arg, "reflectmask"))
|
||||
blob->defaulttextures |= 1u<<10;
|
||||
|
||||
//batch
|
||||
else if (!strcasecmp(arg, "lightmap"))
|
||||
blob->defaulttextures |= 1u<<11;
|
||||
else if (!strcasecmp(arg, "deluxmap"))
|
||||
blob->defaulttextures |= 1u<<12;
|
||||
else if (!strcasecmp(arg, "lightmaps"))
|
||||
blob->defaulttextures |= 1u<<11 | 1u<<13 | 1u<<14 | 1u<<15;
|
||||
else if (!strcasecmp(arg, "deluxmaps"))
|
||||
blob->defaulttextures |= 1u<<12 | 1u<<16 | 1u<<17 | 1u<<18;
|
||||
|
||||
//shader pass
|
||||
else if (atoi(arg))
|
||||
blob->numtextures = atoi(arg);
|
||||
else
|
||||
printf("Unknown texture: \"%s\"\n", arg);
|
||||
} while((arg = strtok(NULL, " ,\n")));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (inheader && !strncmp(command, "//", 2))
|
||||
continue;
|
||||
else if (inheader)
|
||||
{
|
||||
const char *specialnames[] =
|
||||
{
|
||||
//light
|
||||
"uniform sampler2DShadow s_shadowmap;\n",
|
||||
"uniform samplerCube s_projectionmap;\n",
|
||||
|
||||
//material
|
||||
"uniform sampler2D s_diffuse;\n",
|
||||
"uniform sampler2D s_normalmap;\n",
|
||||
"uniform sampler2D s_specular;\n",
|
||||
"uniform sampler2D s_upper;\n",
|
||||
"uniform sampler2D s_lower;\n",
|
||||
"uniform sampler2D s_fullbright;\n",
|
||||
"uniform sampler2D s_paletted;\n",
|
||||
"uniform samplerCube s_reflectcube;\n",
|
||||
"uniform sampler2D s_reflectmask;\n",
|
||||
|
||||
//batch
|
||||
"uniform sampler2D s_lightmap;\n#define s_lightmap0 s_lightmap\n",
|
||||
"uniform sampler2D s_deluxmap;\n#define s_deluxmap0 s_deluxmap\n",
|
||||
"uniform sampler2D s_lightmap1;\n",
|
||||
"uniform sampler2D s_lightmap2;\n",
|
||||
"uniform sampler2D s_lightmap3;\n",
|
||||
"uniform sampler2D s_deluxmap1;\n",
|
||||
"uniform sampler2D s_deluxmap2;\n",
|
||||
"uniform sampler2D s_deluxmap3;\n"
|
||||
};
|
||||
int binding = 2;
|
||||
inheader = 0;
|
||||
fprintf(temp, "#define OFFSETMAPPING (cvar_r_glsl_offsetmapping>0)\n");
|
||||
fprintf(temp, "#define SPECULAR (cvar_gl_specular>0)\n");
|
||||
fprintf(temp, "#ifdef FRAGMENT_SHADER\n");
|
||||
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
|
||||
{
|
||||
if (blob->defaulttextures & (1u<<i))
|
||||
fprintf(temp, "layout(set=0, binding=%u) %s", binding++, specialnames[i]);
|
||||
}
|
||||
for (i = 0; i < blob->numtextures; i++)
|
||||
{
|
||||
fprintf(temp, "layout(set=0, binding=%u) uniform sampler2D s_t%u;\n", binding++, i);
|
||||
}
|
||||
fprintf(temp, "#endif\n");
|
||||
|
||||
//cvar specialisation constants
|
||||
{
|
||||
unsigned char *cb = (unsigned char*)blob + blob->cvarsoffset;
|
||||
while (cb < (unsigned char*)blob + blob->cvarsoffset + blob->cvarslength)
|
||||
{
|
||||
union
|
||||
{
|
||||
float f;
|
||||
unsigned int u;
|
||||
} u[4];
|
||||
unsigned short id;
|
||||
unsigned char type;
|
||||
unsigned char size;
|
||||
char *name;
|
||||
id = *cb++<<8;
|
||||
id |= *cb++;
|
||||
type = *cb++;
|
||||
size = (*cb++)-'0';
|
||||
name = cb;
|
||||
cb += strlen(name)+1;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
u[i].u = (cb[0]<<24)|(cb[1]<<16)|(cb[2]<<8)|(cb[3]<<0);
|
||||
cb+=4;
|
||||
}
|
||||
#if 0 //all is well
|
||||
if (size == 1 && type == 'b')
|
||||
fprintf(temp, "layout(constant_id=%u) const bool cvar_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
|
||||
else if (size == 1 && type == 'i')
|
||||
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, (int)u[0].u);
|
||||
else if (size == 1 && type == 'f')
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %f;\n", id, name, u[0].f);
|
||||
else if (size == 3 && type == 'f')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %f;\n", id+0, name, u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %f;\n", id+1, name, u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %f;\n", id+2, name, u[2].f);
|
||||
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'B')
|
||||
fprintf(temp, "layout(constant_id=%u) const bool arg_%s = %s;\n", id, name, (int)u[0].u?"true":"false");
|
||||
else if (size == 1 && type == 'I')
|
||||
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, (int)u[0].u);
|
||||
else if (size == 1 && type == 'F')
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, u[0].f);
|
||||
else if (size == 3 && type == 'F')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %f;\n", id+0, name, u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %f;\n", id+1, name, u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %f;\n", id+2, name, u[2].f);
|
||||
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
#else
|
||||
//these initialised values are fucked up because glslangvalidator's spirv generator is fucked up and folds specialisation constants.
|
||||
//we get around this by ensuring that all such constants are given unique values to prevent them being folded, with the engine overriding everything explicitly.
|
||||
if (size == 1 && type == 'b')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const int _cvar_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
|
||||
fprintf(temp, "#define cvar_%s (_cvar_%s!=0)\n", name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'i')
|
||||
fprintf(temp, "layout(constant_id=%u) const int cvar_%s = %i;\n", id, name, id);//(int)u[0].u);
|
||||
else if (size == 1 && type == 'f')
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s = %i;\n", id, name, id);//u[0].f);
|
||||
else if (size == 3 && type == 'f')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float cvar_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
|
||||
fprintf(temp, "vec3 cvar_%s = vec3(cvar_%s_x, cvar_%s_y, cvar_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'B')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const int _arg_%s = %i;\n", id, name, id);//(int)u[0].u?"true":"false");
|
||||
fprintf(temp, "#define arg_%s (_arg_%s!=0)\n", name, name);
|
||||
}
|
||||
else if (size == 1 && type == 'I')
|
||||
fprintf(temp, "layout(constant_id=%u) const int arg_%s = %i;\n", id, name, id);//(int)u[0].u);
|
||||
else if (size == 1 && type == 'F')
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s = %i;\n", id, name, id);//u[0].f);
|
||||
else if (size == 3 && type == 'F')
|
||||
{
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_x = %i;\n", id+0, name, id+0);//u[0].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_y = %i;\n", id+1, name, id+1);//u[1].f);
|
||||
fprintf(temp, "layout(constant_id=%u) const float arg_%s_z = %i;\n", id+2, name, id+2);//u[2].f);
|
||||
fprintf(temp, "vec3 arg_%s = vec3(arg_%s_x, arg_%s_y, arg_%s_z);\n", name, name, name, name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//permutation stuff
|
||||
for (i = 0; i < sizeof(specialnames)/sizeof(specialnames[0]); i++)
|
||||
{
|
||||
if (blob->permutations & (1<<i))
|
||||
{
|
||||
#if 0 //all is well
|
||||
fprintf(temp, "layout(constant_id=%u) const bool %s = %s;\n", 16+i, permutationnames[i], "false");
|
||||
#else
|
||||
fprintf(temp, "layout(constant_id=%u) const int _%s = %i;\n", 16+i, permutationnames[i], 16+i);
|
||||
fprintf(temp, "#define %s (_%s!=0)\n", permutationnames[i], permutationnames[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
fputs(command, temp);
|
||||
}
|
||||
fclose(temp);
|
||||
fclose(glsl);
|
||||
|
||||
snprintf(command, sizeof(command),
|
||||
/*preprocess the vertex shader*/
|
||||
"echo #version 450 core > %s && "
|
||||
"cpp %s -DVULKAN -DVERTEX_SHADER -P >> %s && "
|
||||
|
||||
/*preprocess the fragment shader*/
|
||||
"echo #version 450 core > %s && "
|
||||
"cpp %s -DVULKAN -DFRAGMENT_SHADER -P >> %s && "
|
||||
|
||||
/*convert to spir-v (annoyingly we have no control over the output file names*/
|
||||
"glslangValidator -V -l -d %s %s"
|
||||
|
||||
/*strip stuff out, so drivers don't glitch out from stuff that we don't use*/
|
||||
" && spirv-remap -i vert.spv frag.spv -o vulkan/remap"
|
||||
|
||||
,tempvert, tempname, tempvert, tempfrag, tempname, tempfrag, tempvert, tempfrag);
|
||||
|
||||
system(command);
|
||||
|
||||
unlink(tempname);
|
||||
unlink(tempvert);
|
||||
unlink(tempfrag);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
const char *inname = argv[1];
|
||||
const char *blobname = argv[2];
|
||||
FILE *v, *f, *o;
|
||||
char proto[8192];
|
||||
char line[256];
|
||||
int r = 1;
|
||||
|
||||
if (!generatevulkanblobs((struct blobheader*)proto, sizeof(proto), inname))
|
||||
return 1;
|
||||
//should have generated two files
|
||||
v = fopen("vert.spv", "rb");
|
||||
f = fopen("frag.spv", "rb");
|
||||
if (f && v)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
generateprogsblob((struct blobheader*)proto, NULL, v, f);
|
||||
r = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
o = fopen(blobname, "wb");
|
||||
if (o)
|
||||
{
|
||||
generateprogsblob((struct blobheader*)proto, o, v, f);
|
||||
fclose(o);
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
fclose(v);
|
||||
unlink("vert.spv");
|
||||
unlink("frag.spv");
|
||||
|
||||
return r;
|
||||
}
|
|
@ -92,7 +92,7 @@ void main ()
|
|||
|
||||
vec3 lightmaps;
|
||||
if (arg_vertexlit)
|
||||
lightmaps = vc.rgb * e_lmscale[0].rgb;
|
||||
lightmaps = vc.rgb * e_lmscale.rgb;
|
||||
else
|
||||
{
|
||||
//modulate that by the lightmap(s) including deluxemap(s)
|
||||
|
@ -118,10 +118,10 @@ void main ()
|
|||
//don't bother if its lightstyled, such cases will have unpredictable correlations anyway.
|
||||
//FIXME: this rounding is likely not correct with respect to software rendering. oh well.
|
||||
vec2 nearestlm0 = floor(lm0 * 256.0*8.0)/(256.0*8.0);
|
||||
lightmaps = (texture2D(s_lightmap, nearestlm0) * e_lmscale[0]).rgb;
|
||||
lightmaps = (texture2D(s_lightmap, nearestlm0) * e_lmscale).rgb;
|
||||
}
|
||||
else
|
||||
lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale[0]).rgb;
|
||||
lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb;
|
||||
//modulate by the bumpmap dot light
|
||||
if (DELUXE)
|
||||
{
|
||||
|
|
66
engine/shaders/vulkan/fxaa.glsl
Normal file
66
engine/shaders/vulkan/fxaa.glsl
Normal file
|
@ -0,0 +1,66 @@
|
|||
!!samps 1
|
||||
#include "sys/defs.h"
|
||||
//
|
||||
//This shader implements super-sampled anti-aliasing.
|
||||
//
|
||||
|
||||
varying vec2 texcoord;
|
||||
varying vec2 e_sourcesize;
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
texcoord.y = 1.0 - texcoord.y;
|
||||
e_sourcesize = v_colour.rg;
|
||||
gl_Position = ftetransform();
|
||||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
//uniform vec2 e_sourcesize;
|
||||
|
||||
void main( void )
|
||||
{
|
||||
float FXAA_SPAN_MAX = 8.0;
|
||||
float FXAA_REDUCE_MUL = 1.0/8.0;
|
||||
float FXAA_REDUCE_MIN = 1.0/128.0;
|
||||
|
||||
vec3 rgbNW=texture2D(s_t0,texcoord+(vec2(-1.0,-1.0)/e_sourcesize)).xyz;
|
||||
vec3 rgbNE=texture2D(s_t0,texcoord+(vec2(1.0,-1.0)/e_sourcesize)).xyz;
|
||||
vec3 rgbSW=texture2D(s_t0,texcoord+(vec2(-1.0,1.0)/e_sourcesize)).xyz;
|
||||
vec3 rgbSE=texture2D(s_t0,texcoord+(vec2(1.0,1.0)/e_sourcesize)).xyz;
|
||||
vec3 rgbM=texture2D(s_t0,texcoord).xyz;
|
||||
|
||||
vec3 luma=vec3(0.299, 0.587, 0.114);
|
||||
float lumaNW = dot(rgbNW, luma);
|
||||
float lumaNE = dot(rgbNE, luma);
|
||||
float lumaSW = dot(rgbSW, luma);
|
||||
float lumaSE = dot(rgbSE, luma);
|
||||
float lumaM = dot(rgbM, luma);
|
||||
|
||||
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||
|
||||
vec2 dir;
|
||||
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||
|
||||
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||
|
||||
float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||
|
||||
dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||
dir * rcpDirMin)) / e_sourcesize;
|
||||
|
||||
vec3 rgbA = (1.0/2.0) * (texture2D(s_t0, texcoord.xy + dir * (1.0/3.0 - 0.5)).xyz + texture2D(s_t0, texcoord.xy + dir * (2.0/3.0 - 0.5)).xyz);
|
||||
vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (texture2D(s_t0, texcoord.xy + dir * (0.0/3.0 - 0.5)).xyz + texture2D(s_t0, texcoord.xy + dir * (3.0/3.0 - 0.5)).xyz);
|
||||
float lumaB = dot(rgbB, luma);
|
||||
|
||||
if((lumaB < lumaMin) || (lumaB > lumaMax))
|
||||
gl_FragColor.xyz=rgbA;
|
||||
else
|
||||
gl_FragColor.xyz=rgbB;
|
||||
gl_FragColor.a = 1.0;
|
||||
}
|
||||
#endif
|
32
engine/shaders/vulkan/postproc_fisheye.glsl
Normal file
32
engine/shaders/vulkan/postproc_fisheye.glsl
Normal file
|
@ -0,0 +1,32 @@
|
|||
!!cvarf ffov
|
||||
!!samps reflectcube
|
||||
#include "sys/defs.h"
|
||||
|
||||
|
||||
//fisheye view rendering, for silly fovs that are still playable.
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
gl_Position = ftetransform();
|
||||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 texcoord;
|
||||
//uniform float cvar_ffov;
|
||||
void main()
|
||||
{
|
||||
vec3 tc;
|
||||
vec2 d;
|
||||
vec2 ang;
|
||||
d = texcoord;
|
||||
ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov);
|
||||
ang.y = -atan(d.y, d.x);
|
||||
tc.x = sin(ang.x) * cos(ang.y);
|
||||
tc.y = sin(ang.x) * sin(ang.y);
|
||||
tc.z = cos(ang.x);
|
||||
gl_FragColor = textureCube(s_reflectcube, tc);
|
||||
}
|
||||
#endif
|
27
engine/shaders/vulkan/postproc_panorama.glsl
Normal file
27
engine/shaders/vulkan/postproc_panorama.glsl
Normal file
|
@ -0,0 +1,27 @@
|
|||
!!cvarf ffov
|
||||
!!samps reflectcube
|
||||
#include "sys/defs.h"
|
||||
|
||||
//panoramic view rendering, for promo map shots or whatever.
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
gl_Position = ftetransform();
|
||||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
vec3 tc;
|
||||
float ang;
|
||||
ang = texcoord.x*radians(cvar_ffov);
|
||||
tc.x = sin(ang);
|
||||
tc.y = -texcoord.y;
|
||||
tc.z = cos(ang);
|
||||
gl_FragColor = textureCube(s_reflectcube, tc);
|
||||
}
|
||||
#endif
|
37
engine/shaders/vulkan/postproc_stereographic.glsl
Normal file
37
engine/shaders/vulkan/postproc_stereographic.glsl
Normal file
|
@ -0,0 +1,37 @@
|
|||
!!cvarf ffov
|
||||
!!samps reflectcube
|
||||
#include "sys/defs.h"
|
||||
|
||||
//stereographic view rendering, for high fovs that are still playable.
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
varying vec2 texcoord;
|
||||
//uniform float cvar_ffov;
|
||||
void main()
|
||||
{
|
||||
texcoord = v_texcoord.xy;
|
||||
|
||||
//make sure the ffov cvar actually does something meaningful
|
||||
texcoord *= cvar_ffov / 90.0;
|
||||
|
||||
gl_Position = ftetransform();
|
||||
}
|
||||
#endif
|
||||
#ifdef FRAGMENT_SHADER
|
||||
varying vec2 texcoord;
|
||||
void main()
|
||||
{
|
||||
vec3 tc;
|
||||
vec2 d;
|
||||
vec2 ang;
|
||||
d = texcoord;
|
||||
|
||||
//compute the 2d->3d projection
|
||||
float div = 1.0 + d.x*d.x + d.y*d.y;
|
||||
tc.x = 2.0*d.x/div;
|
||||
tc.y = -2.0*d.y/div;
|
||||
tc.z = -(-1.0 + d.x*d.x + d.y*d.y)/div;
|
||||
|
||||
gl_FragColor = textureCube(s_reflectcube, tc);
|
||||
}
|
||||
#endif
|
|
@ -21,13 +21,15 @@ layout(std140, binding=0) uniform entityblock
|
|||
vec3 e_light_ambient; float epad1;
|
||||
vec3 e_light_dir; float epad2;
|
||||
vec3 e_light_mul; float epad3;
|
||||
vec4 e_lmscale[4];
|
||||
vec4 e_lmscales[4];
|
||||
vec3 e_uppercolour; float epad4;
|
||||
vec3 e_lowercolour; float epad5;
|
||||
vec3 e_glowmod; float epad6;
|
||||
vec4 e_colourident;
|
||||
vec4 w_fogcolours;
|
||||
float w_fogdensity; float w_fogdepthbias; vec2 epad6;
|
||||
float w_fogdensity; float w_fogdepthbias; vec2 epad7;
|
||||
};
|
||||
#define e_lmscale (e_lmscales[0])
|
||||
|
||||
layout(std140, binding=1) uniform lightblock
|
||||
{
|
||||
|
|
|
@ -174,9 +174,10 @@ typedef struct
|
|||
vec4_t e_lmscale[4];
|
||||
vec3_t e_uppercolour; float pad4;
|
||||
vec3_t e_lowercolour; float pad5;
|
||||
vec3_t e_glowmod; float pad6;
|
||||
vec4_t e_colourident;
|
||||
vec4_t w_fogcolours;
|
||||
float w_fogdensity; float w_fogdepthbias; vec2_t pad6;
|
||||
float w_fogdensity; float w_fogdepthbias; vec2_t pad7;
|
||||
} cbuf_entity_t;
|
||||
|
||||
enum
|
||||
|
@ -1029,6 +1030,10 @@ qboolean VK_LoadGLSL(program_t *prog, const char *name, unsigned int permu, int
|
|||
if (permu) //FIXME...
|
||||
return false;
|
||||
|
||||
prog->nofixedcompat = false;
|
||||
// prog->supportedpermutations = 0;
|
||||
prog->cvardata = NULL;
|
||||
prog->cvardatasize = 0;
|
||||
prog->pipelines = NULL;
|
||||
prog->vert = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, vert, false);
|
||||
prog->frag = VK_CreateGLSLModule(prog, name, ver, precompilerconstants, frag, true);
|
||||
|
@ -1310,7 +1315,7 @@ void VKBE_Init(void)
|
|||
}
|
||||
}
|
||||
else
|
||||
vk_usedynamicstaging = ~0u;
|
||||
vk_usedynamicstaging = 0u;
|
||||
}
|
||||
|
||||
static struct descpool *VKBE_CreateDescriptorPool(void)
|
||||
|
@ -4245,36 +4250,20 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
|
|||
VectorScale((m+8), mod->clampscale, (m+8));
|
||||
}
|
||||
|
||||
memcpy(cbe->m_model, m, sizeof(cbe->m_model));
|
||||
|
||||
Matrix4_Invert(modelmatrix, cbe->m_modelinv);
|
||||
|
||||
{
|
||||
float modelview[16];
|
||||
Matrix4_Multiply(r_refdef.m_view, m, modelview);
|
||||
Matrix4_Multiply(r_refdef.m_projection, modelview, cbe->m_modelviewproj);
|
||||
}
|
||||
memcpy(cbe->m_model, m, sizeof(cbe->m_model));
|
||||
Matrix4_Invert(modelmatrix, cbe->m_modelinv);
|
||||
Matrix4x4_CM_Transform3(cbe->m_modelinv, r_origin, cbe->e_eyepos);
|
||||
|
||||
cbe->e_time = shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime;
|
||||
|
||||
VectorCopy(e->light_avg, cbe->e_light_ambient);
|
||||
VectorCopy(e->light_dir, cbe->e_light_dir);
|
||||
VectorCopy(e->light_range, cbe->e_light_mul);
|
||||
|
||||
R_FetchPlayerColour(e->topcolour, cbe->e_uppercolour);
|
||||
R_FetchPlayerColour(e->bottomcolour, cbe->e_lowercolour);
|
||||
if (shaderstate.flags & BEF_FORCECOLOURMOD)
|
||||
Vector4Copy(e->shaderRGBAf, cbe->e_colourident);
|
||||
else
|
||||
Vector4Set(cbe->e_colourident, 1, 1, 1, e->shaderRGBAf[3]);
|
||||
|
||||
VectorCopy(r_refdef.globalfog.colour, cbe->w_fogcolours);
|
||||
cbe->w_fogcolours[3] = r_refdef.globalfog.alpha;
|
||||
cbe->w_fogdensity = r_refdef.globalfog.density;
|
||||
cbe->w_fogdepthbias = r_refdef.globalfog.depthbias;
|
||||
|
||||
//various stuff in modelspace
|
||||
Matrix4x4_CM_Transform3(cbe->m_modelinv, r_origin, cbe->e_eyepos);
|
||||
VectorCopy(e->light_avg, cbe->e_light_ambient); cbe->pad1 = 0;
|
||||
VectorCopy(e->light_dir, cbe->e_light_dir); cbe->pad2 = 0;
|
||||
VectorCopy(e->light_range, cbe->e_light_mul); cbe->pad3 = 0;
|
||||
|
||||
for (i = 0; i < MAXRLIGHTMAPS ; i++)
|
||||
{
|
||||
|
@ -4312,6 +4301,21 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
|
|||
Vector4Set(cbe->e_lmscale[i], sc, sc, sc, 1);
|
||||
}
|
||||
|
||||
R_FetchPlayerColour(e->topcolour, cbe->e_uppercolour); cbe->pad4 = 0;
|
||||
R_FetchPlayerColour(e->bottomcolour, cbe->e_lowercolour); cbe->pad5 = 0;
|
||||
VectorCopy(e->glowmod, cbe->e_glowmod); cbe->pad6 = 0;
|
||||
if (shaderstate.flags & BEF_FORCECOLOURMOD)
|
||||
Vector4Copy(e->shaderRGBAf, cbe->e_colourident);
|
||||
else
|
||||
Vector4Set(cbe->e_colourident, 1, 1, 1, e->shaderRGBAf[3]);
|
||||
|
||||
VectorCopy(r_refdef.globalfog.colour, cbe->w_fogcolours);
|
||||
cbe->w_fogcolours[3] = r_refdef.globalfog.alpha;
|
||||
|
||||
cbe->w_fogdensity = r_refdef.globalfog.density;
|
||||
cbe->w_fogdepthbias = r_refdef.globalfog.depthbias;
|
||||
Vector2Set(cbe->pad7, 0, 0);
|
||||
|
||||
ndr = (e->flags & RF_DEPTHHACK)?0.333:1;
|
||||
if (ndr != shaderstate.depthrange)
|
||||
{
|
||||
|
@ -4400,6 +4404,7 @@ void VKBE_RT_Destroy(struct vk_rendertarg *targ)
|
|||
memset(targ, 0, sizeof(*targ));
|
||||
}
|
||||
|
||||
|
||||
struct vkbe_rtpurge
|
||||
{
|
||||
struct vk_fencework fw;
|
||||
|
@ -4414,15 +4419,24 @@ static void VKBE_RT_Purge(void *ptr)
|
|||
VK_DestroyVkTexture(&ctx->depth);
|
||||
VK_DestroyVkTexture(&ctx->colour);
|
||||
}
|
||||
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
|
||||
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear)
|
||||
{
|
||||
//sooooo much work...
|
||||
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkImageCreateInfo depth_imginfo;
|
||||
struct vkbe_rtpurge *purge;
|
||||
static VkClearValue clearvalues[2];
|
||||
|
||||
if (clear)
|
||||
targ->restartinfo.renderPass = vk.renderpass[2];
|
||||
else
|
||||
targ->restartinfo.renderPass = vk.renderpass[1]; //don't care
|
||||
targ->restartinfo.clearValueCount = 2;
|
||||
targ->depthcleared = true; //will be once its activated.
|
||||
|
||||
if (targ->width == width && targ->height == height)
|
||||
return; //no work to do.
|
||||
|
||||
if (targ->framebuffer)
|
||||
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
|
||||
purge = VK_AtFrameEnd(VKBE_RT_Purge, sizeof(*purge));
|
||||
|
@ -4436,15 +4450,22 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
|
|||
|
||||
targ->q_colour.vkimage = &targ->colour;
|
||||
targ->q_depth.vkimage = &targ->depth;
|
||||
targ->q_colour.status = TEX_LOADED;
|
||||
targ->q_colour.width = width;
|
||||
targ->q_colour.height = height;
|
||||
|
||||
targ->width = width;
|
||||
targ->height = height;
|
||||
|
||||
if (width == 0 && height == 0)
|
||||
return; //destroyed
|
||||
|
||||
colour_imginfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
colour_imginfo.flags = 0;
|
||||
colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
colour_imginfo.extent.width = width;
|
||||
colour_imginfo.extent.height = height;
|
||||
colour_imginfo.extent.depth = 1;
|
||||
colour_imginfo.mipLevels = 1;
|
||||
colour_imginfo.arrayLayers = 1;
|
||||
colour_imginfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
@ -4547,69 +4568,265 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
|
|||
fbinfo.layers = 1;
|
||||
VkAssert(vkCreateFramebuffer(vk.device, &fbinfo, vkallocationcb, &targ->framebuffer));
|
||||
}
|
||||
|
||||
targ->restartinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
targ->restartinfo.pNext = NULL;
|
||||
targ->restartinfo.framebuffer = targ->framebuffer;
|
||||
targ->restartinfo.renderArea.offset.x = 0;
|
||||
targ->restartinfo.renderArea.offset.y = 0;
|
||||
targ->restartinfo.renderArea.extent.width = width;
|
||||
targ->restartinfo.renderArea.extent.height = height;
|
||||
targ->restartinfo.pClearValues = clearvalues;
|
||||
clearvalues[1].depthStencil.depth = 1;
|
||||
}
|
||||
|
||||
void VKBE_RT_Begin(struct vk_rendertarg *targ, uint32_t width, uint32_t height)
|
||||
struct vkbe_rtpurge_cube
|
||||
{
|
||||
vkCmdEndRenderPass(vk.frame->cbuf);
|
||||
struct vk_fencework fw;
|
||||
vk_image_t colour;
|
||||
vk_image_t depth;
|
||||
struct
|
||||
{
|
||||
VkFramebuffer framebuffer;
|
||||
VkImageView iv[2];
|
||||
} face[6];
|
||||
};
|
||||
static void VKBE_RT_Purge_Cube(void *ptr)
|
||||
{
|
||||
uint32_t f;
|
||||
struct vkbe_rtpurge_cube *ctx = ptr;
|
||||
for (f = 0; f < 6; f++)
|
||||
{
|
||||
vkDestroyFramebuffer(vk.device, ctx->face[f].framebuffer, vkallocationcb);
|
||||
vkDestroyImageView(vk.device, ctx->face[f].iv[0], vkallocationcb);
|
||||
vkDestroyImageView(vk.device, ctx->face[f].iv[1], vkallocationcb);
|
||||
}
|
||||
VK_DestroyVkTexture(&ctx->depth);
|
||||
VK_DestroyVkTexture(&ctx->colour);
|
||||
}
|
||||
//generate a cubemap-compatible 2d array, set up 6 render targets that render to their own views
|
||||
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear)
|
||||
{
|
||||
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
VkImageCreateInfo depth_imginfo;
|
||||
struct vkbe_rtpurge_cube *purge;
|
||||
uint32_t f;
|
||||
static VkClearValue clearvalues[2];
|
||||
|
||||
if (width != targ->width || height != targ->height)
|
||||
VKBE_RT_Gen(targ, width, height);
|
||||
for (f = 0; f < 6; f++)
|
||||
{
|
||||
if (clear)
|
||||
targ->face[f].restartinfo.renderPass = vk.renderpass[2];
|
||||
else
|
||||
targ->face[f].restartinfo.renderPass = vk.renderpass[1]; //don't care
|
||||
targ->face[f].restartinfo.clearValueCount = 2;
|
||||
}
|
||||
|
||||
if (targ->size == size)
|
||||
return; //no work to do.
|
||||
|
||||
if (targ->size)
|
||||
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
|
||||
purge = VK_AtFrameEnd(VKBE_RT_Purge_Cube, sizeof(*purge));
|
||||
for (f = 0; f < 6; f++)
|
||||
{
|
||||
purge->face[f].framebuffer = targ->face[f].framebuffer;
|
||||
targ->face[f].framebuffer = VK_NULL_HANDLE;
|
||||
purge->face[f].iv[0] = targ->face[f].colour.view;
|
||||
purge->face[f].iv[1] = targ->face[f].depth.view;
|
||||
targ->face[f].colour.view = VK_NULL_HANDLE;
|
||||
targ->face[f].depth.view = VK_NULL_HANDLE;
|
||||
}
|
||||
purge->colour = targ->colour;
|
||||
purge->depth = targ->depth;
|
||||
memset(&targ->colour, 0, sizeof(targ->colour));
|
||||
memset(&targ->depth, 0, sizeof(targ->depth));
|
||||
}
|
||||
|
||||
targ->size = size;
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
targ->q_colour.vkimage = &targ->colour;
|
||||
targ->q_depth.vkimage = &targ->depth;
|
||||
|
||||
colour_imginfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
colour_imginfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||
colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
colour_imginfo.extent.width = size;
|
||||
colour_imginfo.extent.height = size;
|
||||
colour_imginfo.mipLevels = 1;
|
||||
colour_imginfo.arrayLayers = 6;
|
||||
colour_imginfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
colour_imginfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
colour_imginfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
colour_imginfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
colour_imginfo.queueFamilyIndexCount = 0;
|
||||
colour_imginfo.pQueueFamilyIndices = NULL;
|
||||
colour_imginfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkAssert(vkCreateImage(vk.device, &colour_imginfo, vkallocationcb, &targ->colour.image));
|
||||
|
||||
depth_imginfo = colour_imginfo;
|
||||
depth_imginfo.format = vk.depthformat;
|
||||
depth_imginfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
VkAssert(vkCreateImage(vk.device, &depth_imginfo, vkallocationcb, &targ->depth.image));
|
||||
|
||||
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetImageMemoryRequirements(vk.device, targ->colour.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->colour.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, targ->colour.image, targ->colour.memory, 0));
|
||||
}
|
||||
|
||||
{
|
||||
VkMemoryRequirements mem_reqs;
|
||||
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
|
||||
vkGetImageMemoryRequirements(vk.device, targ->depth.image, &mem_reqs);
|
||||
memAllocInfo.allocationSize = mem_reqs.size;
|
||||
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0);
|
||||
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &targ->depth.memory));
|
||||
VkAssert(vkBindImageMemory(vk.device, targ->depth.image, targ->depth.memory, 0));
|
||||
}
|
||||
|
||||
// set_image_layout(vk.frame->cbuf, targ->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
// set_image_layout(vk.frame->cbuf, targ->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
|
||||
//public sampler
|
||||
{
|
||||
VkSamplerCreateInfo lmsampinfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
|
||||
lmsampinfo.minFilter = lmsampinfo.magFilter = VK_FILTER_LINEAR;
|
||||
lmsampinfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
lmsampinfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
lmsampinfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
lmsampinfo.mipLodBias = 0.0;
|
||||
lmsampinfo.anisotropyEnable = VK_FALSE;
|
||||
lmsampinfo.maxAnisotropy = 0;
|
||||
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||
lmsampinfo.minLod = 0;
|
||||
lmsampinfo.maxLod = 0;
|
||||
lmsampinfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
lmsampinfo.unnormalizedCoordinates = VK_FALSE;
|
||||
|
||||
lmsampinfo.compareEnable = VK_FALSE;
|
||||
VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->colour.sampler));
|
||||
|
||||
lmsampinfo.compareEnable = VK_TRUE;
|
||||
VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->depth.sampler));
|
||||
}
|
||||
|
||||
//public cubemap views
|
||||
{
|
||||
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
ivci.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
ivci.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
ivci.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
ivci.subresourceRange.baseMipLevel = 0;
|
||||
ivci.subresourceRange.levelCount = 1;
|
||||
ivci.subresourceRange.baseArrayLayer = 0;
|
||||
ivci.subresourceRange.layerCount = 6;
|
||||
ivci.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
ivci.flags = 0;
|
||||
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ivci.format = colour_imginfo.format;
|
||||
ivci.image = targ->colour.image;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->colour.view));
|
||||
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
ivci.format = depth_imginfo.format;
|
||||
ivci.image = targ->depth.image;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->depth.view));
|
||||
}
|
||||
|
||||
for (f = 0; f < 6; f++)
|
||||
{
|
||||
targ->face[f].width = targ->face[f].height = size;
|
||||
|
||||
//per-face view for the framebuffer
|
||||
{
|
||||
VkImageViewCreateInfo ivci = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};
|
||||
ivci.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||
ivci.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||
ivci.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||
ivci.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
ivci.subresourceRange.baseMipLevel = 0;
|
||||
ivci.subresourceRange.levelCount = 1;
|
||||
ivci.subresourceRange.baseArrayLayer = f;
|
||||
ivci.subresourceRange.layerCount = 1;
|
||||
ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
ivci.flags = 0;
|
||||
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
ivci.format = colour_imginfo.format;
|
||||
ivci.image = targ->colour.image;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->face[f].colour.view));
|
||||
|
||||
ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
ivci.format = depth_imginfo.format;
|
||||
ivci.image = targ->depth.image;
|
||||
VkAssert(vkCreateImageView(vk.device, &ivci, vkallocationcb, &targ->face[f].depth.view));
|
||||
}
|
||||
|
||||
targ->colour.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
targ->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
|
||||
|
||||
{
|
||||
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
|
||||
VkImageView attachments[2] = {targ->face[f].colour.view, targ->face[f].depth.view};
|
||||
fbinfo.flags = 0;
|
||||
fbinfo.renderPass = vk.renderpass[2];
|
||||
fbinfo.attachmentCount = countof(attachments);
|
||||
fbinfo.pAttachments = attachments;
|
||||
fbinfo.width = size;
|
||||
fbinfo.height = size;
|
||||
fbinfo.layers = 1;
|
||||
VkAssert(vkCreateFramebuffer(vk.device, &fbinfo, vkallocationcb, &targ->face[f].framebuffer));
|
||||
}
|
||||
|
||||
targ->face[f].restartinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
targ->face[f].restartinfo.pNext = NULL;
|
||||
targ->face[f].restartinfo.framebuffer = targ->face[f].framebuffer;
|
||||
targ->face[f].restartinfo.renderArea.offset.x = 0;
|
||||
targ->face[f].restartinfo.renderArea.offset.y = 0;
|
||||
targ->face[f].restartinfo.renderArea.extent.width = size;
|
||||
targ->face[f].restartinfo.renderArea.extent.height = size;
|
||||
targ->face[f].restartinfo.pClearValues = clearvalues;
|
||||
}
|
||||
clearvalues[1].depthStencil.depth = 1;
|
||||
}
|
||||
|
||||
void VKBE_RT_Begin(struct vk_rendertarg *targ)
|
||||
{
|
||||
if (vk.rendertarg == targ)
|
||||
return;
|
||||
|
||||
if (vk.rendertarg)
|
||||
vkCmdEndRenderPass(vk.frame->cbuf);
|
||||
|
||||
r_refdef.pxrect.x = 0;
|
||||
r_refdef.pxrect.y = 0;
|
||||
r_refdef.pxrect.width = targ->width;
|
||||
r_refdef.pxrect.height = targ->height;
|
||||
r_refdef.pxrect.maxheight = targ->height;
|
||||
|
||||
vid.fbpwidth = targ->width;
|
||||
vid.fbpheight = targ->height;
|
||||
|
||||
vkCmdBeginRenderPass(vk.frame->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
//future reuse shouldn't clear stuff
|
||||
if (targ->restartinfo.clearValueCount)
|
||||
{
|
||||
VkClearValue clearvalues[2];
|
||||
VkRenderPassBeginInfo rpass = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
|
||||
rpass.renderPass = vk.renderpass[2];
|
||||
rpass.framebuffer = targ->framebuffer;
|
||||
rpass.renderArea.offset.x = 0;
|
||||
rpass.renderArea.offset.y = 0;
|
||||
rpass.renderArea.extent.width = targ->width;
|
||||
rpass.renderArea.extent.height = targ->height;
|
||||
rpass.clearValueCount = 2;
|
||||
rpass.pClearValues = clearvalues;
|
||||
|
||||
Vector4Set(clearvalues[0].color.float32, 0, 0, 0, 0);
|
||||
clearvalues[1].depthStencil.depth = 1;
|
||||
clearvalues[1].depthStencil.stencil = 0;
|
||||
vkCmdBeginRenderPass(vk.frame->cbuf, &rpass, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
rpass.renderPass = vk.renderpass[0];
|
||||
rpass.pClearValues = NULL;
|
||||
rpass.clearValueCount = 0;
|
||||
targ->restartinfo = rpass;
|
||||
targ->prev = vk.rendertarg;
|
||||
vk.rendertarg = targ;
|
||||
targ->depthcleared = true;
|
||||
targ->restartinfo.renderPass = vk.renderpass[0];
|
||||
targ->restartinfo.clearValueCount = 0;
|
||||
}
|
||||
|
||||
{
|
||||
VkRect2D wrekt;
|
||||
VkViewport viewport;
|
||||
viewport.x = r_refdef.pxrect.x;
|
||||
viewport.y = r_refdef.pxrect.y;
|
||||
viewport.width = r_refdef.pxrect.width;
|
||||
viewport.height = r_refdef.pxrect.height;
|
||||
viewport.minDepth = 0;
|
||||
viewport.maxDepth = shaderstate.depthrange;
|
||||
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport);
|
||||
wrekt.offset.x = viewport.x;
|
||||
wrekt.offset.y = viewport.y;
|
||||
wrekt.extent.width = viewport.width;
|
||||
wrekt.extent.height = viewport.height;
|
||||
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt);
|
||||
}
|
||||
}
|
||||
void VKBE_RT_End(void)
|
||||
{
|
||||
vkCmdEndRenderPass(vk.frame->cbuf);
|
||||
|
||||
vk.rendertarg = vk.rendertarg->prev;
|
||||
|
||||
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vk.rendertarg = targ;
|
||||
|
||||
{
|
||||
VkRect2D wrekt;
|
||||
|
@ -4633,6 +4850,7 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
|||
{
|
||||
float oldil;
|
||||
int oldbem;
|
||||
struct vk_rendertarg *targ;
|
||||
//these flags require rendering some view as an fbo
|
||||
if (r_refdef.recurse)
|
||||
return false;
|
||||
|
@ -4640,9 +4858,11 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
|||
return false;
|
||||
oldbem = shaderstate.mode;
|
||||
oldil = shaderstate.identitylighting;
|
||||
targ = vk.rendertarg;
|
||||
|
||||
if (bs->flags & SHADER_HASREFLECT)
|
||||
{
|
||||
struct vk_rendertarg *targ = vk.rendertarg;
|
||||
vrect_t orect = r_refdef.vrect;
|
||||
pxrect_t oprect = r_refdef.pxrect;
|
||||
|
||||
|
@ -4650,11 +4870,11 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
|||
r_refdef.vrect.y = 0;
|
||||
r_refdef.vrect.width = vid.fbvwidth/2;
|
||||
r_refdef.vrect.height = vid.fbvheight/2;
|
||||
VKBE_RT_Begin(&shaderstate.rt_reflection, vid.fbpwidth/2, vid.fbpheight/2);
|
||||
VKBE_RT_Gen(&shaderstate.rt_reflection, vid.fbpwidth/2, vid.fbpheight/2, false);
|
||||
VKBE_RT_Begin(&shaderstate.rt_reflection);
|
||||
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
|
||||
r_refdef.vrect = orect;
|
||||
r_refdef.pxrect = oprect;
|
||||
VKBE_RT_End();
|
||||
}
|
||||
if (bs->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH))
|
||||
{
|
||||
|
@ -4668,16 +4888,18 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
|||
r_refdef.vrect.y = 0;
|
||||
r_refdef.vrect.width = vid.fbvwidth/2;
|
||||
r_refdef.vrect.height = vid.fbvheight/2;
|
||||
VKBE_RT_Begin(&shaderstate.rt_refraction, vid.fbpwidth/2, vid.fbpheight/2);
|
||||
VKBE_RT_Gen(&shaderstate.rt_refraction, vid.fbpwidth/2, vid.fbpheight/2, false);
|
||||
VKBE_RT_Begin(&shaderstate.rt_refraction);
|
||||
R_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
|
||||
r_refdef.vrect = ovrect;
|
||||
r_refdef.pxrect = oprect;
|
||||
VKBE_RT_End();
|
||||
|
||||
shaderstate.tex_refraction = &shaderstate.rt_refraction.q_colour;
|
||||
VKBE_RT_Begin(targ);
|
||||
}
|
||||
else
|
||||
{
|
||||
VKBE_RT_Begin(targ);
|
||||
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 3);
|
||||
T_Gen_CurrentRender();
|
||||
shaderstate.tex_refraction = shaderstate.tex_currentrender;
|
||||
|
@ -4737,6 +4959,7 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
|
|||
BE_RT_End();
|
||||
}
|
||||
*/
|
||||
VKBE_RT_Begin(targ);
|
||||
VKBE_SelectMode(oldbem);
|
||||
shaderstate.identitylighting = oldil;
|
||||
|
||||
|
@ -5698,7 +5921,7 @@ void VKBE_DoneShadows(void)
|
|||
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
viewport.x = r_refdef.pxrect.x;
|
||||
viewport.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL...
|
||||
viewport.y = r_refdef.pxrect.y;//r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL...
|
||||
viewport.width = r_refdef.pxrect.width;
|
||||
viewport.height = r_refdef.pxrect.height;
|
||||
viewport.minDepth = 0;
|
||||
|
@ -5798,6 +6021,7 @@ void VKBE_DrawWorld (batch_t **worldbatches, qbyte *vis)
|
|||
else
|
||||
#endif
|
||||
shaderstate.identitylighting = 1;
|
||||
shaderstate.identitylighting *= r_refdef.hdr_value;
|
||||
shaderstate.identitylightmap = shaderstate.identitylighting / (1<<gl_overbright.ival);
|
||||
|
||||
VKBE_SelectMode(BEM_STANDARD);
|
||||
|
|
|
@ -54,8 +54,9 @@ static void VK_DestroyRenderPass(void);
|
|||
static void VK_CreateRenderPass(void);
|
||||
|
||||
struct vulkaninfo_s vk;
|
||||
static struct vk_rendertarg postproc[2];
|
||||
static struct vk_rendertarg postproc[4];
|
||||
static unsigned int postproc_buf;
|
||||
static struct vk_rendertarg_cube vk_rt_cubemap;
|
||||
|
||||
qboolean VK_SCR_GrabBackBuffer(void);
|
||||
|
||||
|
@ -1091,7 +1092,7 @@ void VK_R_DeInit (void)
|
|||
Image_Shutdown();
|
||||
}
|
||||
|
||||
void VK_SetupViewPortProjection(void)
|
||||
void VK_SetupViewPortProjection(qboolean flipy)
|
||||
{
|
||||
extern cvar_t gl_mindist;
|
||||
|
||||
|
@ -1112,7 +1113,19 @@ void VK_SetupViewPortProjection(void)
|
|||
// screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
|
||||
|
||||
/*view matrix*/
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
|
||||
if (flipy) //mimic gl and give bottom-up
|
||||
{
|
||||
vec3_t down;
|
||||
VectorNegate(vup, down);
|
||||
VectorCopy(down, vup);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, down, r_refdef.vieworg);
|
||||
r_refdef.flipcull = SHADER_CULL_FRONT | SHADER_CULL_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
|
||||
r_refdef.flipcull = 0;
|
||||
}
|
||||
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, bound(0.1, gl_mindist.value, 4));
|
||||
}
|
||||
|
||||
|
@ -1304,10 +1317,292 @@ void VK_Init_PostProc(void)
|
|||
}
|
||||
|
||||
|
||||
|
||||
static qboolean VK_R_RenderScene_Cubemap(struct vk_rendertarg *fb)
|
||||
{
|
||||
int cmapsize = 512;
|
||||
int i;
|
||||
static vec3_t ang[6] =
|
||||
{ {0, -90, 0}, {0, 90, 0},
|
||||
{90, 0, 0}, {-90, 0, 0},
|
||||
{0, 0, 0}, {0, -180, 0} };
|
||||
vec3_t saveang;
|
||||
vec3_t saveorg;
|
||||
|
||||
vrect_t vrect;
|
||||
pxrect_t prect;
|
||||
extern cvar_t ffov;
|
||||
|
||||
shader_t *shader;
|
||||
int facemask;
|
||||
extern cvar_t r_projection;
|
||||
int oldfbo = -1;
|
||||
qboolean fboreset = false;
|
||||
int osm = r_refdef.stereomethod;
|
||||
struct vk_rendertarg_cube *rtc = &vk_rt_cubemap;
|
||||
|
||||
if (!*ffov.string || !strcmp(ffov.string, "0"))
|
||||
{
|
||||
if (ffov.vec4[0] != scr_fov.value)
|
||||
{
|
||||
ffov.value = ffov.vec4[0] = scr_fov.value;
|
||||
Shader_NeedReload(false); //gah!
|
||||
}
|
||||
}
|
||||
|
||||
facemask = 0;
|
||||
switch(r_projection.ival)
|
||||
{
|
||||
default: //invalid.
|
||||
return false;
|
||||
case PROJ_STEREOGRAPHIC:
|
||||
shader = R_RegisterShader("postproc_stereographic", SUF_NONE,
|
||||
"{\n"
|
||||
"program postproc_stereographic\n"
|
||||
"{\n"
|
||||
"map $sourcecube\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
facemask |= 1<<4; /*front view*/
|
||||
if (ffov.value > 70)
|
||||
{
|
||||
facemask |= (1<<0) | (1<<1); /*side/top*/
|
||||
if (ffov.value > 85)
|
||||
facemask |= (1<<2) | (1<<3); /*bottom views*/
|
||||
if (ffov.value > 300)
|
||||
facemask |= 1<<5; /*back view*/
|
||||
}
|
||||
break;
|
||||
case PROJ_FISHEYE:
|
||||
shader = R_RegisterShader("postproc_fisheye", SUF_NONE,
|
||||
"{\n"
|
||||
"program postproc_fisheye\n"
|
||||
"{\n"
|
||||
"map $sourcecube\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
//fisheye view sees up to a full sphere
|
||||
facemask |= 1<<4; /*front view*/
|
||||
if (ffov.value > 77)
|
||||
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
|
||||
if (ffov.value > 270)
|
||||
facemask |= 1<<5; /*back view*/
|
||||
break;
|
||||
case PROJ_PANORAMA:
|
||||
shader = R_RegisterShader("postproc_panorama", SUF_NONE,
|
||||
"{\n"
|
||||
"program postproc_panorama\n"
|
||||
"{\n"
|
||||
"map $sourcecube\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
//panoramic view needs at most the four sides
|
||||
facemask |= 1<<4; /*front view*/
|
||||
if (ffov.value > 90)
|
||||
{
|
||||
facemask |= (1<<0) | (1<<1); /*side views*/
|
||||
if (ffov.value > 270)
|
||||
facemask |= 1<<5; /*back view*/
|
||||
}
|
||||
facemask = 0x3f;
|
||||
break;
|
||||
case PROJ_LAEA:
|
||||
shader = R_RegisterShader("postproc_laea", SUF_NONE,
|
||||
"{\n"
|
||||
"program postproc_laea\n"
|
||||
"{\n"
|
||||
"map $sourcecube\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
facemask |= 1<<4; /*front view*/
|
||||
if (ffov.value > 90)
|
||||
{
|
||||
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
|
||||
if (ffov.value > 270)
|
||||
facemask |= 1<<5; /*back view*/
|
||||
}
|
||||
break;
|
||||
|
||||
case PROJ_EQUIRECTANGULAR:
|
||||
shader = R_RegisterShader("postproc_equirectangular", SUF_NONE,
|
||||
"{\n"
|
||||
"program postproc_equirectangular\n"
|
||||
"{\n"
|
||||
"map $sourcecube\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
facemask = 0x3f;
|
||||
#if 0
|
||||
facemask |= 1<<4; /*front view*/
|
||||
if (ffov.value > 90)
|
||||
{
|
||||
facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/
|
||||
if (ffov.value > 270)
|
||||
facemask |= 1<<5; /*back view*/
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
if (!shader || !shader->prog)
|
||||
return false; //erk. shader failed.
|
||||
|
||||
//FIXME: we should be able to rotate the view
|
||||
|
||||
vrect = r_refdef.vrect;
|
||||
prect = r_refdef.pxrect;
|
||||
// prect.x = (vrect.x * vid.pixelwidth)/vid.width;
|
||||
// prect.width = (vrect.width * vid.pixelwidth)/vid.width;
|
||||
// prect.y = (vrect.y * vid.pixelheight)/vid.height;
|
||||
// prect.height = (vrect.height * vid.pixelheight)/vid.height;
|
||||
|
||||
if (sh_config.texture_non_power_of_two_pic)
|
||||
{
|
||||
cmapsize = prect.width > prect.height?prect.width:prect.height;
|
||||
if (cmapsize > 4096)//sh_config.texture_maxsize)
|
||||
cmapsize = 4096;//sh_config.texture_maxsize;
|
||||
}
|
||||
|
||||
|
||||
r_refdef.flags |= RDF_FISHEYE;
|
||||
vid.fbpwidth = vid.fbpheight = cmapsize;
|
||||
|
||||
//FIXME: gl_max_size
|
||||
|
||||
VectorCopy(r_refdef.vieworg, saveorg);
|
||||
VectorCopy(r_refdef.viewangles, saveang);
|
||||
saveang[2] = 0;
|
||||
|
||||
r_refdef.stereomethod = STEREO_OFF;
|
||||
|
||||
VKBE_RT_Gen_Cube(rtc, cmapsize, r_clear.ival?true:false);
|
||||
|
||||
vrect = r_refdef.vrect; //save off the old vrect
|
||||
|
||||
r_refdef.vrect.width = (cmapsize * vid.fbvwidth) / vid.fbpwidth;
|
||||
r_refdef.vrect.height = (cmapsize * vid.fbvheight) / vid.fbpheight;
|
||||
r_refdef.vrect.x = 0;
|
||||
r_refdef.vrect.y = prect.y;
|
||||
|
||||
ang[0][0] = -saveang[0];
|
||||
ang[0][1] = -90;
|
||||
ang[0][2] = -saveang[0];
|
||||
|
||||
ang[1][0] = -saveang[0];
|
||||
ang[1][1] = 90;
|
||||
ang[1][2] = saveang[0];
|
||||
ang[5][0] = -saveang[0]*2;
|
||||
|
||||
//in theory, we could use a geometry shader to duplicate the polygons to each face.
|
||||
//that would of course require that every bit of glsl had such a geometry shader.
|
||||
//it would at least reduce cpu load quite a bit.
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (!(facemask & (1<<i)))
|
||||
continue;
|
||||
|
||||
VKBE_RT_Begin(&rtc->face[i]);
|
||||
|
||||
r_refdef.fov_x = 90;
|
||||
r_refdef.fov_y = 90;
|
||||
r_refdef.viewangles[0] = saveang[0]+ang[i][0];
|
||||
r_refdef.viewangles[1] = saveang[1]+ang[i][1];
|
||||
r_refdef.viewangles[2] = saveang[2]+ang[i][2];
|
||||
|
||||
|
||||
VK_SetupViewPortProjection(true);
|
||||
|
||||
/*if (!vk.rendertarg->depthcleared)
|
||||
{
|
||||
VkClearAttachment clr;
|
||||
VkClearRect rect;
|
||||
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
clr.clearValue.depthStencil.depth = 1;
|
||||
clr.clearValue.depthStencil.stencil = 0;
|
||||
clr.colorAttachment = 1;
|
||||
rect.rect.offset.x = r_refdef.pxrect.x;
|
||||
rect.rect.offset.y = r_refdef.pxrect.y;
|
||||
rect.rect.extent.width = r_refdef.pxrect.width;
|
||||
rect.rect.extent.height = r_refdef.pxrect.height;
|
||||
rect.layerCount = 1;
|
||||
rect.baseArrayLayer = 0;
|
||||
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
|
||||
vk.rendertarg->depthcleared = true;
|
||||
}*/
|
||||
|
||||
VKBE_SelectEntity(&r_worldentity);
|
||||
|
||||
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
|
||||
RQ_BeginFrame();
|
||||
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
|
||||
{
|
||||
if (cl.worldmodel)
|
||||
P_DrawParticles ();
|
||||
}
|
||||
Surf_DrawWorld();
|
||||
RQ_RenderBatchClear();
|
||||
|
||||
vk.rendertarg->depthcleared = false;
|
||||
|
||||
if (R2D_Flush)
|
||||
Con_Printf("no flush\n");
|
||||
}
|
||||
|
||||
r_refdef.vrect = vrect;
|
||||
r_refdef.pxrect = prect;
|
||||
VectorCopy(saveorg, r_refdef.vieworg);
|
||||
r_refdef.stereomethod = osm;
|
||||
|
||||
VKBE_RT_Begin(fb);
|
||||
|
||||
r_refdef.flipcull = 0;
|
||||
VK_Set2D();
|
||||
|
||||
shader->defaulttextures->reflectcube = &rtc->q_colour;
|
||||
|
||||
// draw it through the shader
|
||||
if (r_projection.ival == PROJ_EQUIRECTANGULAR)
|
||||
{
|
||||
//note vr screenshots have requirements here
|
||||
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, 0, 1, 1, 0, shader);
|
||||
}
|
||||
else if (r_projection.ival == PROJ_PANORAMA)
|
||||
{
|
||||
float saspect = .5;
|
||||
float taspect = vrect.height / vrect.width * ffov.value / 90;//(0.5 * vrect.width) / vrect.height;
|
||||
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, -saspect, taspect, saspect, -taspect, shader);
|
||||
}
|
||||
else if (vrect.width > vrect.height)
|
||||
{
|
||||
float aspect = (0.5 * vrect.height) / vrect.width;
|
||||
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, -0.5, aspect, 0.5, -aspect, shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
float aspect = (0.5 * vrect.width) / vrect.height;
|
||||
R2D_Image(vrect.x, vrect.y, vrect.width, vrect.height, -aspect, 0.5, aspect, -0.5, shader);
|
||||
}
|
||||
|
||||
if (R2D_Flush)
|
||||
R2D_Flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VK_R_RenderView (void)
|
||||
{
|
||||
extern unsigned int r_viewcontents;
|
||||
struct vk_rendertarg *rt;
|
||||
struct vk_rendertarg *rt, *rtscreen = vk.rendertarg;
|
||||
extern cvar_t r_fxaa;
|
||||
extern cvar_t r_renderscale, r_postprocshader;
|
||||
float renderscale = r_renderscale.value;
|
||||
|
@ -1381,6 +1676,7 @@ void VK_R_RenderView (void)
|
|||
r_refdef.pxrect.y = y;
|
||||
r_refdef.pxrect.width = x2 - x;
|
||||
r_refdef.pxrect.height = y2 - y;
|
||||
r_refdef.pxrect.maxheight = vid.pixelheight;
|
||||
}
|
||||
|
||||
if (renderscale != 1.0)
|
||||
|
@ -1388,79 +1684,90 @@ void VK_R_RenderView (void)
|
|||
r_refdef.flags |= RDF_RENDERSCALE;
|
||||
r_refdef.pxrect.width *= renderscale;
|
||||
r_refdef.pxrect.height *= renderscale;
|
||||
r_refdef.pxrect.maxheight = r_refdef.pxrect.height;
|
||||
}
|
||||
|
||||
if (r_refdef.pxrect.width <= 0 || r_refdef.pxrect.height <= 0)
|
||||
return; //you're not allowed to do that, dude.
|
||||
|
||||
//FIXME: RDF_BLOOM|RDF_FISHEYE
|
||||
//FIXME: VF_RT_*
|
||||
//FIXME: if we're meant to be using msaa, render the scene to an msaa target and then resolve.
|
||||
|
||||
if (R_CanBloom())
|
||||
r_refdef.flags |= RDF_BLOOM;
|
||||
|
||||
postproc_buf = 0;
|
||||
if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE))
|
||||
{
|
||||
r_refdef.pxrect.x = 0;
|
||||
r_refdef.pxrect.y = 0;
|
||||
rt = &postproc[postproc_buf++%countof(postproc)];
|
||||
if (rt->width != r_refdef.pxrect.width || rt->height != r_refdef.pxrect.height)
|
||||
VKBE_RT_Gen(rt, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
VKBE_RT_Begin(rt, rt->width, rt->height);
|
||||
VKBE_RT_Gen(rt, r_refdef.pxrect.width, r_refdef.pxrect.height, false);
|
||||
}
|
||||
else
|
||||
rt = NULL;
|
||||
|
||||
VK_SetupViewPortProjection();
|
||||
rt = rtscreen;
|
||||
|
||||
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && VK_R_RenderScene_Cubemap(rt))
|
||||
{
|
||||
VkViewport vp[1];
|
||||
VkRect2D scissor[1];
|
||||
vp[0].x = r_refdef.pxrect.x;
|
||||
vp[0].y = r_refdef.pxrect.y;
|
||||
vp[0].width = r_refdef.pxrect.width;
|
||||
vp[0].height = r_refdef.pxrect.height;
|
||||
vp[0].minDepth = 0.0;
|
||||
vp[0].maxDepth = 1.0;
|
||||
scissor[0].offset.x = r_refdef.pxrect.x;
|
||||
scissor[0].offset.y = r_refdef.pxrect.y;
|
||||
scissor[0].extent.width = r_refdef.pxrect.width;
|
||||
scissor[0].extent.height = r_refdef.pxrect.height;
|
||||
vkCmdSetViewport(vk.frame->cbuf, 0, countof(vp), vp);
|
||||
vkCmdSetScissor(vk.frame->cbuf, 0, countof(scissor), scissor);
|
||||
}
|
||||
|
||||
if (!vk.rendertarg->depthcleared)
|
||||
else
|
||||
{
|
||||
VkClearAttachment clr;
|
||||
VkClearRect rect;
|
||||
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
clr.clearValue.depthStencil.depth = 1;
|
||||
clr.clearValue.depthStencil.stencil = 0;
|
||||
clr.colorAttachment = 1;
|
||||
rect.rect.offset.x = r_refdef.pxrect.x;
|
||||
rect.rect.offset.y = r_refdef.pxrect.y;
|
||||
rect.rect.extent.width = r_refdef.pxrect.width;
|
||||
rect.rect.extent.height = r_refdef.pxrect.height;
|
||||
rect.layerCount = 1;
|
||||
rect.baseArrayLayer = 0;
|
||||
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
|
||||
vk.rendertarg->depthcleared = true;
|
||||
VKBE_RT_Begin(rt);
|
||||
|
||||
VK_SetupViewPortProjection(false);
|
||||
|
||||
{
|
||||
VkViewport vp[1];
|
||||
VkRect2D scissor[1];
|
||||
vp[0].x = r_refdef.pxrect.x;
|
||||
vp[0].y = r_refdef.pxrect.y;
|
||||
vp[0].width = r_refdef.pxrect.width;
|
||||
vp[0].height = r_refdef.pxrect.height;
|
||||
vp[0].minDepth = 0.0;
|
||||
vp[0].maxDepth = 1.0;
|
||||
scissor[0].offset.x = r_refdef.pxrect.x;
|
||||
scissor[0].offset.y = r_refdef.pxrect.y;
|
||||
scissor[0].extent.width = r_refdef.pxrect.width;
|
||||
scissor[0].extent.height = r_refdef.pxrect.height;
|
||||
vkCmdSetViewport(vk.frame->cbuf, 0, countof(vp), vp);
|
||||
vkCmdSetScissor(vk.frame->cbuf, 0, countof(scissor), scissor);
|
||||
}
|
||||
|
||||
if (!vk.rendertarg->depthcleared)
|
||||
{
|
||||
VkClearAttachment clr;
|
||||
VkClearRect rect;
|
||||
clr.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
clr.clearValue.depthStencil.depth = 1;
|
||||
clr.clearValue.depthStencil.stencil = 0;
|
||||
clr.colorAttachment = 1;
|
||||
rect.rect.offset.x = r_refdef.pxrect.x;
|
||||
rect.rect.offset.y = r_refdef.pxrect.y;
|
||||
rect.rect.extent.width = r_refdef.pxrect.width;
|
||||
rect.rect.extent.height = r_refdef.pxrect.height;
|
||||
rect.layerCount = 1;
|
||||
rect.baseArrayLayer = 0;
|
||||
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
|
||||
vk.rendertarg->depthcleared = true;
|
||||
}
|
||||
|
||||
VKBE_SelectEntity(&r_worldentity);
|
||||
|
||||
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
|
||||
RQ_BeginFrame();
|
||||
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
|
||||
{
|
||||
if (cl.worldmodel)
|
||||
P_DrawParticles ();
|
||||
}
|
||||
Surf_DrawWorld();
|
||||
RQ_RenderBatchClear();
|
||||
|
||||
vk.rendertarg->depthcleared = false;
|
||||
|
||||
VK_Set2D ();
|
||||
}
|
||||
|
||||
VKBE_SelectEntity(&r_worldentity);
|
||||
|
||||
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
|
||||
RQ_BeginFrame();
|
||||
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
|
||||
{
|
||||
if (cl.worldmodel)
|
||||
P_DrawParticles ();
|
||||
}
|
||||
Surf_DrawWorld();
|
||||
RQ_RenderBatchClear();
|
||||
|
||||
vk.rendertarg->depthcleared = false;
|
||||
|
||||
VK_Set2D ();
|
||||
|
||||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
if (!vk.scenepp_waterwarp)
|
||||
|
@ -1469,46 +1776,56 @@ void VK_R_RenderView (void)
|
|||
if (r_refdef.flags & RDF_WATERWARP)
|
||||
{
|
||||
r_refdef.flags &= ~RDF_WATERWARP;
|
||||
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
|
||||
vk.sourcecolour = &rt->q_colour;
|
||||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
VKBE_RT_Begin(rt, 320, 240);
|
||||
VKBE_RT_Gen(rt, 320, 200, false);
|
||||
}
|
||||
|
||||
else
|
||||
rt = rtscreen;
|
||||
VKBE_RT_Begin(rt);
|
||||
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 0, 1, 1, vk.scenepp_waterwarp);
|
||||
R2D_Flush();
|
||||
}
|
||||
if (r_refdef.flags & RDF_CUSTOMPOSTPROC)
|
||||
{
|
||||
r_refdef.flags &= ~RDF_CUSTOMPOSTPROC;
|
||||
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
|
||||
vk.sourcecolour = &rt->q_colour;
|
||||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
VKBE_RT_Begin(rt, 320, 240);
|
||||
VKBE_RT_Gen(rt, 320, 200, false);
|
||||
}
|
||||
|
||||
else
|
||||
rt = rtscreen;
|
||||
VKBE_RT_Begin(rt);
|
||||
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 1, 1, 0, custompostproc);
|
||||
R2D_Flush();
|
||||
}
|
||||
if (r_refdef.flags & RDF_ANTIALIAS)
|
||||
{
|
||||
r_refdef.flags &= ~RDF_ANTIALIAS;
|
||||
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
|
||||
R2D_ImageColours(rt->width, rt->height, 1, 1);
|
||||
vk.sourcecolour = &rt->q_colour;
|
||||
if (r_refdef.flags & RDF_ALLPOSTPROC)
|
||||
{
|
||||
rt = &postproc[postproc_buf++];
|
||||
VKBE_RT_Begin(rt, 320, 240);
|
||||
VKBE_RT_Gen(rt, 320, 200, false);
|
||||
}
|
||||
|
||||
else
|
||||
rt = rtscreen;
|
||||
VKBE_RT_Begin(rt);
|
||||
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 1, 1, 0, vk.scenepp_antialias);
|
||||
R2D_ImageColours(1, 1, 1, 1);
|
||||
R2D_Flush();
|
||||
}
|
||||
//FIXME: bloom
|
||||
if (r_refdef.flags & RDF_BLOOM)
|
||||
{
|
||||
VKBE_RT_Begin(rtscreen);
|
||||
VK_R_BloomBlend(&rt->q_colour, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height);
|
||||
rt = rtscreen;
|
||||
}
|
||||
}
|
||||
else if (r_refdef.flags & RDF_RENDERSCALE)
|
||||
{
|
||||
|
@ -1521,8 +1838,9 @@ void VK_R_RenderView (void)
|
|||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
VKBE_RT_End(); //WARNING: redundant begin+end renderpasses.
|
||||
vk.sourcecolour = &rt->q_colour;
|
||||
rt = rtscreen;
|
||||
VKBE_RT_Begin(rt);
|
||||
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 0, 1, 1, vk.scenepp_rescale);
|
||||
R2D_Flush();
|
||||
}
|
||||
|
@ -1938,6 +2256,9 @@ qboolean VK_SCR_GrabBackBuffer(void)
|
|||
rpbi.pClearValues = clearvalues;
|
||||
vkCmdBeginRenderPass(vk.frame->cbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
vk.frame->backbuf->width = vid.pixelwidth;
|
||||
vk.frame->backbuf->height = vid.pixelheight;
|
||||
|
||||
rpbi.clearValueCount = 0;
|
||||
rpbi.pClearValues = NULL;
|
||||
rpbi.renderPass = vk.renderpass[0];
|
||||
|
@ -2843,7 +3164,9 @@ void VK_Shutdown(void)
|
|||
VK_DestroySwapChain();
|
||||
|
||||
for (i = 0; i < countof(postproc); i++)
|
||||
VKBE_RT_Destroy(&postproc[i]);
|
||||
VKBE_RT_Gen(&postproc[i], 0, 0, false);
|
||||
VKBE_RT_Gen_Cube(&vk_rt_cubemap, 0, false);
|
||||
VK_R_BloomShutdown();
|
||||
|
||||
vkDestroyCommandPool(vk.device, vk.cmdpool, vkallocationcb);
|
||||
VK_DestroyRenderPass();
|
||||
|
|
|
@ -201,7 +201,13 @@ struct vk_rendertarg
|
|||
qboolean depthcleared; //starting a new gameview needs cleared depth relative to other views, but the first probably won't.
|
||||
|
||||
VkRenderPassBeginInfo restartinfo;
|
||||
struct vk_rendertarg *prev;
|
||||
};
|
||||
struct vk_rendertarg_cube
|
||||
{
|
||||
uint32_t size;
|
||||
image_t q_colour, q_depth; //extra sillyness...
|
||||
vk_image_t colour, depth;
|
||||
struct vk_rendertarg face[6];
|
||||
};
|
||||
|
||||
extern struct vulkaninfo_s
|
||||
|
@ -336,6 +342,10 @@ qboolean VK_LoadTextureMips (texid_t tex, struct pendingtextureinfo *mips);
|
|||
qboolean VK_Init(rendererstate_t *info, const char *sysextname, qboolean (*createSurface)(void));
|
||||
void VK_Shutdown(void);
|
||||
|
||||
void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h);
|
||||
void VK_R_BloomShutdown(void);
|
||||
qboolean R_CanBloom(void);
|
||||
|
||||
struct programshared_s;
|
||||
qboolean VK_LoadGLSL(struct programshared_s *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
|
||||
|
||||
|
@ -374,9 +384,9 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height);
|
|||
void VKBE_BeginShadowmapFace(void);
|
||||
void VKBE_DoneShadows(void);
|
||||
|
||||
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height);
|
||||
void VKBE_RT_Begin(struct vk_rendertarg *targ, uint32_t width, uint32_t height);
|
||||
void VKBE_RT_End(void);
|
||||
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear);
|
||||
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear);
|
||||
void VKBE_RT_Begin(struct vk_rendertarg *targ);
|
||||
void VKBE_RT_Destroy(struct vk_rendertarg *targ);
|
||||
|
||||
|
||||
|
|
|
@ -2248,15 +2248,11 @@ qintptr_t IRC_Frame(qintptr_t *args)
|
|||
{
|
||||
memmove(ircclient->bufferedoutmessage, ircclient->bufferedoutmessage+flushed, ircclient->bufferedoutammount - flushed);
|
||||
ircclient->bufferedoutammount -= flushed;
|
||||
|
||||
if (!ircclient->bufferedoutammount)
|
||||
{
|
||||
pNet_Close(ircclient->socket);
|
||||
ircclient->socket = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ircclient->quitting && !ircclient->bufferedoutammount)
|
||||
stat = IRC_KILL;
|
||||
if (stat == IRC_KILL)
|
||||
{
|
||||
pNet_Close(ircclient->socket);
|
||||
|
|
|
@ -93,7 +93,7 @@ float (float event, float parama, float paramb, float devid) CSQC_InputEvent =
|
|||
{
|
||||
if (!thedesktop)
|
||||
return event!=IE_KEYUP;
|
||||
if (items_keypress(thedesktop, event, parama, paramb, devid))
|
||||
if (items_keypress_(thedesktop, event, parama, paramb, devid))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
This file was automatically generated by FTE QuakeWorld v1.03
|
||||
This file was automatically generated by FTE QuakeWorld v1.05
|
||||
This file can be regenerated by issuing the following command:
|
||||
pr_dumpplatform
|
||||
Available options:
|
||||
|
@ -68,12 +68,12 @@ Available options:
|
|||
#define DP_EF_FULLBRIGHT
|
||||
#define DP_EF_NODEPTHTEST
|
||||
#define DP_EF_NODRAW
|
||||
#define DP_EF_NOGUNBOB
|
||||
#define DP_EF_NOSHADOW
|
||||
#define DP_EF_RED
|
||||
#define DP_ENT_CUSTOMCOLORMAP
|
||||
#define DP_ENT_EXTERIORMODELTOCLIENT
|
||||
#define DP_ENT_TRAILEFFECTNUM /* self.traileffectnum=particleeffectnum("myeffectname
|
||||
"); can be used to attach a particle trail to the given server entity. This is equivelent to calling trailparticles each frame. */
|
||||
#define DP_ENT_TRAILEFFECTNUM /* self.traileffectnum=particleeffectnum("myeffectname"); can be used to attach a particle trail to the given server entity. This is equivelent to calling trailparticles each frame. */
|
||||
#define DP_ENT_VIEWMODEL
|
||||
#define DP_GECKO_SUPPORT
|
||||
#define DP_GFX_SKINFILES
|
||||
|
@ -163,25 +163,27 @@ Available options:
|
|||
#define EXT_DIMENSION_PHYSICS
|
||||
#define EXT_DIMENSION_GHOST
|
||||
#define FRIK_FILE
|
||||
#define FTE_CALLTIMEOFDAY
|
||||
#define FTE_CSQC_ALTCONSOLES_WIP
|
||||
#define FTE_CSQC_BASEFRAME /* Specifies that .basebone, .baseframe, .baselerpfrac, etc exist. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations. */
|
||||
#define FTE_CALLTIMEOFDAY /* Replication of mvdsv functionality (call calltimeofday to cause 'timeofday' to be called, with arguments that can be saved off to a global). Generally strftime is simpler to use. */
|
||||
#define FTE_CSQC_ALTCONSOLES /* The engine tracks multiple consoles. These may or may not be directly visible to the user. */
|
||||
#define FTE_CSQC_BASEFRAME /* Specifies that .basebone, .baseframe2, .baselerpfrac, baseframe1time, etc exist in csqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations. */
|
||||
#define FTE_QC_BASEFRAME /* Specifies that .basebone and .baseframe exist in ssqc. These fields affect all bones in the entity's model with a lower index than the .basebone field, allowing you to give separate control to the legs of a skeletal model, without affecting the torso animations, from ssqc. */
|
||||
#define FTE_CSQC_SERVERBROWSER
|
||||
#define FTE_CSQC_SKELETONOBJECTS
|
||||
#define FTE_CSQC_RENDERTARGETS_WIP /* VF_DESTCOLOUR etc exist and are supported */
|
||||
#define FTE_CSQC_SKELETONOBJECTS /* Provides container objects for skeletal bone data, which can be modified on a per bone basis if needed. This allows you to dynamically generate animations (or just blend them with greater customisation) instead of being limited to a single animation or two. */
|
||||
#define FTE_CSQC_RENDERTARGETS /* VF_RT_DESTCOLOUR exists and can be used to redirect any rendering to a texture instead of the screen. */
|
||||
#define FTE_ENT_SKIN_CONTENTS /* self.skin = CONTENTS_WATER; makes a brush entity into water. use -16 for a ladder. */
|
||||
#define FTE_ENT_UNIQUESPAWNID
|
||||
#define FTE_EXTENDEDTEXTCODES
|
||||
#define FTE_FORCESHADER
|
||||
#define FTE_FORCEINFOKEY
|
||||
#define FTE_GFX_QUAKE3SHADERS
|
||||
#define FTE_FORCESHADER /* Allows csqc to override shaders on models with an explicitly named replacement. Also allows you to define shaders with a fallback if it does not exist on disk. */
|
||||
#define FTE_FORCEINFOKEY /* Provides an easy way to change a user's userinfo from the server. */
|
||||
#define FTE_GFX_QUAKE3SHADERS /* specifies that the engine has full support for vanilla quake3 shaders */
|
||||
#define FTE_GFX_REMAPSHADER /* With the raw power of stuffcmds, the r_remapshader console command is exposed! This mystical command can be used to remap any shader to another. Remapped shaders that specify $diffuse etc in some form will inherit the textures implied by the surface. */
|
||||
#define FTE_ISBACKBUFFERED /* Allows you to check if a client has too many reliable messages pending. */
|
||||
#define FTE_MEMALLOC /* Allows dynamically allocating memory. Use pointers to access this memory. Memory will not be saved into saved games. */
|
||||
#define FTE_MEDIA_AVI /* playfilm command supports avi files. */
|
||||
#define FTE_MEDIA_CIN /* playfilm command supports q2 cin files. */
|
||||
#define FTE_MEDIA_ROQ /* playfilm command supports q3 roq files. */
|
||||
#define FTE_MULTIPROGS /* Multiple progs.dat files can be loaded inside the same qcvm. */
|
||||
#define FTE_MULTITHREADED
|
||||
#define FTE_MULTIPROGS /* Multiple progs.dat files can be loaded inside the same qcvm. Insert new ones with addprogs inside the 'init' function, and use externvalue+externset to rewrite globals (and hook functions) to link them together. Note that the result is generally not very clean unless you carefully design for it beforehand. */
|
||||
#define FTE_MULTITHREADED /* Faux multithreading, allowing multiple contexts to run in sequence. */
|
||||
#define FTE_MVD_PLAYERSTATS /* In csqc, getplayerstat can be used to query any player's stats when playing back MVDs. isdemo will return 2 in this case. */
|
||||
#define FTE_NPCCHAT
|
||||
#define FTE_PART_SCRIPT /* Specifies that the r_particledesc cvar can be used to select a list of particle effects to load from particles/*.cfg, the format of which is documented elsewhere. */
|
||||
#define FTE_PART_NAMESPACES /* Specifies that the engine can use foo.bar to load effect foo from particle description bar. When used via ssqc, this should cause the client to download whatever effects as needed. */
|
||||
|
@ -189,38 +191,40 @@ Available options:
|
|||
#define FTE_QC_CHECKCOMMAND /* Provides a way to test if a console command exists, and whether its a command/alias/cvar. Does not say anything about the expected meanings of any arguments or values. */
|
||||
#define FTE_QC_CHECKPVS
|
||||
#define FTE_QC_HARDWARECURSORS /* setcursormode exists in both csqc+menuqc, and accepts additional arguments to specify a cursor image to use when this module has focus. If the image exceeds hardware limits, it will be emulated using regular draws - this at least still avoids conflicting cursors. */
|
||||
#define FTE_QC_HASHTABLES
|
||||
#define FTE_QC_INTCONV
|
||||
#define FTE_QC_HASHTABLES /* Provides efficient string-based lookups. */
|
||||
#define FTE_QC_INTCONV /* Provides string<>int conversions, including hex representations. */
|
||||
#define FTE_QC_MATCHCLIENTNAME
|
||||
#define FTE_QC_PAUSED
|
||||
#define FTE_QC_PERSISTENTTEMPSTRINGS /* Supersedes DP_QC_MULTIPLETEMPSTRINGS. Temp strings are garbage collected automatically, and do not expire while they're still in use. This makes strzone redundant. */
|
||||
#define FTE_QC_RAGDOLL_WIP
|
||||
#define FTE_QC_SENDPACKET
|
||||
#define FTE_QC_SENDPACKET /* Allows the use of out-of-band udp packets to/from other hosts. Includes the SV_ParseConnectionlessPacket event. */
|
||||
#define FTE_QC_TRACETRIGGER
|
||||
#define FTE_QUAKE2_CLIENT /* This engine is able to act as a quake2 client */
|
||||
#define FTE_QUAKE2_SERVER /* This engine is able to act as a quake2 server */
|
||||
#define FTE_QUAKE3_CLIENT /* This engine is able to act as a quake3 client */
|
||||
#define FTE_QUAKE3_SERVER /* This engine is able to act as a quake3 server */
|
||||
#define FTE_SOLID_LADDER
|
||||
#define FTE_SQL
|
||||
#define FTE_STRINGS
|
||||
#define FTE_SOLID_LADDER /* Allows a simple trigger to remove effects of gravity (solid 20). obsolete. will prolly be removed at some point as it is not networked properly. Use FTE_ENT_SKIN_CONTENTS */
|
||||
#define FTE_SQL /* Provides sql* builtins which can be used for sql database access */
|
||||
#define FTE_SQL_SQLITE /* SQL functionality is able to utilise sqlite databases */
|
||||
#define FTE_STRINGS /* Extra builtins (and additional behaviour) to make string manipulation easier */
|
||||
#define FTE_SV_POINTPARTICLES /* Specifies that particleeffectnum, pointparticles, and trailparticles exist in ssqc as well as csqc. particleeffectnum acts as a precache, allowing ssqc values to be networked up with csqc for use. Use in combination with FTE_PART_SCRIPT+FTE_PART_NAMESPACES to use custom effects. This extension is functionally identical to the DP version, but avoids any misplaced assumptions about the format of the client's particle descriptions. */
|
||||
#define FTE_SV_REENTER
|
||||
#define FTE_TE_STANDARDEFFECTBUILTINS
|
||||
#define FTE_TE_STANDARDEFFECTBUILTINS /* Provides builtins to replace writebytes, with a QW compatible twist. */
|
||||
#define FTE_TERRAIN_MAP /* This engine supports .hmp files, as well as terrain embedded within bsp files. */
|
||||
#define FTE_RAW_MAP /* This engine supports directly loading .map files, as well as realtime editing of the various brushes. */
|
||||
#define KRIMZON_SV_PARSECLIENTCOMMAND
|
||||
#define KRIMZON_SV_PARSECLIENTCOMMAND /* SSQC's SV_ParseClientCommand function is able to handle client 'cmd' commands. The tokenizing parts also work in csqc. */
|
||||
#define NEH_CMD_PLAY2
|
||||
#define NEH_RESTOREGAME
|
||||
#define QSG_CVARSTRING
|
||||
#define QW_ENGINE
|
||||
#define QWE_MVD_RECORD
|
||||
#define QWE_MVD_RECORD /* You can use the easyrecord command to record MVD demos serverside. */
|
||||
#define TEI_MD3_MODEL
|
||||
#define ZQ_MOVETYPE_FLY
|
||||
#define ZQ_MOVETYPE_NOCLIP
|
||||
#define ZQ_MOVETYPE_NONE
|
||||
#define TENEBRAE_GFX_DLIGHTS /* Allows ssqc to attach rtlights to entities with various special properties. */
|
||||
#define ZQ_MOVETYPE_FLY /* MOVETYPE_FLY works on players. */
|
||||
#define ZQ_MOVETYPE_NOCLIP /* MOVETYPE_NOCLIP works on players. */
|
||||
#define ZQ_MOVETYPE_NONE /* MOVETYPE_NONE works on players. */
|
||||
#define ZQ_VWEP
|
||||
#define ZQ_QC_STRINGS
|
||||
#define ZQ_QC_STRINGS /* The strings-only subset of FRIK_FILE is supported. */
|
||||
#define strbuf float
|
||||
#define searchhandle float
|
||||
#define hashtable float
|
||||
|
@ -456,8 +460,13 @@ vector input_cursor_trace_endpos;
|
|||
float input_cursor_trace_entnum;
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
int trace_endcontents;
|
||||
int trace_surfaceflags;
|
||||
int trace_brush_id;
|
||||
int trace_brush_faceid;
|
||||
int trace_surface_id; /* 1-based. 0 if not known. */
|
||||
int trace_bone_id; /* 1-based. 0 if not known. typically needs MOVE_HITMODEL. */
|
||||
int trace_triangle_id; /* 1-based. 0 if not known. */
|
||||
vector global_gravitydir = '0 0 -1'; /* The direction gravity should act in if not otherwise specified per entity. */
|
||||
int serverid; /* The unique id of this server within the server cluster. */
|
||||
#endif
|
||||
|
@ -475,11 +484,18 @@ int serverid; /* The unique id of this server within the server cluster. */
|
|||
.void(float old, float new) contentstransition; /* This function is called when the entity moves between water and air. If specified, default splash sounds will be disabled allowing you to provide your own. */
|
||||
.float dimension_solid; /* This is the bitmask of dimensions which the entity is solid within. */
|
||||
.float dimension_hit; /* This is the bitmask of dimensions which the entity will be blocked by. If other.dimension_solid & self.dimension_hit, our traces will impact and not proceed. If its false, the traces will NOT impact, allowing self to pass straight through. */
|
||||
.float hitcontentsmask;
|
||||
.int hitcontentsmaski; /* Traces performed for this entity will impact against surfaces that match this contents mask. */
|
||||
.float scale; /* Multiplier that resizes the entity. 1 is normal sized, 2 is double sized. scale 0 is remapped to 1. In SSQC, this is limited to 1/16th precision, with a maximum just shy of 16. */
|
||||
.float fatness; /* How many QuakeUnits to push the entity's verticies along their normals by. */
|
||||
.float alpha; /* The transparency of the entity. 1 means opaque, 0.0001 means virtually invisible. 0 is remapped to 1, for compatibility. */
|
||||
.float modelflags; /* Used to override the flags set in the entity's model. Should be set according to the MF_ constants. Use effects|=EF_NOMODELFLAGS to ignore the model's flags completely. The traileffectnum field is more versatile. */
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
.float frame1time; /* This controls the time into the framegroup/animation named by .frame, you should increment this value according to frametime or to distance moved, depending on the sort of animation you're attempting. You may wish to avoid incrementing this while lerpfrac is still changing, to avoid wasting parts of the animation. */
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
.float basebone; /* The base* frame animations are equivelent to their non-base versions, except that they only affect bone numbers below the 'basebone' value. This means that the base* animation can affect the legs of a skeletal model independantly of the normal animation fields affecting the torso area. For more complex animation than this, use skeletal objects. */
|
||||
.float baseframe; /* See basebone */
|
||||
.void() customphysics; /* Called once each physics frame, overriding the entity's .movetype field and associated logic. You'll probably want to use tracebox to move it through the world. Be sure to call .think as appropriate. */
|
||||
.entity tag_entity;
|
||||
.float tag_index;
|
||||
|
@ -506,10 +522,13 @@ int serverid; /* The unique id of this server within the server cluster. */
|
|||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
.float pitch_speed;
|
||||
.vector color; /* This affects the colour of realtime lights that were enabled via the pflags field. */
|
||||
.float light_lev; /* This is the radius of an entity's light. This is not normally used by the engine, but is used for realtime lights (ones that are enabled with the pflags field). */
|
||||
.float style; /* Used by the light util to decide how an entity's light should animate. On an entity with pflags set, this also affects realtime lights. */
|
||||
.float pflags; /* Realtime lighting flags */
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
.float maxspeed;
|
||||
.float items2;
|
||||
.entity view2;
|
||||
.vector movement; /* These are the directions that the player is currently trying to move in (ie: which +forward/+moveright/+moveup etc buttons they have held), expressed relative to that player's angles. Order is forward, right, up. */
|
||||
.float vw_index;
|
||||
|
@ -523,28 +542,25 @@ int serverid; /* The unique id of this server within the server cluster. */
|
|||
.float button6;
|
||||
.float button7;
|
||||
.float button8;
|
||||
.float viewzoom;
|
||||
.float glow_size;
|
||||
.float glow_color;
|
||||
.float glow_trail;
|
||||
.float traileffectnum; /* This should be set to the result of particleeffectnum, in order to attach a custom trail effect to an entity as it moves. */
|
||||
.vector color; /* This affects the colour of realtime lights that were enabled via the pflags field. */
|
||||
.float light_lev; /* This is the radius of an entity's light. This is not normally used by the engine, but is used for realtime lights (ones that are enabled with the pflags field). */
|
||||
.float style; /* Used by the light util to decide how an entity's light should animate. On an entity with pflags set, this also affects realtime lights. */
|
||||
.float pflags; /* Realtime lighting flags */
|
||||
.float clientcolors;
|
||||
.float dimension_see; /* This is the dimension mask (bitfield) that the client is allowed to see. Entities and events not in this dimension mask will be invisible. */
|
||||
.float dimension_seen; /* This is the dimension mask (bitfield) that the client is visible within. Clients that cannot see this dimension mask will not see this entity. */
|
||||
.float dimension_ghost; /* If this entity is visible only within these dimensions, it will become transparent, as if a ghost. */
|
||||
.float dimension_ghost_alpha; /* If this entity is subject to dimension_ghost, this is the scaler for its alpha value. If 0, 0.5 will be used instead. */
|
||||
.float playerclass;
|
||||
.float drawflags; /* Various flags that affect lighting values and scaling. Typically set to 96 in quake for proper compatibility with DP_QC_SCALE. */
|
||||
.float hasted;
|
||||
.float light_level; /* Used by hexen2 to indicate the light level where the player is standing. */
|
||||
.float abslight; /* Allows overriding light levels. Use drawflags to state that this field should actually be used. */
|
||||
.float(entity playerent, float changedflags) SendEntity; /* Called by the engine whenever an entity needs to be (re)sent to a client's csprogs, either because SendFlags was set or because data was lost. Must write its data to the MSG_ENTITY buffer. Will be called at the engine's leasure. */
|
||||
.float SendFlags; /* Indicates that something in the entity has been changed, and that it needs to be updated to all players that can see it. The engine will clear it at some point, with the cleared bits appearing in the 'changedflags' argument of the SendEntity method. */
|
||||
.float Version; /* Obsolete, set a SendFlags bit instead. */
|
||||
.float clientcolors;
|
||||
.float viewzoom;
|
||||
.float items2;
|
||||
.float playerclass;
|
||||
.float hasted;
|
||||
.float light_level; /* Used by hexen2 to indicate the light level where the player is standing. */
|
||||
.float pvsflags; /* Reconfigures when the entity is visible to clients */
|
||||
.float uniquespawnid; /* Incremented by 1 whenever the entity is respawned. Persists across remove calls, for when the two-second grace period is insufficient. */
|
||||
.float() customizeentityforclient; /* Called just before an entity is sent to a client (non-csqc protocol). This gives you a chance to tailor 'self' according to what 'other' should see. */
|
||||
|
@ -555,12 +571,10 @@ int serverid; /* The unique id of this server within the server cluster. */
|
|||
.float lerpfrac3;
|
||||
.float lerpfrac4;
|
||||
.float forceshader; /* Contains a shader handle used to replace all surfaces upon the entity. */
|
||||
.float baseframe; /* See basebone */
|
||||
.float baseframe2; /* See basebone */
|
||||
.float baseframe1time; /* See basebone */
|
||||
.float baseframe2time; /* See basebone */
|
||||
.float baselerpfrac; /* See basebone */
|
||||
.float basebone; /* The base* frame animations are equivelent to their non-base versions, except that they only affect bone numbers below the 'basebone' value. This means that the base* animation can affect the legs of a skeletal model independantly of the normal animation fields affecting the torso area. For more complex animation than this, use skeletal objects. */
|
||||
#endif
|
||||
void(float reqid, float responsecode, string resourcebody) URI_Get_Callback; /* Called as an eventual result of the uri_get builtin. */
|
||||
#ifdef SSQC
|
||||
|
@ -612,10 +626,11 @@ void() initents; /* Part of FTE_MULTIPROGS. Called after fields have been finali
|
|||
#ifdef MENU
|
||||
void() m_init;
|
||||
void() m_shutdown;
|
||||
void() m_draw;
|
||||
void(vector screensize) m_draw; /* Provides the menuqc with a chance to draw. Will be called even if the menu does not have focus, so be sure to avoid that. COMPAT: screensize is not provided in DP. */
|
||||
void(float scan, float chr) m_keydown;
|
||||
void(float scan, float chr) m_keyup;
|
||||
void(float wantmode) m_toggle;
|
||||
float(string cmd) m_consolecommand;
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
float parm17, parm18, parm19, parm20, parm21, parm22, parm23, parm24, parm25, parm26, parm27, parm28, parm29, parm30, parm31, parm32;
|
||||
|
@ -741,6 +756,21 @@ const float CONTENT_SLIME = -4;
|
|||
const float CONTENT_LAVA = -5;
|
||||
const float CONTENT_SKY = -6;
|
||||
const float CONTENT_LADDER = -16; /* If this value is assigned to a solid_bsp's .skin field, the entity will become a ladder volume. */
|
||||
const int CONTENTBIT_NONE = 0x00000000;
|
||||
const int CONTENTBIT_SOLID = 0x00000001;
|
||||
const int CONTENTBIT_LAVA = 0x00000008;
|
||||
const int CONTENTBIT_SLIME = 0x00000010;
|
||||
const int CONTENTBIT_WATER = 0x00000020;
|
||||
const int CONTENTBIT_FTELADDER = 0x00004000;
|
||||
const int CONTENTBIT_PLAYERCLIP = 0x00010000;
|
||||
const int CONTENTBIT_MONSTERCLIP = 0x00020000;
|
||||
const int CONTENTBIT_BODY = 0x02000000i;
|
||||
const int CONTENTBIT_CORPSE = 0x04000000i;
|
||||
const int CONTENTBIT_Q2LADDER = 0x20000000i;
|
||||
const int CONTENTBIT_SKY = 0x80000000i;
|
||||
const int CONTENTBITS_POINTSOLID = (0x00000001i|0x00000002i|0x02000000i);
|
||||
const int CONTENTBITS_BOXSOLID = (0x00000001i|0x00010000i|0x00000002i|0x02000000i);
|
||||
const int CONTENTBITS_FLUID = (0x00000020i|0x00000010i|0x00000008i|0x80000000i);
|
||||
const float CHAN_AUTO = 0; /* The automatic channel, play as many sounds on this channel as you want, and they'll all play, however the other channels will replace each other. */
|
||||
const float CHAN_WEAPON = 1;
|
||||
const float CHAN_VOICE = 2;
|
||||
|
@ -762,10 +792,19 @@ const float SOUNDFLAG_FORCELOOP = 2; /* The sound will restart once it reaches t
|
|||
#ifdef CSQC
|
||||
const float SOUNDFLAG_NOSPACIALISE = 4; /* The different audio channels are played at the same volume regardless of which way the player is facing, without needing to use 0 attenuation. */
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
const float SOUNDFLAG_NOREVERB = 32; /* Disables the use of underwater/reverb effects on this sound effect. */
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
const float SOUNDFLAG_UNICAST = 256; /* The sound will be heard only by the player specified by msg_entity. */
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
const float SOUNDFLAG_FOLLOW = 64; /* The sound's origin will updated to follow the emitting entity. */
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
const float SOUNDFLAG_SENDVELOCITY = 512; /* The entity's current velocity will be sent to the client, only useful if doppler is enabled. */
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
const float ATTN_NONE = 0; /* Sounds with this attenuation can be heard throughout the map */
|
||||
const float ATTN_NORM = 1; /* Standard attenuation */
|
||||
const float ATTN_IDLE = 2; /* Extra attenuation so that sounds don't travel too far. */
|
||||
|
@ -890,6 +929,7 @@ const float MOVE_LAGGED = 64; /* Will use antilag based upon the player's latenc
|
|||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
const float MOVE_ENTCHAIN = 128; /* Returns a list of entities impacted via the trace_ent.chain field */
|
||||
const float MOVE_OTHERONLY = 256; /* Traces that use this trace type will collide against *only* the entity specified via the 'other' global, and will ignore all owner/solid_not/dimension etc rules, they will still adhere to contents and bsp/bbox rules though. */
|
||||
#endif
|
||||
const float RESTYPE_MODEL = 0; /* RESTYPE_* constants are used as arguments with the resourcestatus builtin. */
|
||||
const float RESTYPE_SOUND = 1; /* precache_sound */
|
||||
|
@ -919,15 +959,16 @@ const float EF_FLAG1 = 16;
|
|||
const float EF_FLAG2 = 32;
|
||||
#endif
|
||||
#if defined(CSQC) || defined(NQSSQC)
|
||||
const float EF_ADDITIVE = 32;
|
||||
const float EF_NODRAW = 16;
|
||||
const float EF_ADDITIVE = 32; /* The entity will be drawn with an additive blend. */
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
const float EF_BLUE = 64;
|
||||
const float EF_RED = 128;
|
||||
const float EF_GREEN = 262144;
|
||||
const float EF_FULLBRIGHT = 512;
|
||||
const float EF_NOSHADOW = 4096;
|
||||
const float EF_NODEPTHTEST = 8192;
|
||||
const float EF_BLUE = 64; /* A blue glow */
|
||||
const float EF_RED = 128; /* A red glow */
|
||||
const float EF_GREEN = 262144; /* A green glow */
|
||||
const float EF_FULLBRIGHT = 512; /* This entity will ignore lighting */
|
||||
const float EF_NOSHADOW = 4096; /* This entity will not cast shadows */
|
||||
const float EF_NODEPTHTEST = 8192; /* This entity will be drawn over the top of other things that are closer. */
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
const float EF_NOMODELFLAGS = 8388608; /* Surpresses the normal flags specified in the model. */
|
||||
|
@ -935,15 +976,15 @@ const float EF_NOMODELFLAGS = 8388608; /* Surpresses the normal flags specified
|
|||
#if defined(CSQC) || defined(SSQC)
|
||||
const float MF_ROCKET = 1;
|
||||
const float MF_GRENADE = 2;
|
||||
const float MF_GIB = 4;
|
||||
const float MF_GIB = 4; /* Regular blood trail */
|
||||
const float MF_ROTATE = 8;
|
||||
const float MF_TRACER = 16;
|
||||
const float MF_ZOMGIB = 32;
|
||||
const float MF_TRACER2 = 64;
|
||||
const float MF_TRACER3 = 128;
|
||||
const float MF_TRACER = 16; /* AKA: green scrag trail */
|
||||
const float MF_ZOMGIB = 32; /* Dark blood trail */
|
||||
const float MF_TRACER2 = 64; /* AKA: hellknight projectile trail */
|
||||
const float MF_TRACER3 = 128; /* AKA: purple vore trail */
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
const float SL_ORG_TL = 20;
|
||||
const float SL_ORG_TL = 20; /* Used with showpic etc, specifies that the x+y values are relative to the top-left of the screen */
|
||||
const float SL_ORG_TR = 21;
|
||||
const float SL_ORG_BL = 22;
|
||||
const float SL_ORG_BR = 23;
|
||||
|
@ -1049,6 +1090,7 @@ Note that any rendertarget textures may be destroyed on video mode changes or so
|
|||
const float VF_RT_SOURCECOLOUR = 209; /* The texture name to use with shaders that specify a $sourcecolour map. */
|
||||
const float VF_RT_DEPTH = 210; /* The texture name to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16bit=4,24bit=5,32bit=6), sizexy. */
|
||||
const float VF_RT_RIPPLE = 211; /* The texture name to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy. */
|
||||
const float VF_ENVMAP = 220; /* The cubemap name to use as a fallback for $reflectcube, if a shader was unable to load one. Note that this doesn't automatically change shader permutations or anything. */
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
const float RF_VIEWMODEL = 1; /* Specifies that the entity is a view model, and that its origin is relative to the current view position. These entities are also subject to viewweapon bob. */
|
||||
|
@ -1069,6 +1111,7 @@ const float IE_MOUSEABS = 3; /* Specifies that a mouse cursor or touch event was
|
|||
const float IE_ACCELEROMETER = 4;
|
||||
const float IE_FOCUS = 5; /* Specifies that input focus was given. parama says mouse focus, paramb says keyboard focus. If either are -1, then it is unchanged. */
|
||||
const float IE_JOYAXIS = 6; /* Specifies that what value a joystick/controller axis currently specifies. x=axis, y=value. Will be called multiple times, once for each axis of each active controller. */
|
||||
const float IE_GYROSCOPE = 7;
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
const float CLIENTTYPE_DISCONNECTED = 0; /* Return value from clienttype() builtin. This entity is a player slot that is currently empty. */
|
||||
|
@ -1226,7 +1269,7 @@ float() isserver = #60;
|
|||
float() clientcount = #61;
|
||||
float() clientstate = #62;
|
||||
void(string map) changelevel = #64;
|
||||
void(string sample) localsound = #65;
|
||||
void(string sample, optional float channel, optional float volume) localsound = #65;
|
||||
vector() getmousepos = #66;
|
||||
float(optional float timetype) gettime = #67;
|
||||
void(string data) loadfromdata = #68;
|
||||
|
@ -1313,6 +1356,7 @@ void(entity e) remove = #15; /*
|
|||
void(vector v1, vector v2, float flags, entity ent) traceline = #16; /*
|
||||
Traces an infinitely thin line through the world from v1 towards v2.
|
||||
Will not collide with ent, ent.owner, or any entity who's owner field refers to ent.
|
||||
The passed entity will also be used to determine whether to use a capsule trace, the contents that the trace should impact, and a couple of other extra fields that define the trace.
|
||||
There are no side effects beyond the trace_* globals being written.
|
||||
flags&MOVE_NOMONSTERS will not impact on non-bsp entities.
|
||||
flags&MOVE_MISSILE will impact with increased size.
|
||||
|
@ -1344,7 +1388,7 @@ void(entity client, string s) stuffcmd = #21; /*
|
|||
Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \n.
|
||||
This builtin is generally considered evil. */
|
||||
|
||||
void(entity client, float flags, string s) stuffcmdflags = #0/*:stuffcmdflags*/; /*
|
||||
void(entity client, float flags, string s) stuffcmdflags = #0:stuffcmdflags; /*
|
||||
Sends a console command (or cvar) to the client, where it will be executed. Different clients support different commands. Do NOT forget the final \n.
|
||||
This (just as evil) variant allows specifying some flags too. See the STUFFCMD_* constants. */
|
||||
|
||||
|
@ -1481,7 +1525,7 @@ float(float angle) cos = #61; /* Part of DP_QC_SINCOSSQRTPOW*/
|
|||
float(float value) sqrt = #62; /* Part of DP_QC_SINCOSSQRTPOW*/
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
float(float a, float n) modulo = #0/*:modulo*/;
|
||||
float(float a, float n) modulo = #0:modulo;
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
void(entity ent) changepitch = #63; /* Part of DP_QC_CHANGEPITCH*/
|
||||
|
@ -1559,7 +1603,7 @@ float(float minimum, float val, float maximum) bound = #96; /* Part of DP_QC_MIN
|
|||
|
||||
float(float value, float exp) pow = #97; /* Part of DP_QC_SINCOSSQRTPOW*/
|
||||
#endif
|
||||
float(float v, optional float base) logarithm = #0/*:logarithm*/; /*
|
||||
float(float v, optional float base) logarithm = #0:logarithm; /*
|
||||
Determines the logarithm of the input value according to the specified base. This can be used to calculate how much something was shifted by. */
|
||||
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
|
@ -1573,7 +1617,7 @@ float(string extname) checkextension = #99; /*
|
|||
Use cvar("pr_checkextension") to see if this builtin exists. */
|
||||
|
||||
#endif
|
||||
float(__variant funcref) checkbuiltin = #0/*:checkbuiltin*/; /*
|
||||
float(__variant funcref) checkbuiltin = #0:checkbuiltin; /*
|
||||
Checks to see if the specified builtin is supported/mapped. This is intended as a way to check for #0 functions, allowing for simple single-builtin functions. */
|
||||
|
||||
#ifdef SSQC
|
||||
|
@ -1591,10 +1635,24 @@ void(string slot, float x, float y, float zone, optional entity player) movepic
|
|||
void(string slot, string picname, optional entity player) changepic = #107; /* Part of TEI_SHOWLMP2*/
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
filestream(string filename, float mode, optional float mmapminsize) fopen = #110; /* Part of FRIK_FILE*/
|
||||
filestream(string filename, float mode, optional float mmapminsize) fopen = #110; /* Part of FRIK_FILE
|
||||
Opens a file, typically prefixed with "data/", for either read or write access. */
|
||||
|
||||
void(filestream fhandle) fclose = #111; /* Part of FRIK_FILE*/
|
||||
string(filestream fhandle) fgets = #112; /* Part of FRIK_FILE*/
|
||||
void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7) fputs = #113; /* Part of FRIK_FILE*/
|
||||
string(filestream fhandle) fgets = #112; /* Part of FRIK_FILE
|
||||
Reads a single line out of the file. The new line character is not returned as part of the string. Returns the null string on EOF (use if not(string) to easily test for this, which distinguishes it from the empty string which is returned if the line being read is blank */
|
||||
|
||||
void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7) fputs = #113; /* Part of FRIK_FILE
|
||||
Writes the given string(s) into the file. For compatibility with fgets, you should ensure that the string is terminated with a \n - this will not otherwise be done for you. It is up to the engine whether dos or unix line endings are actually written. */
|
||||
|
||||
#endif
|
||||
int(filestream fhandle, void *ptr, int size) fread = #0:fread; /*
|
||||
Reads binary data out of the file. Returns truncated lengths if the read exceeds the length of the file. */
|
||||
|
||||
int(filestream fhandle, void *ptr, int size) fwrite = #0:fwrite; /*
|
||||
Writes binary data out of the file. */
|
||||
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
float(string s) strlen = #114; /* Part of FRIK_FILE, FTE_STRINGS, ZQ_QC_STRINGS*/
|
||||
string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8) strcat = #115; /* Part of FRIK_FILE, FTE_STRINGS, ZQ_QC_STRINGS*/
|
||||
string(string s, float start, float length) substring = #116; /* Part of FRIK_FILE, FTE_STRINGS, ZQ_QC_STRINGS*/
|
||||
|
@ -1610,6 +1668,9 @@ void(string s) strunzone = #119; /* Part of FRIK_FILE, FTE_STRINGS, ZQ_QC_STRING
|
|||
void(string cvar, float val) cvar_setf = #176;
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
void(string soundname, optional float channel, optional float volume) localsound = #177; /*
|
||||
Plays a sound... locally... probably best not to call this from ssqc. Also disables reverb. */
|
||||
|
||||
float(string modelname, optional float queryonly) getmodelindex = #200; /*
|
||||
Acts as an alternative to precache_model(foo);setmodel(bar, foo); return bar.modelindex;
|
||||
If queryonly is set and the model was not previously precached, the builtin will return 0 without needlessly precaching the model. */
|
||||
|
@ -1717,7 +1778,7 @@ float(string s1, string s2, float len, optional float s1ofs, optional float s2of
|
|||
Compares up to 'len' chars in the two strings without case sensitivity. s1ofs allows you to treat s2 as a substring to compare against, or should be 0.
|
||||
Returns 0 if they are equal. The sign of the return value may be significant, but should not be depended upon. */
|
||||
|
||||
string(string s) strtrim = #0/*:strtrim*/; /*
|
||||
string(string s) strtrim = #0:strtrim; /*
|
||||
Trims the whitespace from the start+end of the string. */
|
||||
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
|
@ -1737,7 +1798,7 @@ void(float num, float type, .__variant fld) clientstat = #232; /*
|
|||
void(float num, float type, string name) globalstat = #233; /*
|
||||
Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, name however, is the name of the global to read in the form of a string (pass "foo"). */
|
||||
|
||||
void(float num, float type, __variant *address) pointerstat = #0/*:pointerstat*/; /*
|
||||
void(float num, float type, __variant *address) pointerstat = #0:pointerstat; /*
|
||||
Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, address however, is the address of the variable you would like to use (pass &foo). */
|
||||
|
||||
float(entity player) isbackbuffered = #234; /* Part of FTE_ISBACKBUFFERED
|
||||
|
@ -1760,7 +1821,7 @@ float(string shadername, optional string defaultshader, ...) shaderforname = #23
|
|||
void(vector org, optional float count) te_bloodqw = #239; /* Part of FTE_TE_STANDARDEFFECTBUILTINS*/
|
||||
#endif
|
||||
#ifdef SSQC
|
||||
void(entity ent) te_muzzleflash = #0/*:te_muzzleflash*/;
|
||||
void(entity ent) te_muzzleflash = #0:te_muzzleflash;
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
float(vector viewpos, entity entity) checkpvs = #240; /* Part of FTE_QC_CHECKPVS*/
|
||||
|
@ -1783,8 +1844,8 @@ string(float serveridx, optional float queryidx) sqlerror = #255; /* Part of FTE
|
|||
string(float serveridx, string data) sqlescape = #256; /* Part of FTE_SQL*/
|
||||
string(float serveridx) sqlversion = #257; /* Part of FTE_SQL*/
|
||||
float(float serveridx, float queryidx, float row, float column) sqlreadfloat = #258; /* Part of FTE_SQL*/
|
||||
int(float serveridx, float queryidx, float row, float column, _variant *ptr, int maxsize) sqlreadblob = #0/*:sqlreadblob*/;
|
||||
string(float serveridx, _variant *ptr, int maxsize) sqlescapeblob = #0/*:sqlescapeblob*/;
|
||||
int(float serveridx, float queryidx, float row, float column, __variant *ptr, int maxsize) sqlreadblob = #0:sqlreadblob;
|
||||
string(float serveridx, __variant *ptr, int maxsize) sqlescapeblob = #0:sqlescapeblob;
|
||||
#endif
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
int(string) stoi = #259; /* Part of FTE_QC_INTCONV
|
||||
|
@ -1800,10 +1861,10 @@ string(int) htos = #262; /* Part of FTE_QC_INTCONV
|
|||
Formats an integer as a base16 string, with leading 0s and no prefix. Always returns 8 characters. */
|
||||
|
||||
#endif
|
||||
int(float) ftoi = #0/*:ftoi*/; /*
|
||||
int(float) ftoi = #0:ftoi; /*
|
||||
Converts the given float into a true integer without depending on extended qcvm instructions. */
|
||||
|
||||
float(int) itof = #0/*:itof*/; /*
|
||||
float(int) itof = #0:itof; /*
|
||||
Converts the given true integer into a float without depending on extended qcvm instructions. */
|
||||
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
|
@ -1868,25 +1929,25 @@ typedef struct
|
|||
vector tdir;
|
||||
float tbias;
|
||||
} brushface_t;
|
||||
int(float modelidx, int brushid, brushface_t *out_faces, int maxfaces, int *out_contents) brush_get = #0/*:brush_get*/; /*
|
||||
int(float modelidx, int brushid, brushface_t *out_faces, int maxfaces, int *out_contents) brush_get = #0:brush_get; /*
|
||||
Queries a brush's information. You must pre-allocate the face array for the builtin to write to. Return value is the number of faces retrieved, 0 on error. */
|
||||
|
||||
int(float modelidx, brushface_t *in_faces, int numfaces, int contents) brush_create = #0/*:brush_create*/; /*
|
||||
int(float modelidx, brushface_t *in_faces, int numfaces, int contents) brush_create = #0:brush_create; /*
|
||||
Inserts a new brush into the model. Return value is the new brush's id. */
|
||||
|
||||
void(float modelidx, int brushid) brush_delete = #0/*:brush_delete*/; /*
|
||||
void(float modelidx, int brushid) brush_delete = #0:brush_delete; /*
|
||||
Destroys the specified brush. */
|
||||
|
||||
float(float modelid, int brushid, int faceid, float selectedstate) brush_selected = #0/*:brush_selected*/; /*
|
||||
float(float modelid, int brushid, int faceid, float selectedstate) brush_selected = #0:brush_selected; /*
|
||||
Allows you to easily set transient visual properties of a brush. returns old value. selectedstate=-1 changes nothing (called for its return value). */
|
||||
|
||||
int(float modelid, int brushid, int faceid, vector *points, int maxpoints) brush_getfacepoints = #0/*:brush_getfacepoints*/; /*
|
||||
int(float modelid, int brushid, int faceid, vector *points, int maxpoints) brush_getfacepoints = #0:brush_getfacepoints; /*
|
||||
Returns the list of verticies surrounding the given face. If face is 0, returns the center of the brush (if space for 1 point) or the mins+maxs (if space for 2 points). */
|
||||
|
||||
int(int faceid, brushface_t *in_faces, int numfaces, vector *points, int maxpoints) brush_calcfacepoints = #0/*:brush_calcfacepoints*/; /*
|
||||
int(int faceid, brushface_t *in_faces, int numfaces, vector *points, int maxpoints) brush_calcfacepoints = #0:brush_calcfacepoints; /*
|
||||
Determines the points of the specified face, if the specified brush were to actually be created. */
|
||||
|
||||
int(float modelid, vector *planes, float *dists, int numplanes, int *out_brushes, int *out_faces, int maxresults) brush_findinvolume = #0/*:brush_findinvolume*/; /*
|
||||
int(float modelid, vector *planes, float *dists, int numplanes, int *out_brushes, int *out_faces, int maxresults) brush_findinvolume = #0:brush_findinvolume; /*
|
||||
Allows you to easily obtain a list of brushes+faces within the given bounding region. If out_faces is not null, the same brush might be listed twice. */
|
||||
|
||||
void(optional entity ent, optional vector neworigin) touchtriggers = #279; /*
|
||||
|
@ -1949,10 +2010,10 @@ string(string s) argescape = #295; /*
|
|||
Marks up a string so that it can be reliably tokenized as a single argument later. */
|
||||
|
||||
#ifdef SSQC
|
||||
void(string dest, string from, string cmd, string info) clusterevent = #0/*:clusterevent*/; /*
|
||||
void(string dest, string from, string cmd, string info) clusterevent = #0:clusterevent; /*
|
||||
Only functions in mapcluster mode. Sends an event to whichever server the named player is on. The destination server can then dispatch the event to the client or handle it itself via the SV_ParseClusterEvent entrypoint. If dest is empty, the event is broadcast to ALL servers. If the named player can't be found, the event will be returned to this server with the cmd prefixed with 'error:'. */
|
||||
|
||||
string(entity player, optional string newnode) clustertransfer = #0/*:clustertransfer*/; /*
|
||||
string(entity player, optional string newnode) clustertransfer = #0:clustertransfer; /*
|
||||
Only functions in mapcluster mode. Initiate transfer of the player to a different node. Can take some time. If dest is specified, returns null on error. Otherwise returns the current/new target node (or null if not transferring). */
|
||||
|
||||
#endif
|
||||
|
@ -1964,7 +2025,7 @@ void() clearscene = #300; /*
|
|||
#ifdef CSQC
|
||||
void(float mask) addentities = #301; /*
|
||||
Walks through all entities effectively doing this:
|
||||
if (ent.drawmask&mask){ ent.predaw(); if (wasremoved(ent)||(ent.renderflags&RF_NOAUTOADD))continue; addentity(ent); }
|
||||
if (ent.drawmask&mask){ if (!ent.predaw()) addentity(ent); }
|
||||
If mask&MASK_DELTA, non-csqc entities, particles, and related effects will also be added to the rentity list.
|
||||
If mask&MASK_STDVIEWMODEL then the default view model will also be added. */
|
||||
|
||||
|
@ -1973,6 +2034,13 @@ void(float mask) addentities = #301; /*
|
|||
void(entity ent) addentity = #302; /*
|
||||
Copies the entity fields into a new rentity for later rendering via addscene. */
|
||||
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
void(string texturename, float flags, void *verts, int *indexes, int numindexes) addtrisoup_1 = #0:addtrisoup_1; /*
|
||||
Adds the specified trisoup into the scene as additional geometry. This permits caching geometry to reduce builtin spam. Indexes are a triangle list (so eg quads will need 6 indicies to form two triangles). NOTE: this is not going to be a speedup over polygons if you're still generating lots of new data every frame. */
|
||||
|
||||
#endif
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
#define setviewprop setproperty
|
||||
float(float property, ...) setproperty = #303; /*
|
||||
Allows you to override default view properties like viewport, fov, and whether the engine hud will be drawn. Different VF_ values have slightly different arguments, some are vectors, some floats. */
|
||||
|
@ -2013,7 +2081,7 @@ vector (vector v) project = #311; /*
|
|||
|
||||
#endif
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
void(vector pos, vector size, float alignflags, string text) drawtextfield = #0/*:drawtextfield*/; /*
|
||||
void(vector pos, vector size, float alignflags, string text) drawtextfield = #0:drawtextfield; /*
|
||||
Draws a multi-line block of text, including word wrapping and alignment. alignflags bits are RTLB, typically 3. */
|
||||
|
||||
#endif
|
||||
|
@ -2027,6 +2095,12 @@ float(string name) iscachedpic = #316; /*
|
|||
string(string name, optional float trywad) precache_pic = #317; /*
|
||||
Forces the engine to load the named image. If trywad is specified, the specified name must any lack path and extension. */
|
||||
|
||||
void(string imagename, int width, int height, int *pixeldata) r_uploadimage = #0:r_uploadimage; /*
|
||||
Updates a texture with the specified rgba data. Will be created if needed. */
|
||||
|
||||
int*(string filename, __out int width, __out int height) r_readimage = #0:r_readimage; /*
|
||||
Reads and decodes an image from disk, providing raw pixel data. Returns __NULL__ if the image could not be read for any reason. Use memfree to free the data once you're done with it. */
|
||||
|
||||
#define draw_getimagesize drawgetimagesize
|
||||
vector(string picname) drawgetimagesize = #318; /*
|
||||
Returns the dimensions of the named image. Images specified with .lmp should give the original .lmp's dimensions even if texture replacements use a different resolution. */
|
||||
|
@ -2074,10 +2148,10 @@ void(vector pos, vector sz, string pic, vector srcpos, vector srcsz, vector rgb,
|
|||
|
||||
#endif
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
void(vector pivot, vector mins, vector maxs, string pic, vector rgb, float alpha, float angle) drawrotpic = #0/*:drawrotpic*/; /*
|
||||
void(vector pivot, vector mins, vector maxs, string pic, vector rgb, float alpha, float angle) drawrotpic = #0:drawrotpic; /*
|
||||
Draws an image rotating at the pivot. To rotate in the center, use mins+maxs of half the size with mins negated. Angle is in degrees. */
|
||||
|
||||
void(vector pivot, vector mins, vector maxs, string pic, vector txmin, vector txsize, vector rgb, vector alphaandangles) drawrotsubpic = #0/*:drawrotsubpic*/; /*
|
||||
void(vector pivot, vector mins, vector maxs, string pic, vector txmin, vector txsize, vector rgb, vector alphaandangles) drawrotsubpic = #0:drawrotsubpic; /*
|
||||
Overcomplicated draw function for over complicated people. Positions follow drawrotpic, while texture coords follow drawsubpic. Due to argument count limitations in builtins, the alpha value and angles are combined into separate fields of a vector (tip: use fteqcc's [alpha, angle] feature. */
|
||||
|
||||
#endif
|
||||
|
@ -2093,7 +2167,7 @@ string(float stnum) getstats = #332; /*
|
|||
Retrieves the value of the given EV_STRING stat, as a tempstring.
|
||||
Older engines may use 4 consecutive integer stats, with a limit of 15 chars (yes, really. 15.), but FTE QuakeWorld uses a separate namespace for string stats and has a much higher length limit. */
|
||||
|
||||
__variant(float playernum, float statnum, float stattype) getplayerstat = #0/*:getplayerstat*/; /*
|
||||
__variant(float playernum, float statnum, float stattype) getplayerstat = #0:getplayerstat; /*
|
||||
Retrieves a specific player's stat, matching the type specified on the server. This builtin is primarily intended for mvd playback where ALL players are known. For EV_ENTITY, world will be returned if the entity is not in the pvs, use type-punning with EV_INTEGER to get the entity number if you just want to see if its set. STAT_ITEMS should be queried as an EV_INTEGER on account of runes and items2 being packed into the upper bits. */
|
||||
|
||||
void(entity e, float mdlindex) setmodelindex = #333; /*
|
||||
|
@ -2152,7 +2226,7 @@ string(float keynum) getkeybind = #342; /*
|
|||
void(float usecursor, optional string cursorimage, optional vector hotspot, optional float scale) setcursormode = #343; /*
|
||||
Pass TRUE if you want the engine to release the mouse cursor (absolute input events + touchscreen mode). Pass FALSE if you want the engine to grab the cursor (relative input events + standard looking). If the image name is specified, the engine will use that image for a cursor (use an empty string to clear it again), in a way that will not conflict with the console. Images specified this way will be hardware accelerated, if supported by the platform/port. */
|
||||
|
||||
float(float effective) getcursormode = #0/*:getcursormode*/; /*
|
||||
float(float effective) getcursormode = #0:getcursormode; /*
|
||||
Reports the cursor mode this module previously attempted to use. If 'effective' is true, reports the cursor mode currently active (if was overriden by a different module which has precidence, for instance, or if there is only a touchscreen and no mouse). */
|
||||
|
||||
#endif
|
||||
|
@ -2189,9 +2263,39 @@ float() isdemo = #349; /*
|
|||
float() isserver = #350; /*
|
||||
Returns if the client is acting as the server (aka: listen server) */
|
||||
|
||||
void(vector origin, vector forward, vector right, vector up, optional float inwater) SetListener = #351; /*
|
||||
Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default. */
|
||||
void(vector origin, vector forward, vector right, vector up, optional float reverbtype) SetListener = #351; /*
|
||||
Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default. For reverbtype, see setup_reverb or treat as 'underwater'. */
|
||||
|
||||
typedef struct {
|
||||
float flDensity;
|
||||
float flDiffusion;
|
||||
float flGain;
|
||||
float flGainHF;
|
||||
float flGainLF;
|
||||
float flDecayTime;
|
||||
float flDecayHFRatio;
|
||||
float flDecayLFRatio;
|
||||
float flReflectionsGain;
|
||||
float flReflectionsDelay;
|
||||
vector flReflectionsPan;
|
||||
float flLateReverbGain;
|
||||
float flLateReverbDelay;
|
||||
vector flLateReverbPan;
|
||||
float flEchoTime;
|
||||
float flEchoDepth;
|
||||
float flModulationTime;
|
||||
float flModulationDepth;
|
||||
float flAirAbsorptionGainHF;
|
||||
float flHFReference;
|
||||
float flLFReference;
|
||||
float flRoomRolloffFactor;
|
||||
int iDecayHFLimit;
|
||||
} reverbinfo_t;
|
||||
void(float reverbslot, reverbinfo_t *reverbinfo, int sizeofreverinfo_t) setup_reverb = #0:setup_reverb; /*
|
||||
Reconfigures a reverb slot for weird effects. Slot 0 is reserved for no effects. Slot 1 is reserved for underwater effects. Reserved slots will be reinitialised on snd_restart, but can otherwise be changed. These reverb slots can be activated with SetListener. Note that reverb will currently only work when using OpenAL. */
|
||||
|
||||
#endif
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
void(string cmdname) registercommand = #352; /*
|
||||
Register the given console command, for easy console use.
|
||||
Console commands that are later used will invoke CSQC_ConsoleCommand. */
|
||||
|
@ -2201,11 +2305,11 @@ void(string cmdname) registercommand = #352; /*
|
|||
float(entity ent) wasfreed = #353; /*
|
||||
Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust. */
|
||||
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
string(string key) serverkey = #354; /*
|
||||
Look up a key in the server's public serverinfo string */
|
||||
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
string(optional string resetstring) getentitytoken = #355; /*
|
||||
Grab the next token in the map's entity lump.
|
||||
If resetstring is not specified, the next token will be returned with no other sideeffects.
|
||||
|
@ -2219,7 +2323,7 @@ float(string s) findfont = #356; /*
|
|||
Looks up a named font slot. Matches the actual font name as a last resort. */
|
||||
|
||||
float(string fontname, string fontmaps, string sizes, float slot, optional float fix_scale, optional float fix_voffset) loadfont = #357; /*
|
||||
too convoluted for me to even try to explain correct usage. Try drawfont = loadfont("foo", "cour", "16", 0, 0, 0); to switch to the courier font, if you have the freetype2 library in windows.. */
|
||||
too convoluted for me to even try to explain correct usage. Try drawfont = loadfont("", "cour", "16", -1, 0, 0); to switch to the courier font (optimised for 16 virtual pixels high), if you have the freetype2 library in windows.. */
|
||||
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
|
@ -2260,7 +2364,7 @@ void(entity e, string skinfilename, optional string skindata) setcustomskin = #3
|
|||
qwskin "foo" - use an unmodified quakeworld player skin (including crop+repalette rules)
|
||||
q1lower 0xff0000 - specify an override for the entity's lower colour, in this case to red
|
||||
q1upper 0x0000ff - specify an override for the entity's lower colour, in this case to blue
|
||||
compose "surfacename" "shader" "imagename@x,y:w,h?r,g,b,a" - compose a skin texture from multiple images.
|
||||
compose "surfacename" "shader" "imagename@x,y:w,h$s,t,s2,t2?r,g,b,a" - compose a skin texture from multiple images.
|
||||
The texture is determined to be sufficient to hold the first named image, additional images can be named as extra tokens on the same line.
|
||||
Use a + at the end of the line to continue reading image tokens from the next line also, the named shader must use 'map $diffuse' to read the composed texture (compatible with the defaultskin shader). */
|
||||
|
||||
|
@ -2286,27 +2390,34 @@ void(__variant *dst, float ofs, __variant val) memsetval = #389; /*
|
|||
__variant*(__variant *base, float ofs) memptradd = #390; /*
|
||||
Perform some pointer maths. Woo. */
|
||||
|
||||
float(string s) memstrsize = #0/*:memstrsize*/; /*
|
||||
float(string s) memstrsize = #0:memstrsize; /*
|
||||
strlen, except ignores utf-8 */
|
||||
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
string(string conname, string field, optional string newvalue) con_getset = #391; /* Part of FTE_CSQC_ALTCONSOLES_WIP
|
||||
string(string conname, string field, optional string newvalue) con_getset = #391; /* Part of FTE_CSQC_ALTCONSOLES
|
||||
Reads or sets a property from a console object. The old value is returned. Iterrate through consoles with the 'next' field. Valid properties: title, name, next, unseen, markup, forceutf8, close, clear, hidden, linecount */
|
||||
|
||||
void(string conname, string messagefmt, ...) con_printf = #392; /* Part of FTE_CSQC_ALTCONSOLES_WIP
|
||||
void(string conname, string messagefmt, ...) con_printf = #392; /* Part of FTE_CSQC_ALTCONSOLES
|
||||
Prints onto a named console. */
|
||||
|
||||
void(string conname, vector pos, vector size, float fontsize) con_draw = #393; /* Part of FTE_CSQC_ALTCONSOLES_WIP
|
||||
void(string conname, vector pos, vector size, float fontsize) con_draw = #393; /* Part of FTE_CSQC_ALTCONSOLES
|
||||
Draws the named console. */
|
||||
|
||||
float(string conname, float inevtype, float parama, float paramb, float paramc) con_input = #394; /* Part of FTE_CSQC_ALTCONSOLES_WIP
|
||||
float(string conname, float inevtype, float parama, float paramb, float paramc) con_input = #394; /* Part of FTE_CSQC_ALTCONSOLES
|
||||
Forwards input events to the named console. Mouse updates should be absolute only. */
|
||||
|
||||
float() cvars_haveunsaved = #0/*:cvars_haveunsaved*/; /*
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
void(string newcaption) setwindowcaption = #0:setwindowcaption; /*
|
||||
Replaces the title of the game window, as seen when task switching or just running in windowed mode. */
|
||||
|
||||
#endif
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
float() cvars_haveunsaved = #0:cvars_haveunsaved; /*
|
||||
Returns true if any archived cvar has an unsaved value. */
|
||||
|
||||
#endif
|
||||
float(entity e, float nowreadonly) entityprotection = #0/*:entityprotection*/; /*
|
||||
float(entity e, float nowreadonly) entityprotection = #0:entityprotection; /*
|
||||
Changes the protection on the specified entity to protect it from further edits from QC. The return value is the previous setting. Note that this can be used to unprotect the world, but doing so long term is not advised as you will no longer be able to detect invalid entity references. Also, world is not networked, so results might not be seen by clients (or in other words, world.avelocity_y=64 is a bad idea). */
|
||||
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
|
@ -2403,10 +2514,10 @@ string(searchhandle handle, float num) search_getfilename = #447; /* Part of DP_
|
|||
Retrieves name of one of the files that was found by the initial search. */
|
||||
|
||||
#endif
|
||||
float(searchhandle handle, float num) search_getfilesize = #0/*:search_getfilesize*/; /*
|
||||
float(searchhandle handle, float num) search_getfilesize = #0:search_getfilesize; /*
|
||||
Retrieves the size of one of the files that was found by the initial search. */
|
||||
|
||||
string(searchhandle handle, float num) search_getfilemtime = #0/*:search_getfilemtime*/; /*
|
||||
string(searchhandle handle, float num) search_getfilemtime = #0:search_getfilemtime; /*
|
||||
Retrieves modification time of one of the files. */
|
||||
|
||||
#if defined(CSQC) || defined(SSQC)
|
||||
|
@ -2465,7 +2576,7 @@ vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; /*
|
|||
#endif
|
||||
#if defined(CSQC) || defined(MENU)
|
||||
float(string name) gecko_create = #487; /* Part of DP_GECKO_SUPPORT
|
||||
Create a new 'browser tab' shader with the specified name that can then be drawn via drawpic. In order to function correctly, this builtin depends upon external plugins being available. Use gecko_navigate to navigate it to a page of your choosing. */
|
||||
Create a new 'browser tab' shader with the specified name that can then be drawn via drawpic (shader should not already exist - including from map/model textures or disk). In order to function correctly, this builtin depends upon external plugins being available. Use gecko_navigate to navigate it to a page of your choosing. */
|
||||
|
||||
void(string name) gecko_destroy = #488; /* Part of DP_GECKO_SUPPORT
|
||||
Destroy a shader. */
|
||||
|
@ -2483,19 +2594,29 @@ void(string name, float w, float h) gecko_resize = #492; /* Part of DP_GECKO_SUP
|
|||
Request to resize a media decoder. */
|
||||
|
||||
vector(string name) gecko_get_texture_extent = #493; /* Part of DP_GECKO_SUPPORT
|
||||
Query a media decoder for its current pixel size. */
|
||||
Retrieves a media decoder current image pixel sizes. */
|
||||
|
||||
string(string shadname, string propname) gecko_getproperty = #0:gecko_getproperty; /*
|
||||
Queries the media decoder (especially browser ones) for decoder-specific properties. The cef plugin recognises url, title, status. */
|
||||
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
float(string file, string id) cin_open = #0:cin_open;
|
||||
void(string id) cin_close = #0:cin_close;
|
||||
void(string id, float newstate) cin_setstate = #0:cin_setstate;
|
||||
float(string id) cin_getstate = #0:cin_getstate;
|
||||
void(string file) cin_restart = #0:cin_restart;
|
||||
#endif
|
||||
float(float caseinsensitive, string s, ...) crc16 = #494; /* Part of DP_QC_CRC16*/
|
||||
float(string name) cvar_type = #495; /* Part of DP_QC_CVAR_TYPE*/
|
||||
float() numentityfields = #496; /* Part of DP_QC_ENTITYDATA
|
||||
Gives the number of named entity fields. Note that this is not the size of an entity, but rather just the number of unique names (ie: vectors use 4 names rather than 3). */
|
||||
|
||||
float(string fieldname) findentityfield = #0/*:findentityfield*/; /*
|
||||
float(string fieldname) findentityfield = #0:findentityfield; /*
|
||||
Find a field index by name. */
|
||||
|
||||
typedef .__variant field_t;
|
||||
field_t(float fieldnum) entityfieldref = #0/*:entityfieldref*/; /*
|
||||
field_t(float fieldnum) entityfieldref = #0:entityfieldref; /*
|
||||
Returns a field value that can be directly used to read entity fields. Be sure to validate the type with entityfieldtype before using. */
|
||||
|
||||
string(float fieldnum) entityfieldname = #497; /* Part of DP_QC_ENTITYDATA
|
||||
|
@ -2549,7 +2670,7 @@ string(float keynum) keynumtostring_omgwtf = #520;
|
|||
string(string command, optional float bindmap) findkeysforcommand = #521; /*
|
||||
Returns a list of keycodes that perform the given console command in a format that can only be parsed via tokenize (NOT tokenize_console). This only and always returns two values - if only one key is actually bound, -1 will be returned. The bindmap argument is listed for compatibility with dp-specific defs, but is ignored in FTE. */
|
||||
|
||||
string(string command, optional float bindmap) findkeysforcommandex = #0/*:findkeysforcommandex*/; /*
|
||||
string(string command, optional float bindmap) findkeysforcommandex = #0:findkeysforcommandex; /*
|
||||
Returns a list of key bindings in keyname format instead of keynums. Use tokenize to parse. This list may contain modifiers. May return large numbers of keys. */
|
||||
|
||||
#endif
|
||||
|
@ -2565,7 +2686,7 @@ void(string s) loadfromfile = #530; /*
|
|||
float(string mname) precache_vwep_model = #532; /* Part of ZQ_VWEP*/
|
||||
#endif
|
||||
#ifdef CSQC
|
||||
float(entity e, float channel, string newsample, float volume, float attenuation, float pitchpct, float flags, float timeoffset) soundupdate = #0/*:soundupdate*/; /*
|
||||
float(entity e, float channel, string newsample, float volume, float attenuation, float pitchpct, float flags, float timeoffset) soundupdate = #0:soundupdate; /*
|
||||
Changes the properties of the current sound being played on the given entity channel. newsample may be empty, and will be ignored in this case. timeoffset is relative to the current position (subtract the result of getsoundtime for absolute positions). Negative volume can be used to stop the sound. Return value is a fractional value based upon the number of audio devices that could be updated - test against TRUE rather than non-zero. */
|
||||
|
||||
float(entity e, float channel) getsoundtime = #533; /*
|
||||
|
@ -2629,8 +2750,11 @@ string(string command, optional float bindmap) findkeysforcommand = #610;
|
|||
float(float type) gethostcachevalue = #611; /* Part of FTE_CSQC_SERVERBROWSER*/
|
||||
string(float type, float hostnr) gethostcachestring = #612; /* Part of FTE_CSQC_SERVERBROWSER*/
|
||||
#endif
|
||||
void(entity e, string s) parseentitydata = #613; /*
|
||||
Reads a single entity's fields into an already-spawned entity. s should contain field pairs like in a saved game: {"foo1" "bar" "foo2" "5"} */
|
||||
float(entity e, string s, optional float offset) parseentitydata = #613; /*
|
||||
Reads a single entity's fields into an already-spawned entity. s should contain field pairs like in a saved game: {"foo1" "bar" "foo2" "5"}. Returns <=0 on failure, otherwise returns the offset in the string that was read to. */
|
||||
|
||||
string(entity e) generateentitydata = #0:generateentitydata; /*
|
||||
Dumps the entities fields into a string which can later be parsed with parseentitydata. */
|
||||
|
||||
#ifdef MENU
|
||||
float(string key) stringtokeynum = #614; /*
|
||||
|
|
|
@ -71,7 +71,7 @@ void(mitem_desktop desktop) M_Pop =
|
|||
|
||||
mitem_desktop desktop;
|
||||
void() m_shutdown = {};
|
||||
void() m_draw = {items_draw(desktop);};
|
||||
void(vector screensize) m_draw = {items_draw(desktop);};
|
||||
void(float scan, float chr) m_keydown = {items_keypress(desktop, scan, chr, TRUE);};
|
||||
void(float scan, float chr) m_keyup = {items_keypress(desktop, scan, chr, FALSE);};
|
||||
void(float mode) m_toggle
|
||||
|
|
Loading…
Reference in a new issue