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();
|
||||
}
|
||||
|
@ -1752,7 +2070,7 @@ static void VK_PaintScreen(void)
|
|||
// scr_con_forcedraw = true;
|
||||
|
||||
nohud = true;
|
||||
}
|
||||
}
|
||||
|
||||
SCR_DrawTwoDimensional(uimenu, nohud);
|
||||
|
||||
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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