added 3D skybox rendering (to-do: fix some quirks), fixing lighting issues (to-do: fix tangents or normal maps or something i dont know)
This commit is contained in:
parent
aa2740979c
commit
def459e72c
@ -3,7 +3,7 @@
|
||||
"scenes": {
|
||||
"start": "StartMenu",
|
||||
"lights": { "enabled": true,
|
||||
"lightmaps": false,
|
||||
"lightmaps": true,
|
||||
"max": 32,
|
||||
"shadows": {
|
||||
"enabled": true,
|
||||
@ -426,7 +426,7 @@
|
||||
},
|
||||
"loader": {
|
||||
"assert": true,
|
||||
"async": true
|
||||
"async": false
|
||||
},
|
||||
"hooks": {
|
||||
"defer lazy calls": true
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
"physics": { "type": "mesh", "static": true, "mass": 0 },
|
||||
"grid": { "size": [8,1,8], "epsilon": 0.001, "cleanup": true, "print": true, "clip": true },
|
||||
"unwrap mesh": true
|
||||
},
|
||||
}
|
||||
/*"light_environment": { "ignore": false, "light": {
|
||||
// "color": [0.1, 0.1, 0.1],
|
||||
"power": 1000,
|
||||
@ -36,8 +36,7 @@
|
||||
// "/^prop_dynamic/": { "action": "load", "payload": { "import": "ent://prop.json" } },
|
||||
// "/^func_physbox/": { "action": "load", "payload": { "import": "ent://prop.json" } },
|
||||
// "/^prop_physics/": { "action": "load", "payload": { "import": "ent://prop.json" } },
|
||||
|
||||
"/^tools\\/toolsnodraw/": { "material": { "base": [ 1.0, 1.0, 1.0, 0.0 ] } }
|
||||
// "/^tools\\/toolsnodraw/": { "material": { "base": [ 1.0, 1.0, 1.0, 0.0 ] } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
bin/data/scenes/sourceengine/de_dust2.json
Normal file
7
bin/data/scenes/sourceengine/de_dust2.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"import": "./base_sourceengine.json",
|
||||
"assets": [
|
||||
{ "filename": "./maps/de_dust2.bsp" }
|
||||
// { "filename": "./maps/de_dust2/graph.json" }
|
||||
]
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
{
|
||||
"import": "./base_sourceengine.json",
|
||||
"assets": [
|
||||
// { "filename": "./maps/mcdonalds-mds.bsp" }
|
||||
{ "filename": "./maps/mcdonalds-mds/graph.json" },
|
||||
{ "filename": "ent://burger.json", "delay": 1 },
|
||||
{ "filename": "ent://craeture.json", "delay": 2 }
|
||||
{ "filename": "./maps/mcdonalds-mds.bsp" }
|
||||
// { "filename": "./maps/mcdonalds-mds/graph.json" }
|
||||
// ,{ "filename": "ent://burger.json", "delay": 1 }
|
||||
// ,{ "filename": "ent://craeture.json", "delay": 2 }
|
||||
]
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
{
|
||||
// "import": "./rp_downtown_v2.json"
|
||||
// "import": "./ss2_medsci1.json"
|
||||
"import": "./mds_mcdonalds.json"
|
||||
// "import": "./mds_mcdonalds.json"
|
||||
// "import": "./cs_office.json"
|
||||
"import": "./de_dust2.json"
|
||||
// "import": "./gm_construct.json"
|
||||
}
|
||||
@ -322,21 +322,21 @@ void populateSurfaceMaterial() {
|
||||
if ( 0 <= cubemapIndex && surface.material.roughness < 1.0 ) {
|
||||
const Texture texture = textures[cubemapIndex];
|
||||
|
||||
vec3 V = normalize(surface.position.eye);
|
||||
vec3 N = surface.normal.eye;
|
||||
vec3 R = reflect(V, N);
|
||||
vec3 V = normalize(surface.position.eye);
|
||||
vec3 N = surface.normal.eye;
|
||||
vec3 R = reflect(V, N);
|
||||
|
||||
mat3 invView = mat3(ubo.eyes[surface.pass].iView);
|
||||
vec3 worldR = invView * R;
|
||||
mat3 invView = mat3(ubo.eyes[surface.pass].iView);
|
||||
vec3 worldR = invView * R;
|
||||
|
||||
float mipLevel = surface.material.roughness * mipLevels(textureSize(samplerCubemaps[nonuniformEXT(texture.index)], 0).xy);
|
||||
vec3 reflection = textureLod(samplerCubemaps[nonuniformEXT(texture.index)], worldR, mipLevel).rgb;
|
||||
float mipLevel = surface.material.roughness * mipLevels(textureSize(samplerCubemaps[nonuniformEXT(texture.index)], 0).xy);
|
||||
vec3 reflection = textureLod(samplerCubemaps[nonuniformEXT(texture.index)], worldR, mipLevel).rgb;
|
||||
|
||||
vec3 F0 = mix(vec3(0.04), surface.material.albedo.rgb, surface.material.metallic);
|
||||
float cosTheta = max(dot(N, -V), 0.0);
|
||||
vec3 F = F0 + (max(vec3(1.0 - surface.material.roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
float cosTheta = max(dot(N, -V), 0.0);
|
||||
vec3 F = F0 + (max(vec3(1.0 - surface.material.roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||
|
||||
surface.light.rgb += reflection * F * surface.material.occlusion;
|
||||
surface.light.rgb += reflection * F * surface.material.occlusion;
|
||||
}
|
||||
// (Occlusion/)Metallic/Roughness map
|
||||
if ( validTextureIndex( material.indexMetallicRoughness ) ) {
|
||||
@ -402,6 +402,8 @@ uvec4 uvec2_16x4( uvec2 i ) {
|
||||
void populateSurface( InstanceAddresses addresses, uvec3 indices ) {
|
||||
Triangle triangle;
|
||||
Vertex points[3];
|
||||
|
||||
float uvHandedness = 1.0;
|
||||
if ( isValidAddress(addresses.position) ) {
|
||||
VPos buf = VPos(nonuniformEXT(addresses.position));
|
||||
#pragma unroll 3
|
||||
@ -432,9 +434,12 @@ void populateSurface( InstanceAddresses addresses, uvec3 indices ) {
|
||||
vec2 deltaUV1 = points[1].uv - points[0].uv;
|
||||
vec2 deltaUV2 = points[2].uv - points[0].uv;
|
||||
|
||||
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
|
||||
float det = (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
|
||||
float r = 1.0f / det;
|
||||
vec3 tangent_tri = (edge1 * deltaUV2.y - edge2 * deltaUV1.y) * r;
|
||||
|
||||
uvHandedness = (det < 0.0) ? -1.0 : 1.0;
|
||||
|
||||
#pragma unroll 3
|
||||
for ( uint _ = 0; _ < 3; ++_ ) points[_].tangent = tangent_tri;
|
||||
}
|
||||
@ -489,7 +494,7 @@ void populateSurface( InstanceAddresses addresses, uvec3 indices ) {
|
||||
surface.tangent.world = normalize(vec3( surface.object.model * vec4(triangle.point.tangent, 0.0) ));
|
||||
surface.tangent.world = normalize(surface.tangent.world - dot(surface.tangent.world, surface.normal.world) * surface.normal.world);
|
||||
|
||||
vec3 bitangent = normalize(vec3( surface.object.model * vec4(cross( triangle.point.normal, triangle.point.tangent ), 0.0) ));
|
||||
vec3 bitangent = normalize(vec3( surface.object.model * vec4(cross( triangle.point.normal, triangle.point.tangent ) * uvHandedness, 0.0) ));
|
||||
surface.tbn = mat3(surface.tangent.world, bitangent, surface.normal.world);
|
||||
}
|
||||
// bind UVs
|
||||
|
||||
@ -198,7 +198,7 @@ void populateSurface() {
|
||||
surface.material.roughness = 0;
|
||||
surface.material.occlusion = 0;
|
||||
|
||||
float depth = 0.0;
|
||||
float depth = IMAGE_LOAD(samplerDepth).r;
|
||||
{
|
||||
|
||||
#if USE_CAMERA_VIEWPORT
|
||||
@ -218,10 +218,8 @@ void populateSurface() {
|
||||
surface.ray.direction = normalize( far3 - near3 );
|
||||
surface.ray.origin = ubo.eyes[surface.pass].eyePos.xyz; // near3.xyz; // eyePos.xyz
|
||||
|
||||
depth = IMAGE_LOAD(samplerDepth).r;
|
||||
|
||||
vec4 eye = iProjection * vec4(surface.fragCoord, depth, 1.0);
|
||||
eye /= eye.w;
|
||||
if ( eye.w > 0.0001 ) eye /= eye.w;
|
||||
|
||||
surface.position.eye = eye.xyz;
|
||||
surface.position.world = vec3( iView * eye );
|
||||
@ -234,7 +232,7 @@ void populateSurface() {
|
||||
const uvec2 ID = msaa.IDs[msaa.currentID];
|
||||
#endif
|
||||
|
||||
if ( ID.x == 0 || ID.y == 0 || depth <= 0.0 ) {
|
||||
if ( ID.x == 0 || ID.y == 0 /*|| depth <= 0.0*/ ) {
|
||||
USE_SKYBOX_ON_DIVERGENCE = true;
|
||||
}
|
||||
/*
|
||||
|
||||
@ -10,7 +10,7 @@ layout (location = 1) in vec2 inUv;
|
||||
layout (location = 2) in vec4 inColor;
|
||||
layout (location = 3) in vec2 inSt;
|
||||
layout (location = 4) in vec3 inNormal;
|
||||
layout (location = 5) in vec4 inTangent;
|
||||
layout (location = 5) in vec3 inTangent;
|
||||
#if SKINNED
|
||||
layout (location = 6) in uvec4 inJoints;
|
||||
layout (location = 7) in vec4 inWeights;
|
||||
@ -19,6 +19,7 @@ layout (location = 5) in vec4 inTangent;
|
||||
layout( push_constant ) uniform PushBlock {
|
||||
uint pass;
|
||||
uint draw;
|
||||
uint aux;
|
||||
} PushConstant;
|
||||
|
||||
layout (binding = 0) uniform Camera {
|
||||
@ -69,12 +70,15 @@ void main() {
|
||||
const Object object = objects[instance.objectID];
|
||||
const uint jointID = instance.jointID;
|
||||
|
||||
uint viewportIndex = gl_ViewIndex;
|
||||
if ( PushConstant.aux == 1 ) viewportIndex += 2;
|
||||
|
||||
#if BAKING
|
||||
const mat4 view = mat4(1);
|
||||
const mat4 projection = mat4(1);
|
||||
#else
|
||||
const mat4 view = camera.viewport[/*PushConstant.pass*/gl_ViewIndex].view;
|
||||
const mat4 projection = camera.viewport[/*PushConstant.pass*/gl_ViewIndex].projection;
|
||||
const mat4 view = camera.viewport[viewportIndex].view;
|
||||
const mat4 projection = camera.viewport[viewportIndex].projection;
|
||||
#endif
|
||||
#if SKINNED
|
||||
const mat4 skinned = joints.length() <= 0 || jointID < 0 ? mat4(1.0) : inWeights.x * joints[jointID + int(inJoints.x)] + inWeights.y * joints[jointID + int(inJoints.y)] + inWeights.z * joints[jointID + int(inJoints.z)] + inWeights.w * joints[jointID + int(inJoints.w)];
|
||||
|
||||
@ -98,19 +98,17 @@ uf::stl::vector<T> uf::stl::KeyMap<T,Key>::flattenByIndex() const {
|
||||
|
||||
template<typename T, typename Key>
|
||||
void uf::stl::KeyMap<T,Key>::merge( KeyMap<T, Key>&& other ) {
|
||||
this->reserve( this->keys.size() + other.keys.size() );
|
||||
this->reserve( this->keys.size() + other.keys.size() );
|
||||
|
||||
for ( auto& key : other.keys ) {
|
||||
// Bypass custom operator[] and force a direct map assignment
|
||||
if ( this->map.count(key) == 0 ) {
|
||||
this->indices[key] = this->keys.size();
|
||||
this->keys.emplace_back(key);
|
||||
}
|
||||
// Explicitly copy to prevent any weird std::move state corruption
|
||||
this->map[key] = other.map.at(key);
|
||||
}
|
||||
for ( auto& key : other.keys ) {
|
||||
if ( this->map.count(key) == 0 ) {
|
||||
this->indices[key] = this->keys.size();
|
||||
this->keys.emplace_back(key);
|
||||
}
|
||||
this->map[key] = other.map.at(key);
|
||||
}
|
||||
|
||||
other.clear();
|
||||
other.clear();
|
||||
}
|
||||
|
||||
template<typename T, typename Key>
|
||||
|
||||
@ -282,8 +282,8 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
#endif
|
||||
}
|
||||
void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
// auto& assetLoader = this->getComponent<uf::asset>();
|
||||
uf::asset::processQueue();
|
||||
// auto& assetLoader = this->getComponent<uf::asset>();
|
||||
|
||||
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
@ -625,8 +625,9 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
constexpr uint32_t MODE_CUBEMAP = 1;
|
||||
constexpr uint32_t MODE_SEPARATE_2DS = 2;
|
||||
|
||||
for ( uint32_t i = 0; i < entities.size(); ++i ) {
|
||||
auto& info = entities[i];
|
||||
//for ( uint32_t i = 0; i < entities.size(); ++i ) {
|
||||
for ( auto idx : indices ) {
|
||||
auto& info = entities[idx];
|
||||
uf::Entity* entity = info.entity;
|
||||
|
||||
int32_t boundIndexMap = -1;
|
||||
|
||||
@ -710,12 +710,20 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
|
||||
graphic.initialize();
|
||||
graphic.initializeMesh( mesh );
|
||||
|
||||
|
||||
graphic.device = &uf::renderer::device;
|
||||
graphic.material.device = &uf::renderer::device;
|
||||
graphic.descriptor.frontFace = graphMetadataJson["renderer"]["invert"].as<bool>(true) ? uf::renderer::enums::Face::CW : uf::renderer::enums::Face::CCW;
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK;
|
||||
|
||||
auto& entityName = entity.getName();
|
||||
auto& metadataJson = entity.getComponent<uf::Serializer>();
|
||||
auto& metadataValve = metadataJson["valve"];
|
||||
if ( entityName == "skybox" || metadataValve["skyboxed"].as<bool>(false) ) {
|
||||
graphic.descriptor.aux = 1; // to-do: some global enums for this shit
|
||||
}
|
||||
|
||||
auto tag = ext::json::find( entity.getName(), graphMetadataJson["tags"] );
|
||||
auto tag = ext::json::find( entityName, graphMetadataJson["tags"] );
|
||||
if ( !ext::json::isObject( tag ) ) {
|
||||
tag["renderer"] = graphMetadataJson["renderer"];
|
||||
}
|
||||
@ -731,7 +739,7 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
|
||||
}
|
||||
|
||||
// query materials if culling needs to be disabled
|
||||
if ( entity.getName() != "worldspawn" ) {
|
||||
if ( entityName != "worldspawn" ) {
|
||||
for ( auto& primitive : primitives ) {
|
||||
auto materialID = primitive.instance.materialID;
|
||||
if ( 0 <= materialID && materialID <= graph.materials.size() ) {
|
||||
@ -1019,6 +1027,9 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
// nodraw
|
||||
if ( name.starts_with("tools/") ) {
|
||||
material.colorBase.w = 0.0f;
|
||||
material.modeAlpha = pod::Material::AlphaMode::MASK;
|
||||
material.factorAlphaCutoff = 1.0f;
|
||||
material.indexAlbedo = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -67,12 +67,6 @@ const uf::Entity& uf::Scene::getController() const {
|
||||
}
|
||||
|
||||
uf::Camera& uf::Scene::getCamera( uf::Entity& controller ) {
|
||||
// ???
|
||||
/*
|
||||
if ( auto currentRenderMode = uf::renderer::getCurrentRenderMode(); currentRenderMode && !currentRenderMode->getName().empty() ) {
|
||||
return controller.getComponent<uf::Camera>();
|
||||
}
|
||||
*/
|
||||
#if !UF_SCENE_GLOBAL_GRAPH
|
||||
auto& metadata = this->getComponent<uf::SceneBehavior::Metadata>();
|
||||
#endif
|
||||
@ -83,15 +77,39 @@ uf::Camera& uf::Scene::getCamera( uf::Entity& controller ) {
|
||||
|
||||
if ( lastFrame != uf::time::frame ) {
|
||||
auto& sourceCamera = controller.getComponent<uf::Camera>();
|
||||
if ( controller.getName() == "Player" ) sourceCamera.update();
|
||||
auto& controllerName = controller.getName();
|
||||
if ( controllerName == "Player" ) sourceCamera.update();
|
||||
// copy all matrices
|
||||
for ( auto i = 0; i < uf::camera::maxViews; ++i ) {
|
||||
cachedCamera.setView(sourceCamera.getView(i), i);
|
||||
cachedCamera.setProjection(sourceCamera.getProjection(i), i);
|
||||
}
|
||||
// flatten the transform in the event the parent transform updates later
|
||||
cachedCamera.setTransform(uf::transform::flatten(sourceCamera.getTransform()));
|
||||
auto transform = uf::transform::flatten(sourceCamera.getTransform());
|
||||
cachedCamera.setTransform(transform);
|
||||
lastFrame = uf::time::frame;
|
||||
|
||||
// handle sky_camera
|
||||
if ( auto entity = this->findByName("sky_camera"); entity && controllerName == "Player" ) {
|
||||
auto& metadatavalve = entity->getComponent<uf::Serializer>()["valve"];
|
||||
float scale = metadatavalve["scale"].as<float>(16.0f);
|
||||
|
||||
auto cameraTransform = entity->getComponent<pod::Transform<>>();
|
||||
cameraTransform.position += (transform.position / scale);
|
||||
cameraTransform.orientation = transform.orientation;
|
||||
|
||||
uf::Camera skyCamera = sourceCamera;
|
||||
skyCamera.setTransform(cameraTransform);
|
||||
skyCamera.update();
|
||||
|
||||
int auxOffset = 2;
|
||||
for ( auto i = 0; i < 2; ++i ) {
|
||||
if ( (i + auxOffset) < uf::camera::maxViews ) {
|
||||
cachedCamera.setView(skyCamera.getView(i), i + auxOffset);
|
||||
cachedCamera.setProjection(sourceCamera.getProjection(i), i + auxOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return cachedCamera;
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <uf/ext/zlib/zlib.h>
|
||||
|
||||
#include <uf/utils/mesh/grid.h>
|
||||
#include <uf/utils/memory/unordered_set.h>
|
||||
|
||||
namespace impl {
|
||||
struct RGBE {
|
||||
@ -121,6 +122,31 @@ namespace impl {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct BspPlane {
|
||||
pod::Vector3f normal;
|
||||
float dist;
|
||||
int32_t type;
|
||||
};
|
||||
|
||||
struct BspNode {
|
||||
int32_t planenum;
|
||||
int32_t children[2];
|
||||
int16_t mins[3], maxs[3];
|
||||
uint16_t firstface, numfaces;
|
||||
int16_t area;
|
||||
int16_t padding;
|
||||
};
|
||||
|
||||
struct BspLeaf {
|
||||
int32_t contents;
|
||||
int16_t cluster;
|
||||
int16_t area_flags;
|
||||
int16_t mins[3], maxs[3];
|
||||
uint16_t firstleafface, numleaffaces;
|
||||
uint16_t firstleafbrush, numleafbrushes;
|
||||
int16_t leafWaterDataID;
|
||||
};
|
||||
|
||||
struct BspDispSubNeighbor {
|
||||
uint16_t neighbor;
|
||||
uint8_t neighborOrientation;
|
||||
@ -205,14 +231,17 @@ namespace impl {
|
||||
uf::stl::vector<int32_t> surfedges;
|
||||
uf::stl::vector<impl::BspFace> faces;
|
||||
// brush, brushside
|
||||
// node, leaf
|
||||
// leafface, leaffbrush
|
||||
uf::stl::vector<impl::BspPlane> planes;
|
||||
uf::stl::vector<impl::BspNode> nodes;
|
||||
uf::stl::vector<impl::BspLeaf> leafs;
|
||||
uf::stl::vector<uint16_t> leaffaces;
|
||||
// leaffbrush
|
||||
uf::stl::vector<impl::BspTexInfo> texinfos;
|
||||
uf::stl::vector<impl::BspTexData> texdatas;
|
||||
uf::stl::vector<int32_t> stringTable;
|
||||
uf::stl::string stringData;
|
||||
uf::stl::vector<impl::BspModel> models;
|
||||
// visibility
|
||||
uf::stl::vector<uint8_t> visibility;
|
||||
uf::stl::vector<int8_t> entities;
|
||||
uf::stl::vector<impl::BspGameLump> gameLumps;
|
||||
uf::stl::vector<impl::BspDispInfo> dispinfos;
|
||||
@ -228,6 +257,8 @@ namespace impl {
|
||||
// worldlight
|
||||
// other
|
||||
|
||||
int32_t skyArea = -1;
|
||||
uf::stl::unordered_set<int32_t> skyboxFaces;
|
||||
uf::stl::vector<int32_t> modelToMesh;
|
||||
uf::stl::vector<int32_t> texdataToMaterial;
|
||||
uf::stl::vector<int32_t> cubemapIDs;
|
||||
@ -258,6 +289,49 @@ namespace impl {
|
||||
return io;
|
||||
}
|
||||
|
||||
int32_t findLeaf( const impl::BspContext& context, const pod::Vector3f& pos ) {
|
||||
if ( context.nodes.empty() || context.planes.empty() || context.leafs.empty() ) return 0;
|
||||
|
||||
int32_t node = 0;
|
||||
while ( node >= 0 ) {
|
||||
const auto& n = context.nodes[node];
|
||||
const auto& p = context.planes[n.planenum];
|
||||
|
||||
float d = uf::vector::dot(pos, p.normal) - p.dist;
|
||||
|
||||
node = n.children[d < 0 ? 1 : 0];
|
||||
}
|
||||
return -node - 1;
|
||||
}
|
||||
|
||||
bool isClusterVisible( const impl::BspContext& context, int32_t visCluster, int32_t testCluster ) {
|
||||
if ( context.visibility.size() < 8 || visCluster < 0 || testCluster < 0 ) return true;
|
||||
|
||||
// PVS Header: [num_clusters] [byteofs_pvs[num_clusters]] [byteofs_phs[num_clusters]]
|
||||
int32_t numClusters = *(int32_t*)(context.visibility.data());
|
||||
if ( visCluster >= numClusters || testCluster >= numClusters ) return false;
|
||||
|
||||
// offset to this cluster's PVS data
|
||||
int32_t byteOffset = *(int32_t*)(context.visibility.data() + 4 + visCluster * 8);
|
||||
const uint8_t* pvs = context.visibility.data() + byteOffset;
|
||||
|
||||
// decompress RLE
|
||||
int32_t clusterCounter = 0;
|
||||
while ( clusterCounter <= testCluster ) {
|
||||
if ( *pvs == 0 ) {
|
||||
clusterCounter += 8 * pvs[1];
|
||||
pvs += 2;
|
||||
} else {
|
||||
if ( clusterCounter + 8 > testCluster ) {
|
||||
return (*pvs & (1 << (testCluster - clusterCounter))) != 0;
|
||||
}
|
||||
clusterCounter += 8;
|
||||
pvs++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t findClosestCubemap( const impl::BspContext& context, const pod::Vector3f& position ) {
|
||||
if ( context.cubemapIDs.empty() ) return -1;
|
||||
|
||||
@ -392,10 +466,13 @@ namespace impl {
|
||||
|
||||
pod::Vector3f tangent = uf::vector::normalize(pR - pL);
|
||||
pod::Vector3f bitangent = uf::vector::normalize(pU - pD);
|
||||
|
||||
pod::Vector3f normal = uf::vector::normalize(uf::vector::cross(bitangent, tangent));
|
||||
|
||||
// float w = (uf::vector::dot(uf::vector::cross(normal, tangent), bitangent) < 0.0f) ? -1.0f : 1.0f;
|
||||
|
||||
meshlet.vertices[id].normal = normal;
|
||||
meshlet.vertices[id].tangent = tangent;
|
||||
meshlet.vertices[id].tangent = tangent = uf::vector::normalize(tangent - normal * uf::vector::dot(normal, tangent));
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,7 +512,7 @@ namespace impl {
|
||||
const auto& face = context.faces[faceID];
|
||||
pod::Vector4f vertex = context.vertices[vertexID];
|
||||
vertex.w = 1; // for dot products
|
||||
|
||||
|
||||
// add index
|
||||
meshlet.indices.emplace_back((uint32_t)(meshlet.vertices.size()));
|
||||
// add vertex
|
||||
@ -443,7 +520,7 @@ namespace impl {
|
||||
v.position = pos;
|
||||
v.color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
v.normal = normal;
|
||||
|
||||
|
||||
// has texture information
|
||||
if ( face.texinfo >= 0 && face.texinfo < context.texinfos.size() ) {
|
||||
const auto& info = context.texinfos[face.texinfo];
|
||||
@ -459,7 +536,11 @@ namespace impl {
|
||||
|
||||
v.st = uf::atlas::mapUv( context.lightmapAtlas, v.st, impl::faceHash( faceID ) );
|
||||
|
||||
v.tangent = uf::vector::normalize( impl::convertPos( info.textureVecs[0], 1) );
|
||||
pod::Vector3f t = uf::vector::normalize( impl::convertPos( info.textureVecs[0], 1.0f ) );
|
||||
pod::Vector3f b = uf::vector::normalize( impl::convertPos( info.textureVecs[1], 1.0f ) );
|
||||
|
||||
v.tangent = uf::vector::normalize(t - normal * uf::vector::dot(normal, t));
|
||||
// float w = (uf::vector::dot( uf::vector::cross(normal, t), b ) < 0.0f) ? -1.0f : 1.0f;
|
||||
}
|
||||
};
|
||||
|
||||
@ -478,6 +559,21 @@ namespace impl {
|
||||
return data;
|
||||
}
|
||||
|
||||
template<>
|
||||
void extractLump( const uf::stl::vector<uint8_t>& buffer, const impl::BspLump& lump, uf::stl::vector<impl::BspLeaf>& data ) {
|
||||
if ( lump.length == 0 || lump.offset >= buffer.size() ) return;
|
||||
|
||||
int stride = (lump.version == 0) ? 56 : 32;
|
||||
|
||||
size_t count = lump.length / stride;
|
||||
data.resize(count);
|
||||
|
||||
const uint8_t* src = buffer.data() + lump.offset;
|
||||
for ( size_t i = 0; i < count; ++i ) {
|
||||
std::memcpy(&data[i], src + (i * stride), sizeof(impl::BspLeaf));
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void extractLump( const uf::stl::vector<uint8_t>& buffer, const impl::BspLump& lump, uf::stl::vector<impl::BspGameLump>& data ) {
|
||||
if ( lump.length == 0 || lump.offset >= buffer.size() ) return;
|
||||
@ -516,6 +612,9 @@ namespace impl {
|
||||
for ( auto nodeID : graph.root.children ) {
|
||||
auto& node = graph.nodes[nodeID];
|
||||
auto& metadata = node.metadata["valve"];
|
||||
|
||||
if ( !ext::json::isObject( metadata ) ) continue;
|
||||
|
||||
auto classname = metadata["classname"].as<uf::stl::string>("");
|
||||
//UF_MSG_INFO("Entity found: {}", classname);
|
||||
node.name = classname;
|
||||
@ -691,11 +790,16 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
impl::extractLump<impl::BspEdge>(buffer, header->lumps[impl::BspLump::LUMP_EDGES], context.edges);
|
||||
impl::extractLump<int32_t>(buffer, header->lumps[impl::BspLump::LUMP_SURFEDGES], context.surfedges);
|
||||
impl::extractLump<impl::BspFace>(buffer, header->lumps[impl::BspLump::LUMP_FACES], context.faces);
|
||||
impl::extractLump<impl::BspPlane>(buffer, header->lumps[impl::BspLump::LUMP_PLANES], context.planes);
|
||||
impl::extractLump<impl::BspNode>(buffer, header->lumps[impl::BspLump::LUMP_NODES], context.nodes);
|
||||
impl::extractLump<impl::BspLeaf>(buffer, header->lumps[impl::BspLump::LUMP_LEAFS], context.leafs);
|
||||
impl::extractLump<uint16_t>(buffer, header->lumps[impl::BspLump::LUMP_LEAFFACES], context.leaffaces);
|
||||
impl::extractLump<impl::BspTexInfo>(buffer, header->lumps[impl::BspLump::LUMP_TEXINFO], context.texinfos);
|
||||
impl::extractLump<impl::BspTexData>(buffer, header->lumps[impl::BspLump::LUMP_TEXDATA], context.texdatas);
|
||||
impl::extractLump<int32_t>(buffer, header->lumps[impl::BspLump::LUMP_TEXDATA_STRING_TABLE], context.stringTable);
|
||||
impl::extractLumpString(buffer, header->lumps[impl::BspLump::LUMP_TEXDATA_STRING_DATA], context.stringData);
|
||||
impl::extractLump<impl::BspModel>(buffer, header->lumps[impl::BspLump::LUMP_MODELS], context.models);
|
||||
impl::extractLump<uint8_t>(buffer, header->lumps[impl::BspLump::LUMP_VISIBILITY], context.visibility);
|
||||
impl::extractLump<int8_t>(buffer, header->lumps[impl::BspLump::LUMP_ENTITIES], context.entities);
|
||||
impl::extractLump<impl::BspGameLump>(buffer, header->lumps[impl::BspLump::LUMP_GAME_LUMP], context.gameLumps);
|
||||
impl::extractLump<impl::BspDispInfo>(buffer, header->lumps[impl::BspLump::LUMP_DISPINFO], context.dispinfos);
|
||||
@ -730,7 +834,6 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
auto& image = storage.images[matName].data;
|
||||
auto& texture = storage.images[matName].handle;
|
||||
if ( ext::valve::loadVtf( image, vtfPath ) ) {
|
||||
UF_MSG_DEBUG("Loaded cubemap={}", vtfPath);
|
||||
context.cubemapIDs.emplace_back( storage.materials[matName].indexCubemap = textureID );
|
||||
}
|
||||
}
|
||||
@ -787,106 +890,6 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
storage.textures[textureKey].index = atlasImageID;
|
||||
}
|
||||
|
||||
// read models
|
||||
for ( auto m = 0; m < context.models.size(); ++m ) {
|
||||
const auto& model = context.models[m];
|
||||
uf::stl::unordered_map<int32_t, impl::Meshlet> meshlets; // group by material IDs
|
||||
|
||||
for ( auto i = 0; i < model.numfaces; ++i ) {
|
||||
const auto faceID = model.firstface + i;
|
||||
const auto& face = context.faces[faceID];
|
||||
|
||||
if ( face.numedges < 3 ) continue;
|
||||
if ( face.texinfo < 0 || face.texinfo >= context.texinfos.size() ) continue;
|
||||
|
||||
int32_t texDataID = context.texinfos[face.texinfo].texData;
|
||||
if ( texDataID < 0 || texDataID >= context.texdatas.size() ) continue;
|
||||
|
||||
size_t materialID = context.texdataToMaterial[texDataID];
|
||||
auto& matName = graph.materials[materialID];
|
||||
|
||||
// read brush
|
||||
auto& meshlet = meshlets[materialID];
|
||||
meshlet.primitive.instance.materialID = materialID;
|
||||
|
||||
if ( 0 <= face.lightofs ) {
|
||||
meshlet.primitive.instance.lightmapID = atlasTextureID;
|
||||
}
|
||||
|
||||
if ( !context.cubemapIDs.empty() ) {
|
||||
int32_t pivotSurfEdge = context.surfedges[face.firstedge];
|
||||
uint16_t pivotVertID = pivotSurfEdge >= 0 ? context.edges[pivotSurfEdge].x : context.edges[-pivotSurfEdge].y;
|
||||
pod::Vector3f p0 = impl::convertPos( context.vertices[pivotVertID] );
|
||||
|
||||
meshlet.primitive.instance.cubemapID = impl::findClosestCubemap( context, p0 );
|
||||
}
|
||||
|
||||
if ( face.dispinfo != -1 ) {
|
||||
impl::buildDisplacement( context, meshlet, faceID );
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto edgeID = face.firstedge;
|
||||
int32_t pivotSurfEdge = context.surfedges[edgeID];
|
||||
uint16_t pivotVertID = pivotSurfEdge >= 0 ? context.edges[pivotSurfEdge].x : context.edges[-pivotSurfEdge].y;
|
||||
pod::Vector3f p0 = impl::convertPos( context.vertices[pivotVertID] );
|
||||
|
||||
for ( int16_t i = 1; i < face.numedges - 1; ++i ) {
|
||||
int32_t se1 = context.surfedges[edgeID + i];
|
||||
int32_t se2 = context.surfedges[edgeID + i + 1];
|
||||
|
||||
uint16_t v1 = se1 >= 0 ? context.edges[se1].x : context.edges[-se1].y;
|
||||
uint16_t v2 = se2 >= 0 ? context.edges[se2].x : context.edges[-se2].y;
|
||||
|
||||
pod::Vector3f p1 = impl::convertPos( context.vertices[v1] );
|
||||
pod::Vector3f p2 = impl::convertPos( context.vertices[v2] );
|
||||
pod::Vector3f normal = uf::vector::normalize(uf::vector::cross(p1 - p0, p2 - p0));
|
||||
|
||||
impl::addVertex( context, meshlet, pivotVertID, p0, normal, faceID );
|
||||
impl::addVertex( context, meshlet, v1, p1, normal, faceID );
|
||||
impl::addVertex( context, meshlet, v2, p2, normal, faceID );
|
||||
}
|
||||
}
|
||||
|
||||
if ( meshlets.empty() ) continue;
|
||||
|
||||
|
||||
auto meshName = ::fmt::format("model_{}", m);
|
||||
context.modelToMesh[m] = graph.meshes.size();
|
||||
|
||||
graph.meshes.emplace_back(meshName);
|
||||
graph.primitives.emplace_back(meshName);
|
||||
|
||||
auto& mesh = storage.meshes[meshName];
|
||||
auto& primitives = storage.primitives[meshName];
|
||||
|
||||
// slice worldspawn
|
||||
if ( false && m == 0 ) {
|
||||
/*
|
||||
if ( ext::json::isObject( meshgrid.metadata ) ) {
|
||||
if ( meshgrid.metadata["size"].is<size_t>() ) {
|
||||
size_t d = meshgrid.metadata["size"].as<size_t>();
|
||||
meshgrid.grid.divisions = {d, d, d};
|
||||
} else {
|
||||
meshgrid.grid.divisions = uf::vector::decode( meshgrid.metadata["size"], meshgrid.grid.divisions );
|
||||
}
|
||||
|
||||
meshgrid.eps = meshgrid.metadata["epsilon"].as(meshgrid.eps);
|
||||
meshgrid.print = meshgrid.metadata["print"].as(meshgrid.print);
|
||||
meshgrid.clip = meshgrid.metadata["clip"].as(meshgrid.clip);
|
||||
meshgrid.cleanup = meshgrid.metadata["cleanup"].as(meshgrid.cleanup);
|
||||
}
|
||||
*/
|
||||
uf::meshgrid::Grid grid;
|
||||
grid.divisions = {8, 8, 8};
|
||||
auto mlets = uf::stl::values( meshlets );
|
||||
auto partitioned = uf::meshgrid::partition( grid, mlets, EPS, true, true );
|
||||
mesh.compile( partitioned, primitives );
|
||||
} else {
|
||||
mesh.compile( meshlets, primitives );
|
||||
}
|
||||
}
|
||||
|
||||
// read entities
|
||||
{
|
||||
bool parsing = false;
|
||||
@ -941,6 +944,186 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
}
|
||||
}
|
||||
|
||||
// prepare for segregating skybox from worldspawn
|
||||
{
|
||||
pod::Vector3f skyCameraOrigin = {NAN, NAN, NAN};
|
||||
for ( auto& node : graph.nodes ) {
|
||||
auto& metadataValve = node.metadata["valve"];
|
||||
if ( metadataValve["classname"].as<uf::stl::string>("") != "sky_camera" ) continue;
|
||||
auto originStr = metadataValve["origin"].as<uf::stl::string>("");
|
||||
if ( originStr == "" ) continue;
|
||||
skyCameraOrigin = impl::str2vec<pod::Vector3f>( originStr );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( uf::vector::isValid( skyCameraOrigin ) ) {
|
||||
int32_t skyLeafIdx = impl::findLeaf(context, skyCameraOrigin);
|
||||
|
||||
context.skyArea = context.leafs[skyLeafIdx].area_flags & 0x01FF;
|
||||
|
||||
for ( const auto& leaf : context.leafs ) {
|
||||
int16_t leafArea = leaf.area_flags & 0x01FF;
|
||||
|
||||
if ( leafArea == context.skyArea ) {
|
||||
for ( int i = 0; i < leaf.numleaffaces; ++i ) {
|
||||
context.skyboxFaces.insert(context.leaffaces[leaf.firstleafface + i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read models
|
||||
for ( auto m = 0; m < context.models.size(); ++m ) {
|
||||
const auto& model = context.models[m];
|
||||
uf::stl::unordered_map<int32_t, impl::Meshlet> meshlets; // group by material IDs
|
||||
uf::stl::unordered_map<int32_t, impl::Meshlet> skyboxMeshlets; // segregate skybox geometry
|
||||
|
||||
for ( auto i = 0; i < model.numfaces; ++i ) {
|
||||
const auto faceID = model.firstface + i;
|
||||
const auto& face = context.faces[faceID];
|
||||
|
||||
if ( face.numedges < 3 ) continue;
|
||||
if ( face.texinfo < 0 || face.texinfo >= context.texinfos.size() ) continue;
|
||||
|
||||
int32_t texDataID = context.texinfos[face.texinfo].texData;
|
||||
if ( texDataID < 0 || texDataID >= context.texdatas.size() ) continue;
|
||||
|
||||
size_t materialID = context.texdataToMaterial[texDataID];
|
||||
auto& matName = graph.materials[materialID];
|
||||
|
||||
// deduce which group to use
|
||||
bool isSkybox = (m == 0 && context.skyboxFaces.count(faceID) > 0);
|
||||
if ( !isSkybox && m == 0 && context.skyArea != -1 ) {
|
||||
int32_t se0 = context.surfedges[face.firstedge];
|
||||
int32_t se1 = context.surfedges[face.firstedge + 1];
|
||||
int32_t se2 = context.surfedges[face.firstedge + 2];
|
||||
|
||||
uint16_t v0 = se0 >= 0 ? context.edges[se0].x : context.edges[-se0].y;
|
||||
uint16_t v1 = se1 >= 0 ? context.edges[se1].x : context.edges[-se1].y;
|
||||
uint16_t v2 = se2 >= 0 ? context.edges[se2].x : context.edges[-se2].y;
|
||||
|
||||
pod::Vector3f p0 = context.vertices[v0];
|
||||
pod::Vector3f p1 = context.vertices[v1];
|
||||
pod::Vector3f p2 = context.vertices[v2];
|
||||
|
||||
pod::Vector3f normal = uf::vector::normalize(uf::vector::cross(p1 - p0, p2 - p0));
|
||||
|
||||
pod::Vector3f testPos = p0 + normal * 2.0f;
|
||||
|
||||
int32_t testLeafIdx = impl::findLeaf(context, testPos);
|
||||
if ( testLeafIdx >= 0 && testLeafIdx < context.leafs.size() ) {
|
||||
int16_t testArea = context.leafs[testLeafIdx].area_flags & 0x01FF;
|
||||
if ( testArea == context.skyArea ) {
|
||||
isSkybox = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read brush
|
||||
auto& meshlet = (isSkybox ? skyboxMeshlets : meshlets)[materialID];
|
||||
meshlet.primitive.instance.materialID = materialID;
|
||||
|
||||
if ( 0 <= face.lightofs ) {
|
||||
meshlet.primitive.instance.lightmapID = atlasTextureID;
|
||||
}
|
||||
|
||||
if ( !context.cubemapIDs.empty() ) {
|
||||
int32_t pivotSurfEdge = context.surfedges[face.firstedge];
|
||||
uint16_t pivotVertID = pivotSurfEdge >= 0 ? context.edges[pivotSurfEdge].x : context.edges[-pivotSurfEdge].y;
|
||||
pod::Vector3f p0 = impl::convertPos( context.vertices[pivotVertID] );
|
||||
|
||||
meshlet.primitive.instance.cubemapID = impl::findClosestCubemap( context, p0 );
|
||||
}
|
||||
|
||||
if ( face.dispinfo != -1 ) {
|
||||
impl::buildDisplacement( context, meshlet, faceID );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const auto edgeID = face.firstedge;
|
||||
int32_t pivotSurfEdge = context.surfedges[edgeID];
|
||||
uint16_t pivotVertID = pivotSurfEdge >= 0 ? context.edges[pivotSurfEdge].x : context.edges[-pivotSurfEdge].y;
|
||||
pod::Vector3f p0 = impl::convertPos( context.vertices[pivotVertID] );
|
||||
|
||||
const auto& plane = context.planes[face.planenum];
|
||||
|
||||
pod::Vector3f faceNormal = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
for ( int16_t i = 1; i < face.numedges - 1; ++i ) {
|
||||
int32_t se1 = context.surfedges[edgeID + i];
|
||||
int32_t se2 = context.surfedges[edgeID + i + 1];
|
||||
|
||||
uint16_t v1 = se1 >= 0 ? context.edges[se1].x : context.edges[-se1].y;
|
||||
uint16_t v2 = se2 >= 0 ? context.edges[se2].x : context .edges[-se2].y;
|
||||
|
||||
pod::Vector3f p1 = impl::convertPos( context.vertices[v1] );
|
||||
pod::Vector3f p2 = impl::convertPos( context.vertices[v2] );
|
||||
|
||||
faceNormal += uf::vector::cross(p1 - p0, p2 - p0);
|
||||
}
|
||||
|
||||
faceNormal = uf::vector::normalize(faceNormal);
|
||||
|
||||
for ( int16_t i = 1; i < face.numedges - 1; ++i ) {
|
||||
int32_t se1 = context.surfedges[edgeID + i];
|
||||
int32_t se2 = context.surfedges[edgeID + i + 1];
|
||||
|
||||
uint16_t v1 = se1 >= 0 ? context.edges[se1].x : context.edges[-se1].y;
|
||||
uint16_t v2 = se2 >= 0 ? context.edges[se2].x : context.edges[-se2].y;
|
||||
|
||||
pod::Vector3f p1 = impl::convertPos( context.vertices[v1] );
|
||||
pod::Vector3f p2 = impl::convertPos( context.vertices[v2] );
|
||||
|
||||
impl::addVertex( context, meshlet, pivotVertID, p0, faceNormal, faceID );
|
||||
impl::addVertex( context, meshlet, v1, p1, faceNormal, faceID );
|
||||
impl::addVertex( context, meshlet, v2, p2, faceNormal, faceID );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !meshlets.empty() ) {
|
||||
auto meshName = ::fmt::format("model_{}", m);
|
||||
context.modelToMesh[m] = graph.meshes.size();
|
||||
|
||||
graph.meshes.emplace_back(meshName);
|
||||
graph.primitives.emplace_back(meshName);
|
||||
|
||||
auto& mesh = storage.meshes[meshName];
|
||||
auto& primitives = storage.primitives[meshName];
|
||||
|
||||
// for ( auto& pair : meshlets ) uf::mesh::tangents( pair.second.vertices, pair.second.indices );
|
||||
|
||||
// slice worldspawn
|
||||
if ( false && m == 0 ) {
|
||||
uf::meshgrid::Grid grid;
|
||||
grid.divisions = {8, 8, 8};
|
||||
auto mlets = uf::stl::values( meshlets );
|
||||
auto partitioned = uf::meshgrid::partition( grid, mlets, EPS, true, true );
|
||||
mesh.compile( partitioned, primitives );
|
||||
} else {
|
||||
mesh.compile( meshlets, primitives );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !skyboxMeshlets.empty() ) {
|
||||
auto meshName = ::fmt::format("model_{}_skybox", m);
|
||||
graph.meshes.emplace_back(meshName);
|
||||
graph.primitives.emplace_back(meshName);
|
||||
|
||||
auto& mesh = storage.meshes[meshName];
|
||||
auto& primitives = storage.primitives[meshName];
|
||||
mesh.compile( skyboxMeshlets, primitives );
|
||||
|
||||
// create a skybox node for this
|
||||
auto nodeID = graph.nodes.size();
|
||||
auto& node = graph.nodes.emplace_back();
|
||||
node.name = "skybox";
|
||||
node.mesh = (int32_t)(graph.meshes.size() - 1);
|
||||
graph.root.children.emplace_back(nodeID);
|
||||
}
|
||||
}
|
||||
|
||||
// read static props
|
||||
for ( const auto& item : context.gameLumps ) {
|
||||
if ( item.id == 1936749168 ) { // 'sprp' (Static Props)
|
||||
@ -991,6 +1174,16 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
metadata["model"] = dict[type];
|
||||
metadata["origin"] = ::fmt::format("{} {} {}", origin.x, origin.y, origin.z);
|
||||
metadata["angles"] = ::fmt::format("{} {} {}", angles.x, angles.y, angles.z);
|
||||
|
||||
if ( context.skyArea != -1 ) {
|
||||
int32_t propLeafIdx = impl::findLeaf(context, origin);
|
||||
if ( propLeafIdx >= 0 && propLeafIdx < context.leafs.size() ) {
|
||||
int16_t propArea = context.leafs[propLeafIdx].area_flags & 0x01FF;
|
||||
if ( propArea == context.skyArea ) {
|
||||
metadata["skyboxed"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
graph.root.children.emplace_back( nodeID );
|
||||
}
|
||||
@ -1004,6 +1197,9 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
// load materials
|
||||
uf::stl::vector<uint8_t> missing_pixels = { 255, 0, 255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 0, 255, 255 };
|
||||
for ( auto matName : graph.materials ) {
|
||||
if ( matName == "" ) {
|
||||
continue;
|
||||
}
|
||||
uf::Serializer vmt;
|
||||
auto vmtPath = ::fmt::format("materials/{}.vmt", matName);
|
||||
auto vtfPath = ::fmt::format("materials/{}.vtf", matName);
|
||||
@ -1054,13 +1250,15 @@ void ext::valve::loadBsp( pod::Graph& graph, const uf::stl::string& filename, co
|
||||
texture.viewType = uf::renderer::enums::Image::VIEW_TYPE_CUBE;
|
||||
|
||||
if ( ext::valve::loadVtf( image, vtfPath ) ) {
|
||||
UF_MSG_DEBUG("Loaded cubemap={}", matName);
|
||||
material.indexCubemap = textureID;
|
||||
}
|
||||
}
|
||||
}
|
||||
// bumpmap
|
||||
if ( vmt["$ssbump"].as<int>(0) == 1 ) {
|
||||
material.indexNormal = -1;
|
||||
// normal map
|
||||
if ( vmt["$bumpmap"].is<uf::stl::string>() ) {
|
||||
} else if ( vmt["$bumpmap"].is<uf::stl::string>() ) {
|
||||
auto matName = uf::string::lowercase(vmt["$bumpmap"].as<uf::stl::string>());
|
||||
auto vtfPath = ::fmt::format("materials/{}.vtf", matName);
|
||||
|
||||
|
||||
@ -320,94 +320,66 @@ bool ext::valve::loadMdl( pod::Graph& graph, const uf::stl::string& filename ) {
|
||||
const impl::mstudiomesh_t* mdlMeshes = (const impl::mstudiomesh_t*)((uint8_t*)&mdlModels[m] + mdlModels[m].meshindex);
|
||||
|
||||
for ( int meshID = 0; meshID < lod0.numMeshes; ++meshID ) {
|
||||
const impl::vtxMesh_t& mesh = meshes[meshID];
|
||||
const impl::mstudiomesh_t& mdlMesh = mdlMeshes[meshID];
|
||||
const impl::vtxMesh_t& mesh = meshes[meshID];
|
||||
const impl::mstudiomesh_t& mdlMesh = mdlMeshes[meshID];
|
||||
|
||||
auto& meshlet = meshlets.emplace_back();
|
||||
uf::stl::unordered_map<uint16_t, uint32_t> vertRemap;
|
||||
auto& meshlet = meshlets.emplace_back();
|
||||
uf::stl::unordered_map<uint16_t, uint32_t> vertRemap;
|
||||
|
||||
const impl::vtxStripGroup_t* stripGroups = (const impl::vtxStripGroup_t*)((uint8_t*)&mesh + mesh.stripGroupHeaderOffset);
|
||||
for ( int sg = 0; sg < mesh.numStripGroups; ++sg ) {
|
||||
const impl::vtxStripGroup_t& stripGroup = stripGroups[sg];
|
||||
const impl::vtxStripGroup_t* stripGroups = (const impl::vtxStripGroup_t*)((uint8_t*)&mesh + mesh.stripGroupHeaderOffset);
|
||||
for ( int sg = 0; sg < mesh.numStripGroups; ++sg ) {
|
||||
const impl::vtxStripGroup_t& stripGroup = stripGroups[sg];
|
||||
|
||||
const uint16_t* indices = (const uint16_t*)((uint8_t*)&stripGroup + stripGroup.indexOffset);
|
||||
const impl::vtxVertex_t* vtxVerts = (const impl::vtxVertex_t*)((uint8_t*)&stripGroup + stripGroup.vertOffset);
|
||||
const uint16_t* indices = (const uint16_t*)((uint8_t*)&stripGroup + stripGroup.indexOffset);
|
||||
const impl::vtxVertex_t* vtxVerts = (const impl::vtxVertex_t*)((uint8_t*)&stripGroup + stripGroup.vertOffset);
|
||||
|
||||
for ( int i = 0; i < stripGroup.numIndices; i += 3 ) {
|
||||
uint32_t tri[3];
|
||||
for ( int j = 0; j < 3; ++j ) {
|
||||
uint16_t localVertIndex = indices[i + j];
|
||||
const impl::vtxVertex_t& vtxVert = vtxVerts[localVertIndex];
|
||||
uint16_t originalVvdID = vtxVert.origMeshVertID;
|
||||
for ( int i = 0; i < stripGroup.numIndices; i += 3 ) {
|
||||
uint32_t tri[3];
|
||||
for ( int j = 0; j < 3; ++j ) {
|
||||
uint16_t localVertIndex = indices[i + j];
|
||||
const impl::vtxVertex_t& vtxVert = vtxVerts[localVertIndex];
|
||||
uint16_t originalVvdID = vtxVert.origMeshVertID;
|
||||
|
||||
if ( vertRemap.find(originalVvdID) == vertRemap.end() ) {
|
||||
vertRemap[originalVvdID] = meshlet.vertices.size();
|
||||
auto& vert = meshlet.vertices.emplace_back();
|
||||
if ( vertRemap.find(originalVvdID) == vertRemap.end() ) {
|
||||
vertRemap[originalVvdID] = meshlet.vertices.size();
|
||||
auto& vert = meshlet.vertices.emplace_back();
|
||||
|
||||
const auto& srcVert = lod0Vertices[mdlMesh.vertexoffset + originalVvdID];
|
||||
const auto& srcVert = lod0Vertices[mdlMesh.vertexoffset + originalVvdID];
|
||||
|
||||
vert.position = impl::convertPos( srcVert.m_vecPosition );
|
||||
vert.normal = uf::vector::normalize( impl::convertPos( srcVert.m_vecNormal, 1.0f ) );
|
||||
if ( !lod0Tangents.empty() ) {
|
||||
vert.tangent = uf::vector::normalize( impl::convertPos( lod0Tangents[mdlMesh.vertexoffset + originalVvdID], 1.0f ) );
|
||||
} else {
|
||||
vert.tangent = {};
|
||||
}
|
||||
vert.position = impl::convertPos( srcVert.m_vecPosition );
|
||||
vert.normal = uf::vector::normalize( impl::convertPos( srcVert.m_vecNormal, 1.0f ) );
|
||||
|
||||
vert.uv = srcVert.m_vecTexCoord;
|
||||
vert.color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
vert.joints.x = srcVert.m_BoneWeights.numbones > 0 ? std::max<int8_t>(0, srcVert.m_BoneWeights.bone[0]) : 0;
|
||||
vert.joints.y = srcVert.m_BoneWeights.numbones > 1 ? std::max<int8_t>(0, srcVert.m_BoneWeights.bone[1]) : 0;
|
||||
vert.joints.z = srcVert.m_BoneWeights.numbones > 2 ? std::max<int8_t>(0, srcVert.m_BoneWeights.bone[2]) : 0;
|
||||
vert.joints.w = 0;
|
||||
if ( !lod0Tangents.empty() ) {
|
||||
vert.tangent = uf::vector::normalize( impl::convertPos( lod0Tangents[mdlMesh.vertexoffset + originalVvdID], 1.0f ) );
|
||||
}
|
||||
|
||||
vert.weights.x = srcVert.m_BoneWeights.numbones > 0 ? srcVert.m_BoneWeights.weight[0] : 1.0f;
|
||||
vert.weights.y = srcVert.m_BoneWeights.numbones > 1 ? srcVert.m_BoneWeights.weight[1] : 0.0f;
|
||||
vert.weights.z = srcVert.m_BoneWeights.numbones > 2 ? srcVert.m_BoneWeights.weight[2] : 0.0f;
|
||||
vert.weights.w = 0.0f;
|
||||
vert.uv = srcVert.m_vecTexCoord;
|
||||
vert.color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
vert.joints.x = srcVert.m_BoneWeights.numbones > 0 ? std::max<int8_t>(0, srcVert.m_BoneWeights.bone[0]) : 0;
|
||||
vert.joints.y = srcVert.m_BoneWeights.numbones > 1 ? std::max<int8_t>(0, srcVert.m_BoneWeights.bone[1]) : 0;
|
||||
vert.joints.z = srcVert.m_BoneWeights.numbones > 2 ? std::max<int8_t>(0, srcVert.m_BoneWeights.bone[2]) : 0;
|
||||
vert.joints.w = 0;
|
||||
|
||||
// Bounds calculation
|
||||
auto& bounds = meshlet.primitive.instance.bounds;
|
||||
if ( vertRemap.size() == 1 ) {
|
||||
bounds.min = bounds.max = vert.position;
|
||||
} else {
|
||||
bounds.min = uf::vector::min( bounds.min, vert.position );
|
||||
bounds.max = uf::vector::max( bounds.max, vert.position );
|
||||
}
|
||||
}
|
||||
vert.weights.x = srcVert.m_BoneWeights.numbones > 0 ? srcVert.m_BoneWeights.weight[0] : 1.0f;
|
||||
vert.weights.y = srcVert.m_BoneWeights.numbones > 1 ? srcVert.m_BoneWeights.weight[1] : 0.0f;
|
||||
vert.weights.z = srcVert.m_BoneWeights.numbones > 2 ? srcVert.m_BoneWeights.weight[2] : 0.0f;
|
||||
vert.weights.w = 0.0f;
|
||||
|
||||
meshlet.indices.push_back(tri[j] = vertRemap[originalVvdID]);
|
||||
}
|
||||
auto& bounds = meshlet.primitive.instance.bounds;
|
||||
if ( vertRemap.size() == 1 ) {
|
||||
bounds.min = bounds.max = vert.position;
|
||||
} else {
|
||||
bounds.min = uf::vector::min( bounds.min, vert.position );
|
||||
bounds.max = uf::vector::max( bounds.max, vert.position );
|
||||
}
|
||||
}
|
||||
|
||||
if ( lod0Tangents.empty() ) {
|
||||
auto& v0 = meshlet.vertices[tri[0]];
|
||||
auto& v1 = meshlet.vertices[tri[1]];
|
||||
auto& v2 = meshlet.vertices[tri[2]];
|
||||
meshlet.indices.push_back(tri[j] = vertRemap[originalVvdID]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pod::Vector3f edge1 = v1.position - v0.position;
|
||||
pod::Vector3f edge2 = v2.position - v0.position;
|
||||
pod::Vector2f duv1 = v1.uv - v0.uv;
|
||||
pod::Vector2f duv2 = v2.uv - v0.uv;
|
||||
|
||||
float f = 1.0f / (duv1.x * duv2.y - duv2.x * duv1.y);
|
||||
pod::Vector3f tangent = {
|
||||
f * (duv2.y * edge1.x - duv1.y * edge2.x),
|
||||
f * (duv2.y * edge1.y - duv1.y * edge2.y),
|
||||
f * (duv2.y * edge1.z - duv1.y * edge2.z)
|
||||
};
|
||||
|
||||
v0.tangent += tangent;
|
||||
v1.tangent += tangent;
|
||||
v2.tangent += tangent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( lod0Tangents.empty() ) {
|
||||
for ( auto& vert : meshlet.vertices ) {
|
||||
vert.tangent = uf::vector::normalize(vert.tangent - vert.normal * uf::vector::dot(vert.normal, vert.tangent));
|
||||
}
|
||||
}
|
||||
if ( lod0Tangents.empty() ) uf::mesh::tangents( meshlet.vertices, meshlet.indices );
|
||||
|
||||
size_t materialID = 0;
|
||||
uf::stl::string matName = "missing_texture";
|
||||
|
||||
@ -12,6 +12,7 @@ namespace impl {
|
||||
constexpr uint32_t IMAGE_FORMAT_DXT5 = 15;
|
||||
|
||||
constexpr uint32_t TEXTUREFLAGS_ENVMAP = 0x00002000;
|
||||
constexpr uint32_t TEXTUREFLAGS_NORMAL = 0x00000080;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct VTFHeader {
|
||||
@ -284,5 +285,28 @@ bool ext::valve::loadVtf( pod::Image& image, const uf::stl::string& filename ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( (header->flags & impl::TEXTUREFLAGS_NORMAL) != 0 && header->highResImageFormat == impl::IMAGE_FORMAT_DXT5 ) {
|
||||
size_t pixelCount = image.pixels.size() / 4;
|
||||
for ( size_t i = 0; i < pixelCount; ++i ) {
|
||||
uint8_t& r = image.pixels[i * 4 + 0];
|
||||
uint8_t& g = image.pixels[i * 4 + 1];
|
||||
uint8_t& b = image.pixels[i * 4 + 2];
|
||||
uint8_t& a = image.pixels[i * 4 + 3];
|
||||
|
||||
float x = (a / 255.0f) * 2.0f - 1.0f;
|
||||
float y = (g / 255.0f) * 2.0f - 1.0f;
|
||||
|
||||
y = -y;
|
||||
|
||||
float z = std::sqrt(std::max(1.0f - (x * x + y * y), 0.0f));
|
||||
|
||||
r = (uint8_t)((x * 0.5f + 0.5f) * 255.0f);
|
||||
g = (uint8_t)((y * 0.5f + 0.5f) * 255.0f);
|
||||
b = (uint8_t)((z * 0.5f + 0.5f) * 255.0f);
|
||||
|
||||
a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -447,7 +447,8 @@ void ext::vulkan::Pipeline::record( const Graphic& graphic, VkCommandBuffer comm
|
||||
struct PushConstant {
|
||||
uint32_t pass;
|
||||
uint32_t draw;
|
||||
} pushConstant = { pass, draw };
|
||||
uint32_t aux;
|
||||
} pushConstant = { pass, draw, descriptor.aux };
|
||||
vkCmdPushConstants( commandBuffer, pipelineLayout, shader->descriptor.stage, 0, sizeof(pushConstant), &pushConstant );
|
||||
} else if ( !shader->pushConstants.empty() ) {
|
||||
auto& pushConstant = shader->pushConstants.front();
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
const uf::stl::string DEFERRED_MODE = "compute";
|
||||
|
||||
namespace postprocesses {
|
||||
struct {
|
||||
ext::vulkan::Buffer atomicCounter;
|
||||
@ -243,25 +241,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
/*.layer = */0,
|
||||
/*.autoBuildPipeline =*/ true
|
||||
);
|
||||
if ( DEFERRED_MODE == "fragment" ) {
|
||||
renderTarget.addPass(
|
||||
/*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
|
||||
/*.colors =*/ { attachments.color, attachments.scratch, attachments.motion },
|
||||
#if BARYCENTRIC
|
||||
#if !BARYCENTRIC_CALCULATE
|
||||
/*.inputs =*/ { attachments.id, attachments.depth, attachments.bary },
|
||||
#else
|
||||
/*.inputs =*/ { attachments.id, attachments.depth },
|
||||
#endif
|
||||
#else
|
||||
/*.inputs =*/ { attachments.id, attachments.depth, attachments.uv, attachments.normal },
|
||||
#endif
|
||||
/*.resolve =*/{},
|
||||
/*.depth = */attachments.depth,
|
||||
/*.layer = */0,
|
||||
/*.autoBuildPipeline =*/ false
|
||||
);
|
||||
}
|
||||
|
||||
// metadata.outputs.emplace_back(metadata.attachments["output"]);
|
||||
renderTarget.initialize( device );
|
||||
@ -339,34 +318,19 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
}
|
||||
|
||||
if ( settings::pipelines::deferred ) {
|
||||
if ( DEFERRED_MODE == "compute" ) {
|
||||
uf::stl::string computeShaderFilename = "comp.spv"; {
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ uf::renderer::settings::pipelines::rt, "rt.comp" },
|
||||
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
|
||||
{ msaa > 1, "msaa.comp" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", settings[i].second );
|
||||
}
|
||||
computeShaderFilename = uf::io::root+"/shaders/display/deferred/comp/" + computeShaderFilename;
|
||||
blitter.material.attachShader(uf::io::resolveURI(computeShaderFilename), uf::renderer::enums::Shader::COMPUTE, "deferred");
|
||||
UF_MSG_DEBUG("Using deferred shader: {}", computeShaderFilename);
|
||||
} else if ( DEFERRED_MODE == "fragment" ) {
|
||||
uf::stl::string vertexShaderFilename = "vert.spv";
|
||||
uf::stl::string fragmentShaderFilename = "frag.spv"; {
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ uf::renderer::settings::pipelines::rt, "rt.frag" },
|
||||
{ uf::renderer::settings::pipelines::vxgi, "vxgi.frag" },
|
||||
{ msaa > 1, "msaa.frag" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) fragmentShaderFilename = uf::string::replace( fragmentShaderFilename, "frag", settings[i].second );
|
||||
}
|
||||
fragmentShaderFilename = uf::io::root+"/shaders/display/deferred/frag/" + fragmentShaderFilename;
|
||||
blitter.material.attachShader(uf::io::resolveURI(fragmentShaderFilename), uf::renderer::enums::Shader::FRAGMENT, "deferred");
|
||||
UF_MSG_DEBUG("Using deferred shader: {}", fragmentShaderFilename);
|
||||
uf::stl::string computeShaderFilename = "comp.spv"; {
|
||||
std::pair<bool, uf::stl::string> settings[] = {
|
||||
{ uf::renderer::settings::pipelines::rt, "rt.comp" },
|
||||
{ uf::renderer::settings::pipelines::vxgi, "vxgi.comp" },
|
||||
{ msaa > 1, "msaa.comp" },
|
||||
};
|
||||
FOR_ARRAY( settings ) if ( settings[i].first ) computeShaderFilename = uf::string::replace( computeShaderFilename, "comp", settings[i].second );
|
||||
}
|
||||
computeShaderFilename = uf::io::root+"/shaders/display/deferred/comp/" + computeShaderFilename;
|
||||
blitter.material.attachShader(uf::io::resolveURI(computeShaderFilename), uf::renderer::enums::Shader::COMPUTE, "deferred");
|
||||
UF_MSG_DEBUG("Using deferred shader: {}", computeShaderFilename);
|
||||
|
||||
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
|
||||
auto& shader = blitter.material.getShader("compute", "deferred");
|
||||
|
||||
size_t maxLights = uf::config["engine"]["scenes"]["lights"]["max"].as<size_t>(512);
|
||||
size_t maxTextures2D = uf::config["engine"]["scenes"]["textures"]["max"]["2D"].as<size_t>(512);
|
||||
@ -561,8 +525,8 @@ void ext::vulkan::DeferredRenderMode::build( bool resized ) {
|
||||
}
|
||||
|
||||
// (re)bind aliases
|
||||
if ( blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
|
||||
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
|
||||
if ( blitter.material.hasShader("compute", "deferred") ) {
|
||||
auto& shader = blitter.material.getShader("compute", "deferred");
|
||||
|
||||
shader.metadata.aliases.buffers.clear();
|
||||
shader.aliasBuffer( storage.buffers.camera );
|
||||
@ -587,15 +551,10 @@ void ext::vulkan::DeferredRenderMode::build( bool resized ) {
|
||||
descriptor.bind.height = height;
|
||||
descriptor.bind.depth = 1;
|
||||
|
||||
if ( settings::pipelines::deferred && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
|
||||
if ( settings::pipelines::deferred && blitter.material.hasShader("compute", "deferred") ) {
|
||||
descriptor.pipeline = "deferred";
|
||||
if ( DEFERRED_MODE == "fragment" ) {
|
||||
descriptor.subpass = 1;
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
} else if ( DEFERRED_MODE == "compute" ) {
|
||||
descriptor.subpass = 0;
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
}
|
||||
descriptor.subpass = 0;
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||
blitter.update( descriptor );
|
||||
}
|
||||
|
||||
@ -894,48 +853,57 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
|
||||
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
|
||||
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
|
||||
|
||||
// render to geometry buffers
|
||||
{
|
||||
size_t currentPass = 0;
|
||||
size_t currentDraw = 0;
|
||||
// render skybox geometry
|
||||
for ( auto graphic : graphics ) {
|
||||
if ( graphic->descriptor.renderMode != this->getName() ) continue;
|
||||
if ( graphic->descriptor.renderTarget != 0 /*this->getName()*/ ) continue;
|
||||
if ( graphic->descriptor.aux != 1 ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, ::fmt::format("graphic[skybox][{}]", currentDraw) );
|
||||
graphic->record( commandBuffer, descriptor, 0, currentDraw++, frame );
|
||||
}
|
||||
// clear depth buffer
|
||||
if ( currentDraw > 0 ) {
|
||||
VkClearAttachment clearDepth = {};
|
||||
clearDepth.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
clearDepth.clearValue.depthStencil = { depthClear, 0 };
|
||||
|
||||
VkClearRect clearRect = {};
|
||||
clearRect.rect.offset = { 0, 0 };
|
||||
clearRect.rect.extent = { width, height };
|
||||
clearRect.baseArrayLayer = 0;
|
||||
clearRect.layerCount = metadata.eyes > 0 ? metadata.eyes : 1;
|
||||
|
||||
vkCmdClearAttachments(commandBuffer, 1, &clearDepth, 1, &clearRect);
|
||||
}
|
||||
// render normal geometry
|
||||
for ( auto graphic : graphics ) {
|
||||
// only draw graphics that are assigned to this type of render mode
|
||||
if ( graphic->descriptor.renderMode != this->getName() ) continue;
|
||||
if ( graphic->descriptor.renderTarget != 0 /*this->getName()*/ ) continue;
|
||||
if ( graphic->descriptor.aux != 0 ) continue;
|
||||
ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, ::fmt::format("graphic[{}]", currentDraw) );
|
||||
graphic->record( commandBuffer, descriptor, 0, currentDraw++, frame );
|
||||
}
|
||||
}
|
||||
// skip deferred pass if RT is enabled, we still process geometry for a depth buffer
|
||||
if ( DEFERRED_MODE == "fragment" ) {
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "nextSubpass" );
|
||||
vkCmdNextSubpass(commandBuffer, VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass;
|
||||
|
||||
size_t currentPass = 0;
|
||||
size_t currentDraw = 0;
|
||||
{
|
||||
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor; // = bindGraphicDescriptor(blitter.descriptor, currentSubpass);
|
||||
descriptor.renderMode = "";
|
||||
descriptor.pipeline = "deferred";
|
||||
descriptor.subpass = currentSubpass;
|
||||
descriptor.bind.point = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::GENERIC, "deferred" );
|
||||
blitter.record(commandBuffer, descriptor, 0, currentDraw++, frame);
|
||||
}
|
||||
}
|
||||
device->UF_CHECKPOINT_MARK( commandBuffer, pod::Checkpoint::END, "renderPass[end]" );
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
#if 1
|
||||
if ( settings::pipelines::deferred && DEFERRED_MODE == "compute" && blitter.material.hasShader(DEFERRED_MODE, "deferred") ) {
|
||||
if ( settings::pipelines::deferred && blitter.material.hasShader("compute", "deferred") ) {
|
||||
VkMemoryBarrier computeBarrier = {};
|
||||
computeBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
|
||||
computeBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
||||
computeBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &computeBarrier, 0, nullptr, 0, nullptr );
|
||||
|
||||
auto& shader = blitter.material.getShader(DEFERRED_MODE, "deferred");
|
||||
auto& shader = blitter.material.getShader("compute", "deferred");
|
||||
ext::vulkan::GraphicDescriptor descriptor = blitter.descriptor;
|
||||
descriptor.renderMode = "";
|
||||
descriptor.pipeline = "deferred";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user