More Physics corrections and Forward Renderer physics

This commit is contained in:
Halbear 2026-07-06 13:03:42 +01:00
parent eb09963e3a
commit d05c5d0171
9 changed files with 216 additions and 18 deletions

View file

@ -0,0 +1,11 @@
#version 450
layout(location = 0) in vec3 outTexCoords;
layout(location = 0) out vec4 outColor;
layout(set = 2, binding = 0) uniform samplerCube skyboxSampler;
void main() {
outColor = vec4(texture(skyboxSampler, outTexCoords).rgb, 1.0);
}

View file

@ -2,7 +2,7 @@
layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.6545;
const float GAMMA_CONST = 0.4545;
const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0;

View file

@ -4,6 +4,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.joml.primitives.AABBf;
import java.util.ArrayList;
import java.util.HashMap;
@ -18,6 +19,8 @@ public class RigidBody {
public final ConvexMesh shape;
public AABBf BoundingBox;
public final Vector3f Position;
public final Quaternionf Rotation;
public Vector3f WeightBalance = new Vector3f(0,0,0);
@ -37,7 +40,7 @@ public class RigidBody {
public final Matrix3f InverseInertiaLocal = new Matrix3f();
public final Matrix3f InverseInertiaWorld = new Matrix3f();
public float Restitution = 0.0f; // 0 = fully inelastic, 1 = perfectly elastic
public float Restitution = 0.0f; // 0 = not bouncy, 1 = bouncy
public float Friction = 0.5f;
public boolean IsStatic = false;

View file

@ -5,8 +5,8 @@ import org.joml.Vector3f;
//Resolves the Separating Axis Theorem Test into reaction forces in impulses and position correction
public class RigidCollision {
private static final float CORRECTION_THRESHOLD = 1.0f; //how much it gets corrected positionally per physics step
private static final float SLOP = 0.000f; // amount of overlap can happen before collision gets corrected
private static final float CORRECTION_THRESHOLD = 0.9f; //how much it gets corrected positionally per physics step
private static final float SLOP = 0.001f; // amount of overlap can happen before collision gets corrected
public synchronized static void ResolveCollision(RigidBody body1, RigidBody body2, SeparatingAxisTheoremTester.CollisionResult collisionResult){
Vector3f Normal = collisionResult.Normal;
@ -44,7 +44,7 @@ public class RigidCollision {
Impulse.set(normal).mul(j);
body1.LinearVelocity.mul(-1,body1.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body1.Bounciness,body1.LinearVelocity.y < 0 ? 1 : body1.Bounciness,body1.Bounciness);
body2.LinearVelocity.mul(-1,body1.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body1.Bounciness,body1.LinearVelocity.y < 0 ? 1 : body1.Bounciness,body1.Bounciness);
body2.LinearVelocity.mul(-1,body2.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body2.Bounciness,body2.LinearVelocity.y < 0 ? 1 : body2.Bounciness,body2.Bounciness);
body1.ApplyImpulse(NegatedImpulse.set(Impulse).negate(), Point);

View file

@ -97,6 +97,16 @@ public class RigidPhysicsController implements IPhysicsController {
public void PhysicsTick(float DeltaTime, float TargetFrameRate) {
DeltaTime/=10f;
// if(DeltaTime >0.1f) DeltaTime = 0.1f;
if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") {
RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID);
rigidBody.Integrate(DeltaTime, new Vector3f(0,-1.8f,0));
if(Actor.Actors.get(ActorID) != null) {
Actor.Actors.get(ActorID).SetPosition(new Vector3f(rigidBody.Position));
Actor.Actors.get(ActorID).SetRotation(rigidBody.Rotation);
}
}
/*
if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") {
RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID);
rigidBody.Integrate(DeltaTime, new Vector3f(0,-1.8f,0));
@ -113,7 +123,7 @@ public class RigidPhysicsController implements IPhysicsController {
Actor.Actors.get(ActorID).SetPosition(new Vector3f(rigidBody.Position));
Actor.Actors.get(ActorID).SetRotation(rigidBody.Rotation);
}
}
}*/
}
@Override

View file

@ -1,6 +1,9 @@
package net.halbear.Terrain4J.EngineCore.Logic.Physics;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidCollision;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.SeparatingAxisTheoremTester;
import net.halbear.Terrain4J.EngineCore.Threads.PhysicsThread;
import java.util.ArrayList;
@ -19,7 +22,7 @@ public class WorldPhysicsManager {
public static final Map<String, IPhysicsController> PhysicsObjects = new HashMap<>();
public static List<String> ActiveControllers = new ArrayList<>();
public static float FixedTimeStep = 1f / 60f;
public static float FixedTimeStep = 1f / 24f;
public static int MaxSubStepsPerFrame = 8;
private static float Accumulator = 0f;
private static boolean SingleThread = false;
@ -58,6 +61,60 @@ public class WorldPhysicsManager {
// }
}
public static void SteppedPhysicsTick2(float DeltaTime, float TargetFrameTime){
DeltaTime *= EngineConfig.getInstance().PhysicsSpeed();
if(EngineConfig.getInstance().IsEngineThrottled()) return;
Accumulator += DeltaTime;
float maxAccumulated = FixedTimeStep * MaxSubStepsPerFrame;
if (Accumulator > maxAccumulated) Accumulator = maxAccumulated;
int stepsRun = 0;
while (Accumulator >= FixedTimeStep && stepsRun < MaxSubStepsPerFrame) {
PhysicsTick++;
for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).PhysicsTick(FixedTimeStep, TargetFrameTime);
}
ResolveAllCollisions();
Accumulator -= FixedTimeStep;
stepsRun++;
}
for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).Collisions().clear();
}
}
private static void ResolveAllCollisions() {
List<String> ids = RigidBody.RigidBodies;
for (int i = 0; i < ids.size(); i++) {
RigidBody a = RigidBody.RigidBodyRegister.get(ids.get(i));
if (a == null) continue;
for (int j = i + 1; j < ids.size(); j++) {
RigidBody b = RigidBody.RigidBodyRegister.get(ids.get(j));
if (b == null) continue;
if (a.IsStatic && b.IsStatic) continue;
SeparatingAxisTheoremTester.CollisionResult result = SeparatingAxisTheoremTester.TestCollision(a.shape, b.shape);
if (result != null) {
RigidCollision.ResolveCollision(a, b, result);
}
}
}
}
public static void PhysicsTick2(float DeltaTime, float TargetFrameTime){
DeltaTime *= EngineConfig.getInstance().PhysicsSpeed();
if(EngineConfig.getInstance().IsEngineThrottled()) return;
PhysicsTick++;
for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).PhysicsTick(DeltaTime, TargetFrameTime);
}
ResolveAllCollisions();
for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).Collisions().clear();
}
}
public static void PhysicsTick(float DeltaTime, float TargetFrameTime){
DeltaTime *= EngineConfig.getInstance().PhysicsSpeed();
if(!EngineConfig.getInstance().IsEngineThrottled()) {

View file

@ -340,7 +340,7 @@ public class GameCore implements GameLogic {
if(PrimaryRuntime.GetFastThread().Ticks(20)==0){
//CollisionManager.UpdateCollisionChunks();
}
WorldPhysicsManager.PhysicsTick(DeltaTime, PhysicsFramerate);
WorldPhysicsManager.SteppedPhysicsTick2(DeltaTime, PhysicsFramerate);
}
@Override

View file

@ -38,6 +38,10 @@ import static org.lwjgl.vulkan.VK13.*;
public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
private static final String SKYBOX_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/forward_skybox_fragment.glsl";
private static final String SKYBOX_FRAGMENT_SHADER_FILE_SPV = SKYBOX_FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String SKYBOX_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/skybox_vertex.glsl";
private static final String SKYBOX_VERTEX_SHADER_FILE_SPV = SKYBOX_VERTEX_SHADER_FILE_GLSL + ".spv";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment.glsl";
private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_translucent_fragment.glsl";
private static final String FRAGMENT_OPAQUE_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_opaque_fragment.glsl";
@ -50,6 +54,9 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
private static final String DESCRIPTOR_ID_PRJ = "SCN_DESC_ID_PRJ";
private static final String DESCRIPTOR_ID_TEXT = "SCN_DESC_ID_TEXT";
private static final String DESCRIPTOR_ID_VIEW = "SCN_DESC_ID_VIEW";
private static final String DESCRIPTOR_ID_SKYBOX_VIEW = "SCN_DESC_ID_SKYBOX_VIEW";
public static final String DESCRIPTOR_ID_SKYBOX_CUBEMAP = "SCN_DESC_ID_SKYBOX_CUBEMAP";
public static String SkyBoxID = "SKYBOX_TEXTURE";
private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE;
private final VulkanBuffer BufferProjectionMatrix;
private final DescriptorSetLayout descriptorLayoutFragStorage;
@ -82,6 +89,10 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
private Pipeline VkPipelineOpaque;
private Pipeline VkPipelineTranslucent;
private Matrix4f ProjectionMatrix;
private DescriptorSetLayout descriptorLayoutSkyboxTexture;
private VulkanBuffer[] BufferSkyboxViewMatrices;
private Pipeline VkSkyboxPipeline;
private long skyboxMeshBufferId;
private boolean Deferred = false;
public static long GetGPUTimeNS(){
@ -125,12 +136,17 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, TextureCache.MAX_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT
));
BufferViewMatrices = VulkanUtils.CreateHostVisibleBuffers(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.MAX_IN_FLIGHT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_VIEW, descriptorLayoutVertexUniform);
descriptorLayoutSkyboxTexture = new DescriptorSetLayout(vulkanContext,
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, 1, VK_SHADER_STAGE_FRAGMENT_BIT));
BufferSkyboxViewMatrices = VulkanUtils.CreateHostVisibleBuffers(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_SKYBOX_VIEW, descriptorLayoutVertexUniform);
CreatePipelines(vulkanContext);
Logger.debug("Forward Renderer Pipelines:\nSingle Pass -> [{}]\nOpaque Dual Pass -> [{}]\nTranslucent Dual Pass -> [{}]",VkPipeline.GetVulkanPipeline(),VkPipelineOpaque.GetVulkanPipeline(), VkPipelineTranslucent.GetVulkanPipeline());
}
public void CreatePipelines(VulkanContext vulkanContext){
DescriptorSetLayout[] layouts = new DescriptorSetLayout[]{
descriptorLayoutVertexUniform,
descriptorLayoutVertexUniform,
@ -139,11 +155,24 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
};
ShaderModule[] shaderModules = CreateShaderModules(vulkanContext,0);
VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts, true, false,EngineConfig.getInstance().AlphaToCoverage());
VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts, true,true, false,EngineConfig.getInstance().AlphaToCoverage(),0);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
shaderModules = CreateShaderModules(vulkanContext,1);
VkPipelineOpaque = CreatePipeline(vulkanContext, shaderModules, layouts, true, true,EngineConfig.getInstance().AlphaToCoverage());
VkPipelineOpaque = CreatePipeline(vulkanContext, shaderModules, layouts, true,false, true,EngineConfig.getInstance().AlphaToCoverage(),0);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
shaderModules = CreateShaderModules(vulkanContext,2);
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,EngineConfig.getInstance().AlphaToCoverage());
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
DescriptorSetLayout[] skyboxLayouts = new DescriptorSetLayout[]{
descriptorLayoutVertexUniform,
descriptorLayoutVertexUniform,
descriptorLayoutSkyboxTexture
};
shaderModules = CreateSkyboxShaderModules(vulkanContext);
VkSkyboxPipeline = CreateSkyboxPipeline(vulkanContext, shaderModules, skyboxLayouts, false, false, false,false);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
}
@ -192,6 +221,17 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
.clearValue(clearValue);
}
private static ShaderModule[] CreateSkyboxShaderModules(VulkanContext VkCtx){
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(SKYBOX_VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
ShaderCompiler.CompileGLSLShaderOnChange( SKYBOX_FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader);
}
return new ShaderModule[]{
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, SKYBOX_VERTEX_SHADER_FILE_SPV,null),
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, SKYBOX_FRAGMENT_SHADER_FILE_SPV,null)
};
}
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
if(EngineConfig.getInstance().RecompileShaders()){
@ -202,14 +242,57 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV,null),
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, Translucent == 2 ? FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV : Translucent == 1 ? FRAGMENT_OPAQUE_SHADER_FILE_SPV : FRAGMENT_SHADER_FILE_SPV,null)
};
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean AlphaToCoverage){
private static Pipeline CreateSkyboxPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage){
int[] skyboxFormats = new int[] {
MultiRenderTargetAttachments.POSITION_FORMAT,
MultiRenderTargetAttachments.ALBEDO_FORMAT,
MultiRenderTargetAttachments.NORMAL_FORMAT,
MultiRenderTargetAttachments.PBR_FORMAT
};
try (MemoryStack MemStack = MemoryStack.stackPush()) {
VkVertexInputBindingDescription.Buffer bindingDescription = VkVertexInputBindingDescription.calloc(1, MemStack)
.binding(0)
.stride(3 * Float.BYTES)
.inputRate(VK_VERTEX_INPUT_RATE_VERTEX);
VkVertexInputAttributeDescription.Buffer attributeDescription = VkVertexInputAttributeDescription.calloc(1, MemStack)
.binding(0)
.location(0)
.format(VK_FORMAT_R32G32B32_SFLOAT)
.offset(0);
VkPipelineVertexInputStateCreateInfo skyboxVertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO)
.pVertexBindingDescriptions(bindingDescription)
.pVertexAttributeDescriptions(attributeDescription);
var BuildInfo = new PipelineBuildInfo(ShaderModules, skyboxVertexInputState, skyboxFormats)
.SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT)
.SetDepthWrite(false)
.SetDepthTest(true)
.SetPushConstantRanges(new PushConstantsRange[0])
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(true)
.SetDualPass(false)
.SetAlphaToCoverage(false);
var pipeline = new DefaultPipeline(VkCtx, BuildInfo);
Logger.debug("Skybox Pipeline Created Successfully");
return pipeline;
}
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage, int BlendingMethod){
var vertexBufferStructure = new VertexBufferStructure();
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{
MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT})
.SetDepthFormat(DEPTH_FORMAT)
.SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT)
.SetDepthWrite(DepthWrite)
.SetPushConstantRanges(
new PushConstantsRange[]{
@ -217,10 +300,12 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT,VulkanUtils.MATRIX4X4_SIZE,VulkanUtils.INT_SIZE)
})
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(DualRender ? !DepthWrite : true)
.SetBlendingMethod(BlendingMethod)
.BlendingIsUsed(Blending)
.SetDualPass(DualRender)
.SetAlphaToCoverage(AlphaToCoverage);
var pipeline = new DefaultPipeline(VkCtx, BuildInfo);
Logger.debug("Pipeline Created");
vertexBufferStructure.cleanup();
return pipeline;
}
@ -270,11 +355,32 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
.put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false);
Matrix4f skyboxViewMatrix = new Matrix4f().identity();
skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix());
skyboxViewMatrix.m30(0.0f);
skyboxViewMatrix.m31(0.0f);
skyboxViewMatrix.m32(0.0f);
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferSkyboxViewMatrices[CurrentFrame], skyboxViewMatrix, 0);
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkSkyboxPipeline.GetVulkanPipeline());
LongBuffer skyboxDescriptorSets = MemStack.mallocLong(3)
.put(0, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet())
.put(1, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SKYBOX_VIEW, CurrentFrame).GetVkDescriptorSet())
.put(2, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SKYBOX_CUBEMAP).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkSkyboxPipeline.GetVulkanPipelineLayout(), 0, skyboxDescriptorSets, null);
modelsCache.bindAndDrawCubeMesh(CommandHandle, DeferredSceneRender.SkyBoxID);
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0); // here
if(DualPassRendering) {
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineTranslucent.GetVulkanPipeline());
vkCmdSetViewport(CommandHandle, 0, Viewport);
vkCmdSetScissor(CommandHandle, 0, Scissor);
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineTranslucent.GetVulkanPipelineLayout(), 0, DescriptorSets, null);
} else{
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipeline());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
}
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true);
@ -356,6 +462,17 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList();
descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device,DESCRIPTOR_ID_TEXT,descriptorLayoutTexture);
descriptorSet.SetImageArray(device,imageViews,textureSampler,0);
DescriptorSet descSetSkyBox = descriptorAllocator.AddDescriptorSet(device, DESCRIPTOR_ID_SKYBOX_CUBEMAP, descriptorLayoutSkyboxTexture);
ITexture SkyBoxTexture = textureCache.GetTexture(DeferredSceneRender.SkyBoxID);
if (SkyBoxTexture == null) {
throw new RuntimeException("Skybox texture map was not properly cached before descriptor binding phase!");
}
descSetSkyBox.SetImage(
device,
SkyBoxTexture.GetImageView(),
textureSampler,
descriptorLayoutSkyboxTexture.GetLayoutInfo().Binding()
);
}
private static VkRenderingInfo CreateDeferredRenderInfo(VulkanContext VkCtx, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){