mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
Merge branch 'wip-rua_scene'
This commit is contained in:
commit
5b103f2570
146 changed files with 4234 additions and 1711 deletions
|
@ -2133,7 +2133,8 @@ SEARCH_INCLUDES = YES
|
|||
INCLUDE_PATH = @TOPSRC@/include \
|
||||
@TOPSRC@/nq/include \
|
||||
@TOPSRC@/qw/include \
|
||||
@TOPSRC@/qtv/include
|
||||
@TOPSRC@/qtv/include \
|
||||
@TOPSRC@
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
|
@ -2152,6 +2153,7 @@ INCLUDE_FILE_PATTERNS = *.h
|
|||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED = "__attribute__(x)=" \
|
||||
IN_DOXYGEN=1 \
|
||||
VISIBLE=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
|
|
|
@ -45,8 +45,8 @@ void gl_R_RotateForEntity (struct entity_s *e);
|
|||
|
||||
struct model_s;
|
||||
struct entqueue_s;
|
||||
void gl_R_NewMap (struct model_s *worldmodel, struct model_s **models,
|
||||
int num_models);
|
||||
struct scene_s;
|
||||
void gl_R_NewScene (struct scene_s *scene);
|
||||
void gl_R_RenderView (void);
|
||||
void gl_R_RenderEntities (struct entqueue_s *queue);
|
||||
void gl_R_ClearState (void);
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
#define __QF_GLSL_qf_main_h
|
||||
|
||||
struct entqueue_s;
|
||||
struct scene_s;
|
||||
|
||||
void glsl_R_NewMap (model_t *worldmodel, model_t **models, int num_models);
|
||||
void glsl_R_NewScene (struct scene_s *scene);
|
||||
void glsl_R_RenderEntities (struct entqueue_s *queue);
|
||||
void glsl_R_RenderView (void);
|
||||
void glsl_R_ClearState (void);
|
||||
|
|
|
@ -149,6 +149,7 @@ include_qf_scene = \
|
|||
include/QF/scene/camera.h \
|
||||
include/QF/scene/entity.h \
|
||||
include/QF/scene/hierarchy.h \
|
||||
include/QF/scene/light.h \
|
||||
include/QF/scene/transform.h \
|
||||
include/QF/scene/scene.h \
|
||||
include/QF/scene/types.h
|
||||
|
@ -178,7 +179,6 @@ include_qf_vulkan = \
|
|||
include/QF/Vulkan/debug.h \
|
||||
include/QF/Vulkan/descriptor.h \
|
||||
include/QF/Vulkan/device.h \
|
||||
include/QF/Vulkan/draw.h \
|
||||
include/QF/Vulkan/funclist.h \
|
||||
include/QF/Vulkan/image.h \
|
||||
include/QF/Vulkan/instance.h \
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#ifndef __QF_Vulkan_barrier_h
|
||||
#define __QF_Vulkan_barrier_h
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
#define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct {
|
||||
VkPipelineStageFlags srcStages;
|
||||
VkPipelineStageFlags dstStages;
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#ifndef __QF_Vulkan_buffer_h
|
||||
#define __QF_Vulkan_buffer_h
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
#define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "QF/darray.h"
|
||||
|
||||
typedef struct qfv_buffertransition_s {
|
||||
|
|
|
@ -23,7 +23,9 @@ typedef struct qfv_capture_s {
|
|||
int canBlit;
|
||||
VkExtent2D extent;
|
||||
qfv_capture_image_set_t *image_set;
|
||||
size_t imgsize;
|
||||
size_t memsize;
|
||||
byte *data;
|
||||
VkDeviceMemory memory;
|
||||
} qfv_capture_t;
|
||||
|
||||
|
|
|
@ -1,237 +0,0 @@
|
|||
/*
|
||||
draw.h
|
||||
|
||||
Video buffer handling definitions and prototypes
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __QF_draw_h
|
||||
#define __QF_draw_h
|
||||
|
||||
/** \defgroup video Video Sub-sytem */
|
||||
|
||||
/** \defgroup video_renderer Renderer Sub-system
|
||||
\ingroup video
|
||||
*/
|
||||
|
||||
/** \defgroup video_renderer_draw Generic draw functions
|
||||
\ingroup video_renderer
|
||||
*/
|
||||
///@{
|
||||
|
||||
#include "QF/wad.h"
|
||||
|
||||
extern byte *draw_chars;
|
||||
|
||||
/** Initialize the draw stuff.
|
||||
*/
|
||||
void Draw_Init (void);
|
||||
|
||||
/** Draws one 8*8 graphics character with 0 being transparent.
|
||||
It can be clipped to the top of the screen to allow the console to be
|
||||
smoothly scrolled off.
|
||||
\param x horizontal location of the top left corner of the character.
|
||||
\param y vertical location of the top left corner of the character.
|
||||
\param ch 8 bit character to draw.
|
||||
\note The character drawn is from the quake character set, which is
|
||||
(by default) standard ascii for 0x20-0x7e (white). 0xa0-0xfe is
|
||||
also standard ascii (brown). 0x01-0x1f and 0x80-0x9f are
|
||||
various drawing characters, and 0x7f is a backwards arrow.
|
||||
*/
|
||||
void Draw_Character (int x, int y, unsigned ch);
|
||||
|
||||
/** Draws a character string to the screen.
|
||||
No line wrapping is performed.
|
||||
\param x horizontal location of the top left corner of the character.
|
||||
\param y vertical location of the top left corner of the character.
|
||||
\param str 8 bit character string to draw.
|
||||
\note See Draw_Character() for character set description.
|
||||
String is normal nul terminated C string.
|
||||
*/
|
||||
void Draw_String (int x, int y, const char *str);
|
||||
|
||||
/** Draws a character sub-string to the screen.
|
||||
No line wrapping is performed.
|
||||
\param x horizontal location of the top left corner of the character.
|
||||
\param y vertical location of the top left corner of the character.
|
||||
\param str 8 bit character string to draw.
|
||||
\param count Maximum characters of the string to draw.
|
||||
\note See Draw_Character() for character set description.
|
||||
Draws up to \p count characters, or stops at the first nul
|
||||
character.
|
||||
*/
|
||||
void Draw_nString (int x, int y, const char *str, int count);
|
||||
|
||||
/** Draws a character string to the screen.
|
||||
No line wrapping is performed.
|
||||
\param x horizontal location of the top left corner of the character.
|
||||
\param y vertical location of the top left corner of the character.
|
||||
\param str 8 bit character string to draw.
|
||||
\note See Draw_Character() for character set description.
|
||||
String is normal nul terminated C string.
|
||||
Characters of the string are forced to have their high bit set
|
||||
(ie, they will be in the range 0x80-0xff).
|
||||
*/
|
||||
void Draw_AltString (int x, int y, const char *str);
|
||||
|
||||
/** Draw the console background with various optional effects.
|
||||
\param lines Vertical size in pixels of the console.
|
||||
\param alpha Console transparency level (255 = opaque).
|
||||
\note \p alpha is effective only in the OpenGL renderer. Effectively
|
||||
255 (opaque) for the software renderer.
|
||||
|
||||
\c gl_conspin causes the background to spin.
|
||||
|
||||
\c gl_constretch causes the background to stretch rather than slide.
|
||||
*/
|
||||
void Draw_ConsoleBackground (int lines, byte alpha);
|
||||
|
||||
/** Draw a crosshair at the center of the screen.
|
||||
\c crosshair specifies which crosshair (1 = '+', 2 = large 'x' shape,
|
||||
3 = fancy '+' shape)
|
||||
\c cl_crossx and \c cl_crossy offset the crosshair from the center of the
|
||||
screen.
|
||||
*/
|
||||
void Draw_Crosshair (void);
|
||||
|
||||
/** Draw the specified crosshair on the screen.
|
||||
\param ch crosshair to draw
|
||||
\param x horizontal position of the center of the crosshair.
|
||||
\param y vertical position of the center of the crosshair.
|
||||
|
||||
See Draw_Crosshair() for description of crosshair values.
|
||||
*/
|
||||
void Draw_CrosshairAt (int ch, int x, int y);
|
||||
|
||||
/** Clear a rectangle with a tiled background.
|
||||
\param x horizontal position of the upper left corner of the rectangle
|
||||
\param y horizontal position of the upper left corner of the rectangle
|
||||
\param w width of the rectangle
|
||||
\param h height of the rectangle
|
||||
|
||||
The background used is the "backtile" WAD lump.
|
||||
*/
|
||||
void Draw_TileClear (int x, int y, int w, int h);
|
||||
|
||||
/** Clear a rectangle with a solid color.
|
||||
\param x horizontal position of the upper left corner of the rectangle
|
||||
\param y horizontal position of the upper left corner of the rectangle
|
||||
\param w width of the rectangle
|
||||
\param h height of the rectangle
|
||||
\param c 8 bit color index.
|
||||
|
||||
The color comes from the quake palette.
|
||||
*/
|
||||
void Draw_Fill (int x, int y, int w, int h, int c);
|
||||
|
||||
/** Draw a text box on the screen
|
||||
\param x horizontal location of the upper left corner of the box
|
||||
\param y vertical location of the upper left corner of the box
|
||||
\param width horizontal size in character cells of the region
|
||||
\param lines vertical size in character cells of the region
|
||||
\param alpha transparency of the box
|
||||
*/
|
||||
void Draw_TextBox (int x, int y, int width, int lines, byte alpha);
|
||||
|
||||
/** Darken the screen.
|
||||
*/
|
||||
void Draw_FadeScreen (void);
|
||||
|
||||
/** Shift the screen colors.
|
||||
*/
|
||||
void Draw_BlendScreen (quat_t color);
|
||||
///@}
|
||||
|
||||
/** \defgroup video_renderer_draw_qpic QPic functions
|
||||
\ingroup video_renderer_draw
|
||||
*/
|
||||
///@{
|
||||
/** Load a qpic from the filesystem.
|
||||
\param path path of the file within the quake filesystem
|
||||
\param alpha transparency level of the pic.
|
||||
\return pointer qpic data.
|
||||
\note Up to MAX_CACHED_PICS qpics can be loaded at a time this way
|
||||
*/
|
||||
qpic_t *Draw_CachePic (const char *path, qboolean alpha);
|
||||
|
||||
/** Remove a qpic from the qpic cache.
|
||||
|
||||
This affects only those qpics that were loaded via Draw_CachePic.
|
||||
|
||||
\param path path of the file within the quake filesystem
|
||||
*/
|
||||
void Draw_UncachePic (const char *path);
|
||||
|
||||
/** Create a qpic from raw data.
|
||||
|
||||
\param width The width of the pic.
|
||||
\param height The height of the pic.
|
||||
\param data The raw data bytes. The system palette will be used for
|
||||
colors.
|
||||
\return pointer qpic data.
|
||||
*/
|
||||
qpic_t *Draw_MakePic (int width, int height, const byte *data);
|
||||
|
||||
/** Destroy a qpic created by Draw_MakePic.
|
||||
|
||||
\param pic The qpic to destory.
|
||||
*/
|
||||
void Draw_DestroyPic (qpic_t *pic);
|
||||
|
||||
/** Load a qpic from gfx.wad.
|
||||
\param name name of the was lump to load
|
||||
\return pointer qpic data.
|
||||
*/
|
||||
qpic_t *Draw_PicFromWad (const char *name);
|
||||
|
||||
/** Draw a qpic to the screen
|
||||
\param x horizontal location of the upper left corner of the qpic
|
||||
\param y vertical location of the upper left corner of the qpic
|
||||
\param pic qpic to draw
|
||||
*/
|
||||
void Draw_Pic (int x, int y, qpic_t *pic);
|
||||
|
||||
/** Draw a qpic to the screen
|
||||
\param x horizontal location of the upper left corner of the qpic
|
||||
\param y vertical location of the upper left corner of the qpic
|
||||
\param pic qpic to draw
|
||||
*/
|
||||
void Draw_Picf (float x, float y, qpic_t *pic);
|
||||
|
||||
/** Draw a sub-region of a qpic to the screan
|
||||
\param x horizontal screen location of the upper left corner of the
|
||||
sub-region
|
||||
\param y vertical screen location of the upper left corner of the
|
||||
sub-region
|
||||
\param pic qpic to draw
|
||||
\param srcx horizontal qpic location of the upper left corner of the
|
||||
sub-region
|
||||
\param srcy vertical qpic location of the upper left corner of the
|
||||
sub-region
|
||||
\param width horizontal size of the sub-region to be drawn
|
||||
\param height vertical size of the sub-region to be drawn
|
||||
*/
|
||||
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
|
||||
///@}
|
||||
|
||||
#endif//__QF_draw_h
|
|
@ -131,6 +131,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeMemory)
|
|||
DEVICE_LEVEL_VULKAN_FUNCTION (vkMapMemory)
|
||||
DEVICE_LEVEL_VULKAN_FUNCTION (vkUnmapMemory)
|
||||
DEVICE_LEVEL_VULKAN_FUNCTION (vkFlushMappedMemoryRanges)
|
||||
DEVICE_LEVEL_VULKAN_FUNCTION (vkInvalidateMappedMemoryRanges)
|
||||
|
||||
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSampler)
|
||||
DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateDescriptorSetLayout)
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
#ifndef __QF_Vulkan_image_h
|
||||
#define __QF_Vulkan_image_h
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
#define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/image.h"
|
||||
|
||||
typedef struct qfv_imageset_s
|
||||
DARRAY_TYPE (VkImage) qfv_imageset_t;
|
||||
|
@ -95,4 +101,14 @@ void QFV_GenerateMipMaps (struct qfv_device_s *device, VkCommandBuffer cmd,
|
|||
unsigned width, unsigned height, unsigned layers);
|
||||
int QFV_MipLevels (int width, int height) __attribute__((const));
|
||||
|
||||
/** Convert QFFormat to VkFormat
|
||||
*
|
||||
* \param format The format to convert.
|
||||
* \return The corresponding VkFormat.
|
||||
*
|
||||
* \note For tex_palette, VK_FORMAT_R8_UINT is returned. If \a format is
|
||||
* not a valid QFFormat, then VK_FORMAT_R8_SRGB is returned.
|
||||
*/
|
||||
VkFormat QFV_ImageFormat (QFFormat format);
|
||||
|
||||
#endif//__QF_Vulkan_image_h
|
||||
|
|
|
@ -94,10 +94,8 @@ struct qfv_renderframe_s;
|
|||
struct entity_s;
|
||||
struct mod_alias_ctx_s;
|
||||
|
||||
void *Vulkan_Mod_LoadSkin (struct mod_alias_ctx_s *alias_ctx, byte *skin,
|
||||
int skinsize, int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Mod_LoadAllSkins (struct mod_alias_ctx_s *alias_ctx,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Mod_FinalizeAliasModel (struct mod_alias_ctx_s *alias_ctx,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Mod_LoadExternalSkins (struct mod_alias_ctx_s *alias_ctx,
|
||||
|
|
113
include/QF/Vulkan/qf_iqm.h
Normal file
113
include/QF/Vulkan/qf_iqm.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
qf_iqm.h
|
||||
|
||||
Vulkan specific iqm model stuff
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2022/5/3
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifndef __QF_Vulkan_qf_iqm_h
|
||||
#define __QF_Vulkan_qf_iqm_h
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/model.h"
|
||||
#include "QF/modelgen.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
|
||||
// geometry attributes
|
||||
typedef struct iqmgvert_s {
|
||||
float vertex[3];
|
||||
byte bones[4]; // uint
|
||||
byte weights[4]; // unorm
|
||||
} iqmgvert_t;
|
||||
|
||||
// rendering attributes
|
||||
typedef struct iqmrvert_s {
|
||||
float uv[2];
|
||||
float normal[3];
|
||||
float tangent[4];
|
||||
byte color[4]; // unorm
|
||||
} iqmrvert_t;
|
||||
|
||||
typedef struct qfv_iqm_skin_s {
|
||||
VkImageView view;
|
||||
byte colora[4];
|
||||
byte colorb[4];
|
||||
VkDescriptorSet descriptor;
|
||||
} qfv_iqm_skin_t;
|
||||
|
||||
typedef struct qfv_iqm_s {
|
||||
VkBuffer geom_buffer;
|
||||
VkBuffer rend_buffer;
|
||||
VkBuffer index_buffer;
|
||||
qfv_iqm_skin_t *skins;
|
||||
struct qfv_resource_s *mesh;
|
||||
struct qfv_resource_s *bones;
|
||||
} qfv_iqm_t;
|
||||
|
||||
typedef enum {
|
||||
QFV_iqmDepth,
|
||||
QFV_iqmGBuffer,
|
||||
QFV_iqmTranslucent,
|
||||
|
||||
QFV_iqmNumPasses
|
||||
} QFV_IQMSubpass;
|
||||
|
||||
typedef struct iqm_frame_s {
|
||||
qfv_cmdbufferset_t cmdSet;
|
||||
} iqm_frame_t;
|
||||
|
||||
typedef struct iqm_frameset_s
|
||||
DARRAY_TYPE (iqm_frame_t) iqm_frameset_t;
|
||||
|
||||
typedef struct iqmindset_s
|
||||
DARRAY_TYPE (unsigned) iqmindset_t;
|
||||
|
||||
typedef struct iqmctx_s {
|
||||
iqm_frameset_t frames;
|
||||
VkPipeline depth;
|
||||
VkPipeline gbuf;
|
||||
VkPipelineLayout layout;
|
||||
VkSampler sampler;
|
||||
} iqmctx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
struct qfv_renderframe_s;
|
||||
struct entity_s;
|
||||
struct mod_iqm_ctx_s;
|
||||
|
||||
void Vulkan_Mod_IQMFinish (struct model_s *mod, struct vulkan_ctx_s *ctx);
|
||||
|
||||
void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin);
|
||||
void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin);
|
||||
|
||||
void Vulkan_IQMBegin (struct qfv_renderframe_s *rFrame);
|
||||
void Vulkan_DrawIQM (struct entity_s *ent, struct qfv_renderframe_s *rFrame);
|
||||
void Vulkan_IQMEnd (struct qfv_renderframe_s *rFrame);
|
||||
|
||||
void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_IQM_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
|
||||
#endif//__QF_Vulkan_qf_iqm_h
|
|
@ -33,53 +33,26 @@
|
|||
#include "QF/darray.h"
|
||||
#include "QF/model.h"
|
||||
#include "QF/modelgen.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
typedef struct qfv_light_s {
|
||||
vec3_t color;
|
||||
int data;
|
||||
vec3_t position;
|
||||
float light;
|
||||
vec3_t direction;
|
||||
float cone;
|
||||
} qfv_light_t;
|
||||
|
||||
typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t;
|
||||
typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightintset_t;
|
||||
typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t;
|
||||
typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t;
|
||||
|
||||
#define MaxLights 256
|
||||
|
||||
#define StyleMask 0x07f
|
||||
#define ModelMask 0x380
|
||||
#define ShadowMask 0xc00
|
||||
|
||||
#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve)
|
||||
#define LM_INVERSE (1 << 7) // distFactor1 * light / dist
|
||||
#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist)
|
||||
#define LM_INFINITE (3 << 7) // light
|
||||
#define LM_AMBIENT (4 << 7) // light
|
||||
#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2
|
||||
|
||||
#define ST_NONE (0 << 10) // no shadows
|
||||
#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight)
|
||||
#define ST_CASCADE (2 << 10) // cascaded shadow maps
|
||||
#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight)
|
||||
|
||||
#define NumStyles 64
|
||||
#define ST_NONE 0 // no shadows
|
||||
#define ST_PLANE 1 // single plane shadow map (small spotlight)
|
||||
#define ST_CASCADE 2 // cascaded shadow maps
|
||||
#define ST_CUBE 3 // cubemap (omni, large spotlight)
|
||||
|
||||
typedef struct qfv_light_buffer_s {
|
||||
float intensity[NumStyles + 4];
|
||||
float distFactor1;
|
||||
float distFactor2;
|
||||
light_t lights[MaxLights] __attribute__((aligned(16)));
|
||||
int lightCount;
|
||||
qfv_light_t lights[MaxLights] __attribute__((aligned(16)));
|
||||
mat4f_t shadowMat[MaxLights];
|
||||
vec4f_t shadowCascade[MaxLights];
|
||||
//mat4f_t shadowMat[MaxLights];
|
||||
//vec4f_t shadowCascade[MaxLights];
|
||||
} qfv_light_buffer_t;
|
||||
|
||||
#define LIGHTING_BUFFER_INFOS 1
|
||||
|
@ -101,11 +74,6 @@ typedef struct lightingframe_s {
|
|||
VkWriteDescriptorSet shadowWrite;
|
||||
};
|
||||
};
|
||||
// A fat PVS of leafs visible from visible leafs so hidden lights can
|
||||
// illuminate the leafs visible to the player
|
||||
struct set_s *pvs;
|
||||
struct mleaf_s *leaf; // the last leaf used to generate the pvs
|
||||
qfv_lightvisset_t lightvis;
|
||||
} lightingframe_t;
|
||||
|
||||
typedef struct lightingframeset_s
|
||||
|
@ -118,13 +86,13 @@ typedef struct lightingctx_s {
|
|||
VkSampler sampler;
|
||||
VkDeviceMemory light_memory;
|
||||
VkDeviceMemory shadow_memory;
|
||||
qfv_lightset_t lights;
|
||||
qfv_lightintset_t lightleafs;
|
||||
qfv_lightmatset_t lightmats;
|
||||
qfv_imageset_t lightimages;
|
||||
qfv_lightintset_t lightlayers;
|
||||
lightintset_t lightlayers;
|
||||
qfv_imageviewset_t lightviews;
|
||||
struct set_s *sun_pvs;
|
||||
|
||||
struct lightingdata_s *ldata;
|
||||
struct scene_s *scene;
|
||||
} lightingctx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
|
@ -133,7 +101,6 @@ struct qfv_renderframe_s;
|
|||
void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame);
|
||||
void Vulkan_LoadLights (model_t *model, const char *entity_data,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx);
|
||||
|
||||
#endif//__QF_Vulkan_qf_lighting_h
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
struct vulkan_ctx_s;
|
||||
struct qfv_renderframe_s;
|
||||
struct entqueue_s;
|
||||
struct scene_s;
|
||||
|
||||
void Vulkan_NewMap (model_t *worldmodel, struct model_s **models,
|
||||
int num_models, struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_RenderView (struct qfv_renderframe_s *rFrame);
|
||||
void Vulkan_RenderEntities (struct entqueue_s *queue,
|
||||
struct qfv_renderframe_s *rFrame);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
vulkan vid stuff from the renderer.
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
@ -40,8 +40,8 @@ typedef enum {
|
|||
QFV_passDepth, // geometry
|
||||
QFV_passTranslucent, // geometry
|
||||
QFV_passGBuffer, // geometry
|
||||
QFV_passLighting, // single quad
|
||||
QFV_passCompose, // single quad
|
||||
QFV_passLighting, // single triangle
|
||||
QFV_passCompose, // single triangle
|
||||
|
||||
QFV_NumPasses
|
||||
} QFV_Subpass;
|
||||
|
|
|
@ -70,6 +70,8 @@ typedef struct qfv_renderpass_s {
|
|||
VkDeviceMemory attachmentMemory;
|
||||
|
||||
qfv_framebufferset_t *framebuffers;
|
||||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
|
||||
qfv_renderframeset_t frames;
|
||||
|
||||
|
|
68
include/QF/Vulkan/resource.h
Normal file
68
include/QF/Vulkan/resource.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef __QF_Vulkan_resource_h
|
||||
#define __QF_Vulkan_resource_h
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
#define VK_NO_PROTOTYPES
|
||||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef enum {
|
||||
qfv_res_buffer = 1,
|
||||
qfv_res_buffer_view,
|
||||
qfv_res_image,
|
||||
qfv_res_image_view,
|
||||
} qfv_res_type;
|
||||
|
||||
typedef struct qfv_resobj_s {
|
||||
const char *name;
|
||||
qfv_res_type type;
|
||||
union {
|
||||
struct {
|
||||
VkDeviceSize size;
|
||||
VkBufferUsageFlags usage;
|
||||
VkBuffer buffer;
|
||||
} buffer;
|
||||
struct {
|
||||
unsigned buffer;
|
||||
VkFormat format;
|
||||
VkDeviceSize offset;
|
||||
VkDeviceSize size;
|
||||
VkBufferView view;
|
||||
} buffer_view;
|
||||
struct {
|
||||
int cubemap;
|
||||
VkImageType type;
|
||||
VkFormat format;
|
||||
VkExtent3D extent;
|
||||
uint32_t num_mipmaps;
|
||||
uint32_t num_layers;
|
||||
VkSampleCountFlags samples;
|
||||
VkImageUsageFlags usage;
|
||||
VkImage image;
|
||||
} image;
|
||||
struct {
|
||||
unsigned image;
|
||||
VkImageViewType type;
|
||||
VkFormat format;
|
||||
VkImageAspectFlags aspect;
|
||||
VkImageView view;
|
||||
} image_view;
|
||||
};
|
||||
} qfv_resobj_t;
|
||||
|
||||
typedef struct qfv_resource_s {
|
||||
const char *name;
|
||||
struct va_ctx_s *va_ctx;
|
||||
VkMemoryPropertyFlags memory_properties;
|
||||
unsigned num_objects;
|
||||
qfv_resobj_t *objects;
|
||||
VkDeviceMemory memory;
|
||||
} qfv_resource_t;
|
||||
|
||||
struct qfv_device_s;
|
||||
|
||||
int QFV_CreateResource (struct qfv_device_s *device, qfv_resource_t *resource);
|
||||
void QFV_DestroyResource (struct qfv_device_s *device,
|
||||
qfv_resource_t *resource);
|
||||
|
||||
#endif//__QF_Vulkan_resource_h
|
|
@ -28,6 +28,9 @@
|
|||
#ifndef __QF_input_h
|
||||
#define __QF_input_h
|
||||
|
||||
/** \defgroup input Input Sub-system */
|
||||
|
||||
///@{
|
||||
typedef struct in_axisinfo_s {
|
||||
int deviceid;
|
||||
int axis;
|
||||
|
@ -135,4 +138,6 @@ extern int lookstrafe;
|
|||
|
||||
#endif
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__QF_input_h
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
#include "QF/mathlib.h"
|
||||
#endif
|
||||
|
||||
/** \defgroup input_bindings Input Bindings
|
||||
\ingroup input
|
||||
*/
|
||||
///@{
|
||||
|
||||
/*** Recipe for converting an axis to a floating point value.
|
||||
|
||||
Absolute axes are converted to the 0..1 range for unbalanced axes, and
|
||||
|
@ -366,4 +371,6 @@ void IN_Binding_LoadConfig (struct plitem_s *config);
|
|||
|
||||
#endif
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__QF_input_binding_h
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
|
||||
#include "QF/qtypes.h"
|
||||
|
||||
/** \defgroup input_events Input Events
|
||||
\ingroup input
|
||||
*/
|
||||
///@{
|
||||
|
||||
typedef struct {
|
||||
int xpos, ypos;
|
||||
int xlen, ylen;
|
||||
|
@ -122,4 +127,6 @@ void IE_Remove_Handler (int handle);
|
|||
void IE_Set_Focus (int handle);
|
||||
int IE_Get_Focus (void) __attribute__ ((pure));
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__QF_in_event_h
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
#ifndef __QF_input_imt_h
|
||||
#define __QF_input_imt_h
|
||||
|
||||
/** \defgroup input_imt Input Mapping Tables
|
||||
\ingroup input
|
||||
*/
|
||||
///@{
|
||||
|
||||
#ifndef __QFCC__
|
||||
|
||||
#include "QF/darray.h"
|
||||
|
@ -134,4 +139,6 @@ void IMT_LoadConfig (struct plitem_s *config);
|
|||
|
||||
#endif
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__QF_input_imt_h
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
# include "QF/quakeio.h"
|
||||
#endif
|
||||
|
||||
/** \defgroup input Input Sub-system */
|
||||
|
||||
/** \defgroup input_keybinding Key Binding Sub-system
|
||||
\ingroup input
|
||||
*/
|
||||
|
|
|
@ -438,6 +438,7 @@ void Mod_Init_Cvars (void);
|
|||
void Mod_ClearAll (void);
|
||||
model_t *Mod_ForName (const char *name, qboolean crash);
|
||||
void Mod_TouchModel (const char *name);
|
||||
void Mod_UnloadModel (model_t *model);
|
||||
// brush specific
|
||||
mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure));
|
||||
struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model);
|
||||
|
|
|
@ -67,12 +67,12 @@ struct plfield_s;
|
|||
dictionary objects.
|
||||
|
||||
If null, then the default parser for the object type is used:
|
||||
* QFString: the point to the actual string. The string continues
|
||||
to be owned by the string object.
|
||||
* QFString: pointer to the actual string. The string continues to
|
||||
be owned by the string object.
|
||||
* QFBinary: pointer to fixed-size DARRAY_TYPE(byte) (so size isn't
|
||||
lost)
|
||||
* QFArray: pointer to fixed-size DARRAY_TYPE(plitem_t *) with the
|
||||
indivisual objects. The individual objects continue to be owned
|
||||
individual objects. The individual objects continue to be owned
|
||||
by the array object.
|
||||
* QFDictionary: pointer to the hashtab_t hash table used for the
|
||||
dictionary object. The hash table continues to be owned by the
|
||||
|
@ -86,7 +86,9 @@ struct plfield_s;
|
|||
checking is done: it is up to the top-level caller to
|
||||
parse out the messages.
|
||||
\param context Additional context data passed to the parser.
|
||||
\return 0 for error, 1 for success. See \a PL_ParseDictionary.
|
||||
\return 0 for error, 1 for success. See \a PL_ParseStruct,
|
||||
\a PL_ParseArray, \a PL_ParseLabeledArray, and
|
||||
\a PL_ParseSymtab.
|
||||
*/
|
||||
typedef int (*plparser_t) (const struct plfield_s *field,
|
||||
const struct plitem_s *item,
|
||||
|
@ -96,7 +98,15 @@ typedef int (*plparser_t) (const struct plfield_s *field,
|
|||
|
||||
/** A field to be parsed from a dictionary item.
|
||||
|
||||
something
|
||||
\a PL_ParseStruct uses an array (terminated by an element with \a name
|
||||
set to null) of these to describe the fields in the structure being
|
||||
parsed.
|
||||
|
||||
\a PL_ParseArray, \a PL_ParseLabeledArray, and \a PL_ParseSymtab use only
|
||||
a single \a plfield_t object, and then only the \a data field, which must
|
||||
point to a \a plelement_t object. This allows all the parse functions to
|
||||
be used directly as either a \a plfield_t or \a plelement_t object's
|
||||
\a parser.
|
||||
*/
|
||||
typedef struct plfield_s {
|
||||
const char *name; ///< matched by dictionary key
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
struct plitem_s;
|
||||
struct cvar_s;
|
||||
struct scene_s;
|
||||
struct skin_s;
|
||||
|
||||
struct mod_alias_ctx_s;
|
||||
|
@ -58,9 +59,7 @@ typedef struct vid_model_funcs_s {
|
|||
void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer);
|
||||
void (*Mod_MakeAliasModelDisplayLists) (struct mod_alias_ctx_s *alias_ctx,
|
||||
void *_m, int _s, int extra);
|
||||
void *(*Mod_LoadSkin) (struct mod_alias_ctx_s *alias_ctx, byte *skin,
|
||||
int skinsize, int snum, int gnum,
|
||||
qboolean group, maliasskindesc_t *skindesc);
|
||||
void (*Mod_LoadAllSkins) (struct mod_alias_ctx_s *alias_ctx);
|
||||
void (*Mod_FinalizeAliasModel) (struct mod_alias_ctx_s *alias_ctx);
|
||||
void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx);
|
||||
void (*Mod_IQMFinish) (model_t *mod);
|
||||
|
@ -107,7 +106,7 @@ typedef struct vid_render_funcs_s {
|
|||
void (*R_Init) (void);
|
||||
void (*R_ClearState) (void);
|
||||
void (*R_LoadSkys) (const char *);
|
||||
void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models);
|
||||
void (*R_NewScene) (struct scene_s *scene);
|
||||
void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height);
|
||||
|
||||
void (*begin_frame) (void);
|
||||
|
|
|
@ -433,7 +433,9 @@ typedef enum {
|
|||
#define OP_BREAK 0x8000
|
||||
|
||||
typedef enum {
|
||||
#ifndef IN_DOXYGEN
|
||||
#include "QF/progs/pr_opcode.hinc"
|
||||
#endif
|
||||
} pr_opcode_e;
|
||||
|
||||
// Used for both branch and comparison, with jump and call being ignored for
|
||||
|
|
|
@ -167,7 +167,6 @@ typedef struct {
|
|||
int drawflat;
|
||||
|
||||
struct model_s *worldmodel;
|
||||
struct mleaf_s *viewleaf;
|
||||
} refdef_t;
|
||||
|
||||
// REFRESH ====================================================================
|
||||
|
|
80
include/QF/scene/light.h
Normal file
80
include/QF/scene/light.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
light.h
|
||||
|
||||
Entity management
|
||||
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2021/02/26
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __QF_scene_light_h
|
||||
#define __QF_scene_light_h
|
||||
|
||||
#include "QF/darray.h"
|
||||
#include "QF/qtypes.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
struct mod_brush_s;
|
||||
|
||||
#define NumStyles 64
|
||||
|
||||
#define LM_LINEAR 0 // light - dist (or radius + dist if -ve)
|
||||
#define LM_INVERSE 1 // distFactor1 * light / dist
|
||||
#define LM_INVERSE2 2 // distFactor2 * light / (dist * dist)
|
||||
#define LM_INFINITE 3 // light
|
||||
#define LM_AMBIENT 4 // light
|
||||
#define LM_INVERSE3 5 // distFactor2 * light / (dist + distFactor2)**2
|
||||
|
||||
typedef struct light_s {
|
||||
vec4f_t color;
|
||||
vec4f_t position;
|
||||
vec4f_t direction;
|
||||
vec4f_t attenuation;
|
||||
} light_t;
|
||||
|
||||
typedef struct lightset_s DARRAY_TYPE (light_t) lightset_t;
|
||||
typedef struct lightleafset_s DARRAY_TYPE (int) lightintset_t;
|
||||
typedef struct lightvisset_s DARRAY_TYPE (byte) lightvisset_t;
|
||||
|
||||
typedef struct lightingdata_s {
|
||||
lightset_t lights;
|
||||
lightintset_t lightstyles;
|
||||
lightintset_t lightleafs;
|
||||
lightvisset_t lightvis;
|
||||
struct set_s *sun_pvs;
|
||||
// A fat PVS of leafs visible from visible leafs so hidden lights can
|
||||
// illuminate the leafs visible to the player
|
||||
struct set_s *pvs;
|
||||
struct mleaf_s *leaf; // the last leaf used to generate the pvs
|
||||
struct scene_s *scene;
|
||||
} lightingdata_t;
|
||||
|
||||
lightingdata_t *Light_CreateLightingData (struct scene_s *scene);
|
||||
void Light_DestroyLightingData (lightingdata_t *ldata);
|
||||
void Light_ClearLights (lightingdata_t *ldata);
|
||||
void Light_AddLight (lightingdata_t *ldata, const light_t *light, int style);
|
||||
void Light_EnableSun (lightingdata_t *ldata);
|
||||
void Light_FindVisibleLights (lightingdata_t *ldata);
|
||||
|
||||
#endif//__QF_scene_light_h
|
|
@ -43,6 +43,11 @@
|
|||
typedef struct scene_s {
|
||||
struct scene_resources_s *const resources;
|
||||
struct hierarchy_s *hierarchies;
|
||||
struct model_s *worldmodel;
|
||||
int num_models;
|
||||
struct model_s **models;
|
||||
struct mleaf_s *viewleaf;
|
||||
struct lightingdata_s *lights;
|
||||
} scene_t;
|
||||
|
||||
scene_t *Scene_NewScene (void);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#ifndef __QF_screen_h
|
||||
#define __QF_screen_h
|
||||
|
||||
struct scene_s;
|
||||
struct transform_s;
|
||||
struct tex_s;
|
||||
|
||||
|
@ -47,6 +48,8 @@ void SCR_SetFOV (float fov);
|
|||
void SCR_SetFullscreen (qboolean fullscreen);
|
||||
void SCR_SetBottomMargin (int lines);
|
||||
|
||||
void SCR_NewScene (struct scene_s *scene);
|
||||
|
||||
extern int hud_fps;
|
||||
extern int hud_time;
|
||||
extern int r_timegraph;
|
||||
|
|
|
@ -175,7 +175,7 @@ mat4fquat (mat4f_t m, vec4f_t q)
|
|||
vec4f_t b = _mm_xor_ps (shuff103 (yq), (__m128) mpm);
|
||||
vec4f_t c = _mm_xor_ps (shuff230 (zq), (__m128) pmm);
|
||||
vec4f_t d = _mm_xor_ps (shuff321 (wq), (__m128) mmp);
|
||||
|
||||
// column: ww + xx - yy - zz // 2xy + 2wz // 2zx - 2wy // 0
|
||||
m[0] = _mm_and_ps (a + b - c - d, (__m128) mask);
|
||||
}
|
||||
{
|
||||
|
@ -183,6 +183,7 @@ mat4fquat (mat4f_t m, vec4f_t q)
|
|||
vec4f_t b = yq;
|
||||
vec4f_t c = _mm_xor_ps (shuff321 (zq), (__m128) mmp);
|
||||
vec4f_t d = _mm_xor_ps (shuff230 (wq), (__m128) pmm);
|
||||
// column: 2xy - 2wz // ww - xx + yy - zz // 2yz + 2wx // 0
|
||||
m[1] = _mm_and_ps (b + c - a - d, (__m128) mask);
|
||||
}
|
||||
{
|
||||
|
@ -190,6 +191,7 @@ mat4fquat (mat4f_t m, vec4f_t q)
|
|||
vec4f_t b = _mm_xor_ps (shuff321 (yq), (__m128) mmp);
|
||||
vec4f_t c = zq;
|
||||
vec4f_t d = _mm_xor_ps (shuff103 (wq), (__m128) mpm);
|
||||
// column: 2xz + 2wy // 2yz - 2wx // ww - xx - yy + zz // 0
|
||||
m[2] = _mm_and_ps (a - b + c - d, (__m128) mask);
|
||||
}
|
||||
m[3] = (vec4f_t) { 0, 0, 0, 1 };
|
||||
|
|
|
@ -133,9 +133,6 @@ void S_StopAllSounds(void);
|
|||
render some sound.
|
||||
\param ear Transform for the position and orientation of the stereo
|
||||
sound pickup.
|
||||
\param v_forward 3d vector of the client's facing direction
|
||||
\param v_right 3d vector of the client's rightward direction
|
||||
\param v_up 3d vector of the client's upward direction
|
||||
\param ambient_sound_level NUM_AMBIENTS bytes indicating current ambient
|
||||
sound levels
|
||||
*/
|
||||
|
|
|
@ -44,6 +44,7 @@ SYS_DEVELOPER (glt)
|
|||
SYS_DEVELOPER (glsl)
|
||||
SYS_DEVELOPER (skin)
|
||||
SYS_DEVELOPER (model)
|
||||
SYS_DEVELOPER (lighting)
|
||||
SYS_DEVELOPER (vulkan)
|
||||
SYS_DEVELOPER (vulkan_parse)
|
||||
|
||||
|
|
|
@ -44,6 +44,17 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
targa_colormap = 1,
|
||||
targa_truecolor = 2,
|
||||
targa_greyscale = 3,
|
||||
targa_colormap_rle = 9,
|
||||
targa_truecolor_rle = 10,
|
||||
targa_greyscale_rle = 11,
|
||||
|
||||
targa_max_image_type = 15
|
||||
} TargaImageType;
|
||||
|
||||
typedef struct _TargaHeader {
|
||||
unsigned char id_length; // __attribute__((packed));
|
||||
unsigned char colormap_type; // __attribute__((packed));
|
||||
|
|
|
@ -43,7 +43,6 @@ typedef struct worldscene_s {
|
|||
struct scene_s *scene;
|
||||
struct plitem_s *edicts;
|
||||
struct plitem_s *worldspawn;
|
||||
struct model_s *worldmodel;
|
||||
modelset_t models;
|
||||
} worldscene_t;
|
||||
|
||||
|
@ -51,6 +50,7 @@ extern worldscene_t cl_world;
|
|||
|
||||
struct msg_s;
|
||||
struct entity_state_s;
|
||||
struct lightingdata_s;
|
||||
|
||||
void CL_World_Init (void);
|
||||
|
||||
|
@ -66,5 +66,6 @@ void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline,
|
|||
void CL_ParseStatic (struct msg_s *msg, int version);
|
||||
void CL_MapCfg (const char *mapname);
|
||||
void CL_World_NewMap (const char *mapname, const char *skyname);
|
||||
void CL_LoadLights (struct plitem_s *entities, struct scene_s *scene);
|
||||
|
||||
#endif//__client_world_h
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Linux Frame Buffer Device Configuration
|
||||
*
|
||||
* © Copyright 1995-1998 by Geert Uytterhoeven
|
||||
* © Copyright 1995-1998 by Geert Uytterhoeven
|
||||
* (Geert.Uytterhoeven@cs.kuleuven.ac.be)
|
||||
*
|
||||
* --------------------------------------------------------------------------
|
||||
|
|
|
@ -7,9 +7,17 @@
|
|||
#include "QF/skin.h"
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
typedef struct mod_alias_skin_s {
|
||||
int skin_num;
|
||||
int group_num; // -1 if not in an animated group
|
||||
byte *texels;
|
||||
maliasskindesc_t *skindesc;
|
||||
} mod_alias_skin_t;
|
||||
|
||||
typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t;
|
||||
typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t;
|
||||
typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t;
|
||||
typedef struct askinset_s DARRAY_TYPE (mod_alias_skin_t) askinset_t;
|
||||
|
||||
typedef struct mod_alias_ctx_s {
|
||||
aliashdr_t *header;
|
||||
|
@ -17,6 +25,7 @@ typedef struct mod_alias_ctx_s {
|
|||
stvertset_t stverts;
|
||||
mtriangleset_t triangles;
|
||||
trivertxset_t poseverts;
|
||||
askinset_t skins;
|
||||
int aliasbboxmins[3];
|
||||
int aliasbboxmaxs[3];
|
||||
} mod_alias_ctx_t;
|
||||
|
@ -49,27 +58,21 @@ extern vid_model_funcs_t *m_funcs;
|
|||
|
||||
void gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
|
||||
int _s, int extra);
|
||||
void *gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc);
|
||||
void gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
|
||||
void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx);
|
||||
void gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx);
|
||||
void gl_Mod_IQMFinish (model_t *mod);
|
||||
|
||||
void glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx,
|
||||
void *_m, int _s, int extra);
|
||||
void *glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc);
|
||||
void glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
|
||||
void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx);
|
||||
void glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx);
|
||||
void glsl_Mod_IQMFinish (model_t *mod);
|
||||
|
||||
void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
|
||||
int _s, int extra);
|
||||
void *sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc);
|
||||
void sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx);
|
||||
void sw_Mod_IQMFinish (model_t *mod);
|
||||
|
||||
void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp);
|
||||
|
|
|
@ -45,7 +45,8 @@ struct psystem_s *glsl_ParticleSystem (void);
|
|||
struct psystem_s *sw_ParticleSystem (void);
|
||||
void R_RunParticles (float dT);
|
||||
|
||||
void R_NewMap (model_t *worldmodel, model_t **models, int num_models);
|
||||
struct scene_s;
|
||||
void R_NewScene (struct scene_s *scene);
|
||||
|
||||
// LordHavoc: relative bmodel lighting
|
||||
void R_PushDlights (const vec3_t entorigin);
|
||||
|
@ -73,7 +74,7 @@ struct entity_s;
|
|||
struct animation_s;
|
||||
void R_DrawAliasModel (struct entity_s *e);
|
||||
|
||||
void R_MarkLeaves (void);
|
||||
void R_MarkLeaves (struct mleaf_s *viewleaf);
|
||||
|
||||
void GL_SetPalette (void *data, const byte *palette);
|
||||
void GLSL_SetPalette (void *data, const byte *palette);
|
||||
|
|
|
@ -202,8 +202,6 @@ extern void R_RotateBmodel (struct transform_s *transform);
|
|||
extern int c_faceclip;
|
||||
extern int r_polycount;
|
||||
|
||||
extern model_t *cl_worldmodel;
|
||||
|
||||
extern int *pfrustum_indexes[4];
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
|
|
|
@ -62,6 +62,9 @@ struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle);
|
|||
|
||||
void RUA_Input_Init (struct progs_s *pr, int secure);
|
||||
void RUA_Mersenne_Init (struct progs_s *pr, int secure);
|
||||
void RUA_Model_Init (struct progs_s *pr, int secure);
|
||||
struct model_s *Model_GetModel (progs_t *pr, int handle);
|
||||
void RUA_Scene_Init (struct progs_s *pr, int secure);
|
||||
struct scene_s *Scene_GetScene (struct progs_s *pr, pr_ulong_t handle);
|
||||
|
||||
#endif//__rua_internal_h
|
||||
|
|
|
@ -353,10 +353,8 @@ void SND_AmbientOn (snd_t *snd);
|
|||
/** Update the sound engine with the client's position and orientation and
|
||||
render some sound.
|
||||
\param snd sound system state
|
||||
\param origin 3d coords of the client
|
||||
\param v_forward 3d vector of the client's facing direction
|
||||
\param v_right 3d vector of the client's rightward direction
|
||||
\param v_up 3d vector of the client's upward direction
|
||||
\param ear Transform for the position and orientation of the stereo
|
||||
sound pickup.
|
||||
\param ambient_sound_level Pointer to 4 bytes indicating the levels at
|
||||
which to play the ambient sounds.
|
||||
*/
|
||||
|
|
|
@ -67,15 +67,13 @@ typedef struct vulkan_ctx_s {
|
|||
struct matrixctx_s *matrix_context;
|
||||
struct aliasctx_s *alias_context;
|
||||
struct bspctx_s *bsp_context;
|
||||
struct iqmctx_s *iqm_context;
|
||||
struct particlectx_s *particle_context;
|
||||
struct spritectx_s *sprite_context;
|
||||
struct drawctx_s *draw_context;
|
||||
struct lightingctx_s *lighting_context;
|
||||
struct composectx_s *compose_context;
|
||||
|
||||
VkBuffer quad_buffer;
|
||||
VkDeviceMemory quad_memory;
|
||||
|
||||
VkCommandPool cmdpool;
|
||||
VkCommandBuffer cmdbuffer;
|
||||
VkFence fence; // for ctx->cmdbuffer only
|
||||
|
@ -95,8 +93,9 @@ typedef struct vulkan_ctx_s {
|
|||
struct qfv_tex_s *default_magenta;
|
||||
struct qfv_tex_s *default_magenta_array;
|
||||
|
||||
VkViewport viewport;
|
||||
VkRect2D scissor;
|
||||
// size of window
|
||||
int window_width;
|
||||
int window_height;
|
||||
|
||||
//FIXME not sure I like it being here (also, type name)
|
||||
qfv_output_t output;
|
||||
|
|
|
@ -7,6 +7,7 @@ libs_client_libQFclient_la_SOURCES= \
|
|||
libs/client/cl_effects.c \
|
||||
libs/client/cl_entities.c \
|
||||
libs/client/cl_input.c \
|
||||
libs/client/cl_light.c \
|
||||
libs/client/cl_particles.c \
|
||||
libs/client/cl_temp_entities.c \
|
||||
libs/client/cl_view.c \
|
||||
|
|
291
libs/client/cl_light.c
Normal file
291
libs/client/cl_light.c
Normal file
|
@ -0,0 +1,291 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/model.h"
|
||||
#include "QF/plist.h"
|
||||
#include "QF/progs.h" //for ED_ConvertToPlist
|
||||
#include "QF/set.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
#include "client/world.h"
|
||||
|
||||
static void
|
||||
dump_light (light_t *light, int leaf)
|
||||
{
|
||||
Sys_MaskPrintf (SYS_lighting,
|
||||
"[%g, %g, %g] %g, "
|
||||
"[%g, %g, %g, %g], [%g %g %g] %g, [%g, %g, %g, %g] %d\n",
|
||||
VEC4_EXP (light->color),
|
||||
VEC4_EXP (light->position),
|
||||
VEC4_EXP (light->direction),
|
||||
VEC4_EXP (light->attenuation),
|
||||
leaf);
|
||||
}
|
||||
|
||||
static float
|
||||
parse_float (const char *str, float defval)
|
||||
{
|
||||
float val = defval;
|
||||
if (str) {
|
||||
char *end;
|
||||
val = strtof (str, &end);
|
||||
if (end == str) {
|
||||
val = defval;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_vector (const char *str, vec_t *val)
|
||||
{
|
||||
if (str) {
|
||||
int num = sscanf (str, "%f %f %f", VectorExpandAddr (val));
|
||||
while (num < 3) {
|
||||
val[num++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float
|
||||
ecos (float ang)
|
||||
{
|
||||
if (ang == 90 || ang == -90) {
|
||||
return 0;
|
||||
}
|
||||
if (ang == 180 || ang == -180) {
|
||||
return -1;
|
||||
}
|
||||
if (ang == 0 || ang == 360) {
|
||||
return 1;
|
||||
}
|
||||
return cos (ang * M_PI / 180);
|
||||
}
|
||||
|
||||
static float
|
||||
esin (float ang)
|
||||
{
|
||||
if (ang == 90) {
|
||||
return 1;
|
||||
}
|
||||
if (ang == -90) {
|
||||
return -1;
|
||||
}
|
||||
if (ang == 180 || ang == -180) {
|
||||
return 0;
|
||||
}
|
||||
if (ang == 0 || ang == 360) {
|
||||
return 0;
|
||||
}
|
||||
return sin (ang * M_PI / 180);
|
||||
}
|
||||
|
||||
static vec4f_t
|
||||
sun_vector (const vec_t *ang)
|
||||
{
|
||||
// ang is yaw, pitch (maybe roll, but ignored
|
||||
vec4f_t vec = {
|
||||
ecos (ang[1]) * ecos (ang[0]),
|
||||
ecos (ang[1]) * esin (ang[0]),
|
||||
esin (ang[1]),
|
||||
0,
|
||||
};
|
||||
return vec;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_sun (lightingdata_t *ldata, plitem_t *entity)
|
||||
{
|
||||
light_t light = {};
|
||||
float sunlight;
|
||||
//float sunlight2;
|
||||
vec3_t sunangle = { 0, -90, 0 };
|
||||
|
||||
Light_EnableSun (ldata);
|
||||
sunlight = parse_float (PL_String (PL_ObjectForKey (entity,
|
||||
"_sunlight")), 0);
|
||||
//sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity,
|
||||
// "_sunlight2")), 0);
|
||||
parse_vector (PL_String (PL_ObjectForKey (entity, "_sun_mangle")),
|
||||
sunangle);
|
||||
if (sunlight <= 0) {
|
||||
return;
|
||||
}
|
||||
VectorSet (1, 1, 1, light.color);
|
||||
light.color[3] = sunlight;
|
||||
light.position = -sun_vector (sunangle);
|
||||
light.direction = light.position;
|
||||
light.direction[3] = 1;
|
||||
light.attenuation = (vec4f_t) { 0, 0, 1, 0 };
|
||||
Light_AddLight (ldata, &light, 0);
|
||||
}
|
||||
|
||||
static vec4f_t
|
||||
parse_position (const char *str)
|
||||
{
|
||||
vec3_t vec = {};
|
||||
sscanf (str, "%f %f %f", VectorExpandAddr (vec));
|
||||
return (vec4f_t) {vec[0], vec[1], vec[2], 1};
|
||||
}
|
||||
|
||||
static void
|
||||
parse_light (light_t *light, int *style, const plitem_t *entity,
|
||||
const plitem_t *targets)
|
||||
{
|
||||
const char *str;
|
||||
int model = 0;
|
||||
|
||||
/*Sys_Printf ("{\n");
|
||||
for (int i = PL_D_NumKeys (entity); i-- > 0; ) {
|
||||
const char *field = PL_KeyAtIndex (entity, i);
|
||||
const char *value = PL_String (PL_ObjectForKey (entity, field));
|
||||
Sys_Printf ("\t%s = %s\n", field, value);
|
||||
}
|
||||
Sys_Printf ("}\n");*/
|
||||
|
||||
// omnidirectional light (unit length xyz so not treated as ambient)
|
||||
light->direction = (vec4f_t) { 0, 0, 1, 1 };
|
||||
// bright white
|
||||
light->color = (vec4f_t) { 1, 1, 1, 300 };
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) {
|
||||
light->position = parse_position (str);
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "target")))) {
|
||||
plitem_t *target = PL_ObjectForKey (targets, str);
|
||||
vec4f_t dir = { 1, 0, 0, 0 };
|
||||
if (target) {
|
||||
if ((str = PL_String (PL_ObjectForKey (target, "origin")))) {
|
||||
dir = parse_position (str);
|
||||
dir = normalf (dir - light->position);
|
||||
}
|
||||
}
|
||||
|
||||
float angle = 40;
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "angle")))) {
|
||||
angle = atof (str);
|
||||
}
|
||||
dir[3] = -cos (angle * M_PI / 360); // half angle
|
||||
light->direction = dir;
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "light_lev")))
|
||||
|| (str = PL_String (PL_ObjectForKey (entity, "_light")))) {
|
||||
light->color[3] = atof (str);
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "style")))) {
|
||||
*style = atoi (str) & 0x3f;
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) {
|
||||
model = atoi (str) & 0x7;
|
||||
if (model == LM_INVERSE2) {
|
||||
model = LM_INVERSE3; //FIXME for marcher (need a map)
|
||||
}
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "color")))
|
||||
|| (str = PL_String (PL_ObjectForKey (entity, "_color")))) {
|
||||
sscanf (str, "%f %f %f", VectorExpandAddr (light->color));
|
||||
VectorScale (light->color, 1/255.0, light->color);
|
||||
}
|
||||
|
||||
vec4f_t attenuation = { 1, 0, 0, 0 }; // inverse square
|
||||
switch (model) {
|
||||
case LM_LINEAR:
|
||||
attenuation = (vec4f_t) { 0, 0, 1, 1 / fabsf (light->color[3]) };
|
||||
break;
|
||||
case LM_INVERSE:
|
||||
attenuation = (vec4f_t) { 0, 1.0 / 128, 0, 0 };
|
||||
break;
|
||||
case LM_INVERSE2:
|
||||
attenuation = (vec4f_t) { 1.0 / 16384, 0, 0, 0 };
|
||||
break;
|
||||
case LM_INFINITE:
|
||||
attenuation = (vec4f_t) { 0, 0, 1, 0 };
|
||||
break;
|
||||
case LM_AMBIENT:
|
||||
attenuation = (vec4f_t) { 0, 0, 1, 0 };
|
||||
light->direction = (vec4f_t) { 0, 0, 0, 1 };
|
||||
break;
|
||||
case LM_INVERSE3:
|
||||
attenuation = (vec4f_t) { 1.0 / 16384, 2.0 / 128, 1, 0 };
|
||||
break;
|
||||
}
|
||||
light->attenuation = attenuation;
|
||||
}
|
||||
|
||||
void
|
||||
CL_LoadLights (plitem_t *entities, scene_t *scene)
|
||||
{
|
||||
lightingdata_t *ldata = scene->lights;
|
||||
model_t *model = scene->worldmodel;
|
||||
|
||||
Light_ClearLights (ldata);
|
||||
ldata->sun_pvs = set_new_size (model->brush.visleafs);
|
||||
if (!entities) {
|
||||
return;
|
||||
}
|
||||
|
||||
plitem_t *targets = PL_NewDictionary (0);
|
||||
|
||||
// find all the targets so spotlights can be aimed
|
||||
for (int i = 1; i < PL_A_NumObjects (entities); i++) {
|
||||
plitem_t *entity = PL_ObjectAtIndex (entities, i);
|
||||
const char *targetname = PL_String (PL_ObjectForKey (entity,
|
||||
"targetname"));
|
||||
if (targetname && !PL_ObjectForKey (targets, targetname)) {
|
||||
PL_D_AddObject (targets, targetname, entity);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < PL_A_NumObjects (entities); i++) {
|
||||
plitem_t *entity = PL_ObjectAtIndex (entities, i);
|
||||
const char *classname = PL_String (PL_ObjectForKey (entity,
|
||||
"classname"));
|
||||
if (!classname) {
|
||||
continue;
|
||||
}
|
||||
if (!strcmp (classname, "worldspawn")) {
|
||||
// parse_sun can add many lights
|
||||
parse_sun (ldata, entity);
|
||||
const char *str;
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "light_lev")))) {
|
||||
light_t light = {};
|
||||
light.color = (vec4f_t) { 1, 1, 1, atof (str) };
|
||||
light.attenuation = (vec4f_t) { 0, 0, 1, 0 };
|
||||
light.direction = (vec4f_t) { 0, 0, 0, 1 };
|
||||
Light_AddLight (ldata, &light, 0);
|
||||
}
|
||||
} else if (!strncmp (classname, "light", 5)) {
|
||||
light_t light = {};
|
||||
int style = 0;
|
||||
|
||||
parse_light (&light, &style, entity, targets);
|
||||
// some lights have 0 output, so drop them
|
||||
if (light.color[3]) {
|
||||
Light_AddLight (ldata, &light, style);
|
||||
}
|
||||
}
|
||||
}
|
||||
// targets does not own the objects, so need to remove them before
|
||||
// freeing targets
|
||||
for (int i = PL_D_NumKeys (targets); i-- > 0; ) {
|
||||
PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i));
|
||||
}
|
||||
PL_Free (targets);
|
||||
|
||||
for (size_t i = 0; i < ldata->lights.size; i++) {
|
||||
dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]);
|
||||
}
|
||||
Sys_MaskPrintf (SYS_lighting, "loaded %zd lights\n", ldata->lights.size);
|
||||
}
|
|
@ -271,7 +271,7 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx)
|
|||
} else {
|
||||
Transform_SetLocalPosition (tent->ent->transform, position);
|
||||
}
|
||||
R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -632,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
|
|||
|
||||
ent->animation.frame = f;
|
||||
if (!ent->visibility.efrag) {
|
||||
R_AddEfrags (&cl_world.worldmodel->brush, ent);
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -721,7 +721,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
|
|||
angles[2] = 0;
|
||||
CL_TransformEntity (tent->ent, 1, angles, position);
|
||||
|
||||
R_AddEfrags (&cl_world.worldmodel->brush, tent->ent);
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent);
|
||||
}
|
||||
|
||||
*tail = cl_projectiles;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "QF/msg.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
|
@ -64,6 +65,7 @@ void
|
|||
CL_World_Init (void)
|
||||
{
|
||||
cl_world.scene = Scene_NewScene ();
|
||||
cl_world.scene->lights = Light_CreateLightingData (cl_world.scene);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -119,7 +121,7 @@ CL_ParseStatic (qmsg_t *msg, int version)
|
|||
|
||||
CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin);
|
||||
|
||||
R_AddEfrags (&cl_world.worldmodel->brush, ent);
|
||||
R_AddEfrags (&cl_world.scene->worldmodel->brush, ent);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -205,9 +207,11 @@ CL_LoadSky (const char *name)
|
|||
void
|
||||
CL_World_NewMap (const char *mapname, const char *skyname)
|
||||
{
|
||||
model_t *worldmodel = cl_world.models.a[1];
|
||||
cl_world.scene->worldmodel = worldmodel;
|
||||
|
||||
cl_static_entities.size = 0;
|
||||
r_funcs->R_NewMap (cl_world.worldmodel,
|
||||
cl_world.models.a, cl_world.models.size);
|
||||
|
||||
if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) {
|
||||
if (cl_world.edicts) {
|
||||
PL_Free (cl_world.edicts);
|
||||
|
@ -219,5 +223,10 @@ CL_World_NewMap (const char *mapname, const char *skyname)
|
|||
Fog_ParseWorldspawn (cl_world.worldspawn);
|
||||
}
|
||||
}
|
||||
CL_LoadLights (cl_world.edicts, cl_world.scene);
|
||||
|
||||
cl_world.scene->models = cl_world.models.a;
|
||||
cl_world.scene->num_models = cl_world.models.size;
|
||||
SCR_NewScene (cl_world.scene);
|
||||
map_cfg (mapname, 1);
|
||||
}
|
||||
|
|
|
@ -299,17 +299,22 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks)
|
|||
plitem_t *value;
|
||||
char *token;
|
||||
int anglehack;
|
||||
const char *msg = "";
|
||||
|
||||
while (Script_GetToken (script, 1)) {
|
||||
token = script->token->str;
|
||||
if (!strequal (token, "{"))
|
||||
Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
|
||||
if (!strequal (token, "{")) {
|
||||
msg = "EOF without closing brace";
|
||||
goto parse_error;
|
||||
}
|
||||
ent = PL_NewDictionary (hashlinks);
|
||||
while (1) {
|
||||
int n;
|
||||
|
||||
if (!Script_GetToken (script, 1))
|
||||
Sys_Error ("ED_ConvertToPlist: EOF without closing brace");
|
||||
if (!Script_GetToken (script, 1)) {
|
||||
msg = "EOF without closing brace";
|
||||
goto parse_error;
|
||||
}
|
||||
token = script->token->str;
|
||||
if (strequal (token, "}"))
|
||||
break;
|
||||
|
@ -327,12 +332,16 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks)
|
|||
} else {
|
||||
key = PL_NewString (token);
|
||||
}
|
||||
if (!Script_TokenAvailable (script, 0))
|
||||
Sys_Error ("ED_ConvertToPlist: EOL without value");
|
||||
if (!Script_TokenAvailable (script, 0)) {
|
||||
msg = "EOL without value";
|
||||
goto parse_error;
|
||||
}
|
||||
Script_GetToken (script, 0);
|
||||
token = script->token->str;
|
||||
if (strequal (token, "}"))
|
||||
Sys_Error ("ED_ConvertToPlist: closing brace without data");
|
||||
if (strequal (token, "}")) {
|
||||
msg = "closing brace without data";
|
||||
goto parse_error;
|
||||
}
|
||||
if (anglehack) {
|
||||
dsprintf (dstr, "0 %s 0", token);
|
||||
value = PL_NewString (dstr->str);
|
||||
|
@ -346,6 +355,11 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks)
|
|||
}
|
||||
dstring_delete (dstr);
|
||||
return plist;
|
||||
parse_error:
|
||||
Sys_Printf ("%s:%d: %s", script->file, script->line, msg);
|
||||
dstring_delete (dstr);
|
||||
PL_Free (plist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -605,19 +605,25 @@ decode_greyscale_rle (TargaHeader *targa, tex_t *tex, byte *dataByte)
|
|||
|
||||
typedef void (*decoder_t) (TargaHeader *, tex_t *, byte *);
|
||||
static decoder_t decoder_functions[] = {
|
||||
0, // 0 invalid
|
||||
decode_colormap,
|
||||
decode_truecolor,
|
||||
decode_greyscale,
|
||||
0, 0, 0, 0, // 5-7 invalid
|
||||
0, // 8 invalid
|
||||
decode_colormap_rle,
|
||||
decode_truecolor_rle,
|
||||
decode_greyscale_rle,
|
||||
0, 0, 0, 0, // 12-15 invalid
|
||||
[targa_colormap] = decode_colormap,
|
||||
[targa_truecolor] = decode_truecolor,
|
||||
[targa_greyscale] = decode_greyscale,
|
||||
[targa_colormap_rle] = decode_colormap_rle,
|
||||
[targa_truecolor_rle] = decode_truecolor_rle,
|
||||
[targa_greyscale_rle] = decode_greyscale_rle,
|
||||
[targa_max_image_type] = 0
|
||||
};
|
||||
#define NUM_DECODERS (sizeof (decoder_functions) \
|
||||
/ sizeof (decoder_functions[0]))
|
||||
static QFFormat targa_formats[] = {
|
||||
[targa_colormap] = tex_palette,
|
||||
[targa_truecolor] = tex_rgba,
|
||||
[targa_greyscale] = tex_l,
|
||||
[targa_colormap_rle] = tex_palette,
|
||||
[targa_truecolor_rle] = tex_rgba,
|
||||
[targa_greyscale_rle] = tex_l,
|
||||
[targa_max_image_type] = 0
|
||||
};
|
||||
|
||||
struct tex_s *
|
||||
LoadTGA (QFile *fin, int load)
|
||||
|
@ -669,6 +675,11 @@ LoadTGA (QFile *fin, int load)
|
|||
dataByte += targa->id_length;
|
||||
|
||||
decode (targa, tex, dataByte);
|
||||
} else {
|
||||
//FIXME
|
||||
// assume the format is valid so we can return a format type without
|
||||
// having to check individial image type specific data
|
||||
tex->format = targa_formats[targa->image_type];
|
||||
}
|
||||
|
||||
Hunk_FreeToLowMark (0, targa_mark);
|
||||
|
|
|
@ -52,55 +52,67 @@
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
void *
|
||||
gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc)
|
||||
static void
|
||||
gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels,
|
||||
int snum, int gnum, maliasskindesc_t *skindesc)
|
||||
{
|
||||
aliashdr_t *header = alias_ctx->header;
|
||||
byte *pskin;
|
||||
char modname[MAX_QPATH + 4];
|
||||
int fb_texnum = 0, texnum = 0;
|
||||
dstring_t *name = dstring_new ();
|
||||
|
||||
pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name);
|
||||
skindesc->skin = (byte *) pskin - (byte *) header;
|
||||
|
||||
memcpy (pskin, skin, skinsize);
|
||||
|
||||
Mod_FloodFillSkin (pskin, header->mdl.skinwidth, header->mdl.skinheight);
|
||||
Mod_FloodFillSkin (texels, header->mdl.skinwidth, header->mdl.skinheight);
|
||||
// save 8 bit texels for the player model to remap
|
||||
// FIXME remove model restriction
|
||||
if (strequal (alias_ctx->mod->path, "progs/player.mdl"))
|
||||
gl_Skin_SetPlayerSkin (header->mdl.skinwidth, header->mdl.skinheight,
|
||||
pskin);
|
||||
texels);
|
||||
|
||||
QFS_StripExtension (alias_ctx->mod->path, modname);
|
||||
|
||||
if (!alias_ctx->mod->fullbright) {
|
||||
if (group) {
|
||||
if (gnum != -1) {
|
||||
dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum);
|
||||
} else {
|
||||
dsprintf (name, "fb_%s_%i", modname, snum);
|
||||
}
|
||||
fb_texnum = Mod_Fullbright (pskin, header->mdl.skinwidth,
|
||||
fb_texnum = Mod_Fullbright (texels, header->mdl.skinwidth,
|
||||
header->mdl.skinheight, name->str);
|
||||
Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, fb_texnum);
|
||||
}
|
||||
if (group) {
|
||||
if (gnum != -1) {
|
||||
dsprintf (name, "%s_%i_%i", modname, snum, gnum);
|
||||
} else {
|
||||
dsprintf (name, "%s_%i", modname, snum);
|
||||
}
|
||||
texnum = GL_LoadTexture (name->str, header->mdl.skinwidth,
|
||||
header->mdl.skinheight, pskin, true, false, 1);
|
||||
header->mdl.skinheight, texels, true, false, 1);
|
||||
Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, texnum);
|
||||
skindesc->texnum = texnum;
|
||||
skindesc->fb_texnum = fb_texnum;
|
||||
alias_ctx->mod->hasfullbrights = fb_texnum;
|
||||
dstring_delete (name);
|
||||
// alpha param was true for non group skins
|
||||
return skin + skinsize;
|
||||
}
|
||||
|
||||
void
|
||||
gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
|
||||
{
|
||||
aliashdr_t *header = alias_ctx->header;
|
||||
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
|
||||
int num_skins = alias_ctx->skins.size;
|
||||
byte *texel_block = Hunk_AllocName (0, skinsize * num_skins,
|
||||
alias_ctx->mod->name);
|
||||
|
||||
for (int i = 0; i < num_skins; i++) {
|
||||
__auto_type skin = alias_ctx->skins.a + i;
|
||||
byte *texels = texel_block + i * skinsize;
|
||||
|
||||
skin->skindesc->skin = texels - (byte *) header;
|
||||
memcpy (texels, skin->texels, skinsize);
|
||||
gl_Mod_LoadSkin (alias_ctx, texels, skin->skin_num, skin->group_num,
|
||||
skin->skindesc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "QF/GLSL/qf_textures.h"
|
||||
|
||||
#include "mod_internal.h"
|
||||
#include "qfalloca.h"
|
||||
#include "r_shared.h"
|
||||
|
||||
static vec3_t vertex_normals[NUMVERTEXNORMALS] = {
|
||||
|
@ -90,28 +91,34 @@ glsl_alias_clear (model_t *m, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
void *
|
||||
glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc)
|
||||
static void
|
||||
glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels,
|
||||
int snum, int gnum, maliasskindesc_t *skindesc)
|
||||
{
|
||||
aliashdr_t *header = alias_ctx->header;
|
||||
byte *tskin;
|
||||
int w = header->mdl.skinwidth;
|
||||
int h = header->mdl.skinheight;
|
||||
size_t skinsize = w * h;
|
||||
byte *tskin = alloca (skinsize);
|
||||
const char *name;
|
||||
int w, h;
|
||||
|
||||
w = header->mdl.skinwidth;
|
||||
h = header->mdl.skinheight;
|
||||
tskin = malloc (skinsize);
|
||||
memcpy (tskin, skin, skinsize);
|
||||
memcpy (tskin, texels, skinsize);
|
||||
Mod_FloodFillSkin (tskin, w, h);
|
||||
if (group)
|
||||
if (gnum != -1)
|
||||
name = va (0, "%s_%i_%i", alias_ctx->mod->path, snum, gnum);
|
||||
else
|
||||
name = va (0, "%s_%i", alias_ctx->mod->path, snum);
|
||||
skindesc->texnum = GLSL_LoadQuakeTexture (name, w, h, tskin);
|
||||
free (tskin);
|
||||
return skin + skinsize;
|
||||
}
|
||||
|
||||
void
|
||||
glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
|
||||
{
|
||||
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
|
||||
__auto_type skin = alias_ctx->skins.a + i;
|
||||
glsl_Mod_LoadSkin (alias_ctx, skin->texels,
|
||||
skin->skin_num, skin->group_num, skin->skindesc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -75,8 +75,14 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins,
|
|||
pskindesc[snum].type = pskintype->type;
|
||||
if (pskintype->type == ALIAS_SKIN_SINGLE) {
|
||||
skin = (byte *) (pskintype + 1);
|
||||
skin = m_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, snum, 0,
|
||||
false, &pskindesc[snum]);
|
||||
mod_alias_skin_t askin = {
|
||||
.skin_num = snum,
|
||||
.group_num = -1,
|
||||
.texels = skin,
|
||||
.skindesc = &pskindesc[snum],
|
||||
};
|
||||
skin += skinsize;
|
||||
DARRAY_APPEND (&alias_ctx->skins, askin);
|
||||
} else {
|
||||
pskintype++;
|
||||
pinskingroup = (daliasskingroup_t *) pskintype;
|
||||
|
@ -107,13 +113,20 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins,
|
|||
|
||||
for (gnum = 0; gnum < groupskins; gnum++) {
|
||||
paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE;
|
||||
skin = mod_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize,
|
||||
snum, gnum, true,
|
||||
&paliasskingroup->skindescs[gnum]);
|
||||
skin = (byte *) (pskintype + 1);
|
||||
mod_alias_skin_t askin = {
|
||||
.skin_num = snum,
|
||||
.group_num = gnum,
|
||||
.texels = skin,
|
||||
.skindesc = &paliasskingroup->skindescs[gnum],
|
||||
};
|
||||
skin += skinsize;
|
||||
DARRAY_APPEND (&alias_ctx->skins, askin);
|
||||
}
|
||||
}
|
||||
pskintype = (daliasskintype_t *) skin;
|
||||
}
|
||||
mod_funcs->Mod_LoadAllSkins (alias_ctx);
|
||||
|
||||
return pskintype;
|
||||
}
|
||||
|
@ -232,6 +245,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
|
|||
DARRAY_INIT (&alias_ctx.poseverts, 256);
|
||||
DARRAY_INIT (&alias_ctx.stverts, 256);
|
||||
DARRAY_INIT (&alias_ctx.triangles, 256);
|
||||
DARRAY_INIT (&alias_ctx.skins, 256);
|
||||
|
||||
if (LittleLong (* (unsigned int *) buffer) == HEADER_MDL16)
|
||||
extra = 1; // extra precision bytes
|
||||
|
@ -392,4 +406,5 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator)
|
|||
DARRAY_CLEAR (&alias_ctx.poseverts);
|
||||
DARRAY_CLEAR (&alias_ctx.stverts);
|
||||
DARRAY_CLEAR (&alias_ctx.triangles);
|
||||
DARRAY_CLEAR (&alias_ctx.skins);
|
||||
}
|
||||
|
|
|
@ -48,20 +48,22 @@
|
|||
// a pose is a single set of vertexes. a frame may be
|
||||
// an animating sequence of poses
|
||||
|
||||
|
||||
void *
|
||||
sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin,
|
||||
int skinsize, int snum, int gnum,
|
||||
qboolean group, maliasskindesc_t *skindesc)
|
||||
void
|
||||
sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
|
||||
{
|
||||
byte *pskin;
|
||||
aliashdr_t *header = alias_ctx->header;
|
||||
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
|
||||
int num_skins = alias_ctx->skins.size;
|
||||
byte *texel_block = Hunk_AllocName (0, skinsize * num_skins,
|
||||
alias_ctx->mod->name);
|
||||
|
||||
pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name);
|
||||
skindesc->skin = (byte *) pskin - (byte *) alias_ctx->header;
|
||||
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
|
||||
__auto_type skin = alias_ctx->skins.a + i;
|
||||
byte *texels = texel_block + i * skinsize;
|
||||
|
||||
memcpy (pskin, skin, skinsize);
|
||||
|
||||
return skin + skinsize;
|
||||
skin->skindesc->skin = texels - (byte *) header;
|
||||
memcpy (texels, skin->texels, skinsize);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -111,7 +111,7 @@ vulkan_alias_clear (model_t *m, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
void *
|
||||
static void *
|
||||
Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc, vulkan_ctx_t *ctx)
|
||||
|
@ -228,6 +228,20 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
|
|||
return skinpix + skinsize;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx)
|
||||
{
|
||||
aliashdr_t *header = alias_ctx->header;
|
||||
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
|
||||
|
||||
for (size_t i = 0; i < alias_ctx->skins.size; i++) {
|
||||
__auto_type skin = alias_ctx->skins.a + i;
|
||||
Vulkan_Mod_LoadSkin (alias_ctx, skin->texels, skinsize,
|
||||
skin->skin_num, skin->group_num,
|
||||
skin->group_num != -1, skin->skindesc, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -401,6 +415,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m,
|
|||
for (i = 0; i < numtris; i++) {
|
||||
for (j = 0; j < 3; j++) {
|
||||
int vind = alias_ctx->triangles.a[i].vertindex[j];
|
||||
// can't use indexmap to do the test because it indicates only
|
||||
// that the vertex has been duplicated, not whether or not
|
||||
// the vertex is the original or the duplicate
|
||||
if (alias_ctx->stverts.a[vind].onseam
|
||||
&& !alias_ctx->triangles.a[i].facesfront) {
|
||||
vind = indexmap[vind];
|
||||
|
|
|
@ -52,8 +52,6 @@
|
|||
#include "mod_internal.h"
|
||||
#include "r_internal.h"
|
||||
|
||||
static gltex_t gl_notexture = { };
|
||||
|
||||
static tex_t *
|
||||
Mod_LoadAnExternalTexture (const char *tname, const char *mname)
|
||||
{
|
||||
|
@ -122,7 +120,6 @@ gl_Mod_ProcessTexture (model_t *mod, texture_t *tx)
|
|||
const char *name;
|
||||
|
||||
if (!tx) {
|
||||
r_notexture_mip->render = &gl_notexture;
|
||||
return;
|
||||
}
|
||||
if (gl_textures_external) {
|
||||
|
|
|
@ -60,8 +60,6 @@
|
|||
#include "mod_internal.h"
|
||||
#include "r_internal.h"
|
||||
|
||||
static glsltex_t glsl_notexture = { };
|
||||
|
||||
static void
|
||||
glsl_brush_clear (model_t *m, void *data)
|
||||
{
|
||||
|
@ -105,7 +103,6 @@ void
|
|||
glsl_Mod_ProcessTexture (model_t *mod, texture_t *tx)
|
||||
{
|
||||
if (!tx) {
|
||||
r_notexture_mip->render = &glsl_notexture;
|
||||
return;
|
||||
}
|
||||
glsltex_t *tex = tx->render;
|
||||
|
|
|
@ -62,8 +62,6 @@
|
|||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
static vulktex_t vulkan_notexture = { };
|
||||
|
||||
static void
|
||||
vulkan_brush_clear (model_t *mod, void *data)
|
||||
{
|
||||
|
@ -302,8 +300,9 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx)
|
|||
mod->clear = vulkan_brush_clear;
|
||||
mod->data = mctx;
|
||||
|
||||
r_notexture_mip->render = &vulkan_notexture;
|
||||
load_textures (mod, ctx);
|
||||
if (mod->brush.numtextures) {
|
||||
load_textures (mod, ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,468 @@
|
|||
/*
|
||||
vulkan_model_iqm.c
|
||||
|
||||
iqm model processing for Vulkan
|
||||
|
||||
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2022/05/03
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/image.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/Vulkan/barrier.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/resource.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
#include "QF/Vulkan/qf_iqm.h"
|
||||
#include "QF/Vulkan/qf_texture.h"
|
||||
|
||||
#include "mod_internal.h"
|
||||
#include "r_shared.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
static byte null_texture[] = {
|
||||
204, 204, 204, 255,
|
||||
204, 204, 204, 255,
|
||||
204, 204, 204, 255,
|
||||
204, 204, 204, 255,
|
||||
};
|
||||
#if 0
|
||||
static byte null_normmap[] = {
|
||||
127, 127, 255, 255,
|
||||
127, 127, 255, 255,
|
||||
127, 127, 255, 255,
|
||||
127, 127, 255, 255,
|
||||
};
|
||||
#endif
|
||||
static void
|
||||
vulkan_iqm_clear (model_t *mod, void *data)
|
||||
{
|
||||
vulkan_ctx_t *ctx = data;
|
||||
qfv_device_t *device = ctx->device;
|
||||
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
||||
qfv_iqm_t *mesh = iqm->extra_data;
|
||||
|
||||
mod->needload = true;
|
||||
|
||||
QFV_DestroyResource (device, mesh->bones);
|
||||
QFV_DestroyResource (device, mesh->mesh);
|
||||
free (mesh);
|
||||
Mod_FreeIQM (iqm);
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image)
|
||||
{
|
||||
const char *material = iqm->text + iqm->meshes[meshnum].material;
|
||||
dstring_t *str = dstring_new ();
|
||||
dstring_copystr (str, material);
|
||||
QFS_StripExtension (str->str, str->str);
|
||||
|
||||
tex_t *tex;
|
||||
if ((tex = LoadImage (va (0, "textures/%s", str->str), 0))) {
|
||||
*image = (qfv_resobj_t) {
|
||||
.name = material,
|
||||
.type = qfv_res_image,
|
||||
.image = {
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.format = QFV_ImageFormat (tex->format),
|
||||
.extent = {
|
||||
.width = tex->width,
|
||||
.height = tex->height,
|
||||
.depth = 1,
|
||||
},
|
||||
.num_mipmaps = QFV_MipLevels (tex->width, tex->height),
|
||||
.num_layers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
*image = (qfv_resobj_t) {
|
||||
.name = material,
|
||||
.type = qfv_res_image,
|
||||
.image = {
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.format = QFV_ImageFormat (tex_rgba),
|
||||
.extent = {
|
||||
.width = 2,
|
||||
.height = 2,
|
||||
.depth = 1,
|
||||
},
|
||||
.num_mipmaps = QFV_MipLevels (2, 2),
|
||||
.num_layers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
},
|
||||
};
|
||||
}
|
||||
dstring_delete (str);
|
||||
}
|
||||
|
||||
static void
|
||||
iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage,
|
||||
qfv_device_t *device)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
if (tex->format != tex_rgb && tex->format != tex_rgba) {
|
||||
Sys_Error ("can't transfer iqm image");
|
||||
}
|
||||
// FIXME correct only for rgb and rgba
|
||||
size_t layer_size = tex->width * tex->height * tex->format;
|
||||
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (stage);
|
||||
byte *dst = QFV_PacketExtend (packet, layer_size);
|
||||
|
||||
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
|
||||
ib.barrier.image = image;
|
||||
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &ib.barrier);
|
||||
memcpy (dst, tex->data, layer_size);
|
||||
|
||||
int mipLevels = QFV_MipLevels (tex->width, tex->height);
|
||||
if (mipLevels == 1) {
|
||||
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
|
||||
ib.barrier.image = image;
|
||||
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
|
||||
0, 0, 0, 0, 0,
|
||||
1, &ib.barrier);
|
||||
} else {
|
||||
QFV_GenerateMipMaps (device, packet->cmd, image, mipLevels,
|
||||
tex->width, tex->height, 1);
|
||||
}
|
||||
QFV_PacketSubmit (packet);
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_iqm_load_textures (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
|
||||
vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
dstring_t *str = dstring_new ();
|
||||
tex_t *tex;
|
||||
size_t buff_size = 0;
|
||||
qfv_resobj_t *objects = mesh->mesh->objects;
|
||||
|
||||
for (int i = 0; i < iqm->num_meshes; i++) {
|
||||
int image_ind = 3 + 2 * i;
|
||||
VkExtent3D extent = objects[image_ind].image.extent;
|
||||
// probably 3 or 4 bytes per pixel FIXME
|
||||
buff_size = max (buff_size, extent.width * extent.height * 4);
|
||||
}
|
||||
|
||||
qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device,
|
||||
va (ctx->va_ctx, "iqm:%s",
|
||||
mod->name),
|
||||
4 * buff_size,
|
||||
ctx->cmdpool);
|
||||
|
||||
for (int i = 0; i < iqm->num_meshes; i++) {
|
||||
int image_ind = 3 + 2 * i;
|
||||
__auto_type image = &objects[image_ind].image;
|
||||
__auto_type view = &objects[image_ind + 1].image_view;
|
||||
qfv_iqm_skin_t *skin = &mesh->skins[i];
|
||||
*skin = (qfv_iqm_skin_t) {
|
||||
.view = view->view,
|
||||
.colora = { 255, 255, 255, 255 },
|
||||
.colorb = { 255, 255, 255, 255 },
|
||||
};
|
||||
|
||||
dstring_copystr (str, iqm->text + iqm->meshes[i].material);
|
||||
QFS_StripExtension (str->str, str->str);
|
||||
if (!(tex = LoadImage (va (0, "textures/%s", str->str), 1))) {
|
||||
tex_t null_tex = {
|
||||
.width = 2,
|
||||
.height = 2,
|
||||
.format = tex_rgba,
|
||||
.data = null_texture,
|
||||
};
|
||||
tex = &null_tex;
|
||||
}
|
||||
iqm_transfer_texture (tex, image->image, stage, device);
|
||||
}
|
||||
dstring_delete (str);
|
||||
QFV_DestroyStagingBuffer (stage);
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh,
|
||||
vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
size_t geom_size = iqm->num_verts * sizeof (iqmgvert_t);
|
||||
size_t rend_size = iqm->num_verts * sizeof (iqmrvert_t);
|
||||
size_t elem_size = iqm->num_elements * sizeof (uint16_t);
|
||||
size_t buff_size = geom_size + rend_size + elem_size + 1024;
|
||||
qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device,
|
||||
va (ctx->va_ctx, "iqm:%s",
|
||||
mod->name),
|
||||
buff_size, ctx->cmdpool);
|
||||
qfv_packet_t *gpacket = QFV_PacketAcquire (stage);
|
||||
iqmgvert_t *gverts = QFV_PacketExtend (gpacket, geom_size);
|
||||
qfv_packet_t *rpacket = QFV_PacketAcquire (stage);
|
||||
iqmrvert_t *rverts = QFV_PacketExtend (rpacket, rend_size);
|
||||
qfv_packet_t *epacket = QFV_PacketAcquire (stage);
|
||||
uint16_t *elements = QFV_PacketExtend (epacket, elem_size);
|
||||
//FIXME this whole thing is silly, but some person went and interleaved
|
||||
//all the vertex data prematurely
|
||||
for (int i = 0; i < iqm->num_verts; i++) {
|
||||
byte *data = iqm->vertices + i * iqm->stride;
|
||||
iqmgvert_t *gv = gverts + i;
|
||||
iqmrvert_t *rv = rverts + i;
|
||||
for (int j = 0; j < iqm->num_arrays; j++) {
|
||||
__auto_type va = &iqm->vertexarrays[j];
|
||||
// FIXME assumes standard iqm sizes
|
||||
size_t size = 0;
|
||||
switch (va->type) {
|
||||
case IQM_POSITION:
|
||||
size = sizeof (gv->vertex);
|
||||
memcpy (gv->vertex, data, size);
|
||||
break;
|
||||
case IQM_TEXCOORD:
|
||||
size = sizeof (rv->uv);
|
||||
memcpy (rv->uv, data, size);
|
||||
break;
|
||||
case IQM_NORMAL:
|
||||
size = sizeof (rv->normal);
|
||||
memcpy (rv->normal, data, size);
|
||||
break;
|
||||
case IQM_TANGENT:
|
||||
size = sizeof (rv->tangent);
|
||||
memcpy (rv->tangent, data, size);
|
||||
break;
|
||||
case IQM_BLENDINDEXES:
|
||||
size = sizeof (gv->bones);
|
||||
memcpy (gv->bones, data, size);
|
||||
break;
|
||||
case IQM_BLENDWEIGHTS:
|
||||
size = sizeof (gv->weights);
|
||||
memcpy (gv->weights, data, size);
|
||||
break;
|
||||
case IQM_COLOR:
|
||||
size = sizeof (rv->color);
|
||||
memcpy (rv->color, data, size);
|
||||
break;
|
||||
case IQM_CUSTOM:
|
||||
// FIXME model loader doesn't handle these, so nothing to do
|
||||
break;
|
||||
}
|
||||
data += size;
|
||||
}
|
||||
}
|
||||
memcpy (elements, iqm->elements, elem_size);
|
||||
|
||||
qfv_bufferbarrier_t bb[] = {
|
||||
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
|
||||
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
|
||||
bufferBarriers[qfv_BB_Unknown_to_TransferWrite],
|
||||
};
|
||||
bb[0].barrier.buffer = mesh->geom_buffer;
|
||||
bb[0].barrier.size = geom_size;
|
||||
bb[1].barrier.buffer = mesh->rend_buffer;
|
||||
bb[1].barrier.size = rend_size;
|
||||
bb[2].barrier.buffer = mesh->index_buffer;
|
||||
bb[2].barrier.size = elem_size;
|
||||
VkBufferCopy copy_region[] = {
|
||||
{ gpacket->offset, 0, geom_size },
|
||||
{ rpacket->offset, 0, rend_size },
|
||||
{ epacket->offset, 0, elem_size },
|
||||
};
|
||||
|
||||
dfunc->vkCmdPipelineBarrier (gpacket->cmd, bb[0].srcStages, bb[0].dstStages,
|
||||
0, 0, 0, 1, &bb[0].barrier, 0, 0);
|
||||
dfunc->vkCmdPipelineBarrier (rpacket->cmd, bb[0].srcStages, bb[0].dstStages,
|
||||
0, 0, 0, 1, &bb[1].barrier, 0, 0);
|
||||
dfunc->vkCmdPipelineBarrier (epacket->cmd, bb[0].srcStages, bb[0].dstStages,
|
||||
0, 0, 0, 1, &bb[2].barrier, 0, 0);
|
||||
dfunc->vkCmdCopyBuffer (gpacket->cmd, stage->buffer,
|
||||
mesh->geom_buffer, 1, ©_region[0]);
|
||||
dfunc->vkCmdCopyBuffer (rpacket->cmd, stage->buffer,
|
||||
mesh->rend_buffer, 1, ©_region[1]);
|
||||
dfunc->vkCmdCopyBuffer (epacket->cmd, stage->buffer,
|
||||
mesh->index_buffer, 1, ©_region[2]);
|
||||
bb[0] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
|
||||
bb[1] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
|
||||
bb[2] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead];
|
||||
bb[0].barrier.buffer = mesh->geom_buffer;
|
||||
bb[0].barrier.size = geom_size;
|
||||
bb[1].barrier.buffer = mesh->rend_buffer;
|
||||
bb[1].barrier.size = rend_size;
|
||||
bb[2].barrier.buffer = mesh->index_buffer;
|
||||
bb[2].barrier.size = elem_size;
|
||||
dfunc->vkCmdPipelineBarrier (gpacket->cmd, bb[0].srcStages, bb[0].dstStages,
|
||||
0, 0, 0, 1, &bb[0].barrier, 0, 0);
|
||||
dfunc->vkCmdPipelineBarrier (rpacket->cmd, bb[0].srcStages, bb[0].dstStages,
|
||||
0, 0, 0, 1, &bb[1].barrier, 0, 0);
|
||||
dfunc->vkCmdPipelineBarrier (epacket->cmd, bb[0].srcStages, bb[0].dstStages,
|
||||
0, 0, 0, 1, &bb[2].barrier, 0, 0);
|
||||
QFV_PacketSubmit (gpacket);
|
||||
QFV_PacketSubmit (rpacket);
|
||||
QFV_PacketSubmit (epacket);
|
||||
QFV_DestroyStagingBuffer (stage);
|
||||
|
||||
vec4f_t *bone_data;
|
||||
dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE,
|
||||
0, (void **)&bone_data);
|
||||
for (int i = 0; i < 3 * iqm->num_joints; i++) {
|
||||
vec4f_t *bone = bone_data + i * 3;
|
||||
bone[0] = (vec4f_t) {1, 0, 0, 0};
|
||||
bone[1] = (vec4f_t) {0, 1, 0, 0};
|
||||
bone[2] = (vec4f_t) {0, 0, 1, 0};
|
||||
}
|
||||
VkMappedMemoryRange range = {
|
||||
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
mesh->bones->memory, 0, VK_WHOLE_SIZE,
|
||||
};
|
||||
dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range);
|
||||
|
||||
dfunc->vkUnmapMemory (device->dev, mesh->bones->memory);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
iqm_t *iqm = (iqm_t *) mod->aliashdr;
|
||||
mod->clear = vulkan_iqm_clear;
|
||||
mod->data = ctx;
|
||||
|
||||
// FIXME assumes only one texture per mesh (currently the case, but
|
||||
// when materials are added...)
|
||||
// 2 is for image + image view
|
||||
int num_objects = 4 + 2 * iqm->num_meshes;
|
||||
qfv_iqm_t *mesh = calloc (1, sizeof (qfv_iqm_t)
|
||||
+ 2 * sizeof (qfv_resource_t)
|
||||
+ num_objects * sizeof (qfv_resobj_t)
|
||||
+ iqm->num_meshes * sizeof (qfv_iqm_skin_t));
|
||||
mesh->bones = (qfv_resource_t *) &mesh[1];
|
||||
mesh->mesh = &mesh->bones[1];
|
||||
|
||||
mesh->bones[0] = (qfv_resource_t) {
|
||||
.name = mod->name,
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
.num_objects = 1,
|
||||
.objects = (qfv_resobj_t *) &mesh->bones[2],
|
||||
};
|
||||
mesh->bones->objects[0] = (qfv_resobj_t) {
|
||||
.name = "bones",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = 3 * iqm->num_joints * 3 * sizeof (vec4f_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
|
||||
mesh->mesh[0] = (qfv_resource_t) {
|
||||
.name = "mesh",
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
.num_objects = num_objects - 1,
|
||||
.objects = mesh->bones->objects + 1,
|
||||
};
|
||||
mesh->mesh->objects[0] = (qfv_resobj_t) {
|
||||
.name = "geom",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = iqm->num_verts * sizeof (iqmgvert_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
mesh->mesh->objects[1] = (qfv_resobj_t) {
|
||||
.name = "rend",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = iqm->num_verts * sizeof (iqmrvert_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
mesh->mesh->objects[2] = (qfv_resobj_t) {
|
||||
.name = "index",
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = iqm->num_elements * sizeof (uint16_t),
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
||||
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
},
|
||||
};
|
||||
|
||||
for (int i = 0; i < iqm->num_meshes; i++) {
|
||||
int image_ind = 3 + 2 * i;
|
||||
__auto_type image = &mesh->mesh->objects[image_ind];
|
||||
vulkan_iqm_init_image (iqm, i, image);
|
||||
|
||||
mesh->mesh->objects[image_ind + 1] = (qfv_resobj_t) {
|
||||
.name = "view",
|
||||
.type = qfv_res_image_view,
|
||||
.image_view = {
|
||||
.image = image_ind,
|
||||
.type = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = mesh->mesh->objects[image_ind].image.format,
|
||||
.aspect = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
mesh->skins = (qfv_iqm_skin_t *) &mesh->bones->objects[num_objects];
|
||||
|
||||
QFV_CreateResource (device, mesh->mesh);
|
||||
QFV_CreateResource (device, mesh->bones);
|
||||
mesh->geom_buffer = mesh->mesh->objects[0].buffer.buffer;
|
||||
mesh->rend_buffer = mesh->mesh->objects[1].buffer.buffer;
|
||||
mesh->index_buffer = mesh->mesh->objects[2].buffer.buffer;
|
||||
|
||||
vulkan_iqm_load_textures (mod, iqm, mesh, ctx);
|
||||
vulkan_iqm_load_arrays (mod, iqm, mesh, ctx);
|
||||
|
||||
iqm->extra_data = mesh;
|
||||
}
|
|
@ -138,22 +138,31 @@ Mod_Init_Cvars (void)
|
|||
Cvar_Register (&gl_textures_external_cvar, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
mod_unload_model (size_t ind)
|
||||
{
|
||||
model_t *mod = mod_known.a[ind];
|
||||
|
||||
//FIXME this seems to be correct but need to double check the behavior
|
||||
//with alias models
|
||||
if (!mod->needload && mod->clear) {
|
||||
mod->clear (mod, mod->data);
|
||||
}
|
||||
if (mod->type != mod_alias) {
|
||||
mod->needload = true;
|
||||
}
|
||||
if (mod->type == mod_sprite) {
|
||||
mod->cache.data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Mod_ClearAll (void)
|
||||
{
|
||||
size_t i;
|
||||
model_t **mod;
|
||||
|
||||
for (i = 0, mod = mod_known.a; i < mod_numknown; i++, mod++) {
|
||||
//FIXME this seems to be correct but need to double check the behavior
|
||||
//with alias models
|
||||
if (!(*mod)->needload && (*mod)->clear) {
|
||||
(*mod)->clear (*mod, (*mod)->data);
|
||||
}
|
||||
if ((*mod)->type != mod_alias)
|
||||
(*mod)->needload = true;
|
||||
if ((*mod)->type == mod_sprite)
|
||||
(*mod)->cache.data = 0;
|
||||
for (i = 0; i < mod_numknown; i++) {
|
||||
mod_unload_model (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,6 +332,16 @@ Mod_TouchModel (const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Mod_UnloadModel (model_t *model)
|
||||
{
|
||||
for (size_t i = 0; i < mod_numknown; i++) {
|
||||
if (mod_known.a[i] == model) {
|
||||
mod_unload_model (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Mod_Print (void)
|
||||
{
|
||||
|
|
|
@ -34,36 +34,37 @@
|
|||
|
||||
net_driver_t net_drivers[MAX_NET_DRIVERS] = {
|
||||
{
|
||||
"Loopback",
|
||||
false,
|
||||
Loop_Init,
|
||||
Loop_Listen,
|
||||
Loop_SearchForHosts,
|
||||
Loop_Connect,
|
||||
Loop_CheckNewConnections,
|
||||
Loop_GetMessage,
|
||||
Loop_SendMessage,
|
||||
Loop_SendUnreliableMessage,
|
||||
Loop_CanSendMessage,
|
||||
Loop_CanSendUnreliableMessage,
|
||||
Loop_Close,
|
||||
Loop_Shutdown}
|
||||
,
|
||||
.name = "Loopback",
|
||||
.initialized = false,
|
||||
.Init = Loop_Init,
|
||||
.Listen = Loop_Listen,
|
||||
.SearchForHosts = Loop_SearchForHosts,
|
||||
.Connect = Loop_Connect,
|
||||
.CheckNewConnections = Loop_CheckNewConnections,
|
||||
.QGetMessage = Loop_GetMessage,
|
||||
.QSendMessage = Loop_SendMessage,
|
||||
.SendUnreliableMessage = Loop_SendUnreliableMessage,
|
||||
.CanSendMessage = Loop_CanSendMessage,
|
||||
.CanSendUnreliableMessage = Loop_CanSendUnreliableMessage,
|
||||
.Close = Loop_Close,
|
||||
.Shutdown = Loop_Shutdown,
|
||||
},
|
||||
{
|
||||
"Datagram",
|
||||
false,
|
||||
Datagram_Init,
|
||||
Datagram_Listen,
|
||||
Datagram_SearchForHosts,
|
||||
Datagram_Connect,
|
||||
Datagram_CheckNewConnections,
|
||||
Datagram_GetMessage,
|
||||
Datagram_SendMessage,
|
||||
Datagram_SendUnreliableMessage,
|
||||
Datagram_CanSendMessage,
|
||||
Datagram_CanSendUnreliableMessage,
|
||||
Datagram_Close,
|
||||
Datagram_Shutdown}
|
||||
.name = "Datagram",
|
||||
.initialized = false,
|
||||
.Init = Datagram_Init,
|
||||
.Listen = Datagram_Listen,
|
||||
.SearchForHosts = Datagram_SearchForHosts,
|
||||
.Connect = Datagram_Connect,
|
||||
.CheckNewConnections = Datagram_CheckNewConnections,
|
||||
.QGetMessage = Datagram_GetMessage,
|
||||
.QSendMessage = Datagram_SendMessage,
|
||||
.SendUnreliableMessage = Datagram_SendUnreliableMessage,
|
||||
.CanSendMessage = Datagram_CanSendMessage,
|
||||
.CanSendUnreliableMessage = Datagram_CanSendUnreliableMessage,
|
||||
.Close = Datagram_Close,
|
||||
.Shutdown = Datagram_Shutdown,
|
||||
},
|
||||
};
|
||||
|
||||
int net_numdrivers = 2;
|
||||
|
@ -72,26 +73,27 @@ int net_numdrivers = 2;
|
|||
|
||||
net_landriver_t net_landrivers[MAX_NET_DRIVERS] = {
|
||||
{
|
||||
"UDP",
|
||||
false,
|
||||
0,
|
||||
UDP_Init,
|
||||
UDP_Shutdown,
|
||||
UDP_Listen,
|
||||
UDP_OpenSocket,
|
||||
UDP_CloseSocket,
|
||||
UDP_Connect,
|
||||
UDP_CheckNewConnections,
|
||||
UDP_Read,
|
||||
UDP_Write,
|
||||
UDP_Broadcast,
|
||||
UDP_AddrToString,
|
||||
UDP_GetSocketAddr,
|
||||
UDP_GetNameFromAddr,
|
||||
UDP_GetAddrFromName,
|
||||
UDP_AddrCompare,
|
||||
UDP_GetSocketPort,
|
||||
UDP_SetSocketPort}
|
||||
.name = "UDP",
|
||||
.initialized = false,
|
||||
.controlSock = 0,
|
||||
.Init = UDP_Init,
|
||||
.Shutdown = UDP_Shutdown,
|
||||
.Listen = UDP_Listen,
|
||||
.OpenSocket = UDP_OpenSocket,
|
||||
.CloseSocket = UDP_CloseSocket,
|
||||
.Connect = UDP_Connect,
|
||||
.CheckNewConnections = UDP_CheckNewConnections,
|
||||
.Read = UDP_Read,
|
||||
.Write = UDP_Write,
|
||||
.Broadcast = UDP_Broadcast,
|
||||
.AddrToString = UDP_AddrToString,
|
||||
.GetSocketAddr = UDP_GetSocketAddr,
|
||||
.GetNameFromAddr = UDP_GetNameFromAddr,
|
||||
.GetAddrFromName = UDP_GetAddrFromName,
|
||||
.AddrCompare = UDP_AddrCompare,
|
||||
.GetSocketPort = UDP_GetSocketPort,
|
||||
.SetSocketPort = UDP_SetSocketPort,
|
||||
},
|
||||
};
|
||||
|
||||
int net_numlandrivers = 1;
|
||||
|
|
|
@ -33,36 +33,37 @@
|
|||
|
||||
net_driver_t net_drivers[MAX_NET_DRIVERS] = {
|
||||
{
|
||||
"Loopback",
|
||||
false,
|
||||
Loop_Init,
|
||||
Loop_Listen,
|
||||
Loop_SearchForHosts,
|
||||
Loop_Connect,
|
||||
Loop_CheckNewConnections,
|
||||
Loop_GetMessage,
|
||||
Loop_SendMessage,
|
||||
Loop_SendUnreliableMessage,
|
||||
Loop_CanSendMessage,
|
||||
Loop_CanSendUnreliableMessage,
|
||||
Loop_Close,
|
||||
Loop_Shutdown}
|
||||
,
|
||||
.name = "Loopback",
|
||||
.initialized = false,
|
||||
.Init = Loop_Init,
|
||||
.Listen = Loop_Listen,
|
||||
.SearchForHosts = Loop_SearchForHosts,
|
||||
.Connect = Loop_Connect,
|
||||
.CheckNewConnections = Loop_CheckNewConnections,
|
||||
.QGetMessage = Loop_GetMessage,
|
||||
.QSendMessage = Loop_SendMessage,
|
||||
.SendUnreliableMessage = Loop_SendUnreliableMessage,
|
||||
.CanSendMessage = Loop_CanSendMessage,
|
||||
.CanSendUnreliableMessage = Loop_CanSendUnreliableMessage,
|
||||
.Close = Loop_Close,
|
||||
.Shutdown = Loop_Shutdown,
|
||||
},
|
||||
{
|
||||
"Datagram",
|
||||
false,
|
||||
Datagram_Init,
|
||||
Datagram_Listen,
|
||||
Datagram_SearchForHosts,
|
||||
Datagram_Connect,
|
||||
Datagram_CheckNewConnections,
|
||||
Datagram_GetMessage,
|
||||
Datagram_SendMessage,
|
||||
Datagram_SendUnreliableMessage,
|
||||
Datagram_CanSendMessage,
|
||||
Datagram_CanSendUnreliableMessage,
|
||||
Datagram_Close,
|
||||
Datagram_Shutdown}
|
||||
.name = "Datagram",
|
||||
.initialized = false,
|
||||
.Init = Datagram_Init,
|
||||
.Listen = Datagram_Listen,
|
||||
.SearchForHosts = Datagram_SearchForHosts,
|
||||
.Connect = Datagram_Connect,
|
||||
.CheckNewConnections = Datagram_CheckNewConnections,
|
||||
.QGetMessage = Datagram_GetMessage,
|
||||
.QSendMessage = Datagram_SendMessage,
|
||||
.SendUnreliableMessage = Datagram_SendUnreliableMessage,
|
||||
.CanSendMessage = Datagram_CanSendMessage,
|
||||
.CanSendUnreliableMessage = Datagram_CanSendUnreliableMessage,
|
||||
.Close = Datagram_Close,
|
||||
.Shutdown = Datagram_Shutdown,
|
||||
},
|
||||
};
|
||||
|
||||
int net_numdrivers = 2;
|
||||
|
@ -72,26 +73,27 @@ int net_numdrivers = 2;
|
|||
|
||||
net_landriver_t net_landrivers[MAX_NET_DRIVERS] = {
|
||||
{
|
||||
"Winsock TCPIP",
|
||||
false,
|
||||
0,
|
||||
WINS_Init,
|
||||
WINS_Shutdown,
|
||||
WINS_Listen,
|
||||
WINS_OpenSocket,
|
||||
WINS_CloseSocket,
|
||||
WINS_Connect,
|
||||
WINS_CheckNewConnections,
|
||||
WINS_Read,
|
||||
WINS_Write,
|
||||
WINS_Broadcast,
|
||||
WINS_AddrToString,
|
||||
WINS_GetSocketAddr,
|
||||
WINS_GetNameFromAddr,
|
||||
WINS_GetAddrFromName,
|
||||
WINS_AddrCompare,
|
||||
WINS_GetSocketPort,
|
||||
WINS_SetSocketPort},
|
||||
.name = "Winsock TCPIP",
|
||||
.initialized = false,
|
||||
.controlSock = 0,
|
||||
.Init = WINS_Init,
|
||||
.Shutdown = WINS_Shutdown,
|
||||
.Listen = WINS_Listen,
|
||||
.OpenSocket = WINS_OpenSocket,
|
||||
.CloseSocket = WINS_CloseSocket,
|
||||
.Connect = WINS_Connect,
|
||||
.CheckNewConnections = WINS_CheckNewConnections,
|
||||
.Read = WINS_Read,
|
||||
.Write = WINS_Write,
|
||||
.Broadcast = WINS_Broadcast,
|
||||
.AddrToString = WINS_AddrToString,
|
||||
.GetSocketAddr = WINS_GetSocketAddr,
|
||||
.GetNameFromAddr = WINS_GetNameFromAddr,
|
||||
.GetAddrFromName = WINS_GetAddrFromName,
|
||||
.AddrCompare = WINS_AddrCompare,
|
||||
.GetSocketPort = WINS_GetSocketPort,
|
||||
.SetSocketPort = WINS_SetSocketPort,
|
||||
},
|
||||
};
|
||||
|
||||
int net_numlandrivers = 1;
|
||||
|
|
|
@ -38,4 +38,5 @@ libs_ruamoko_libQFruamoko_client_la_SOURCES= \
|
|||
libs/ruamoko/rua_game_init.c \
|
||||
libs/ruamoko/rua_input.c \
|
||||
libs/ruamoko/rua_mersenne.c \
|
||||
libs/ruamoko/rua_model.c \
|
||||
libs/ruamoko/rua_scene.c
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
static void (*init_funcs[])(progs_t *, int) = {
|
||||
RUA_Input_Init,
|
||||
RUA_Mersenne_Init,
|
||||
RUA_Model_Init,
|
||||
RUA_Scene_Init,
|
||||
};
|
||||
|
||||
|
|
182
libs/ruamoko/rua_model.c
Normal file
182
libs/ruamoko/rua_model.c
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
bi_model.c
|
||||
|
||||
Ruamkoko model builtins
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/model.h"
|
||||
#include "QF/progs.h"
|
||||
|
||||
#include "rua_internal.h"
|
||||
|
||||
typedef struct rua_model_s {
|
||||
struct rua_model_s *next;
|
||||
struct rua_model_s **prev;
|
||||
model_t *model;
|
||||
} rua_model_t;
|
||||
|
||||
typedef struct {
|
||||
PR_RESMAP (rua_model_t) model_map;
|
||||
rua_model_t *handles;
|
||||
progs_t *pr;
|
||||
} rua_model_resources_t;
|
||||
|
||||
static rua_model_t *
|
||||
rua_model_handle_new (rua_model_resources_t *res)
|
||||
{
|
||||
return PR_RESNEW (res->model_map);
|
||||
}
|
||||
|
||||
static void
|
||||
rua_model_handle_free (rua_model_resources_t *res, rua_model_t *handle)
|
||||
{
|
||||
PR_RESFREE (res->model_map, handle);
|
||||
}
|
||||
|
||||
static void
|
||||
rua_model_handle_reset (rua_model_resources_t *res)
|
||||
{
|
||||
PR_RESRESET (res->model_map);
|
||||
}
|
||||
|
||||
static inline rua_model_t * __attribute__((pure))
|
||||
rua__model_handle_get (rua_model_resources_t *res, int index, const char *name)
|
||||
{
|
||||
rua_model_t *handle = 0;
|
||||
|
||||
handle = PR_RESGET(res->model_map, index);
|
||||
if (!handle) {
|
||||
PR_RunError (res->pr, "invalid model handle passed to %s", name + 3);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
#define rua_model_handle_get(res, index) \
|
||||
rua__model_handle_get (res, index, __FUNCTION__)
|
||||
|
||||
static inline int __attribute__((pure))
|
||||
rua_model_handle_index (rua_model_resources_t *res, rua_model_t *handle)
|
||||
{
|
||||
return PR_RESINDEX(res->model_map, handle);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_rua_model_clear (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_model_resources_t *res = (rua_model_resources_t *) _res;
|
||||
rua_model_t *handle;
|
||||
|
||||
for (handle = res->handles; handle; handle = handle->next)
|
||||
Mod_UnloadModel (handle->model);
|
||||
res->handles = 0;
|
||||
rua_model_handle_reset (res);
|
||||
}
|
||||
|
||||
static int
|
||||
alloc_handle (rua_model_resources_t *res, model_t *model)
|
||||
{
|
||||
rua_model_t *handle = rua_model_handle_new (res);
|
||||
|
||||
if (!handle)
|
||||
return 0;
|
||||
|
||||
handle->next = res->handles;
|
||||
handle->prev = &res->handles;
|
||||
if (res->handles)
|
||||
res->handles->prev = &handle->next;
|
||||
res->handles = handle;
|
||||
handle->model = model;
|
||||
return rua_model_handle_index (res, handle);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Model_Load (progs_t *pr, void *_res)
|
||||
{
|
||||
__auto_type res = (rua_model_resources_t *) _res;
|
||||
const char *path = P_GSTRING (pr, 0);
|
||||
model_t *model;
|
||||
|
||||
R_INT (pr) = 0;
|
||||
if (!(model = Mod_ForName (path, 0)))
|
||||
return;
|
||||
if (!(R_INT (pr) = alloc_handle (res, model)))
|
||||
Mod_UnloadModel (model);
|
||||
}
|
||||
|
||||
model_t *
|
||||
Model_GetModel (progs_t *pr, int handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
rua_model_resources_t *res = PR_Resources_Find (pr, "Model");
|
||||
rua_model_t *h = rua_model_handle_get (res, handle);
|
||||
|
||||
return h->model;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Model_Unload (progs_t *pr, void *_res)
|
||||
{
|
||||
__auto_type res = (rua_model_resources_t *) _res;
|
||||
int handle = P_INT (pr, 0);
|
||||
rua_model_t *h = rua_model_handle_get (res, handle);
|
||||
|
||||
if (!h)
|
||||
PR_RunError (pr, "invalid model handle passed to Qclose");
|
||||
Mod_UnloadModel (h->model);
|
||||
*h->prev = h->next;
|
||||
if (h->next)
|
||||
h->next->prev = h->prev;
|
||||
rua_model_handle_free (res, h);
|
||||
}
|
||||
|
||||
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
|
||||
#define p(type) PR_PARAM(type)
|
||||
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
|
||||
static builtin_t builtins[] = {
|
||||
bi(Model_Load, 1, p(string)),
|
||||
bi(Model_Unload, 1, p(ptr)),
|
||||
{0}
|
||||
};
|
||||
|
||||
void
|
||||
RUA_Model_Init (progs_t *pr, int secure)
|
||||
{
|
||||
rua_model_resources_t *res = calloc (sizeof (rua_model_resources_t), 1);
|
||||
res->pr = pr;
|
||||
|
||||
PR_Resources_Register (pr, "Model", res, bi_rua_model_clear);
|
||||
PR_RegisterBuiltins (pr, builtins, res);
|
||||
}
|
|
@ -38,9 +38,14 @@
|
|||
|
||||
#include "QF/cmem.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/model.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/render.h"
|
||||
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/scene/transform.h"
|
||||
|
||||
|
@ -52,10 +57,18 @@ typedef struct rua_scene_s {
|
|||
scene_t *scene;
|
||||
} rua_scene_t;
|
||||
|
||||
typedef struct rua_lighting_s {
|
||||
struct rua_lighting_s *next;
|
||||
struct rua_lighting_s **prev;
|
||||
lightingdata_t *ldata;
|
||||
} rua_lighting_t;
|
||||
|
||||
typedef struct rua_scene_resources_s {
|
||||
progs_t *pr;
|
||||
PR_RESMAP (rua_scene_t) scene_map;
|
||||
PR_RESMAP (rua_lighting_t) lighting_map;
|
||||
rua_scene_t *scenes;
|
||||
rua_lighting_t *ldatas;
|
||||
} rua_scene_resources_t;
|
||||
|
||||
static rua_scene_t *
|
||||
|
@ -92,6 +105,12 @@ rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
|
|||
}
|
||||
#define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__)
|
||||
|
||||
static int __attribute__((pure))
|
||||
rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene)
|
||||
{
|
||||
return PR_RESINDEX (res->scene_map, scene);
|
||||
}
|
||||
|
||||
static entity_t * __attribute__((pure))
|
||||
rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
|
||||
{
|
||||
|
@ -130,10 +149,44 @@ rua__transform_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
|
|||
}
|
||||
#define rua_transform_get(res, id) rua__transform_get(res, id, __FUNCTION__)
|
||||
|
||||
static int __attribute__((pure))
|
||||
rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene)
|
||||
static rua_lighting_t *
|
||||
rua_lighting_new (rua_scene_resources_t *res)
|
||||
{
|
||||
return PR_RESINDEX (res->scene_map, scene);
|
||||
return PR_RESNEW (res->lighting_map);
|
||||
}
|
||||
|
||||
static void
|
||||
rua_lighting_free (rua_scene_resources_t *res, rua_lighting_t *ldata)
|
||||
{
|
||||
if (ldata->next) {
|
||||
ldata->next->prev = ldata->prev;
|
||||
}
|
||||
*ldata->prev = ldata->next;
|
||||
ldata->prev = 0;
|
||||
PR_RESFREE (res->lighting_map, ldata);
|
||||
}
|
||||
|
||||
static rua_lighting_t * __attribute__((pure))
|
||||
rua__lighting_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
|
||||
{
|
||||
rua_lighting_t *ldata = 0;
|
||||
|
||||
if (id <= 0xffffffffu) {
|
||||
ldata = PR_RESGET (res->lighting_map, (pr_int_t) id);
|
||||
}
|
||||
|
||||
// ldata->prev will be null if the handle is unallocated
|
||||
if (!ldata || !ldata->prev) {
|
||||
PR_RunError (res->pr, "invalid lighting passed to %s", name + 3);
|
||||
}
|
||||
return ldata;
|
||||
}
|
||||
#define rua_lighting_get(res, id) rua__lighting_get(res, id, __FUNCTION__)
|
||||
|
||||
static int __attribute__((pure))
|
||||
rua_lighting_index (rua_scene_resources_t *res, rua_lighting_t *ldata)
|
||||
{
|
||||
return PR_RESINDEX (res->lighting_map, ldata);
|
||||
}
|
||||
|
||||
#define MAKE_ID(id, sc_id) ((((pr_ulong_t) (id)) << 32) \
|
||||
|
@ -176,6 +229,17 @@ bi_Scene_DeleteScene (progs_t *pr, void *_res)
|
|||
rua_delete_scene (res, scene);
|
||||
}
|
||||
|
||||
scene_t *
|
||||
Scene_GetScene (progs_t *pr, pr_ulong_t handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
rua_scene_resources_t *res = PR_Resources_Find (pr, "Scene");
|
||||
rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 0));
|
||||
return scene->scene;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Scene_CreateEntity (progs_t *pr, void *_res)
|
||||
{
|
||||
|
@ -198,6 +262,22 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res)
|
|||
Scene_DestroyEntity (scene->scene, ent);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Scene_SetLighting (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
pr_ulong_t scene_id = P_ULONG (pr, 0);
|
||||
rua_scene_t *scene = rua_scene_get (res, scene_id);
|
||||
pr_ulong_t ldata_id = P_ULONG (pr, 1);
|
||||
rua_lighting_t *ldata = 0;
|
||||
|
||||
if (ldata_id) {
|
||||
ldata = rua_lighting_get (res, ldata_id);
|
||||
}
|
||||
|
||||
scene->scene->lights = ldata->ldata;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Entity_GetTransform (progs_t *pr, void *_res)
|
||||
{
|
||||
|
@ -209,6 +289,23 @@ bi_Entity_GetTransform (progs_t *pr, void *_res)
|
|||
R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Entity_SetModel (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
pr_ulong_t ent_id = P_ULONG (pr, 0);
|
||||
pr_int_t model_id = P_INT (pr, 1);
|
||||
entity_t *ent = rua_entity_get (res, ent_id);
|
||||
model_t *model = Model_GetModel (pr, model_id);
|
||||
pr_ulong_t scene_id = ent_id & 0xffffffff;
|
||||
// bad scene caught above
|
||||
rua_scene_t *scene = rua_scene_get (res, scene_id);
|
||||
|
||||
R_RemoveEfrags (ent);
|
||||
ent->renderer.model = model;
|
||||
R_AddEfrags (&scene->scene->worldmodel->brush, ent);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Transform_ChildCount (progs_t *pr, void *_res)
|
||||
{
|
||||
|
@ -421,6 +518,74 @@ bi_Transform_Up (progs_t *pr, void *_res)
|
|||
R_PACKED (pr, pr_vec4_t) = Transform_Up (transform);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Light_CreateLightingData (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
pr_ulong_t scene_id = P_ULONG (pr, 0);
|
||||
rua_scene_t *scene = rua_scene_get (res, scene_id);
|
||||
|
||||
rua_lighting_t *ldata = rua_lighting_new (res);
|
||||
|
||||
ldata->ldata = Light_CreateLightingData (scene->scene);
|
||||
|
||||
ldata->next = res->ldatas;
|
||||
if (res->ldatas) {
|
||||
res->ldatas->prev = &ldata->next;
|
||||
}
|
||||
ldata->prev = &res->ldatas;
|
||||
res->ldatas = ldata;
|
||||
|
||||
// ldata id in lower 32-bits for all handles
|
||||
// upper 32-bits reserved
|
||||
R_ULONG (pr) = MAKE_ID (0, rua_lighting_index (res, ldata));
|
||||
}
|
||||
|
||||
static void
|
||||
rua_delete_lighting (rua_scene_resources_t *res, rua_lighting_t *ldata)
|
||||
{
|
||||
Light_DestroyLightingData (ldata->ldata);
|
||||
rua_lighting_free (res, ldata);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Light_DestroyLightingData (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
|
||||
|
||||
rua_delete_lighting (res, ldata);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Light_ClearLights (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
|
||||
|
||||
Light_ClearLights (ldata->ldata);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Light_AddLight (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
|
||||
light_t *light = &P_PACKED (pr, light_t, 1);
|
||||
int style = P_INT (pr, 5);
|
||||
|
||||
Light_AddLight (ldata->ldata, light, style);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Light_EnableSun (progs_t *pr, void *_res)
|
||||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0));
|
||||
|
||||
Light_EnableSun (ldata->ldata);
|
||||
}
|
||||
|
||||
#define p(type) PR_PARAM(type)
|
||||
#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), }
|
||||
#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}}
|
||||
|
@ -429,8 +594,10 @@ static builtin_t builtins[] = {
|
|||
bi(Scene_DeleteScene, 1, p(ulong)),
|
||||
bi(Scene_CreateEntity, 1, p(ulong)),
|
||||
bi(Scene_DestroyEntity, 1, p(ulong)),
|
||||
bi(Scene_SetLighting , 2, p(ulong), p(ulong)),
|
||||
|
||||
bi(Entity_GetTransform, 1, p(ulong)),
|
||||
bi(Entity_SetModel, 2, p(ulong), p(int)),
|
||||
|
||||
bi(Transform_ChildCount, 1, p(ulong)),
|
||||
bi(Transform_GetChild, 2, p(ulong), p(int)),
|
||||
|
@ -463,6 +630,13 @@ static builtin_t builtins[] = {
|
|||
bi(Transform_Right, 1, p(ulong)),
|
||||
bi(Transform_Up, 1, p(ulong)),
|
||||
|
||||
bi(Light_CreateLightingData, 1, p(ulong)),
|
||||
bi(Light_DestroyLightingData, 1, p(ulong)),
|
||||
bi(Light_ClearLights, 1, p(ulong)),
|
||||
bi(Light_AddLight, 5, p(ulong),// really, 3
|
||||
p(vec4), p(vec4), p(vec4), p(vec4), p(int)),
|
||||
bi(Light_EnableSun, 1, p(ulong)),
|
||||
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -471,6 +645,9 @@ bi_scene_clear (progs_t *pr, void *_res)
|
|||
{
|
||||
rua_scene_resources_t *res = _res;
|
||||
|
||||
while (res->ldatas) {
|
||||
rua_delete_lighting (res, res->ldatas);
|
||||
}
|
||||
while (res->scenes) {
|
||||
rua_delete_scene (res, res->scenes);
|
||||
}
|
||||
|
@ -483,6 +660,6 @@ RUA_Scene_Init (progs_t *pr, int secure)
|
|||
|
||||
res->pr = pr;
|
||||
|
||||
PR_Resources_Register (pr, "scene", res, bi_scene_clear);
|
||||
PR_Resources_Register (pr, "Scene", res, bi_scene_clear);
|
||||
PR_RegisterBuiltins (pr, builtins, res);
|
||||
}
|
||||
|
|
|
@ -11,5 +11,6 @@ libs_scene_libQFscene_la_SOURCES= \
|
|||
libs/scene/camera.c \
|
||||
libs/scene/entity.c \
|
||||
libs/scene/hierarchy.c \
|
||||
libs/scene/light.c \
|
||||
libs/scene/scene.c \
|
||||
libs/scene/transform.c
|
||||
|
|
|
@ -80,7 +80,7 @@ hierarchy_calcLocalInverse (hierarchy_t *h, uint32_t index)
|
|||
vec4f_t t = h->localMatrix.a[index][3];
|
||||
|
||||
// "one" is to ensure both the scalar and translation have 1 in their
|
||||
// forth components
|
||||
// fourth components
|
||||
vec4f_t one = { 0, 0, 0, 1 };
|
||||
vec4f_t nx = { x[0], y[0], z[0], 0 };
|
||||
vec4f_t ny = { x[1], y[1], z[1], 0 };
|
||||
|
|
162
libs/scene/light.c
Normal file
162
libs/scene/light.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/model.h"
|
||||
#include "QF/set.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
static void
|
||||
expand_pvs (set_t *pvs, model_t *model)
|
||||
{
|
||||
set_t base_pvs = SET_STATIC_INIT (model->brush.visleafs, alloca);
|
||||
set_assign (&base_pvs, pvs);
|
||||
for (unsigned i = 0; i < model->brush.visleafs; i++) {
|
||||
if (set_is_member (&base_pvs, i)) {
|
||||
Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lightingdata_t *
|
||||
Light_CreateLightingData (scene_t *scene)
|
||||
{
|
||||
lightingdata_t *ldata = calloc (1, sizeof (lightingdata_t));
|
||||
|
||||
DARRAY_INIT (&ldata->lights, 16);
|
||||
DARRAY_INIT (&ldata->lightstyles, 16);
|
||||
DARRAY_INIT (&ldata->lightleafs, 16);
|
||||
DARRAY_INIT (&ldata->lightvis, 16);
|
||||
|
||||
ldata->scene = scene;
|
||||
|
||||
return ldata;
|
||||
}
|
||||
|
||||
void
|
||||
Light_DestroyLightingData (lightingdata_t *ldata)
|
||||
{
|
||||
DARRAY_CLEAR (&ldata->lights);
|
||||
DARRAY_CLEAR (&ldata->lightstyles);
|
||||
DARRAY_CLEAR (&ldata->lightleafs);
|
||||
DARRAY_CLEAR (&ldata->lightvis);
|
||||
|
||||
free (ldata);
|
||||
}
|
||||
|
||||
void
|
||||
Light_ClearLights (lightingdata_t *ldata)
|
||||
{
|
||||
ldata->lights.size = 0;
|
||||
ldata->lightstyles.size = 0;
|
||||
ldata->lightleafs.size = 0;
|
||||
ldata->lightvis.size = 0;
|
||||
if (ldata->sun_pvs) {
|
||||
set_delete (ldata->sun_pvs);
|
||||
}
|
||||
ldata->sun_pvs = 0;
|
||||
if (ldata->pvs) {
|
||||
set_delete (ldata->pvs);
|
||||
}
|
||||
ldata->pvs = 0;
|
||||
ldata->leaf = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Light_AddLight (lightingdata_t *ldata, const light_t *light, int style)
|
||||
{
|
||||
scene_t *scene = ldata->scene;
|
||||
model_t *model = scene->worldmodel;
|
||||
|
||||
DARRAY_APPEND (&ldata->lights, *light);
|
||||
DARRAY_APPEND (&ldata->lightstyles, style);
|
||||
|
||||
int visleaf = -1; // directional light
|
||||
if (light->position[3]) {
|
||||
// positional light
|
||||
mleaf_t *leaf = Mod_PointInLeaf (&light->position[0], model);
|
||||
visleaf = leaf - model->brush.leafs - 1;
|
||||
} else if (!DotProduct (light->direction, light->direction)) {
|
||||
// ambient light
|
||||
visleaf = -2;
|
||||
}
|
||||
DARRAY_APPEND (&ldata->lightleafs, visleaf);
|
||||
DARRAY_APPEND (&ldata->lightvis, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Light_EnableSun (lightingdata_t *ldata)
|
||||
{
|
||||
scene_t *scene = ldata->scene;
|
||||
model_t *model = scene->worldmodel;
|
||||
|
||||
if (!ldata->sun_pvs) {
|
||||
ldata->sun_pvs = set_new_size (model->brush.visleafs);
|
||||
}
|
||||
set_expand (ldata->sun_pvs, model->brush.visleafs);
|
||||
set_empty (ldata->sun_pvs);
|
||||
// Any leaf with sky surfaces can potentially see the sun, thus put
|
||||
// the sun "in" every leaf with a sky surface
|
||||
// however, skip leaf 0 as it is the exterior solid leaf
|
||||
for (unsigned l = 1; l < model->brush.modleafs; l++) {
|
||||
if (model->brush.leaf_flags[l] & SURF_DRAWSKY) {
|
||||
set_add (ldata->sun_pvs, l - 1); //pvs is 1-based
|
||||
}
|
||||
}
|
||||
// any leaf visible from a leaf with a sky surface (and thus the sun)
|
||||
// can receive shadows from the sun
|
||||
expand_pvs (ldata->sun_pvs, model);
|
||||
}
|
||||
|
||||
void
|
||||
Light_FindVisibleLights (lightingdata_t *ldata)
|
||||
{
|
||||
scene_t *scene = ldata->scene;
|
||||
mleaf_t *leaf = scene->viewleaf;
|
||||
model_t *model = scene->worldmodel;
|
||||
|
||||
if (!leaf) {
|
||||
return;
|
||||
}
|
||||
if (!ldata->pvs) {
|
||||
ldata->pvs = set_new_size (model->brush.visleafs);
|
||||
}
|
||||
|
||||
if (leaf != ldata->leaf) {
|
||||
//double start = Sys_DoubleTime ();
|
||||
int flags = 0;
|
||||
|
||||
if (leaf == model->brush.leafs) {
|
||||
set_everything (ldata->pvs);
|
||||
} else {
|
||||
Mod_LeafPVS_set (leaf, model, 0, ldata->pvs);
|
||||
expand_pvs (ldata->pvs, model);
|
||||
}
|
||||
for (unsigned i = 0; i < model->brush.visleafs; i++) {
|
||||
if (set_is_member (ldata->pvs, i)) {
|
||||
flags |= model->brush.leaf_flags[i + 1];
|
||||
}
|
||||
}
|
||||
ldata->leaf = leaf;
|
||||
|
||||
//double end = Sys_DoubleTime ();
|
||||
//Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6);
|
||||
|
||||
int visible = 0;
|
||||
memset (ldata->lightvis.a, 0, ldata->lightvis.size * sizeof (byte));
|
||||
for (size_t i = 0; i < ldata->lightleafs.size; i++) {
|
||||
int l = ldata->lightleafs.a[i];
|
||||
if ((l == -2) || (l == -1 && (flags & SURF_DRAWSKY))
|
||||
|| set_is_member (ldata->pvs, l)) {
|
||||
ldata->lightvis.a[i] = 1;
|
||||
visible++;
|
||||
}
|
||||
}
|
||||
//Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible,
|
||||
// ldata->lightvis.size);
|
||||
}
|
||||
}
|
|
@ -35,8 +35,10 @@
|
|||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/progs.h" // for PR_RESMAP
|
||||
#include "QF/sys.h"
|
||||
#include "QF/model.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
|
@ -44,6 +46,44 @@
|
|||
|
||||
#include "scn_internal.h"
|
||||
|
||||
static byte empty_visdata[] = { 0x01 };
|
||||
|
||||
static mleaf_t empty_leafs[] = {
|
||||
[1] = {
|
||||
.contents = CONTENTS_EMPTY,
|
||||
.mins = {-INFINITY, -INFINITY, -INFINITY},
|
||||
.maxs = { INFINITY, INFINITY, INFINITY},
|
||||
.compressed_vis = empty_visdata,
|
||||
},
|
||||
};
|
||||
|
||||
static mnode_t *empty_leaf_parents[] = {
|
||||
[1] = 0,
|
||||
};
|
||||
|
||||
static int empty_leaf_flags[] = {
|
||||
[1] = SURF_DRAWSKY,
|
||||
};
|
||||
|
||||
static char empty_entities[] = { 0 };
|
||||
|
||||
static model_t empty_world = {
|
||||
.type = mod_brush,
|
||||
.radius = INFINITY,
|
||||
.mins = {-INFINITY, -INFINITY, -INFINITY},
|
||||
.maxs = { INFINITY, INFINITY, INFINITY},
|
||||
.brush = {
|
||||
.modleafs = 2,
|
||||
.visleafs = 1,
|
||||
.nodes = (mnode_t *) &empty_leafs[1],
|
||||
.leafs = empty_leafs,
|
||||
.entities = empty_entities,
|
||||
.visdata = empty_visdata,
|
||||
.leaf_parents = empty_leaf_parents,
|
||||
.leaf_flags = empty_leaf_flags,
|
||||
},
|
||||
};
|
||||
|
||||
scene_t *
|
||||
Scene_NewScene (void)
|
||||
{
|
||||
|
@ -54,6 +94,8 @@ Scene_NewScene (void)
|
|||
res = calloc (1, sizeof (scene_resources_t));
|
||||
*(scene_resources_t **)&scene->resources = res;
|
||||
|
||||
scene->worldmodel = &empty_world;
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
|
@ -84,6 +126,8 @@ Scene_CreateEntity (scene_t *scene)
|
|||
hierarchy_t *h = ent->transform->hierarchy;
|
||||
h->entity.a[ent->transform->index] = ent;
|
||||
|
||||
QuatSet (1, 1, 1, 1, ent->renderer.colormod);
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ libs_video_renderer_librender_gl_la_SOURCES = \
|
|||
shader_src= libs/video/renderer/glsl/quakeforge.glsl
|
||||
shader_gen= libs/video/renderer/glsl/quakeforge.slc
|
||||
|
||||
SUFFICES += .frag .vert .spv .spvc .fc .vc .slc .glsl
|
||||
SUFFIXES += .frag .vert .spv .spvc .fc .vc .slc .glsl
|
||||
.glsl.slc:
|
||||
$(V_SED)sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\
|
||||
$(am__mv) $@.t $@
|
||||
|
@ -207,6 +207,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
|
|||
libs/video/renderer/vulkan/pipeline.c \
|
||||
libs/video/renderer/vulkan/projection.c \
|
||||
libs/video/renderer/vulkan/renderpass.c \
|
||||
libs/video/renderer/vulkan/resource.c \
|
||||
libs/video/renderer/vulkan/scrap.c \
|
||||
libs/video/renderer/vulkan/shader.c \
|
||||
libs/video/renderer/vulkan/staging.c \
|
||||
|
@ -218,6 +219,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \
|
|||
libs/video/renderer/vulkan/vulkan_bsp.c \
|
||||
libs/video/renderer/vulkan/vulkan_compose.c \
|
||||
libs/video/renderer/vulkan/vulkan_draw.c \
|
||||
libs/video/renderer/vulkan/vulkan_iqm.c \
|
||||
libs/video/renderer/vulkan/vulkan_lighting.c \
|
||||
libs/video/renderer/vulkan/vulkan_main.c \
|
||||
libs/video/renderer/vulkan/vulkan_matrices.c \
|
||||
|
@ -299,8 +301,14 @@ alias_gbuf_src = $(vkshaderpath)/alias_gbuf.frag
|
|||
alias_gbuf_c = $(vkshaderpath)/alias_gbuf.frag.spvc
|
||||
alias_shadow_src = $(vkshaderpath)/alias_shadow.vert
|
||||
alias_shadow_c = $(vkshaderpath)/alias_shadow.vert.spvc
|
||||
iqmv_src = $(vkshaderpath)/iqm.vert
|
||||
iqmv_c = $(vkshaderpath)/iqm.vert.spvc
|
||||
iqmf_src = $(vkshaderpath)/iqm.frag
|
||||
iqmf_c = $(vkshaderpath)/iqm.frag.spvc
|
||||
passthrough_src = $(vkshaderpath)/passthrough.vert
|
||||
passthrough_c = $(vkshaderpath)/passthrough.vert.spvc
|
||||
fstriangle_src = $(vkshaderpath)/fstriangle.vert
|
||||
fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc
|
||||
pushcolor_src = $(vkshaderpath)/pushcolor.frag
|
||||
pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc
|
||||
shadow_src = $(vkshaderpath)/shadow.geom
|
||||
|
@ -356,8 +364,14 @@ $(alias_gbuf_c): $(alias_gbuf_src)
|
|||
|
||||
$(alias_shadow_c): $(alias_shadow_src)
|
||||
|
||||
$(iqmv_c): $(iqmv_src)
|
||||
|
||||
$(iqmf_c): $(iqmf_src)
|
||||
|
||||
$(passthrough_c): $(passthrough_src)
|
||||
|
||||
$(fstriangle_c): $(fstriangle_src)
|
||||
|
||||
$(pushcolor_c): $(pushcolor_src)
|
||||
|
||||
$(shadow_c): $(shadow_src)
|
||||
|
@ -390,7 +404,10 @@ vkshader_c = \
|
|||
$(aliasf_c) \
|
||||
$(alias_gbuf_c) \
|
||||
$(alias_shadow_c) \
|
||||
$(iqmv_c) \
|
||||
$(iqmf_c) \
|
||||
$(passthrough_c) \
|
||||
$(fstriangle_c) \
|
||||
$(pushcolor_c) \
|
||||
$(shadow_c)
|
||||
|
||||
|
@ -443,6 +460,7 @@ EXTRA_DIST += \
|
|||
libs/video/renderer/vulkan/shader/compose.frag \
|
||||
libs/video/renderer/vulkan/shader/lighting.frag \
|
||||
libs/video/renderer/vulkan/shader/passthrough.vert \
|
||||
libs/video/renderer/vulkan/shader/fstriangle.vert \
|
||||
libs/video/renderer/vulkan/shader/partphysics.comp \
|
||||
libs/video/renderer/vulkan/shader/partupdate.comp \
|
||||
libs/video/renderer/vulkan/shader/particle.vert \
|
||||
|
|
|
@ -278,7 +278,9 @@ gl_R_RenderView (void)
|
|||
gl_R_DrawWorld ();
|
||||
S_ExtraUpdate (); // don't let sound get messed up if going slow
|
||||
gl_R_RenderDlights ();
|
||||
R_DrawViewModel ();
|
||||
if (vr_data.view_model) {
|
||||
R_DrawViewModel ();
|
||||
}
|
||||
|
||||
gl_Fog_DisableGFog ();
|
||||
}
|
||||
|
|
|
@ -66,12 +66,15 @@
|
|||
#include "QF/GL/qf_vid.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
|
||||
#include "mod_internal.h"
|
||||
#include "r_internal.h"
|
||||
#include "varrays.h"
|
||||
#include "vid_gl.h"
|
||||
|
||||
static gltex_t gl_notexture = { };
|
||||
|
||||
static void
|
||||
gl_R_LoadSky_f (void)
|
||||
{
|
||||
|
@ -114,6 +117,8 @@ gl_R_TimeRefresh_f (void)
|
|||
void
|
||||
gl_R_Init (void)
|
||||
{
|
||||
r_notexture_mip->render = &gl_notexture;
|
||||
|
||||
R_Init_Cvars ();
|
||||
|
||||
Cmd_AddCommand ("timerefresh", gl_R_TimeRefresh_f,
|
||||
|
@ -152,7 +157,7 @@ register_textures (mod_brush_t *brush)
|
|||
}
|
||||
|
||||
void
|
||||
gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
||||
gl_R_NewScene (scene_t *scene)
|
||||
{
|
||||
texture_t *tex;
|
||||
mod_brush_t *brush;
|
||||
|
@ -160,20 +165,19 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
for (int i = 0; i < 256; i++)
|
||||
d_lightstylevalue[i] = 264; // normal light value
|
||||
|
||||
r_refdef.worldmodel = worldmodel;
|
||||
brush = &worldmodel->brush;
|
||||
r_refdef.worldmodel = scene->worldmodel;
|
||||
brush = &scene->worldmodel->brush;
|
||||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
for (unsigned i = 0; i < brush->modleafs; i++)
|
||||
brush->leafs[i].efrags = NULL;
|
||||
|
||||
// Force a vis update
|
||||
r_refdef.viewleaf = NULL;
|
||||
R_MarkLeaves ();
|
||||
R_MarkLeaves (0);
|
||||
|
||||
R_ClearParticles ();
|
||||
|
||||
GL_BuildLightmaps (models, num_models);
|
||||
GL_BuildLightmaps (scene->models, scene->num_models);
|
||||
|
||||
// identify sky texture
|
||||
gl_R_ClearTextures ();
|
||||
|
@ -189,13 +193,13 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
gl_R_InitSurfaceChains (brush);
|
||||
gl_R_AddTexture (r_notexture_mip);
|
||||
register_textures (brush);
|
||||
for (int i = 0; i < num_models; i++) {
|
||||
if (!models[i])
|
||||
for (int i = 0; i < scene->num_models; i++) {
|
||||
if (!scene->models[i])
|
||||
continue;
|
||||
if (*models[i]->path == '*')
|
||||
if (*scene->models[i]->path == '*')
|
||||
continue;
|
||||
if (models[i] != r_refdef.worldmodel
|
||||
&& models[i]->type == mod_brush)
|
||||
register_textures (&models[i]->brush);
|
||||
if (scene->models[i] != r_refdef.worldmodel
|
||||
&& scene->models[i]->type == mod_brush)
|
||||
register_textures (&scene->models[i]->brush);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -712,8 +712,6 @@ R_VisitWorldNodes (glbspctx_t *bctx)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -103,6 +103,7 @@ static double sky_time;
|
|||
|
||||
static quat_t default_color = { 1, 1, 1, 1 };
|
||||
static quat_t last_color;
|
||||
static glsltex_t glsl_notexture = { };
|
||||
|
||||
static const char *bsp_vert_effects[] =
|
||||
{
|
||||
|
@ -831,8 +832,6 @@ R_VisitWorldNodes (glslbspctx_t *bctx)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1284,6 +1283,8 @@ glsl_R_InitBsp (void)
|
|||
int vert;
|
||||
int frag;
|
||||
|
||||
r_notexture_mip->render = &glsl_notexture;
|
||||
|
||||
vert_shader = GLSL_BuildShader (bsp_vert_effects);
|
||||
frag_shader = GLSL_BuildShader (bsp_lit_effects);
|
||||
vert = GLSL_CompileShader ("quakebsp.vert", vert_shader,
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
|
||||
#include "QF/GLSL/defines.h"
|
||||
#include "QF/GLSL/funcs.h"
|
||||
|
@ -142,7 +143,9 @@ glsl_R_RenderView (void)
|
|||
R_SetupView ();
|
||||
glsl_R_DrawWorld ();
|
||||
glsl_R_DrawSky ();
|
||||
R_DrawViewModel ();
|
||||
if (vr_data.view_model) {
|
||||
R_DrawViewModel ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -186,23 +189,22 @@ glsl_R_Init (void)
|
|||
}
|
||||
|
||||
void
|
||||
glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
||||
glsl_R_NewScene (scene_t *scene)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
d_lightstylevalue[i] = 264; // normal light value
|
||||
|
||||
r_refdef.worldmodel = worldmodel;
|
||||
r_refdef.worldmodel = scene->worldmodel;
|
||||
|
||||
// Force a vis update
|
||||
r_refdef.viewleaf = NULL;
|
||||
R_MarkLeaves ();
|
||||
R_MarkLeaves (0);
|
||||
|
||||
R_ClearParticles ();
|
||||
glsl_R_RegisterTextures (models, num_models);
|
||||
glsl_R_BuildLightmaps (models, num_models);
|
||||
glsl_R_BuildDisplayLists (models, num_models);
|
||||
glsl_R_RegisterTextures (scene->models, scene->num_models);
|
||||
glsl_R_BuildLightmaps (scene->models, scene->num_models);
|
||||
glsl_R_BuildDisplayLists (scene->models, scene->num_models);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -47,7 +47,7 @@ static mleaf_t *r_oldviewleaf;
|
|||
static set_t *solid;
|
||||
|
||||
void
|
||||
R_MarkLeaves (void)
|
||||
R_MarkLeaves (mleaf_t *viewleaf)
|
||||
{
|
||||
set_t *vis;
|
||||
int c;
|
||||
|
@ -56,12 +56,12 @@ R_MarkLeaves (void)
|
|||
msurface_t **mark;
|
||||
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
||||
|
||||
if (r_oldviewleaf == r_refdef.viewleaf && !r_novis)
|
||||
if (r_oldviewleaf == viewleaf && !r_novis)
|
||||
return;
|
||||
|
||||
r_visframecount++;
|
||||
r_oldviewleaf = r_refdef.viewleaf;
|
||||
if (!r_refdef.viewleaf)
|
||||
r_oldviewleaf = viewleaf;
|
||||
if (!viewleaf)
|
||||
return;
|
||||
|
||||
if (r_novis) {
|
||||
|
@ -73,7 +73,7 @@ R_MarkLeaves (void)
|
|||
}
|
||||
vis = solid;
|
||||
} else
|
||||
vis = Mod_LeafPVS (r_refdef.viewleaf, r_refdef.worldmodel);
|
||||
vis = Mod_LeafPVS (viewleaf, r_refdef.worldmodel);
|
||||
|
||||
for (unsigned i = 0; i < brush->visleafs; i++) {
|
||||
if (set_is_member (vis, i)) {
|
||||
|
|
|
@ -126,6 +126,10 @@ R_AnimateLight (void)
|
|||
{
|
||||
int i, j, k;
|
||||
|
||||
if (!r_data->lightstyle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// light animations
|
||||
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||
i = (int) (r_data->realtime * 10);
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "QF/va.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/scene/transform.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
||||
|
@ -71,40 +72,41 @@ static framebuffer_t *warp_buffer;
|
|||
|
||||
static float fov_x, fov_y;
|
||||
static float tan_fov_x, tan_fov_y;
|
||||
static scene_t *scr_scene;//FIXME don't want this here
|
||||
|
||||
static mat4f_t box_rotations[] = {
|
||||
[BOX_FRONT] = {
|
||||
{ 1, 0, 0, 0}, // front
|
||||
{ 1, 0, 0, 0},
|
||||
{ 0, 1, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1}
|
||||
},
|
||||
[BOX_RIGHT] = {
|
||||
{ 0,-1, 0, 0}, // right
|
||||
{ 0,-1, 0, 0},
|
||||
{ 1, 0, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1}
|
||||
},
|
||||
[BOX_BEHIND] = {
|
||||
{-1, 0, 0, 0}, // back
|
||||
{-1, 0, 0, 0},
|
||||
{ 0,-1, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1}
|
||||
},
|
||||
[BOX_LEFT] = {
|
||||
{ 0, 1, 0, 0}, // left
|
||||
{ 0, 1, 0, 0},
|
||||
{-1, 0, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1}
|
||||
},
|
||||
[BOX_TOP] = {
|
||||
{ 0, 0, 1, 0}, // top
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 1, 0, 0},
|
||||
{-1, 0, 0, 0},
|
||||
{ 0, 0, 0, 1}
|
||||
},
|
||||
[BOX_BOTTOM] = {
|
||||
{ 0, 0,-1, 0}, // bottom
|
||||
{ 0, 0,-1, 0},
|
||||
{ 0, 1, 0, 0},
|
||||
{ 1, 0, 0, 0},
|
||||
{ 0, 0, 0, 1}
|
||||
|
@ -268,20 +270,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
|
|||
|
||||
R_RunParticles (r_data->frametime);
|
||||
R_AnimateLight ();
|
||||
refdef->viewleaf = 0;
|
||||
if (refdef->worldmodel) {
|
||||
if (scr_scene && scr_scene->worldmodel) {
|
||||
scr_scene->viewleaf = 0;
|
||||
vec4f_t position = refdef->frame.position;
|
||||
refdef->viewleaf = Mod_PointInLeaf ((vec_t*)&position, refdef->worldmodel);//FIXME
|
||||
scr_scene->viewleaf = Mod_PointInLeaf ((vec_t*)&position,
|
||||
scr_scene->worldmodel);//FIXME
|
||||
r_dowarpold = r_dowarp;
|
||||
if (r_waterwarp) {
|
||||
r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER;
|
||||
r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER;
|
||||
}
|
||||
if (r_dowarp && !warp_buffer) {
|
||||
warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width,
|
||||
r_data->vid->height);
|
||||
}
|
||||
R_MarkLeaves (scr_scene->viewleaf);
|
||||
}
|
||||
R_MarkLeaves ();
|
||||
R_PushDlights (vec3_origin);
|
||||
|
||||
r_funcs->begin_frame ();
|
||||
|
@ -505,3 +508,15 @@ SCR_Init (void)
|
|||
Cvar_AddListener (var, viewsize_listener, 0);
|
||||
update_vrect ();
|
||||
}
|
||||
|
||||
void
|
||||
SCR_NewScene (scene_t *scene)
|
||||
{
|
||||
scr_scene = scene;
|
||||
if (scene) {
|
||||
r_funcs->set_fov (tan_fov_x, tan_fov_y);
|
||||
r_funcs->R_NewScene (scene);
|
||||
} else {
|
||||
r_funcs->R_ClearState ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -513,8 +513,6 @@ R_VisitWorldNodes (swbspctx_t *bctx, int clipflags)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "mod_internal.h"
|
||||
|
@ -151,8 +152,9 @@ sw_R_Init (void)
|
|||
}
|
||||
|
||||
void
|
||||
R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
||||
R_NewScene (scene_t *scene)
|
||||
{
|
||||
model_t *worldmodel = scene->worldmodel;
|
||||
mod_brush_t *brush = &worldmodel->brush;
|
||||
|
||||
r_refdef.worldmodel = worldmodel;
|
||||
|
@ -165,8 +167,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
|
|||
R_InitSky (brush->skytexture);
|
||||
|
||||
// Force a vis update
|
||||
r_refdef.viewleaf = NULL;
|
||||
R_MarkLeaves ();
|
||||
R_MarkLeaves (0);
|
||||
|
||||
R_ClearParticles ();
|
||||
|
||||
|
@ -589,7 +590,9 @@ R_RenderView_ (void)
|
|||
|
||||
R_EdgeDrawing (r_ent_queue);
|
||||
|
||||
R_DrawViewModel ();
|
||||
if (vr_data.view_model) {
|
||||
R_DrawViewModel ();
|
||||
}
|
||||
|
||||
if (r_aliasstats)
|
||||
R_PrintAliasStats ();
|
||||
|
|
|
@ -163,7 +163,7 @@ static vid_model_funcs_t model_funcs = {
|
|||
Mod_LoadSpriteModel,
|
||||
|
||||
gl_Mod_MakeAliasModelDisplayLists,
|
||||
gl_Mod_LoadSkin,
|
||||
gl_Mod_LoadAllSkins,
|
||||
gl_Mod_FinalizeAliasModel,
|
||||
gl_Mod_LoadExternalSkins,
|
||||
gl_Mod_IQMFinish,
|
||||
|
@ -510,7 +510,7 @@ vid_render_funcs_t gl_vid_render_funcs = {
|
|||
gl_R_Init,
|
||||
gl_R_ClearState,
|
||||
gl_R_LoadSkys,
|
||||
gl_R_NewMap,
|
||||
gl_R_NewScene,
|
||||
gl_R_LineGraph,
|
||||
gl_begin_frame,
|
||||
gl_render_view,
|
||||
|
|
|
@ -74,7 +74,7 @@ static vid_model_funcs_t model_funcs = {
|
|||
Mod_LoadSpriteModel,
|
||||
|
||||
glsl_Mod_MakeAliasModelDisplayLists,
|
||||
glsl_Mod_LoadSkin,
|
||||
glsl_Mod_LoadAllSkins,
|
||||
glsl_Mod_FinalizeAliasModel,
|
||||
glsl_Mod_LoadExternalSkins,
|
||||
glsl_Mod_IQMFinish,
|
||||
|
@ -454,7 +454,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
|
|||
glsl_R_Init,
|
||||
glsl_R_ClearState,
|
||||
glsl_R_LoadSkys,
|
||||
glsl_R_NewMap,
|
||||
glsl_R_NewScene,
|
||||
glsl_R_LineGraph,
|
||||
glsl_begin_frame,
|
||||
glsl_render_view,
|
||||
|
|
|
@ -83,7 +83,7 @@ static vid_model_funcs_t model_funcs = {
|
|||
Mod_LoadSpriteModel,
|
||||
|
||||
sw_Mod_MakeAliasModelDisplayLists,
|
||||
sw_Mod_LoadSkin,
|
||||
sw_Mod_LoadAllSkins,
|
||||
0,
|
||||
0,
|
||||
sw_Mod_IQMFinish,
|
||||
|
@ -474,7 +474,7 @@ vid_render_funcs_t sw_vid_render_funcs = {
|
|||
sw_R_Init,
|
||||
R_ClearState,
|
||||
R_LoadSkys,
|
||||
R_NewMap,
|
||||
R_NewScene,
|
||||
R_LineGraph,
|
||||
sw_begin_frame,
|
||||
sw_render_view,
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "QF/Vulkan/qf_bsp.h"
|
||||
#include "QF/Vulkan/qf_compose.h"
|
||||
#include "QF/Vulkan/qf_draw.h"
|
||||
#include "QF/Vulkan/qf_iqm.h"
|
||||
#include "QF/Vulkan/qf_lighting.h"
|
||||
#include "QF/Vulkan/qf_lightmap.h"
|
||||
#include "QF/Vulkan/qf_main.h"
|
||||
|
@ -63,6 +64,7 @@
|
|||
#include "QF/ui/view.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/scene.h"
|
||||
|
||||
#include "mod_internal.h"
|
||||
#include "r_internal.h"
|
||||
|
@ -80,7 +82,6 @@ vulkan_ParticleSystem (void)
|
|||
static void
|
||||
vulkan_R_Init (void)
|
||||
{
|
||||
r_ent_queue = EntQueue_New (mod_num_types);
|
||||
Vulkan_CreateStagingBuffers (vulkan_ctx);
|
||||
Vulkan_CreateSwapchain (vulkan_ctx);
|
||||
Vulkan_CreateFrames (vulkan_ctx);
|
||||
|
@ -118,9 +119,9 @@ vulkan_R_LoadSkys (const char *skyname)
|
|||
}
|
||||
|
||||
static void
|
||||
vulkan_R_NewMap (model_t *worldmodel, model_t **models, int num_models)
|
||||
vulkan_R_NewScene (scene_t *scene)
|
||||
{
|
||||
Vulkan_NewMap (worldmodel, models, num_models, vulkan_ctx);
|
||||
Vulkan_NewScene (scene, vulkan_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -541,13 +542,10 @@ vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx,
|
|||
vulkan_ctx);
|
||||
}
|
||||
|
||||
static void *
|
||||
vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize,
|
||||
int snum, int gnum, qboolean group,
|
||||
maliasskindesc_t *skindesc)
|
||||
static void
|
||||
vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
|
||||
{
|
||||
return Vulkan_Mod_LoadSkin (alias_ctx, skin, skinsize, snum, gnum, group,
|
||||
skindesc, vulkan_ctx);
|
||||
Vulkan_Mod_LoadAllSkins (alias_ctx, vulkan_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -564,6 +562,7 @@ vulkan_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx)
|
|||
static void
|
||||
vulkan_Mod_IQMFinish (model_t *mod)
|
||||
{
|
||||
Vulkan_Mod_IQMFinish (mod, vulkan_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -639,7 +638,7 @@ static vid_model_funcs_t model_funcs = {
|
|||
Mod_LoadSpriteModel,
|
||||
|
||||
vulkan_Mod_MakeAliasModelDisplayLists,
|
||||
vulkan_Mod_LoadSkin,
|
||||
vulkan_Mod_LoadAllSkins,
|
||||
vulkan_Mod_FinalizeAliasModel,
|
||||
vulkan_Mod_LoadExternalSkins,
|
||||
vulkan_Mod_IQMFinish,
|
||||
|
@ -729,7 +728,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
|
|||
vulkan_R_Init,
|
||||
vulkan_R_ClearState,
|
||||
vulkan_R_LoadSkys,
|
||||
vulkan_R_NewMap,
|
||||
vulkan_R_NewScene,
|
||||
vulkan_R_LineGraph,
|
||||
vulkan_begin_frame,
|
||||
vulkan_render_view,
|
||||
|
@ -773,8 +772,7 @@ static plugin_t plugin_info = {
|
|||
QFPLUGIN_VERSION,
|
||||
"0.1",
|
||||
"Vulkan Renderer",
|
||||
"Copyright (C) 1996-1997 Id Software, Inc.\n"
|
||||
"Copyright (C) 1999-2019 contributors of the QuakeForge project\n"
|
||||
"Copyright (C) 2019 Bill Currie <bill@taniwha.org>\n"
|
||||
"Please see the file \"AUTHORS\" for a list of contributors",
|
||||
&plugin_info_funcs,
|
||||
&plugin_info_data,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan buffer functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan frame capture support
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
@ -99,22 +98,21 @@ QFV_CreateCapture (qfv_device_t *device, int numframes,
|
|||
image->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
image->cmd = cmdset->a[i];
|
||||
}
|
||||
size_t image_size = QFV_GetImageSize (device,
|
||||
capture->image_set->a[0].image);
|
||||
capture->memsize = numframes * image_size;
|
||||
capture->imgsize = QFV_GetImageSize (device,
|
||||
capture->image_set->a[0].image);
|
||||
capture->memsize = numframes * capture->imgsize;
|
||||
capture->memory = QFV_AllocImageMemory (device,
|
||||
capture->image_set->a[0].image,
|
||||
VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
capture->memsize, 0);
|
||||
byte *data;
|
||||
dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0,
|
||||
(void **) &data);
|
||||
(void **) &capture->data);
|
||||
|
||||
for (int i = 0; i < numframes; i++) {
|
||||
__auto_type image = &capture->image_set->a[i];
|
||||
image->data = data + i * image_size;
|
||||
image->data = capture->data + i * capture->imgsize;
|
||||
dfunc->vkBindImageMemory (device->dev, image->image, capture->memory,
|
||||
image->data - data);
|
||||
image->data - capture->data);
|
||||
}
|
||||
return capture;
|
||||
}
|
||||
|
@ -252,6 +250,15 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame)
|
|||
const byte *
|
||||
QFV_CaptureData (qfv_capture_t *capture, int frame)
|
||||
{
|
||||
qfv_device_t *device = capture->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
__auto_type image = &capture->image_set->a[frame];
|
||||
VkMappedMemoryRange range = {
|
||||
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||
.memory = capture->memory,
|
||||
.offset = image->data - capture->data,
|
||||
.size = capture->imgsize,
|
||||
};
|
||||
dfunc->vkInvalidateMappedMemoryRanges (device->dev, 1, &range);
|
||||
return image->data;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Common Vulkan video driver functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -1,223 +1,101 @@
|
|||
{
|
||||
flat_color_image_template = {
|
||||
imageType = `2d;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
images = {
|
||||
depth = {
|
||||
imageType = `2d;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = x8_d24_unorm_pack32;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = depth_stencil_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
color = {
|
||||
imageType = `2d;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = r8g8b8a8_unorm;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
emission = {
|
||||
imageType = `2d;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = r16g16b16a16_sfloat;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
normal = {
|
||||
imageType = `2d;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = r16g16b16a16_sfloat;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
position = {
|
||||
imageType = `2d;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = r32g32b32a32_sfloat;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
opaque = {
|
||||
imageType = `2d;
|
||||
format = r8g8b8a8_unorm;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = r16g16b16a16_sfloat;
|
||||
};
|
||||
translucent = {
|
||||
imageType = `2d;
|
||||
@inherit = $properties.flat_color_image_template;
|
||||
format = r8g8b8a8_unorm;
|
||||
samples = 1;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|input_attachment|transient_attachment;
|
||||
initialLayout = undefined;
|
||||
};
|
||||
};
|
||||
flat_color_view_template = {
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
imageViews = {
|
||||
depth = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = depth;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.depth.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = depth;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
color = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = color;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.color.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
emission = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = emission;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.emission.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
normal = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = normal;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.normal.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
position = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = position;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.position.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
opaque = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = opaque;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.opaque.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
translucent = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = translucent;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
format = $properties.images.translucent.format;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
framebuffer = {
|
||||
|
@ -238,86 +116,55 @@
|
|||
{ color = "[0, 0, 0, 0]"; }, // translucent
|
||||
{ color = "[0, 0, 0, 1]"; }, // output
|
||||
);
|
||||
attachment_template = {
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
};
|
||||
renderpass = {
|
||||
attachments = (
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.depth.format;
|
||||
samples = 1;
|
||||
loadOp = clear;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = depth_stencil_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.color.format;
|
||||
samples = 1;
|
||||
loadOp = clear;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.emission.format;
|
||||
samples = 1;
|
||||
loadOp = clear;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.normal.format;
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.position.format;
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.opaque.format;
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.translucent.format;
|
||||
samples = 1;
|
||||
loadOp = clear;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $output.format;
|
||||
samples = 1;
|
||||
loadOp = clear;
|
||||
storeOp = store;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = present_src_khr;
|
||||
},
|
||||
);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan descriptor functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Common Vulkan video driver functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2019 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
199
libs/video/renderer/vulkan/forward.plist
Normal file
199
libs/video/renderer/vulkan/forward.plist
Normal file
|
@ -0,0 +1,199 @@
|
|||
{
|
||||
flat_color_image_template = {
|
||||
imageType = `2d;
|
||||
samples = $msaaSamples;
|
||||
extent = {
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
depth = 1;
|
||||
};
|
||||
mipLevels = 1;
|
||||
arrayLayers = 1;
|
||||
tiling = optimal;
|
||||
usage = color_attachment|transient_attachment;
|
||||
};
|
||||
images = {
|
||||
depth = {
|
||||
@inherit = @properties.flat_color_image_template;
|
||||
format = x8_d24_unorm_pack32;
|
||||
usage = depth_stencil_attachment|transient_attachment;
|
||||
};
|
||||
color = {
|
||||
@inherit = @properties.flat_color_image_template;
|
||||
format = $output.format;
|
||||
};
|
||||
};
|
||||
flat_color_view_template = {
|
||||
viewType = `2d;
|
||||
components = {
|
||||
r = identity;
|
||||
g = identity;
|
||||
b = identity;
|
||||
a = identity;
|
||||
};
|
||||
subresourceRange = {
|
||||
aspectMask = color;
|
||||
levelCount = 1;
|
||||
layerCount = 1;
|
||||
};
|
||||
};
|
||||
imageViews = {
|
||||
depth = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = depth;
|
||||
format = $properties.images.depth.format;
|
||||
subresourceRange = {
|
||||
aspectMask = depth;
|
||||
};
|
||||
};
|
||||
color = {
|
||||
@inherit = $properties.flat_color_view_template;
|
||||
image = color;
|
||||
format = $properties.images.color.format;
|
||||
};
|
||||
};
|
||||
framebuffer = {
|
||||
renderPass = $properties.renderpass;
|
||||
attachment = ($output.view, depth);
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
layers = 1;
|
||||
};
|
||||
framebuffer_msaa = {
|
||||
renderPass = $properties.renderpass_msaa;
|
||||
attachment = ($output.view, depth, color);
|
||||
width = $output.extent.width;
|
||||
height = $output.extent.height;
|
||||
layers = 1;
|
||||
};
|
||||
attachment_template = {
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
storeOp = dont_care;
|
||||
stencilLoadOp = dont_care;
|
||||
stencilStoreOp = dont_care;
|
||||
initialLayout = undefined;
|
||||
finalLayout = color_attachment_optimal;
|
||||
};
|
||||
renderpass = {
|
||||
attachments = (
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $output.format;
|
||||
loadOp = clear;
|
||||
storeOp = store;
|
||||
finalLayout = present_src_khr;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.depth.format;
|
||||
loadOp = clear;
|
||||
finalLayout = depth_stencil_attachment_optimal;
|
||||
},
|
||||
);
|
||||
subpasses = (
|
||||
{
|
||||
pipelineBindPoint = graphics;
|
||||
colorAttachments = (
|
||||
{
|
||||
attachment = 0;
|
||||
layout = color_attachment_optimal;
|
||||
}
|
||||
);
|
||||
depthStencilAttachment = {
|
||||
attachment = 1;
|
||||
layout = depth_stencil_attachment_optimal;
|
||||
};
|
||||
preserveAttachments = ();
|
||||
},
|
||||
);
|
||||
dependencies = (
|
||||
{
|
||||
srcSubpass = ~0u; // external
|
||||
dstSubpass = 0;
|
||||
srcStageMask = top_of_pipe;
|
||||
dstStageMask = color_attachment_output;
|
||||
srcAccessMask = memory_read;
|
||||
dstAccessMask = color_attachment_write;
|
||||
dependencyFlags = by_region;
|
||||
},
|
||||
{
|
||||
srcSubpass = 0;
|
||||
dstSubpass = ~0u; // external
|
||||
srcStageMask = color_attachment_output;
|
||||
dstStageMask = bottom_of_pipe;
|
||||
srcAccessMask = color_attachment_write;
|
||||
dstAccessMask = memory_read;
|
||||
dependencyFlags = by_region;
|
||||
},
|
||||
);
|
||||
};
|
||||
renderpass_msaa = {
|
||||
attachments = (
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $output.format;
|
||||
storeOp = store;
|
||||
finalLayout = present_src_khr;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $properties.images.depth.format;
|
||||
samples = $msaaSamples;
|
||||
loadOp = clear;
|
||||
storeOp = dont_care;
|
||||
finalLayout = depth_stencil_attachment_optimal;
|
||||
},
|
||||
{
|
||||
@inherit = $properties.attachment_template;
|
||||
format = $swapchain.format;
|
||||
samples = $msaaSamples;
|
||||
loadOp = clear;
|
||||
storeOp = store;// dont_care?
|
||||
finalLayout = color_attachment_optimal;
|
||||
},
|
||||
);
|
||||
subpasses = (
|
||||
{
|
||||
pipelineBindPoint = graphics;
|
||||
colorAttachments = (
|
||||
{
|
||||
attachment = 2;
|
||||
layout = color_attachment_optimal;
|
||||
}
|
||||
);
|
||||
resolveAttachments = (
|
||||
{
|
||||
attachment = 0;
|
||||
layout = color_attachment_optimal;
|
||||
}
|
||||
);
|
||||
depthStencilAttachment = {
|
||||
attachment = 1;
|
||||
layout = depth_stencil_attachment_optimal;
|
||||
};
|
||||
preserveAttachments = ();
|
||||
},
|
||||
);
|
||||
dependencies = (
|
||||
{
|
||||
srcSubpass = ~0u; // external
|
||||
dstSubpass = 0;
|
||||
srcStageMask = top_of_pipe;
|
||||
dstStageMask = color_attachment_output;
|
||||
srcAccessMask = memory_read;
|
||||
dstAccessMask = color_attachment_write;
|
||||
dependencyFlags = by_region;
|
||||
},
|
||||
{
|
||||
srcSubpass = 0;
|
||||
dstSubpass = ~0u; // external
|
||||
srcStageMask = color_attachment_output;
|
||||
dstStageMask = bottom_of_pipe;
|
||||
srcAccessMask = color_attachment_write;
|
||||
dstAccessMask = memory_read;
|
||||
dependencyFlags = by_region;
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan image functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
@ -266,3 +265,24 @@ QFV_MipLevels (int width, int height)
|
|||
{
|
||||
return ilog2 (max (width, height)) + 1;
|
||||
}
|
||||
|
||||
VkFormat
|
||||
QFV_ImageFormat (QFFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case tex_palette:
|
||||
return VK_FORMAT_R8_UINT;
|
||||
case tex_l:
|
||||
case tex_a:
|
||||
return VK_FORMAT_R8_UNORM;
|
||||
case tex_la:
|
||||
return VK_FORMAT_R8G8_UNORM;
|
||||
case tex_rgb:
|
||||
return VK_FORMAT_R8G8B8_UNORM; // SRGB?
|
||||
case tex_rgba:
|
||||
return VK_FORMAT_R8G8B8A8_UNORM;// SRGB?
|
||||
case tex_frgba:
|
||||
return VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
}
|
||||
return VK_FORMAT_R8_SRGB;
|
||||
}
|
||||
|
|
254
libs/video/renderer/vulkan/iqm.plist
Normal file
254
libs/video/renderer/vulkan/iqm.plist
Normal file
|
@ -0,0 +1,254 @@
|
|||
{
|
||||
setLayouts = {
|
||||
texture_set = {
|
||||
bindings = (
|
||||
{
|
||||
binding = 0;
|
||||
descriptorType = combined_image_sampler;
|
||||
descriptorCount = 1;
|
||||
stageFlags = fragment;
|
||||
},
|
||||
);
|
||||
};
|
||||
};
|
||||
pipelineLayouts = {
|
||||
iqm_layout = {
|
||||
setLayouts = (matrix_set, texture_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = vertex;
|
||||
offset = 0;
|
||||
size = "16 * 4 + 4";
|
||||
},
|
||||
{
|
||||
stageFlags = fragment;
|
||||
offset = 68;
|
||||
size = "3 * 4 + 2 * 4 * 4 + 4";
|
||||
},
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
depthStencil = {
|
||||
test_and_write = {
|
||||
depthTestEnable = true;
|
||||
depthWriteEnable = true;
|
||||
depthCompareOp = less_or_equal;
|
||||
depthBoundsTestEnable = false;
|
||||
stencilTestEnable = false;
|
||||
};
|
||||
test_only = {
|
||||
depthTestEnable = true;
|
||||
depthWriteEnable = false;
|
||||
depthCompareOp = less_or_equal;
|
||||
depthBoundsTestEnable = false;
|
||||
stencilTestEnable = false;
|
||||
};
|
||||
disable = {
|
||||
depthTestEnable = false;
|
||||
depthWriteEnable = false;
|
||||
depthCompareOp = less_or_equal;
|
||||
depthBoundsTestEnable = false;
|
||||
stencilTestEnable = false;
|
||||
};
|
||||
};
|
||||
|
||||
inputAssembly = {
|
||||
iqm = {
|
||||
topology = triangle_list;
|
||||
primitiveRestartEnable = false;
|
||||
};
|
||||
};
|
||||
|
||||
vertexInput = {
|
||||
iqm = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = 20; inputRate = vertex; },
|
||||
{ binding = 1; stride = 40; inputRate = vertex; },
|
||||
);
|
||||
attributes = (
|
||||
{ location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position
|
||||
{ location = 1; binding = 0; format = r8g8b8a8_uint; offset = 0; }, // bonindices
|
||||
{ location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, // boneweights
|
||||
|
||||
{ location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord
|
||||
{ location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal
|
||||
{ location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent
|
||||
{ location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color
|
||||
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
rasterization = {
|
||||
cw_cull_back = {
|
||||
depthClampEnable = false;
|
||||
rasterizerDiscardEnable = false;
|
||||
polygonMode = fill;
|
||||
cullMode = back;
|
||||
frontFace = clockwise;
|
||||
depthBiasEnable = false;
|
||||
lineWidth = 1;
|
||||
};
|
||||
counter_cw_cull_back = {
|
||||
depthClampEnable = false;
|
||||
rasterizerDiscardEnable = false;
|
||||
polygonMode = fill;
|
||||
cullMode = back;
|
||||
frontFace = counter_clockwise;
|
||||
depthBiasEnable = false;
|
||||
lineWidth = 1;
|
||||
};
|
||||
};
|
||||
|
||||
multisample = {
|
||||
rasterizationSamples = $msaaSamples;
|
||||
sampleShadingEnable = false;
|
||||
minSampleShading = 0.5f;
|
||||
alphaToCoverageEnable = false;
|
||||
alphaToOneEnable = false;
|
||||
};
|
||||
|
||||
viewport = {
|
||||
viewports = (
|
||||
{
|
||||
x = 0; y = 0;
|
||||
width = 640; height = 480;
|
||||
minDepth = 0; maxDepth = 1;
|
||||
}
|
||||
);
|
||||
scissors = (
|
||||
{
|
||||
offset = { x = 0; y = 0 };
|
||||
extent = { width = 640; height = 480; };
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
attachmentBlendOp = {
|
||||
disabled = {
|
||||
blendEnable = false;
|
||||
srcColorBlendFactor = src_alpha;
|
||||
dstColorBlendFactor = one_minus_src_alpha;
|
||||
colorBlendOp = add;
|
||||
srcAlphaBlendFactor = src_alpha;
|
||||
dstAlphaBlendFactor = one_minus_src_alpha;
|
||||
alphaBlendOp = add;
|
||||
colorWriteMask = r|g|b|a;
|
||||
};
|
||||
alpha_blend = {
|
||||
blendEnable = true;
|
||||
srcColorBlendFactor = src_alpha;
|
||||
dstColorBlendFactor = one_minus_src_alpha;
|
||||
colorBlendOp = add;
|
||||
srcAlphaBlendFactor = src_alpha;
|
||||
dstAlphaBlendFactor = one_minus_src_alpha;
|
||||
alphaBlendOp = add;
|
||||
colorWriteMask = r|g|b|a;
|
||||
};
|
||||
};
|
||||
|
||||
pipelines = {
|
||||
iqm_shadow = {
|
||||
subpass = 0;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm_shadow.vert;
|
||||
},
|
||||
);
|
||||
vertexInput = {
|
||||
bindings = (
|
||||
"$properties.vertexInput.iqm.bindings[0]",
|
||||
"$properties.vertexInput.iqm.bindings[1]",
|
||||
);
|
||||
attributes = (
|
||||
"$properties.vertexInput.iqm.attributes[0]",
|
||||
"$properties.vertexInput.iqm.attributes[1]",
|
||||
"$properties.vertexInput.iqm.attributes[2]",
|
||||
"$properties.vertexInput.iqm.attributes[3]",
|
||||
);
|
||||
};
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_and_write;
|
||||
colorBlend = $properties.pipelines.iqm_gbuf.colorBlend;
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
layout = iqm_layout;
|
||||
};
|
||||
iqm_depth = {
|
||||
subpass = 0;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm_depth.vert;
|
||||
},
|
||||
);
|
||||
vertexInput = {
|
||||
// depth pass doesn't use UVs
|
||||
bindings = (
|
||||
"$properties.vertexInput.iqm.bindings[0]",
|
||||
"$properties.vertexInput.iqm.bindings[1]",
|
||||
);
|
||||
attributes = (
|
||||
"$properties.vertexInput.iqm.attributes[0]",
|
||||
"$properties.vertexInput.iqm.attributes[1]",
|
||||
"$properties.vertexInput.iqm.attributes[2]",
|
||||
"$properties.vertexInput.iqm.attributes[3]",
|
||||
);
|
||||
};
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_and_write;
|
||||
colorBlend = $properties.pipelines.iqm_gbuf.colorBlend;
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
layout = iqm_layout;
|
||||
renderPass = renderpass;
|
||||
};
|
||||
iqm_gbuf = {
|
||||
subpass = 2;
|
||||
stages = (
|
||||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/iqm.vert;
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/iqm_gbuf.frag;
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.vertexInput.iqm;
|
||||
inputAssembly = $properties.inputAssembly.iqm;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.test_only;
|
||||
colorBlend = {
|
||||
logicOpEnable = false;
|
||||
attachments = (
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
$properties.attachmentBlendOp.disabled,
|
||||
);
|
||||
};
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor, blend_constants );
|
||||
};
|
||||
layout = iqm_layout;
|
||||
renderPass = renderpass;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan memory functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan pipeline functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -206,8 +206,6 @@
|
|||
},
|
||||
);
|
||||
};
|
||||
quakebsp_set = $properties.setLayouts.texture_set;
|
||||
alias_set = $properties.setLayouts.texture_set;
|
||||
sprite_set = {
|
||||
bindings = (
|
||||
{
|
||||
|
@ -337,7 +335,7 @@
|
|||
);
|
||||
};
|
||||
alias_layout = {
|
||||
setLayouts = (matrix_set, alias_set);
|
||||
setLayouts = (matrix_set, texture_set);
|
||||
pushConstantRanges = (
|
||||
{
|
||||
stageFlags = vertex;
|
||||
|
@ -559,17 +557,13 @@
|
|||
};
|
||||
};
|
||||
|
||||
fsquad = {
|
||||
fstriangle = {
|
||||
vertexInput = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = "4 * 4"; inputRate = vertex; },
|
||||
);
|
||||
attributes = (
|
||||
{ location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; },
|
||||
);
|
||||
bindings = ();
|
||||
attributes = ();
|
||||
};
|
||||
inputAssembly = {
|
||||
topology = triangle_strip;
|
||||
topology = triangle_list;
|
||||
primitiveRestartEnable = false;
|
||||
};
|
||||
colorBlend = {
|
||||
|
@ -1008,7 +1002,7 @@
|
|||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/passthrough.vert;
|
||||
module = $builtin/fstriangle.vert;
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
|
@ -1022,13 +1016,13 @@
|
|||
};
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.fsquad.vertexInput;
|
||||
inputAssembly = $properties.fsquad.inputAssembly;
|
||||
vertexInput = $properties.fstriangle.vertexInput;
|
||||
inputAssembly = $properties.fstriangle.inputAssembly;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.counter_cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.disable;
|
||||
colorBlend = $properties.fsquad.colorBlend;
|
||||
colorBlend = $properties.fstriangle.colorBlend;
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
|
@ -1041,7 +1035,7 @@
|
|||
{
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/passthrough.vert;
|
||||
module = $builtin/fstriangle.vert;
|
||||
},
|
||||
{
|
||||
stage = fragment;
|
||||
|
@ -1049,13 +1043,13 @@
|
|||
module = $builtin/compose.frag;
|
||||
},
|
||||
);
|
||||
vertexInput = $properties.fsquad.vertexInput;
|
||||
inputAssembly = $properties.fsquad.inputAssembly;
|
||||
vertexInput = $properties.fstriangle.vertexInput;
|
||||
inputAssembly = $properties.fstriangle.inputAssembly;
|
||||
viewport = $properties.viewport;
|
||||
rasterization = $properties.rasterization.counter_cw_cull_back;
|
||||
multisample = $properties.multisample;
|
||||
depthStencil = $properties.depthStencil.disable;
|
||||
colorBlend = $properties.fsquad.colorBlend;
|
||||
colorBlend = $properties.fstriangle.colorBlend;
|
||||
dynamic = {
|
||||
dynamicState = ( viewport, scissor );
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
Vulkan render pass and frame buffer functions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
271
libs/video/renderer/vulkan/resource.c
Normal file
271
libs/video/renderer/vulkan/resource.c
Normal file
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
resource.c
|
||||
|
||||
Vulkan resource functions
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "QF/Vulkan/buffer.h"
|
||||
#include "QF/Vulkan/debug.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/resource.h"
|
||||
|
||||
int
|
||||
QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
qfv_physdev_t *physdev = device->physDev;
|
||||
VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties;
|
||||
VkMemoryRequirements req;
|
||||
VkDeviceSize size = 0;
|
||||
|
||||
for (unsigned i = 0; i < resource->num_objects; i++) {
|
||||
__auto_type obj = &resource->objects[i];
|
||||
switch (obj->type) {
|
||||
case qfv_res_buffer:
|
||||
{
|
||||
__auto_type buffer = &obj->buffer;
|
||||
buffer->buffer = QFV_CreateBuffer (device,
|
||||
buffer->size,
|
||||
buffer->usage);
|
||||
const char *name = va (resource->va_ctx, "buffer:%s:%s",
|
||||
resource->name, obj->name);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER,
|
||||
buffer->buffer, name);
|
||||
dfunc->vkGetBufferMemoryRequirements (device->dev,
|
||||
buffer->buffer, &req);
|
||||
}
|
||||
break;
|
||||
case qfv_res_buffer_view:
|
||||
{
|
||||
__auto_type buffview = &obj->buffer_view;
|
||||
__auto_type buffobj = &resource->objects[buffview->buffer];
|
||||
if (buffview->buffer >= resource->num_objects
|
||||
|| buffobj->type != qfv_res_buffer) {
|
||||
Sys_Error ("%s:%s invalid buffer for view",
|
||||
resource->name, obj->name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case qfv_res_image:
|
||||
{
|
||||
__auto_type image = &obj->image;
|
||||
image->image = QFV_CreateImage (device,
|
||||
image->cubemap,
|
||||
image->type,
|
||||
image->format,
|
||||
image->extent,
|
||||
image->num_mipmaps,
|
||||
image->num_layers,
|
||||
image->samples,
|
||||
image->usage);
|
||||
const char *name = va (resource->va_ctx, "image:%s:%s",
|
||||
resource->name, obj->name);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE,
|
||||
image->image, name);
|
||||
dfunc->vkGetImageMemoryRequirements (device->dev,
|
||||
image->image, &req);
|
||||
}
|
||||
break;
|
||||
case qfv_res_image_view:
|
||||
{
|
||||
__auto_type imgview = &obj->image_view;
|
||||
__auto_type imgobj = &resource->objects[imgview->image];
|
||||
if (imgview->image >= resource->num_objects
|
||||
|| imgobj->type != qfv_res_image) {
|
||||
Sys_Error ("%s:%s invalid image for view",
|
||||
resource->name, obj->name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Sys_Error ("%s:%s invalid resource type %d",
|
||||
resource->name, obj->name, obj->type);
|
||||
}
|
||||
size = QFV_NextOffset (size, &req);
|
||||
size += req.size;
|
||||
}
|
||||
VkMemoryPropertyFlags properties = resource->memory_properties;
|
||||
for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) {
|
||||
if ((req.memoryTypeBits & (1 << type))
|
||||
&& ((memprops->memoryTypes[type].propertyFlags & properties)
|
||||
== properties)) {
|
||||
VkMemoryAllocateInfo allocate_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = size,
|
||||
.memoryTypeIndex = type,
|
||||
};
|
||||
VkResult res = dfunc->vkAllocateMemory (device->dev, &allocate_info,
|
||||
0, &resource->memory);
|
||||
if (res == VK_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
resource->memory, va (resource->va_ctx, "memory:%s",
|
||||
resource->name));
|
||||
|
||||
VkDeviceSize offset = 0;
|
||||
for (unsigned i = 0; i < resource->num_objects; i++) {
|
||||
__auto_type obj = &resource->objects[i];
|
||||
switch (obj->type) {
|
||||
case qfv_res_buffer:
|
||||
{
|
||||
__auto_type buffer = &obj->buffer;
|
||||
dfunc->vkGetBufferMemoryRequirements (device->dev,
|
||||
buffer->buffer, &req);
|
||||
}
|
||||
break;
|
||||
case qfv_res_image:
|
||||
{
|
||||
__auto_type image = &obj->image;
|
||||
dfunc->vkGetImageMemoryRequirements (device->dev,
|
||||
image->image, &req);
|
||||
}
|
||||
break;
|
||||
case qfv_res_buffer_view:
|
||||
case qfv_res_image_view:
|
||||
break;
|
||||
}
|
||||
|
||||
offset = QFV_NextOffset (offset, &req);
|
||||
switch (obj->type) {
|
||||
case qfv_res_buffer:
|
||||
{
|
||||
__auto_type buffer = &obj->buffer;
|
||||
QFV_BindBufferMemory (device, buffer->buffer,
|
||||
resource->memory, offset);
|
||||
}
|
||||
break;
|
||||
case qfv_res_image:
|
||||
{
|
||||
__auto_type image = &obj->image;
|
||||
QFV_BindImageMemory (device, image->image,
|
||||
resource->memory, offset);
|
||||
}
|
||||
break;
|
||||
case qfv_res_buffer_view:
|
||||
case qfv_res_image_view:
|
||||
break;
|
||||
}
|
||||
offset += req.size;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < resource->num_objects; i++) {
|
||||
__auto_type obj = &resource->objects[i];
|
||||
switch (obj->type) {
|
||||
case qfv_res_buffer:
|
||||
case qfv_res_image:
|
||||
break;
|
||||
case qfv_res_buffer_view:
|
||||
{
|
||||
__auto_type buffview = &obj->buffer_view;
|
||||
__auto_type buffobj = &resource->objects[buffview->buffer];
|
||||
__auto_type buffer = &buffobj->buffer;
|
||||
buffview->view = QFV_CreateBufferView (device,
|
||||
buffer->buffer,
|
||||
buffview->format,
|
||||
buffview->offset,
|
||||
buffview->size);
|
||||
const char *name = va (resource->va_ctx, "bview:%s:%s",
|
||||
resource->name, obj->name);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER_VIEW,
|
||||
buffview->view, name);
|
||||
}
|
||||
break;
|
||||
case qfv_res_image_view:
|
||||
{
|
||||
__auto_type imgview = &obj->image_view;
|
||||
__auto_type imgobj = &resource->objects[imgview->image];
|
||||
__auto_type image = &imgobj->image;
|
||||
imgview->view = QFV_CreateImageView (device,
|
||||
image->image,
|
||||
imgview->type,
|
||||
imgview->format,
|
||||
imgview->aspect);
|
||||
const char *name = va (resource->va_ctx, "iview:%s:%s",
|
||||
resource->name, obj->name);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW,
|
||||
imgview->view, name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource)
|
||||
{
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
for (unsigned i = 0; i < resource->num_objects; i++) {
|
||||
__auto_type obj = &resource->objects[i];
|
||||
switch (obj->type) {
|
||||
case qfv_res_buffer:
|
||||
case qfv_res_image:
|
||||
break;
|
||||
case qfv_res_buffer_view:
|
||||
{
|
||||
__auto_type buffview = &obj->buffer_view;
|
||||
dfunc->vkDestroyBufferView (device->dev, buffview->view, 0);
|
||||
}
|
||||
break;
|
||||
case qfv_res_image_view:
|
||||
{
|
||||
__auto_type imgview = &obj->image_view;
|
||||
dfunc->vkDestroyImageView (device->dev, imgview->view, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < resource->num_objects; i++) {
|
||||
__auto_type obj = &resource->objects[i];
|
||||
switch (obj->type) {
|
||||
case qfv_res_buffer:
|
||||
{
|
||||
__auto_type buffer = &obj->buffer;
|
||||
dfunc->vkDestroyBuffer (device->dev, buffer->buffer, 0);
|
||||
}
|
||||
break;
|
||||
case qfv_res_image:
|
||||
{
|
||||
__auto_type image = &obj->image;
|
||||
dfunc->vkDestroyImage (device->dev, image->image, 0);
|
||||
}
|
||||
break;
|
||||
case qfv_res_buffer_view:
|
||||
case qfv_res_image_view:
|
||||
break;
|
||||
}
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, resource->memory, 0);
|
||||
}
|
|
@ -93,8 +93,14 @@ static
|
|||
static
|
||||
#include "libs/video/renderer/vulkan/shader/alias_shadow.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/iqm.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/iqm.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc"
|
||||
static
|
||||
#include "libs/video/renderer/vulkan/shader/shadow.geom.spvc"
|
||||
|
@ -133,7 +139,10 @@ static shaderdata_t builtin_shaders[] = {
|
|||
{ "alias.frag", alias_frag, sizeof (alias_frag) },
|
||||
{ "alias_gbuf.frag", alias_gbuf_frag, sizeof (alias_gbuf_frag) },
|
||||
{ "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) },
|
||||
{ "iqm.vert", iqm_vert, sizeof (iqm_vert) },
|
||||
{ "iqm.frag", iqm_frag, sizeof (iqm_frag) },
|
||||
{ "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) },
|
||||
{ "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) },
|
||||
{ "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) },
|
||||
{ "shadow.geom", shadow_geom, sizeof (shadow_geom) },
|
||||
{}
|
||||
|
|
|
@ -34,6 +34,6 @@ main (void)
|
|||
pos = (Model * vertex);
|
||||
gl_Position = Projection3d * (View * pos);
|
||||
position = pos;
|
||||
normal = mat3 (Model) * norm;
|
||||
normal = normalize (mat3 (Model) * norm);
|
||||
st = uv;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,6 @@ main (void)
|
|||
|
||||
frag_color = c;
|
||||
frag_emission = e;
|
||||
frag_normal = vec4(normal, 1);
|
||||
frag_normal = vec4(normalize(normal), 1);
|
||||
frag_position = position;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue