Deferred Lighting

This commit is contained in:
Harrison Corlett 2026-06-19 13:04:15 +01:00
parent 441bd95ddd
commit 8d219d2a35
224 changed files with 30309 additions and 385 deletions

View file

@ -6,6 +6,7 @@ import static org.lwjgl.openal.AL10.*;
public class AudioSource {
private final int SourceID;
private float Gain = 1.0f;
public AudioSource(boolean loop, boolean relative){
this.SourceID = alGenSources();
alSourcei(SourceID, AL_LOOPING, loop ? AL_TRUE: AL_FALSE);
@ -20,10 +21,16 @@ public class AudioSource {
Stop();
alSourcei(SourceID, AL_BUFFER, Buffer);
}
public float GetGain(){
return Gain;
}
public boolean isPlaying(){return alGetSourcei(SourceID, AL_SOURCE_STATE) == AL_PLAYING;}
public void Pause(){alSourcePause(SourceID);}
public void Play(){alSourcePlay(SourceID);}
public void SetGain(float gain){alSourcef(SourceID, AL_GAIN, gain);}
public void SetGain(float gain){
alSourcef(SourceID, AL_GAIN, gain);
Gain = gain;
}
public void SetPosition(Vector3f position){alSource3f(SourceID, AL_POSITION, position.x,position.y,position.z);}
public void Stop(){alSourceStop(SourceID);}
}

View file

@ -83,14 +83,14 @@ public class Render {
for(int i = 0; i < VulkanUtils.MAX_IN_FLIGHT; i++){
CommandPools[i] = new CommandPool(RendererContext, GraphicsQueue.GetQueueFamilyIndex(), false);
CommandBuffers[i] = new CommandBuffer(RendererContext, CommandPools[i],true, true);
PresentCompleteSemaphores[i] = new Semaphore(RendererContext);
Fences[i] = new Fence(RendererContext, true);
PresentCompleteSemaphores[i] = new Semaphore(RendererContext);
}
for(int i = 0; i < SwapChainImageCount; i++){
RenderCompleteSemaphores[i] = new Semaphore(RendererContext);
}
if(Deferred) {
sceneRender = new DeferredSceneRender(RendererContext);
sceneRender = new DeferredSceneRender(RendererContext, engineInstance);
lightRenderer = new LightRenderer(RendererContext, sceneRender.GetMRTAttachments().GetAllAttachments());
PostProcessor = new PostProcess(RendererContext, lightRenderer.getAttachment());
} else{
@ -111,10 +111,14 @@ public class Render {
Materials.addAll(initData.Materials());
Logger.debug("Loading {} Materials", Materials.size());
//materialsCache.CleanUp(RendererContext);
materialsCache.LoadMaterials(RendererContext, Materials,textureCache, CommandPools[0], GraphicsQueue);
Logger.debug("Loaded {} Materials", Materials.size());
List<GuiTexture> guiTextures = initData.GuiTextures();
if(guiTextures != null){
initData.GuiTextures().forEach(texture -> textureCache.AddTexture(RendererContext, texture.TexturePath(), texture.TexturePath(), VK_FORMAT_R8G8B8A8_SRGB));
}
Logger.debug("Transitioning Textures");
//textureCache.CleanUp(RendererContext);
textureCache.TransitionTexts(RendererContext, CommandPools[0], GraphicsQueue);
@ -126,11 +130,6 @@ public class Render {
modelsCache.loadModels(RendererContext, Models, CommandPools[0], GraphicsQueue);
Logger.debug("Loaded {} models", Models.size());
List<GuiTexture> guiTextures = initData.GuiTextures();
if(guiTextures != null){
initData.GuiTextures().forEach(texture -> textureCache.AddTexture(RendererContext, texture.TexturePath(), texture.TexturePath(), VK_FORMAT_R8G8B8A8_SRGB));
}
sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache);
GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),textureCache);
}
@ -155,6 +154,9 @@ public class Render {
PostProcessor.CleanUp(RendererContext);
swapChainRender.CleanUp(RendererContext);
GuiRender.CleanUp(RendererContext);
modelsCache.CleanUp(RendererContext);
materialsCache.CleanUp(RendererContext);
textureCache.CleanUp(RendererContext);
Logger.debug("Dynamic Renderer Cleaned up");
Arrays.asList(RenderCompleteSemaphores).forEach(i->i.cleanup(RendererContext));
Logger.debug("Render Semaphores cleaned up");
@ -167,9 +169,6 @@ public class Render {
CommandPools[i].cleanup(RendererContext);
}
Logger.debug("Command pools cleaned up");
modelsCache.CleanUp(RendererContext);
materialsCache.CleanUp(RendererContext);
textureCache.CleanUp(RendererContext);
RendererContext.cleanup();
}
public void DeferredRender(EngineInstance engineInstance){
@ -177,21 +176,21 @@ public class Render {
WaitForFence(CurrentFrame);
int imageAcquisitionIndex = CurrentFrame;
int ImageIndex;
if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[imageAcquisitionIndex])) < 0){
resize(engineInstance);
return;
}
var CommandPool = CommandPools[CurrentFrame];
var CommandBuffer = CommandBuffers[CurrentFrame];
RecordingStart(CommandPool, CommandBuffer);
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame);
lightRenderer.render(RendererContext, CommandBuffer, sceneRender.GetMRTAttachments());
lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), CurrentFrame);
PostProcessor.Render(RendererContext,CommandBuffer,lightRenderer.getAttachment());
GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment());
int ImageIndex;
if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[imageAcquisitionIndex])) < 0){
resize(engineInstance);
return;
}
swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex);
RecordingStop(CommandBuffer);

View file

@ -61,12 +61,14 @@ public class Window {
IconPath =IconLocation.getPath();
Logger.debug("Loading Icon From Location [{}]",IconPath);
} else Logger.warn("Icon specified in config at Location [{}] does not exist, resorting to Engine Icon", IconLocation.getPath());
Icon.set(GLFWImageParser.LoadImage(IconPath).GetWidth(),
GLFWImageParser.LoadImage(IconPath).GetHeight(),
GLFWImageParser.LoadImage(IconPath).GetImage());
IconBuffer.put(0,Icon);
if(new File(IconPath).exists()) {
Icon.set(GLFWImageParser.LoadImage(IconPath).GetWidth(),
GLFWImageParser.LoadImage(IconPath).GetHeight(),
GLFWImageParser.LoadImage(IconPath).GetImage());
IconBuffer.put(0, Icon);
glfwSetWindowIcon(handle, IconBuffer);
glfwSetWindowIcon(handle, IconBuffer);
}
IconBuffer.free(); //free the buffer once icon is set so when the program closes there isn't memory still floating around
Logger.debug("Freeing icon Buffer");

View file

@ -3,13 +3,14 @@ package net.halbear.Terrain4J.EngineCore.Logic;
import net.halbear.Terrain4J.EngineCore.Audio.AudioManager;
import net.halbear.Terrain4J.EngineCore.Display.Render;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Threads.FastTickThread;
import net.halbear.Terrain4J.EngineCore.Threads.MainThread;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
public record EngineInstance(Window window, Scene scene, PrimaryRuntime PrimaryThread, AudioManager audioManager) {
public record EngineInstance(Window window, IScene scene, PrimaryRuntime PrimaryThread, AudioManager audioManager) {
public void cleanup(){
window.cleanup();
audioManager.CleanUp();

View file

@ -113,27 +113,56 @@ public class ModelCompiler {
if(Result == aiReturn_SUCCESS){
diffuse.set(colour.r(), colour.g(), colour.b(), colour.a());
}
String DiffuseTexture = ProcessTexture(aiScene, aiMaterial, BaseDirectory, aiTextureType_DIFFUSE);
return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,diffuse);
String DiffuseTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_DIFFUSE);
String NormalTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_NORMALS);
String MetallicRoughTexture = ProcessTexture(aiScene, aiMaterial, BaseDirectory, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
float[] MetallicArray = new float[]{0.0f};
int[] MaxPointer = new int[]{1};
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_METALLIC_FACTOR,aiTextureType_NONE,0,MetallicArray,MaxPointer);
if(Result != aiReturn_SUCCESS){
MetallicArray = new float[]{0.0f};
}
float[] RoughnessArray = new float[]{0.0f};
Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_ROUGHNESS_FACTOR,aiTextureType_NONE,0,RoughnessArray,MaxPointer);
if(Result != aiReturn_SUCCESS){
RoughnessArray = new float[]{0.0f};
}
return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,NormalTexture, MetallicRoughTexture,diffuse,RoughnessArray[0],MetallicArray[0]);
}
public static MeshData ProcessMesh(AIMesh aiMesh, List<MaterialData> MaterialList, int MeshPosition, ModelBinaryData BinaryData) throws IOException {
List<Float> vertices = ProcessVertices(aiMesh);
List<Float> Vertices = ProcessVertices(aiMesh);
List<Float> Normals = ProcessNormals(aiMesh);
List<Float> Tangents = ProcessTangents(aiMesh,Normals);
List<Float> BiTangents = ProcessBiTangents(aiMesh,Normals);
List<Float> textureCoordinates = ProcessTextureCoords(aiMesh);
List<Integer> indices = ProcessIndices(aiMesh);
int VerticesSize = vertices.size();
int VerticesSize = Vertices.size();
if(textureCoordinates.isEmpty()){textureCoordinates = Collections.nCopies((VerticesSize/3)*2,0.0f);}
DataOutputStream VerticesOutput = BinaryData.GetVertexOutput();
int Rows = VerticesSize/3;
int VertexIncrement = (VerticesSize + textureCoordinates.size()) * VulkanUtils.FLOAT_SIZE;
int VertexIncrement = (VerticesSize + textureCoordinates.size() + Normals.size() + Tangents.size() + BiTangents.size()) * VulkanUtils.FLOAT_SIZE;
for(int row = 0; row < Rows; row++){
int StartPos = row * 3;
int StartTextureCoord = row * 2;
VerticesOutput.writeFloat(vertices.get(StartPos));
VerticesOutput.writeFloat(vertices.get(StartPos + 1));
VerticesOutput.writeFloat(vertices.get(StartPos + 2));
VerticesOutput.writeFloat(Vertices.get(StartPos));
VerticesOutput.writeFloat(Vertices.get(StartPos + 1));
VerticesOutput.writeFloat(Vertices.get(StartPos + 2));
VerticesOutput.writeFloat(Normals.get(StartPos));
VerticesOutput.writeFloat(Normals.get(StartPos + 1));
VerticesOutput.writeFloat(Normals.get(StartPos + 2));
VerticesOutput.writeFloat(Tangents.get(StartPos));
VerticesOutput.writeFloat(Tangents.get(StartPos + 1));
VerticesOutput.writeFloat(Tangents.get(StartPos + 2));
VerticesOutput.writeFloat(BiTangents.get(StartPos));
VerticesOutput.writeFloat(BiTangents.get(StartPos + 1));
VerticesOutput.writeFloat(BiTangents.get(StartPos + 2));
VerticesOutput.writeFloat(textureCoordinates.get(StartTextureCoord));
VerticesOutput.writeFloat(textureCoordinates.get(StartTextureCoord + 1));
}
@ -158,6 +187,48 @@ public class ModelCompiler {
return meshData;
}
public static List<Float> ProcessBiTangents(AIMesh aiMesh, List<Float> Normals){
List<Float> BiTangents = new ArrayList<>();
AIVector3D.Buffer aiBiTangents = aiMesh.mBitangents();
while(aiBiTangents != null && aiBiTangents.remaining() > 0){
AIVector3D aiBiTangent = aiBiTangents.get();
BiTangents.add(aiBiTangent.x());
BiTangents.add(aiBiTangent.y());
BiTangents.add(aiBiTangent.z());
}
if (BiTangents.isEmpty()) { // create empty BiTangents if assimp can't generate them
BiTangents = new ArrayList<>(Collections.nCopies(Normals.size(), 0.0f));
}
return BiTangents;
}
private static List<Float> ProcessNormals(AIMesh aiMesh){
List<Float> Normals = new ArrayList<>();
AIVector3D.Buffer aiNormals = aiMesh.mNormals();
while(aiNormals != null && aiNormals.remaining() > 0){
AIVector3D normal = aiNormals.get();
Normals.add(normal.x());
Normals.add(normal.y());
Normals.add(normal.z());
}
return Normals;
}
private static List<Float> ProcessTangents(AIMesh aiMesh, List<Float> Normals){
List<Float> Tangents = new ArrayList<>();
AIVector3D.Buffer aiTangents = aiMesh.mTangents();
while(aiTangents != null && aiTangents.remaining() > 0){
AIVector3D Tangent = aiTangents.get();
Tangents.add(Tangent.x());
Tangents.add(Tangent.y());
Tangents.add(Tangent.z());
}
if (Tangents.isEmpty()) { // create empty BiTangents if assimp can't generate them
Tangents = new ArrayList<>(Collections.nCopies(Normals.size(), 0.0f));
}
return Tangents;
}
public static List<Float> ProcessTextureCoords(AIMesh aiMesh){
List<Float> TextureCoords = new ArrayList<>();
AIVector3D.Buffer aiTextureCoords = aiMesh.mTextureCoords(0);
@ -185,15 +256,15 @@ public class ModelCompiler {
}
public static List<Float> ProcessVertices(AIMesh aiMesh){
List<Float> vertices = new ArrayList<>();
List<Float> Vertices = new ArrayList<>();
AIVector3D.Buffer aiVertices = aiMesh.mVertices();
while(aiVertices.remaining() > 0){
AIVector3D aiVertex = aiVertices.get();
vertices.add(aiVertex.x());
vertices.add(aiVertex.y());
vertices.add(aiVertex.z());
Vertices.add(aiVertex.x());
Vertices.add(aiVertex.y());
Vertices.add(aiVertex.z());
}
return vertices;
return Vertices;
}
public static String ProcessTexture(AIScene aiScene, AIMaterial aiMaterial, String BaseDirectory,int TextType ) throws IOException{

View file

@ -67,6 +67,7 @@ public class GameCore implements GameLogic {
public long CoolDown = 1000;
public ModelData MusicParticle;
public ModelData radio;
public ILight SkyLight;
@Override
public void cleanup() {
@ -75,7 +76,7 @@ public class GameCore implements GameLogic {
@Override
public InitData Initialise(EngineInstance engineInstance) {
Scene scene = engineInstance.scene();
IScene scene = engineInstance.scene();
List<ModelData> models = new ArrayList<>();
MusicParticle = ModelLoader.LoadModel("resources/models/MusicParticle/MusicParticle.json");
List<MaterialData> MusicParticleMat = ModelLoader.LoadMaterials("resources/models/MusicParticle/MusicParticle_mat.json");
@ -88,29 +89,10 @@ public class GameCore implements GameLogic {
//ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json");
//List<MaterialData> SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json");
scene.AddActor(new Actor("Sponza1", SponzaData.ID(), new Vector3f(0,0f,-5f)));
//JackOfAllTradesActor newJackentity = new JackOfAllTradesActor("Sponza2", radio.ID(), new Vector3f(40.0f, 155.0f, -42.0f),MusicParticle).SetAudio(engineInstance, "resources/EngineResources/audio/sounds/youusedtocallmeonyourcellphone.ogg").SetScale(0.01f);
//entities.add(newJackentity);
//scene.AddActor(newJackentity);
models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json"));
models.add(ModelLoader.LoadModel("resources/models/melona/melona.json"));
models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json"));
models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json"));
models.add(ModelLoader.LoadModel("resources/models/Corvette/corvetteclass.json"));
for(int i = 0; i < 0; i++) {
CubeActors.add(new Actor("AdvancedModel" + i, models.get((int)Math.round(Math.min(Math.max(Math.random() *(Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500))));
angles.add((float)(Math.random() * 360));
rotatingAngles.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2)));
Velocities.add(new Vector3f((float)(-2 + Math.random()*4), -2 + (float)(Math.random()*4), -2 + (float)(Math.random()*4)));
}
CubeActors.forEach(scene::AddActor);
List<MaterialData> materials = new ArrayList<>();
materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/corvetteclass_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json"));
materials.addAll(SponzaMaterial);
materials.addAll(MusicParticleMat);
materials.addAll(SponzaMaterial1);
@ -134,6 +116,21 @@ public class GameCore implements GameLogic {
List<GuiTexture> guiTextures = new ArrayList<>();
guiTextures.add(guiTexture);
scene.GetLightingManager().GetAmbientLightColour().set(0.9f, 0.9f, 1.0f);
scene.GetLightingManager().SetAmbientLightIntensity(0.1f);
SkyLight = new Light(new Vector3f(0.4f, 0.7f, 1.5f),new Vector3f(0.0f, -1.0f, 0.0f), true, 1.0f);
List<ILight> lights = new ArrayList<>();
lights.add(new Light(new Vector3f(3.0f,2.75f,0.0f),new Vector3f(35.0f, 150.0f, -42.0f),false,100.0f));
lights.add(new Light(new Vector3f(0.0f,3.0f,0.0f),new Vector3f(40.0f, 155.0f, -35.0f),false,20.0f));
lights.add(SkyLight);
ILight[] lightArr = new ILight[lights.size()];
lightArr = lights.toArray(lightArr);
scene.GetLightingManager().AddLights(lightArr);
InitiateAudio(engineInstance);
return new InitData(models,materials,guiTextures);
@ -163,7 +160,7 @@ public class GameCore implements GameLogic {
@Override
public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
float Multiplier = MOUSE_SENSITIVITY;
Scene scene = engineInstance.scene();
IScene scene = engineInstance.scene();
Camera camera = scene.GetCamera();
Window window = engineInstance.window();
@ -205,7 +202,7 @@ public class GameCore implements GameLogic {
@Override
public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
Scene scene = engineInstance.scene();
IScene scene = engineInstance.scene();
Window window = engineInstance.window();
KeyboardInput input = window.getKeyboardInput();
@ -303,7 +300,7 @@ public class GameCore implements GameLogic {
}
Ticks++;
if(Ticks == 1000){
engineInstance.scene().StartCameraTrack("Default","Second",24000);
// engineInstance.scene().StartCameraTrack("Default","Second",24000);
}
for(int i = 0; i < entities.size(); i++){
JackOfAllTradesActor entity = entities.get(i);
@ -315,24 +312,24 @@ public class GameCore implements GameLogic {
public void SecondUpdate(EngineInstance engineInstance) {
SettingPerformanceMetrics.clear();
List<String[]> Metrics = new ArrayList<>();
String[] SceneDetails = new String[8];
String[] ISceneDetails = new String[8];
Vector3f Position = engineInstance.scene().GetCamera().GetPosition();
Vector3f Rotation = engineInstance.scene().GetCamera().GetRotation();
SceneDetails[0] = String.format("INSTANCE INFORMATION: ");
SceneDetails[1] = String.format(" Camera Position: X: %.2f Y: %.2f Z: %.2f",Position.x ,Position.y ,Position.z);
SceneDetails[2] = String.format(" Camera Rotation: X: %.2f° Y: %.2f° Z: %.2f°",Rotation.x *EngineConfig.RadToDeg,Rotation.y *EngineConfig.RadToDeg ,Rotation.z *EngineConfig.RadToDeg);
SceneDetails[3] = String.format(" Anti Aliasing: " + EngineConfig.getInstance().RenderAAType().name());
SceneDetails[4] = String.format(" Renderer: " + (PrimaryRuntime.GetRenderThread().GetRenderer().GetDeferred() ? " Deferred" : "Forward"));
SceneDetails[5] = String.format(" Pipeline: " + (ForwardSceneRender.DualPassRendering() ? " Dual Pass" : "Single Pass"));
SceneDetails[6] = String.format(" AlphaToCoverage: " + EngineConfig.getInstance().AlphaToCoverage());
SceneDetails[7] = String.format(" FOV: %.2f°",(EngineConfig.getInstance().GetFOV()*EngineConfig.RadToDeg));
ISceneDetails[0] = String.format("INSTANCE INFORMATION: ");
ISceneDetails[1] = String.format(" Camera Position: X: %.2f Y: %.2f Z: %.2f",Position.x ,Position.y ,Position.z);
ISceneDetails[2] = String.format(" Camera Rotation: X: %.2f° Y: %.2f° Z: %.2f°",Rotation.x *EngineConfig.RadToDeg,Rotation.y *EngineConfig.RadToDeg ,Rotation.z *EngineConfig.RadToDeg);
ISceneDetails[3] = String.format(" Anti Aliasing: " + EngineConfig.getInstance().RenderAAType().name());
ISceneDetails[4] = String.format(" Renderer: " + (PrimaryRuntime.GetRenderThread().GetRenderer().GetDeferred() ? " Deferred" : "Forward"));
ISceneDetails[5] = String.format(" Pipeline: " + (ForwardSceneRender.DualPassRendering() ? " Dual Pass" : "Single Pass"));
ISceneDetails[6] = String.format(" AlphaToCoverage: " + EngineConfig.getInstance().AlphaToCoverage());
ISceneDetails[7] = String.format(" FOV: %.2f°",(EngineConfig.getInstance().GetFOV()*EngineConfig.RadToDeg));
String[] DeviceInfo = new String[5];
DeviceInfo[0] = String.format("SYSTEM INFORMATION: ");
DeviceInfo[1] = String.format(" CPU: " + EngineConfig.getInstance().GetCPUDetails());
DeviceInfo[2] = String.format(" RAM: " + CPUMonitor.RamSize);
DeviceInfo[3] = String.format(" GPU: " + EngineConfig.getInstance().GetGPU());
DeviceInfo[4] = String.format(" VRAM: " + GPUProfiler.GetVramCapacity());
Metrics.add(SceneDetails);
Metrics.add(ISceneDetails);
Metrics.add(DeviceInfo);
SettingPerformanceMetrics.addAll(Metrics);
SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetMemoryProfiling());

View file

@ -0,0 +1,15 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import org.joml.Vector3f;
public interface ILight {
public Vector3f GetColour();
public float GetIntensity();
public Vector3f GetPosition();
public boolean IsDirectional();
public void SetIntensity(float intensity);
public void SetColour(Vector3f Colour);
public void SetPositon(float Position);
public void SetDirectional(boolean Directional);
}

View file

@ -0,0 +1,34 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D;
import java.util.List;
import java.util.Map;
public interface IScene {
public void CameraTick(long FrameDiffNanoSeconds);
public Map<String, CameraFrame> GetCameraFrameReg();
public CameraFrame GetCameraFrame(String Name);
public Scene AddCameraFrame(String Name, CameraFrame frame);
public void StartCameraTrack(String StartFrame, String EndFrame, int TickAmount);
public void SetActiveCameraFrame(String frameName);
public Camera GetCamera();
public void AddActor(Actor NewActor);
public List<Actor> GetActors();
public Project3D GetProjection();
public void RemoveAllActors();
public void RemoveActor(Actor actor);
public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds);
public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds);
public void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds);
public void SecondUpdate(EngineInstance engineInstance);
public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds);
public void RenderGUIs(EngineInstance engineInstance, long frameTimeNS, GameCore parent);
public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds);
public String GetActiveCameraFrame();
public void SetUpAudio(EngineInstance engineInstance);
public ISceneLightingManager GetLightingManager();
}

View file

@ -0,0 +1,14 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import org.joml.Vector3f;
public interface ISceneLightingManager {
public Vector3f GetAmbientLightColour();
public float GetAmbientLightIntensity();
public ILight[] GetLights();
public void SetAmbientLightIntensity(float Intensity);
public void SetAmbientLightColour(Vector3f Colour);
public void SetLights(ILight[] lights);
public void AddLight(ILight light);
public void AddLights(ILight[] lights);
}

View file

@ -44,7 +44,7 @@ public class JackOfAllTradesActor extends Actor {
return this;
}
public void tick(Scene scene){
public void tick(IScene scene){
List<Integer> ParticlesToDelete = new ArrayList<>();
if((int)(Math.random() * 20) == 0){
ParticleActor particle = new ParticleActor("particle" + particleActors.size(), Particle.ID(), new Vector3f(GetPosition()),new Vector3f(1,1,1),0,new Vector3f(-1f + (float)Math.random() * 2,-1f + (float)Math.random() * 2,-1f + (float)Math.random() * 2),0.0005f,5000);

View file

@ -0,0 +1,58 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import org.joml.Vector3f;
public class Light implements ILight{
private final Vector3f Colour;
private final Vector3f Position;
private boolean Directional;
private float Intensity;
public Light(Vector3f Colour, Vector3f Position, boolean Directional, float Intensity){
this.Colour = Colour;
this.Position = Position;
this.Directional = Directional;
this.Intensity = Intensity;
}
@Override
public Vector3f GetColour() {
return Colour;
}
@Override
public float GetIntensity() {
return Intensity;
}
@Override
public Vector3f GetPosition() {
return Position;
}
@Override
public boolean IsDirectional() {
return Directional;
}
@Override
public void SetIntensity(float intensity) {
this.Intensity = intensity;
}
@Override
public void SetColour(Vector3f Colour) {
this.Colour.set(new Vector3f(Colour));
}
@Override
public void SetPositon(float Position) {
this.Position.set(new Vector3f(Position));
}
@Override
public void SetDirectional(boolean Directional) {
this.Directional = Directional;
}
}

View file

@ -1,26 +1,49 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput;
import net.halbear.Terrain4J.EngineCore.Input.MouseListener;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.PerformanceOverlay;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D;
import org.joml.Vector2f;
import org.joml.Vector3f;
import java.util.*;
public class Scene {
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_A;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_D;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_S;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_W;
public class Scene implements IScene {
private static final float MOUSE_SENSITIVITY = 0.1f;
private static final float MOVEMENT_SPEED = 0.025f;
private final List<Actor> Actors;
private final Map<String, CameraFrame> CameraFrames;
private final Project3D Projection;
private final Camera camera;
private String ActiveCameraFrame = "NO_FRAME";
private String SetCameraFrame = "NO_FRAME";
private boolean TransitionCameraFrame = false;
public String ActiveCameraFrame = "NO_FRAME";
public String SetCameraFrame = "NO_FRAME";
public boolean TransitionCameraFrame = false;
private CameraFrame LastCameraFrame;
private int TotalTransitionTicks = 1000;
private float CurrentTransitionTick = 0;
public int TotalTransitionTicks = 1000;
public float CurrentTransitionTick = 0;
private Vector2f LastMousePos = new Vector2f(0,0);
private final ISceneLightingManager lightingManager;
public List<String> ActiveGUIs = new ArrayList<>();
public Map<String, GUIOverlay> GUIReg = new HashMap<>();
public Scene(Window window) {
lightingManager = new SceneLightingManager(10,new Vector3f(1f,1f,1f), 0.5f);
Actors = new ArrayList<>();
CameraFrames = new HashMap<>();
var EngConfig = EngineConfig.getInstance();
@ -28,8 +51,12 @@ public class Scene {
LastCameraFrame = new CameraFrame(camera.GetPosition(),camera.GetRotation(),camera.GetFOV(), "NO_FRAME");
Projection = new Project3D(camera.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(),
window.getWidth(), window.getHeight());
GUIReg.put("PerformanceOverlay",new PerformanceOverlay());
ActiveGUIs.add("PerformanceOverlay");
}
public ISceneLightingManager GetLightingManager(){return lightingManager;}
public void CameraTick(long FrameDiffNanoSeconds){
float FrameTimeMS = FrameDiffNanoSeconds/1000000.0f;
float DeltaTime = FrameTimeMS/(60.0f/240.0f);
@ -39,7 +66,7 @@ public class Scene {
Vector3f StartRot = LastCameraFrame.Rotation();
CameraFrame StartFrame;
if(CameraFrames.containsKey(ActiveCameraFrame)){
StartFrame = CameraFrames.get(ActiveCameraFrame);
StartFrame = CameraFrames.get(ActiveCameraFrame);
} else StartFrame = new CameraFrame(StartPos,StartRot,StartFOV, "NO_FRAME");
float EndFOV = camera.GetFOV();
Vector3f EndPos = camera.GetPosition();
@ -85,10 +112,110 @@ public class Scene {
SetCameraFrame = EndFrame;
}
public void SetActiveCameraFrame(String frameName){SetCameraFrame = frameName;}
public String GetActiveCameraFrame(){return ActiveCameraFrame;}
public Camera GetCamera(){return camera;}
public void AddActor(Actor NewActor){Actors.add(NewActor);}
public List<Actor> GetActors(){return Actors;}
public Project3D GetProjection(){return Projection;}
public void RemoveAllActors(){Actors.clear();}
public void RemoveActor(Actor actor){Actors.removeIf(Actor->Actor.GetID().equals(actor.GetID()));}
public void SetUpAudio(EngineInstance engineInstance){
}
@Override
public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
IScene scene = engineInstance.scene();
Window window = engineInstance.window();
KeyboardInput input = window.getKeyboardInput();
float MovementDist = (float)(FrameDiffNanoSeconds / 1000000L) * MOVEMENT_SPEED;
Camera camera = scene.GetCamera();
if(input.keyPressed(GLFW_KEY_1)){
}
if(input.keyPressed(GLFW_KEY_2)){
}
if(input.keyPressed(GLFW_KEY_3)){
}
if(input.keyPressed(GLFW_KEY_W)){
camera.MoveForward(MovementDist);
}
if(input.keyPressed(GLFW_KEY_S)){
camera.MoveBackward(MovementDist);
}
if(input.keyPressed(GLFW_KEY_A)){
camera.MoveLeft(MovementDist);
}
if(input.keyPressed(GLFW_KEY_D)){
camera.MoveRight(MovementDist);
}
if(input.keyPressed(GLFW_KEY_SPACE)){
camera.MoveUp(MovementDist);
}
if(input.keyPressed(GLFW_KEY_LEFT_SHIFT)){
camera.MoveDown(MovementDist);
}
if(input.keyPressed(GLFW_KEY_LEFT_CONTROL)){
camera.Sprint(true);
} else camera.Sprint(false);
}
@Override
public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
}
@Override
public void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
}
@Override
public void SecondUpdate(EngineInstance engineInstance) {
}
@Override
public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
CameraTick(FrameDiffNanoSeconds);
}
@Override
public void RenderGUIs(EngineInstance engineInstance, long frameTimeNS, GameCore parent) {
List<String> ActiveGuis = new ArrayList<>(ActiveGUIs);
ActiveGuis.forEach(gui->{
if(GUIReg.containsKey(gui)){
GUIReg.get(gui).RenderGUI(engineInstance,frameTimeNS,parent);
}
});
}
@Override
public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
float Multiplier = MOUSE_SENSITIVITY;
IScene scene = engineInstance.scene();
Camera camera = scene.GetCamera();
Window window = engineInstance.window();
MouseListener MouseInput = window.getMouseInput();
Vector2f CurrentMousePos = window.getMouseInput().getCurrentPos();
Vector2f deltaPos = new Vector2f(0,0);
deltaPos.x = 0;
deltaPos.y = 0;
if (LastMousePos.x >= 0 && LastMousePos.y >= 0 && window.getMouseInput().IsWindowFocused()) {
deltaPos.x = CurrentMousePos.x - LastMousePos.x;
deltaPos.y = CurrentMousePos.y - LastMousePos.y;
}
LastMousePos.x = CurrentMousePos.x;
LastMousePos.y = CurrentMousePos.y;
if(MouseInput.isRightButtonPressed()){
camera.AddRotation((float)Math.toRadians(-deltaPos.y * Multiplier),(float)Math.toRadians(-deltaPos.x * Multiplier),0);
}
engineInstance.audioManager().UpdateListenerPosition(camera);
}
}

View file

@ -0,0 +1,84 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import org.joml.Vector3f;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SceneLightingManager implements ISceneLightingManager {
public static int MaxLights;
private Vector3f AmbientLightingColour;
private float AmbientLightIntensity;
private List<ILight> LightingList;
public SceneLightingManager(int MaxLights,Vector3f AmbientLightingColour, float AmbientLightIntensity){
this.MaxLights = MaxLights;
this.AmbientLightingColour = new Vector3f(AmbientLightingColour);
this.AmbientLightIntensity = AmbientLightIntensity;
LightingList = new ArrayList<>();
}
public static int GetMaxLights() {
return MaxLights;
}
public static void SetMaxLights(int MaxLights) {
MaxLights = MaxLights;
}
@Override
public Vector3f GetAmbientLightColour() {
return AmbientLightingColour;
}
@Override
public float GetAmbientLightIntensity() {
return AmbientLightIntensity;
}
@Override
public ILight[] GetLights() {
return LightingList.toArray(new ILight[0]);
}
@Override
public void SetAmbientLightIntensity(float Intensity) {
this.AmbientLightIntensity = Intensity;
}
@Override
public void SetAmbientLightColour(Vector3f Colour) {
this.AmbientLightingColour = new Vector3f(Colour);
}
@Override
public void SetLights(ILight[] lights) {
if(LightingList == null){
LightingList = new ArrayList<>();
}
LightingList.clear();
AddLights(lights);
}
@Override
public void AddLights(ILight[] lights) {
if(LightingList == null){
LightingList = new ArrayList<>();
}
LightingList.addAll(Arrays.asList(lights));
if(LightingList.size() > MaxLights){
List<ILight> cutDown = new ArrayList<>();
cutDown.addAll(LightingList.subList(0,MaxLights));
LightingList = new ArrayList<>(cutDown);
}
}
@Override
public void AddLight(ILight light) {
if(LightingList == null){
LightingList = new ArrayList<>();
}
if(LightingList.size() < MaxLights)LightingList.add(light);
}
}

View file

@ -82,6 +82,7 @@ public class GuiRenderer {
KeyboardInput keyboardInput=engineInstance.window().getKeyboardInput();
keyboardInput.setCharCallBack(new GuiUtils.CharacterCallBack());
keyboardInput.AddKeyCallBack(new GuiUtils.KeyCallBack());
Logger.debug("GUI Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline());
GuiTexturesMap = new HashMap<>();
}
@ -98,7 +99,7 @@ public class GuiRenderer {
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){
var VertexBufferStructure = new GuiVertexBufferStruct();
var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStructure.GetVertexInput(),
PostProcess.COLOUR_FORMAT)
new int[]{PostProcess.COLOUR_FORMAT})
.SetPushConstantRanges(
new PushConstantsRange[]{
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.VEC2_SIZE)

View file

@ -1,7 +1,12 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DeferredRendering;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.Scene.ILight;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Light;
import net.halbear.Terrain4J.EngineCore.Main.Scene.SceneLightingManager;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.EmptyVertexBufferStruct;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment;
@ -13,11 +18,15 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuf
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.shaderc.Shaderc;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.ByteBuffer;
import java.nio.LongBuffer;
import java.util.ArrayList;
import java.util.Arrays;
@ -29,6 +38,8 @@ import static org.lwjgl.vulkan.VK13.*;
public class LightRenderer {
private static final int COLOUR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
private static final String DESC_ID_ATT = "LIGHT_DESC_ID_ATT";
private static final String DESC_ID_LIGHTS = "LIGHT_DESC_ID_LIGHTS";
private static final String DESC_ID_SCENE = "LIGHT_DESC_ID_SCENE ";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_frag.glsl";
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_vertex.glsl";
@ -41,6 +52,10 @@ public class LightRenderer {
private Attachment AttachmentColour;
private VkRenderingAttachmentInfo.Buffer AttachmentInfoColour;
private VkRenderingInfo RenderInfo;
private final VulkanBuffer[] LightBuffer;
private final VulkanBuffer[] SceneBuffer;
private final DescriptorSetLayout SceneDescriptorSetLayout;
private final DescriptorSetLayout StorageDescriptorSetLayout;
public LightRenderer(VulkanContext VkCtx, List<Attachment> attachments){
ClearValueColour = VkClearValue.calloc().color(
@ -64,7 +79,21 @@ public class LightRenderer {
CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, attachments, textureSampler);
pipeline = createPipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout});
StorageDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1,
VK_SHADER_STAGE_FRAGMENT_BIT));
long buffSize = (long) (VulkanUtils.VEC3_SIZE * 2 + VulkanUtils.INT_SIZE + VulkanUtils.FLOAT_SIZE) * SceneLightingManager.MaxLights;
LightBuffer = VulkanUtils.CreateHostVisibleBuffers(VkCtx, buffSize, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, DESC_ID_LIGHTS, StorageDescriptorSetLayout);
SceneDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, 1,
VK_SHADER_STAGE_FRAGMENT_BIT));
buffSize = VulkanUtils.VEC3_SIZE * 2 + VulkanUtils.FLOAT_SIZE + VulkanUtils.INT_SIZE;
SceneBuffer = VulkanUtils.CreateHostVisibleBuffers(VkCtx, buffSize, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESC_ID_SCENE, SceneDescriptorSetLayout);
pipeline = createPipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, StorageDescriptorSetLayout,
SceneDescriptorSetLayout});
Logger.debug("Light Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline());
Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VkCtx));
}
@ -97,9 +126,12 @@ public class LightRenderer {
private static Pipeline createPipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descSetLayouts) {
var vtxBuffStruct = new EmptyVertexBufferStruct();
var buildInfo = new PipelineBuildInfo(shaderModules, vtxBuffStruct.GetVertexInput(), COLOUR_FORMAT)
var buildInfo = new PipelineBuildInfo(shaderModules, vtxBuffStruct.GetVertexInput(),new int[]{COLOUR_FORMAT})
.SetDescriptorSetLayouts(descSetLayouts)
.BlendingIsUsed(true);
.BlendingIsUsed(true)
.SetBlendingMethod(1)
.SetDepthWrite(false)
.SetDepthTest(false);
var pipeline = new DefaultPipeline(VkCtx, buildInfo);
vtxBuffStruct.CleanUp();
return pipeline;
@ -134,7 +166,7 @@ public class LightRenderer {
}
public void render(VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments) {
public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments,int CurrentFrame) {
try (var stack = MemoryStack.stackPush()) {
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
@ -145,6 +177,7 @@ public class LightRenderer {
VK_IMAGE_ASPECT_COLOR_BIT);
List<Attachment> attachments = mrtAttachments.GetColourAttachments();
// Logger.debug("Colour Attachments -> \n1: [{}]\n 2:[{}] \n3:[{}]\n 4:[{}]",attachments.get(0),attachments.get(1),attachments.get(2),attachments.get(3));
int numAttachments = attachments.size();
for (int i = 0; i < numAttachments; i++) {
Attachment attachment = attachments.get(i);
@ -158,12 +191,13 @@ public class LightRenderer {
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
VK_IMAGE_ASPECT_DEPTH_BIT);
vkCmdBeginRendering(cmdHandle, RenderInfo);
vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipeline());
Image ColourImage = AttachmentColour.GetVkImage();
int width = ColourImage.GetWidth();
int height = ColourImage.GetHeight();
@ -182,8 +216,13 @@ public class LightRenderer {
vkCmdSetScissor(cmdHandle, 0, scissor);
DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator();
LongBuffer descriptorSets = stack.mallocLong(1)
.put(0, descAllocator.GetDescriptorSet(DESC_ID_ATT).GetVkDescriptorSet());
LongBuffer descriptorSets = stack.mallocLong(3)
.put(0, descAllocator.GetDescriptorSet(DESC_ID_ATT).GetVkDescriptorSet())
.put(1, descAllocator.GetDescriptorSet(DESC_ID_LIGHTS, CurrentFrame).GetVkDescriptorSet())
.put(2, descAllocator.GetDescriptorSet(DESC_ID_SCENE, CurrentFrame).GetVkDescriptorSet());
IScene scene = engineInstance.scene();
UpdateSceneInfo(VkCtx, scene, CurrentFrame);
UpdateLights(VkCtx, scene, CurrentFrame);
vkCmdBindDescriptorSets(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline.GetVulkanPipelineLayout(), 0, descriptorSets, null);
@ -193,6 +232,48 @@ public class LightRenderer {
}
}
public void UpdateSceneInfo(VulkanContext VkCtx, IScene scene, int CurrentFrame){
VulkanBuffer buffer = SceneBuffer[CurrentFrame];
long MappedMemory = buffer.MapMemory(VkCtx);
ByteBuffer dataBuffer = MemoryUtil.memByteBuffer(MappedMemory, (int)buffer.GetRequestedSize());
int Offset = 0;
scene.GetCamera().GetPosition().get(Offset,dataBuffer);
Offset += VulkanUtils.VEC3_SIZE;
dataBuffer.putFloat(Offset, scene.GetLightingManager().GetAmbientLightIntensity());
Offset += VulkanUtils.FLOAT_SIZE;
scene.GetLightingManager().GetAmbientLightColour().get(Offset, dataBuffer);
Offset += VulkanUtils.VEC3_SIZE;
ILight[] lights = scene.GetLightingManager().GetLights();
int LightCount = lights != null ? lights.length : 0;
dataBuffer.putInt(Offset, LightCount);
buffer.UnMapMemory(VkCtx);
}
public void UpdateLights(VulkanContext VkCtx, IScene scene, int CurrentFrame){
ILight[] lights = scene.GetLightingManager().GetLights();
VulkanBuffer buffer = LightBuffer[CurrentFrame];
long MappedMemory = buffer.MapMemory(VkCtx);
ByteBuffer dataBuffer = MemoryUtil.memByteBuffer(MappedMemory, (int)buffer.GetRequestedSize());
int Offset = 0;
int lightCount = lights != null ? lights.length : 0;
for(int i = 0; i < lightCount; i++){
ILight light = lights[i];
light.GetPosition().get(Offset, dataBuffer);
Offset += VulkanUtils.VEC3_SIZE;
dataBuffer.putInt(Offset, light.IsDirectional() ? 1 : 0);
Offset += VulkanUtils.INT_SIZE;
dataBuffer.putFloat(Offset, light.GetIntensity());
Offset += VulkanUtils.FLOAT_SIZE;
light.GetColour().get(Offset, dataBuffer);
Offset += VulkanUtils.VEC3_SIZE;
}
buffer.UnMapMemory(VkCtx);
}
public void resize(VulkanContext VkCtx, List<Attachment> attachments) {
RenderInfo.free();
AttachmentInfoColour.free();
@ -209,6 +290,10 @@ public class LightRenderer {
}
public void cleanup(VulkanContext VkCtx) {
StorageDescriptorSetLayout.CleanUp(VkCtx);
Arrays.asList(LightBuffer).forEach(b -> b.cleanup(VkCtx));
SceneDescriptorSetLayout.CleanUp(VkCtx);
Arrays.asList(SceneBuffer).forEach(b -> b.cleanup(VkCtx));
pipeline.CleanUp(VkCtx);
AttachmentDescriptorSetLayout.CleanUp(VkCtx);
textureSampler.CleanUp(VkCtx);

View file

@ -13,6 +13,9 @@ import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
public class MultiRenderTargetAttachments {
public static final int ALBEDO_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT;
public static final int NORMAL_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
public static final int PBR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
public static final int POSITION_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
private final List<Attachment> ColourAttachments;
private final Attachment DepthAttachment;
private final int Height;
@ -24,9 +27,18 @@ public class MultiRenderTargetAttachments {
Height = extent2D.height();
ColourAttachments = new ArrayList<>();
var AlbedoAttachment = new Attachment(VkCtx, Width, Height, ALBEDO_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
ColourAttachments.add(AlbedoAttachment);
//Position
var Attachment = new Attachment(VkCtx, Width, Height, POSITION_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
ColourAttachments.add(Attachment);
//albedo
Attachment = new Attachment(VkCtx, Width, Height, ALBEDO_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
ColourAttachments.add(Attachment);
//Normals
Attachment = new Attachment(VkCtx, Width, Height, NORMAL_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
ColourAttachments.add(Attachment);
//PBR
Attachment = new Attachment(VkCtx, Width, Height, PBR_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
ColourAttachments.add(Attachment);
DepthAttachment = new Attachment(VkCtx, Width, Height, DEPTH_FORMAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
}

View file

@ -9,6 +9,8 @@ public class EmptyVertexBufferStruct {
public EmptyVertexBufferStruct(){
VertexInput = VkPipelineVertexInputStateCreateInfo.calloc();
VertexInput.sType$Default();
VertexInput .pVertexBindingDescriptions(null)
.pVertexAttributeDescriptions(null);
}
public void CleanUp(){VertexInput.free();}

View file

@ -88,7 +88,7 @@ public class DefaultPipeline implements Pipeline {
if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){
DepthStencil = VkPipelineDepthStencilStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO)
.depthTestEnable(true)
.depthTestEnable(BuildInfo.GetDepthTest())
.depthWriteEnable(BuildInfo.performDepthWrite())
.depthCompareOp(VK_COMPARE_OP_GREATER_OR_EQUAL)
.depthBoundsTestEnable(false)
@ -123,32 +123,38 @@ public class DefaultPipeline implements Pipeline {
for(int i = 0; i < LayoutCount; i++){
ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout());
}
var BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(1,MemStack)
.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)
.blendEnable(BuildInfo.BlendingUsed());
if(BuildInfo.BlendingUsed()){
BlendAttributeState.get(0).colorBlendOp(VK_BLEND_OP_ADD)
.alphaBlendOp(VK_BLEND_OP_ADD)
.srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA)
.dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
.srcAlphaBlendFactor(VK_BLEND_FACTOR_ONE)
.dstAlphaBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
int[] ColourFormats = BuildInfo.GetColourFormat();
int ColourFormatCount = ColourFormats.length;
IntBuffer ColourFormatsBuffer = MemStack.mallocInt(ColourFormatCount);
ColourFormatsBuffer.put(0,ColourFormats);
var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack)
.sType$Default()
.colorAttachmentCount(ColourFormatCount)
.pColorAttachmentFormats(ColourFormatsBuffer);
if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());}
VkPipelineColorBlendAttachmentState.Buffer BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(ColourFormatCount,MemStack);
for(int i = 0; i < ColourFormatCount; i++){
BlendAttributeState.get(i).colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)
.blendEnable(BuildInfo.BlendingUsed());
if(BuildInfo.BlendingUsed()) {
BlendAttributeState.get(i).colorBlendOp(VK_BLEND_OP_ADD)
.alphaBlendOp(VK_BLEND_OP_ADD)
.srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA)
.dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
.srcAlphaBlendFactor(BuildInfo.GetBlendingMethod() == 0 ? VK_BLEND_FACTOR_ONE : VK_BLEND_FACTOR_SRC_ALPHA)
.dstAlphaBlendFactor(BuildInfo.GetBlendingMethod() == 0 ? VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA : VK_BLEND_FACTOR_ZERO);
}
}
var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack)
.sType$Default()
.pAttachments(BlendAttributeState);
IntBuffer ColourFormats = MemStack.mallocInt(1);
ColourFormats.put(0,BuildInfo.GetColourFormat());
var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack)
.sType$Default()
.colorAttachmentCount(1)
.pColorAttachmentFormats(ColourFormats);
if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());}
var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pSetLayouts(ppLayout)
@ -160,7 +166,6 @@ public class DefaultPipeline implements Pipeline {
var PipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1,MemStack)
.sType$Default()
.renderPass(VK_NULL_HANDLE)
.pStages(ShaderStages)
.pVertexInputState(BuildInfo.GetVertexInputStateCreateInfo())
.pInputAssemblyState(AssemblyStateCreateInfo)

View file

@ -22,7 +22,7 @@ public class Attachment {
}
if((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0){
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT);
AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
DepthAttachment = true;
}
VkImage = new Image(VkCtx, ImageData);

View file

@ -89,7 +89,7 @@ public class Image {
MipMapLevels = 1;
SampleCount = 1;
ArrayLayers = 1;
MemoryUsage = 0;
MemoryUsage = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
}
public ImageData MemoryUsage(int memoryUsage){
this.MemoryUsage = memoryUsage;

View file

@ -61,7 +61,8 @@ public class Texture {
}
public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data){
int Size = data.remaining();
stgBuffer = new VulkanBuffer(VkCtx, Size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
stgBuffer = new VulkanBuffer(VkCtx, Size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
long MappedMemory = stgBuffer.MapMemory(VkCtx);
ByteBuffer buffer = MemoryUtil.memByteBuffer(MappedMemory, (int) stgBuffer.GetRequestedSize());
buffer.put(data);
@ -69,13 +70,35 @@ public class Texture {
stgBuffer.UnMapMemory(VkCtx);
}
private void RecordImageTransition(MemoryStack stack, CommandBuffer cmd) {
var imageBarrier = VkImageMemoryBarrier2.calloc(1, stack)
.sType$Default()
.oldLayout(VK_IMAGE_LAYOUT_UNDEFINED)
.newLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
.srcStageMask(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
.dstStageMask(VK_PIPELINE_STAGE_TRANSFER_BIT)
.srcAccessMask(0)
.dstAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT)
.subresourceRange(it -> it
.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT)
.baseMipLevel(0)
.levelCount(image.GetMipLevels())
.baseArrayLayer(0)
.layerCount(1))
.image(image.getVulkanImage());
VkDependencyInfo depInfo = VkDependencyInfo.calloc(stack)
.sType$Default()
.pImageMemoryBarriers(imageBarrier);
vkCmdPipelineBarrier2(cmd.GetVulkanCommandBuffer(), depInfo);
}
public void RecordTextureTransition(CommandBuffer commandBuffer){
if(stgBuffer != null && !RecordedTransition){
RecordedTransition = true;
try(var MemStack = MemoryStack.stackPush()){
VulkanUtils.ImageBarrier(MemStack, commandBuffer.GetVulkanCommandBuffer(), image.getVulkanImage(),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_2_NONE, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
RecordImageTransition(MemStack, commandBuffer);
RecordCopyBuffer(MemStack, commandBuffer, stgBuffer);
RecordGenerateMipMaps(MemStack, commandBuffer);
}

View file

@ -18,7 +18,7 @@ import java.util.UUID;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB;
public class TextureCache {
public static final int MAX_TEXTURES = 64;
public static final int MAX_TEXTURES = 128;
private final IndexedLinkedHashMap<String, Texture> TextureMap;
private final List<String> ActualTextures;

View file

@ -9,7 +9,6 @@ import org.lwjgl.vulkan.VkPushConstantRange;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_UNDEFINED;
public class PipelineBuildInfo {
private final int ColourFormat;
private final ShaderModule[] ShaderModules;
private final VkPipelineVertexInputStateCreateInfo VertexInput;
private int DepthFormat;
@ -17,17 +16,26 @@ public class PipelineBuildInfo {
private DescriptorSetLayout[] DescriptorSetLayouts;
private boolean useBlend;
private boolean DepthWrite = true;
private boolean DepthTest = true;
private boolean DualPass = false;
private boolean alphaToCoverage = false;
private final int[] ColourFormats;
private int BlendingMethod = 0;
public PipelineBuildInfo(ShaderModule[] shaderModules, VkPipelineVertexInputStateCreateInfo VertexInput, int ColourFormat){
this.ColourFormat = ColourFormat;
public PipelineBuildInfo(ShaderModule[] shaderModules, VkPipelineVertexInputStateCreateInfo VertexInput, int[] ColourFormat){
this.ColourFormats = ColourFormat;
this.ShaderModules = shaderModules;
this.VertexInput = VertexInput;
DepthFormat = VK_FORMAT_UNDEFINED;
useBlend = true;
}
public PipelineBuildInfo SetBlendingMethod(int in){
BlendingMethod = in;
return this;
}
public int GetBlendingMethod(){return BlendingMethod;}
public PipelineBuildInfo SetAlphaToCoverage(boolean alphaToCoverage){
this.alphaToCoverage = alphaToCoverage;
return this;
@ -40,6 +48,11 @@ public class PipelineBuildInfo {
this.DepthWrite = DepthWrite;
return this;
}
public PipelineBuildInfo SetDepthTest(boolean DepthTest){
this.DepthTest = DepthTest;
return this;
}
public boolean GetDepthTest(){return DepthTest;}
public boolean performDepthWrite(){return DepthWrite;}
public boolean PassTwice(){return DualPass;}
@ -71,7 +84,7 @@ public class PipelineBuildInfo {
public PushConstantsRange[] GetPushConstantRanges(){return PushConstRanges;}
public int GetDepthFormat(){return DepthFormat;}
public int GetColourFormat(){return ColourFormat;}
public int[] GetColourFormat(){return ColourFormats;}
public ShaderModule[] GetShaderModules(){return ShaderModules;}
public VkPipelineVertexInputStateCreateInfo GetVertexInputStateCreateInfo(){return VertexInput;}
}

View file

@ -18,6 +18,7 @@ import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.shaderc.Shaderc;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.FloatBuffer;
import java.nio.LongBuffer;
@ -73,6 +74,7 @@ public class PostProcess {
pipeline = CreatePipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, FragmentUniformDescriptorSetLayout});
Arrays.asList(shaderModules).forEach(shader->shader.CleanUp(VkCtx));
Logger.debug("Post Process Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline());
}
private static Attachment CreateColourAttachment(VulkanContext VkCtx){
@ -93,7 +95,7 @@ public class PostProcess {
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){
var VertexBufferStruct = new EmptyVertexBufferStruct();
var BuildInfo = new PipelineBuildInfo(shaderModules,VertexBufferStruct.GetVertexInput(),COLOUR_FORMAT).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var BuildInfo = new PipelineBuildInfo(shaderModules,VertexBufferStruct.GetVertexInput(),new int[]{COLOUR_FORMAT}).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var PipeLine = new DefaultPipeline(VkCtx,BuildInfo);
VertexBufferStruct.CleanUp();
return PipeLine;

View file

@ -16,7 +16,7 @@ public class DescriptorSetLayout {
private final LayoutInformation[] LayoutInfos;
protected long VkDescriptorLayout;
public DescriptorSetLayout(VulkanContext VkCtx, LayoutInformation LayoutInfo){
this(VkCtx, new DescriptorSetLayout.LayoutInformation[]{LayoutInfo});
this(VkCtx, new LayoutInformation[]{LayoutInfo});
}
public DescriptorSetLayout(VulkanContext VkCtx, LayoutInformation[] LayoutInfos){
this.LayoutInfos = LayoutInfos;

View file

@ -5,12 +5,14 @@ import org.lwjgl.vulkan.VkPipelineVertexInputStateCreateInfo;
import org.lwjgl.vulkan.VkVertexInputAttributeDescription;
import org.lwjgl.vulkan.VkVertexInputBindingDescription;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R32G32_SFLOAT;
import static org.lwjgl.vulkan.VK13.VK_FORMAT_R32G32B32_SFLOAT;
import static org.lwjgl.vulkan.VK13.VK_VERTEX_INPUT_RATE_VERTEX;
public class VertexBufferStructure {
public static final int TEXT_COORD_COMPONENTS = 2;
private static final int NUMBER_OF_ATTRIBUTES = 2;
public static final int NORMAL_COMPONENTS = 3;
private static final int NUMBER_OF_ATTRIBUTES = 5;
private final int POSITION_COMPONENTS = 3;
private final VkPipelineVertexInputStateCreateInfo VertexInput;
@ -32,12 +34,36 @@ public class VertexBufferStructure {
.offset(Offset);
i++;
Offset += POSITION_COMPONENTS * VulkanUtils.FLOAT_SIZE;
//texture coordinates
//Normals
VertexInputAttributes.get(i)
.binding(0)
.location(i)
.format(VK_FORMAT_R32G32B32_SFLOAT)
.offset(Offset);
i++;
Offset += NORMAL_COMPONENTS * VulkanUtils.FLOAT_SIZE;
//Tangents
VertexInputAttributes.get(i)
.binding(0)
.location(i)
.format(VK_FORMAT_R32G32B32_SFLOAT)
.offset(Offset);
i++;
Offset += NORMAL_COMPONENTS * VulkanUtils.FLOAT_SIZE;
//BiTangents
VertexInputAttributes.get(i)
.binding(0)
.location(i)
.format(VK_FORMAT_R32G32B32_SFLOAT)
.offset(Offset);
i++;
Offset += NORMAL_COMPONENTS * VulkanUtils.FLOAT_SIZE;
//texture coordinates
VertexInputAttributes.get(i)
.binding(0)
.location(i)
.format(VK_FORMAT_R32G32_SFLOAT)
.offset(Offset);
int Stride = Offset + TEXT_COORD_COMPONENTS * VulkanUtils.FLOAT_SIZE;
VertexInputBindings.get(0)

View file

@ -2,5 +2,5 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
import org.joml.Vector4f;
public record MaterialData(String ID, String TexturePath, Vector4f DiffuseColour) {
public record MaterialData(String ID, String TexturePath,String NormalTexturePath,String MetalRoughnessMap, Vector4f DiffuseColour,float Roughness, float Metallic) {
}

View file

@ -23,7 +23,7 @@ import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO;
import static org.lwjgl.vulkan.VK10.*;
public class MaterialsCache {
private static final int MATERIAL_SIZE = VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE * 4;
private static final int MATERIAL_SIZE = VulkanUtils.VEC4_SIZE * 3;
private final IndexedLinkedHashMap<String, VulkanMaterial> MaterialsMap;
private VulkanBuffer MaterialsBuffer;
@ -36,7 +36,8 @@ public class MaterialsCache {
int MaterialCount = Materials.size();
int BufferSize = MATERIAL_SIZE * MaterialCount;
var SrcBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
MaterialsBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
@ -53,6 +54,7 @@ public class MaterialsCache {
String TexturePath = Material.TexturePath();
boolean ValidTexture = TexturePath != null && !TexturePath.isEmpty();
boolean TransparentTexture;
Logger.debug("Material Texture Path -> [{}]",Material.TexturePath());
if(ValidTexture){
Texture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB);
if(newTexture == null) {
@ -67,18 +69,42 @@ public class MaterialsCache {
VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture);
MaterialsMap.put(newMaterial.ID(), newMaterial);
Logger.trace(Material.toString());
Material.DiffuseColour().get(Offset,data);
data.putInt(Offset + VulkanUtils.VEC4_SIZE, ValidTexture ? 1 : 0);
data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE, textureCache.GetPosition(TexturePath));
//pad data because the minimum size of data in the shader layout is a multiple of Vec4,
// compensate with 2 more as we only need 6 currently
data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE * 2,0);
data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE * 3,0);
Offset += MATERIAL_SIZE;
}
data.position(0);
SrcBuffer.Flush(VkCtx);
Material.DiffuseColour().get(Offset,data);
Offset += VulkanUtils.VEC4_SIZE;
data.putInt(Offset, ValidTexture ? 1 : 0);
Offset += VulkanUtils.INT_SIZE;
data.putInt(Offset, textureCache.GetPosition(TexturePath));
Offset += VulkanUtils.INT_SIZE;
String NormalMap = Material.NormalTexturePath();
boolean hasNormalMap = NormalMap != null && !NormalMap.isEmpty();
if(hasNormalMap){
textureCache.AddTexture(VkCtx,NormalMap,NormalMap,VK_FORMAT_R8G8B8A8_UNORM);
}
data.putInt(Offset, hasNormalMap ? 1 : 0);
Offset += VulkanUtils.INT_SIZE;
data.putInt(Offset, textureCache.GetPosition(NormalMap));
Offset += VulkanUtils.INT_SIZE;
String RoughnessMap = Material.MetalRoughnessMap();
boolean hasRoughness = RoughnessMap != null && !RoughnessMap.isEmpty();
if(hasRoughness){
textureCache.AddTexture(VkCtx,RoughnessMap,RoughnessMap,VK_FORMAT_R8G8B8A8_UNORM);
}
data.putInt(Offset, hasRoughness ? 1 : 0);
Offset += VulkanUtils.INT_SIZE;
data.putInt(Offset, textureCache.GetPosition(RoughnessMap));
Offset += VulkanUtils.INT_SIZE;
data.putFloat(Offset, Material.Roughness());
Offset += VulkanUtils.FLOAT_SIZE;
data.putFloat(Offset, Material.Metallic());
Offset += VulkanUtils.FLOAT_SIZE;
}
// data.position(0);
// SrcBuffer.Flush(VkCtx);
SrcBuffer.UnMapMemory(VkCtx);
transferBuffer.RecordTransferCommand(CmdBuffer);
CmdBuffer.EndRecording();

View file

@ -50,6 +50,7 @@ public class ModelsCache {
StagingBufferList.add(IndicesBuffers.SrcBuffer());
VerticesBuffers.RecordTransferCommand(Command);
IndicesBuffers.RecordTransferCommand(Command);
VulkanMesh VkMesh = new VulkanMesh(meshData.ID(), VerticesBuffers.DstBuffer(), IndicesBuffers.DstBuffer(),
meshData.IndexSize() / VulkanUtils.INT_SIZE, meshData.MaterialID());
VKModel.GetVkMeshList().add(VkMesh);
@ -65,43 +66,6 @@ public class ModelsCache {
}
}
private static TransferBuffer CreateVoxelIndicesBuffer(VulkanContext VkCtx, MeshData meshData, IntBuffer IndexBuffer) throws IOException{
int BufferSize = meshData.IndexSize();
var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
long MappedMemory = SrcBuffer.MapMemory(VkCtx);
IntBuffer data = MemoryUtil.memIntBuffer(MappedMemory,(int) SrcBuffer.GetRequestedSize());
IndexBuffer.rewind();
for(int i = 0; i < meshData.IndexSize(); i++){
data.put(IndexBuffer.get(meshData.OffsetIndex() + i));
}
SrcBuffer.UnMapMemory(VkCtx);
return new TransferBuffer(SrcBuffer,DstBuffer);
}
private static TransferBuffer CreateVoxelVerticesBuffer(VulkanContext VkCtx, MeshData meshData, FloatBuffer VertexBuffer) throws IOException {
Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize());
int BufferSize = meshData.VertexSize();
var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
if (BufferSize <= 0) {
Logger.error("Computed buffer allocation size cannot be 0. SrcBuffer -> [{}] DstBuffer -> [{}]",SrcBuffer,DstBuffer);
throw new RuntimeException("Computed buffer allocation size cannot be 0. SrcBuffer -> ["+SrcBuffer+"] DstBuffer -> ["+DstBuffer+"]");
}
Logger.debug("Starting to create vertex Transfer Buffer");
long MappedMemory = SrcBuffer.MapMemory(VkCtx);
FloatBuffer data = MemoryUtil.memFloatBuffer(MappedMemory, (int) SrcBuffer.GetRequestedSize());
VertexBuffer.rewind();
for(int i = 0; i < meshData.VertexSize(); i++){
data.put(VertexBuffer.get(meshData.OffsetVertex() + i));
}
SrcBuffer.UnMapMemory(VkCtx);
return new TransferBuffer(SrcBuffer,DstBuffer);
}
private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream VertexStream) throws IOException {
Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize());
int BufferSize = meshData.VertexSize();
@ -109,18 +73,10 @@ public class ModelsCache {
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
if (BufferSize <= 0) {
Logger.error("Computed buffer allocation size cannot be 0. SrcBuffer -> [{}] DstBuffer -> [{}]",SrcBuffer,DstBuffer);
throw new RuntimeException("Computed buffer allocation size cannot be 0. SrcBuffer -> ["+SrcBuffer+"] DstBuffer -> ["+DstBuffer+"]");
}
long MappedMemory = SrcBuffer.MapMemory(VkCtx);
FloatBuffer data = MemoryUtil.memFloatBuffer(MappedMemory, (int) SrcBuffer.GetRequestedSize());
int ValuesToRead = meshData.VertexSize()/VulkanUtils.FLOAT_SIZE;
if (ValuesToRead <= 0) {
Logger.error("Cannot allocate vertex buffer: Model mesh has 0 or negative vertices! Vertex Stream -> [{}]",VertexStream);
throw new RuntimeException("Cannot allocate vertex buffer: Model mesh has 0 or negative vertices! Vertex Stream -> [{"+VertexStream+"]");
}
while(ValuesToRead > 0){
data.put(VertexStream.readFloat());
ValuesToRead--;

View file

@ -41,6 +41,9 @@ public class Device {
.sType$Default()
.dynamicRendering(true)
.synchronization2(true);
var features12 = VkPhysicalDeviceVulkan12Features.calloc(MemStack)
.sType$Default()
.scalarBlockLayout(true);
var features2 = VkPhysicalDeviceFeatures2.calloc(MemStack).sType$Default();
var features = features2.features();
@ -50,6 +53,7 @@ public class Device {
features.samplerAnisotropy(true);
}
features2.pNext(features13.address());
features13.pNext(features12.address());
var DeviceCreateInfo = VkDeviceCreateInfo.calloc(MemStack)
.sType$Default()

View file

@ -5,6 +5,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
@ -48,8 +49,8 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
private final DescriptorSetLayout descriptorLayoutVertexUniform;
private final TextureSampler textureSampler;
private static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
private static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT;
public static final int COLOUR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT;
private final VkClearValue ClearValueDepth;
private final ByteBuffer PushConstBuffer;
private VkRenderingAttachmentInfo AttachmentInfoDepth;
@ -62,9 +63,9 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
public static long CYCLES = 0;
private static boolean DualPassRendering = false;
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";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment_deferred.glsl";
private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl";
private static final String FRAGMENT_OPAQUE_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl";
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV = FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL + ".spv";
private static final String FRAGMENT_OPAQUE_SHADER_FILE_SPV = FRAGMENT_OPAQUE_SHADER_FILE_GLSL + ".spv";
@ -74,9 +75,9 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
private Pipeline VkPipeline;
private Pipeline VkPipelineOpaque;
private Pipeline VkPipelineTranslucent;
private float R = 0.5f;
private float G = 0.75f;
private float B = 1.0f;
private float R = 0.01f;
private float G = 0.015f;
private float B = 0.0175f;
private Matrix4f ProjectionMatrix;
private MultiRenderTargetAttachments MRTAttachments;
@ -90,33 +91,38 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
return time;
}
public DeferredSceneRender(VulkanContext vulkanContext){
public DeferredSceneRender(VulkanContext vulkanContext, EngineInstance engineInstance){
ClearValueColour = VkClearValue.calloc().color(
c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f));
c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 0.5f));
ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f));
MRTAttachments = new MultiRenderTargetAttachments(vulkanContext);
AttachmentInfoColour = CreateColourAttachmentInfo(MRTAttachments, ClearValueColour);
AttachmentInfoDepth = CreateDepthAttachmentInfo(MRTAttachments, ClearValueDepth);
AttachmentInfoColour = CreateColourAttachmentInfo(MRTAttachments,ClearValueColour);
RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttachmentInfoDepth);
PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE));
PushConstBuffer = MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE);
descriptorLayoutVertexUniform = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0,1,VK_SHADER_STAGE_VERTEX_BIT));
BufferProjectionMatrix = VulkanUtils.CreateHostVisibleBuffer(vulkanContext, VulkanUtils.MATRIX4X4_SIZE,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_PRJ, descriptorLayoutVertexUniform);
ProjectionMatrix = PrimaryRuntime.GetEngineInstance().scene().GetProjection().GetProjectionMatrix();
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferProjectionMatrix, PrimaryRuntime.GetEngineInstance().scene().GetProjection().GetProjectionMatrix(),0);
0, 1, VK_SHADER_STAGE_VERTEX_BIT));
BufferProjectionMatrix = VulkanUtils.CreateHostVisibleBuffer(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
DESCRIPTOR_ID_PRJ, descriptorLayoutVertexUniform);
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferProjectionMatrix, engineInstance.scene().GetProjection().GetProjectionMatrix(), 0);
BufferViewMatrices = VulkanUtils.CreateHostVisibleBuffers(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_VIEW, descriptorLayoutVertexUniform);
descriptorLayoutFragStorage = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
0,1,VK_SHADER_STAGE_FRAGMENT_BIT));
0, 1, VK_SHADER_STAGE_FRAGMENT_BIT));
var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_BORDER_COLOR_INT_OPAQUE_BLACK,1,true);
textureSampler = new TextureSampler(vulkanContext,textureSamplerInfo);
descriptorLayoutTexture = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(
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);
VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true);
textureSampler = new TextureSampler(vulkanContext, textureSamplerInfo);
descriptorLayoutTexture = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, TextureCache.MAX_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT));
CreatePipelines(vulkanContext);
Logger.debug("Deferred Renderer Pipeline -> [{}]",VkPipeline.GetVulkanPipeline());
}
public void CreatePipelines(VulkanContext vulkanContext){
@ -129,8 +135,10 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
ShaderModule[] shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,0);
VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts, true, false,EngineConfig.getInstance().AlphaToCoverage());
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,1);
VkPipelineOpaque = CreatePipeline(vulkanContext, shaderModules, layouts, true, true,EngineConfig.getInstance().AlphaToCoverage());
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,2);
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,EngineConfig.getInstance().AlphaToCoverage());
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
@ -146,12 +154,6 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
public static boolean DualPassRendering(){return DualPassRendering;}
private static Attachment CreateColourAttachment(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent();
return new Attachment(VkCtx, SwapChainExtent.width(), SwapChainExtent.height(), COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
}
private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(MultiRenderTargetAttachments attachment, VkClearValue ClearValue){
List<Attachment> attachments = attachment.GetColourAttachments();
int numAttachments = attachments.size();
@ -168,13 +170,6 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
return result;
}
private static Attachment CreateDepthAttachment(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent();
return new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(),
DEPTH_FORMAT,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
private static VkRenderingAttachmentInfo CreateDepthAttachmentInfo(MultiRenderTargetAttachments DepthAttachment, VkClearValue clearValue){
return VkRenderingAttachmentInfo.calloc()
@ -186,35 +181,6 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
.clearValue(clearValue);
}
private static Attachment[] createDepthAttachments(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain();
int ImageCount = swapChain.GetImageCount();
VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent();
Attachment[] DepthAttachments = new Attachment[ImageCount];
for(int i = 0; i < ImageCount; i++){
DepthAttachments[i] = new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(),
DEPTH_FORMAT,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
return DepthAttachments;
}
private static VkRenderingAttachmentInfo[] createDepthAttachmentsInfo(VulkanContext VkCtx, Attachment[] DepthAttachments, VkClearValue clearValue){
SwapChain swapChain = VkCtx.GetSwapChain();
int ImageCount = swapChain.GetImageCount();
var Result = new VkRenderingAttachmentInfo[ImageCount];
for(int i = 0; i < ImageCount; i++){
var Attachments = VkRenderingAttachmentInfo.calloc()
.sType$Default()
.imageView(DepthAttachments[i].GetVkImageView().GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE)
.clearValue(clearValue);
Result[i] = Attachments;
}
return Result;
}
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
@ -228,7 +194,8 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean AlphaToCoverage){
var vertexBufferStructure = new VertexBufferStructure();
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),MultiRenderTargetAttachments.ALBEDO_FORMAT)
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{
MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT})
.SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT)
.SetDepthWrite(DepthWrite)
.SetPushConstantRanges(
@ -306,6 +273,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true);
vkCmdEndRendering(CommandHandle);
GPUTIME += System.nanoTime() - InitialTime;
CYCLES++;
}
@ -315,10 +283,9 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
try(var MemStack = MemoryStack.stackPush()){
LongBuffer offsets = MemStack.mallocLong(1).put(0,0L);
LongBuffer vertexBuffer = MemStack.mallocLong(1);
Scene scene = instance.scene();
IScene scene = instance.scene();
List<Actor> Actors = scene.GetActors();
int ActorCount = Actors.size();
List<Actor> translucentObjects = new ArrayList<>();
for(int i = 0; i < ActorCount; i++){
if(i < Actors.size()) {
var Actor = Actors.get(i);
@ -372,25 +339,25 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
VulkanUtils.CopyMatrixToBuffer(VkCtx, BufferProjectionMatrix, instance.scene().GetProjection().GetProjectionMatrix(), 0);}
public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache){
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator();
Device device = VkCtx.GetDevice();
DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSet(device,DESCRIPTOR_ID_MAT,descriptorLayoutFragStorage);
DescriptorSetLayout.LayoutInformation LayoutInfo = descriptorLayoutFragStorage.GetLayoutInfo();
var Buffer = materialsCache.GetMaterialsBuffer();
descriptorSet.SetBuffer(device,Buffer,Buffer.GetRequestedSize(),LayoutInfo.Binding(),LayoutInfo.DescriptorType());
DescriptorSet descSet = descAllocator.AddDescriptorSet(device, DESCRIPTOR_ID_MAT, descriptorLayoutFragStorage);
DescriptorSetLayout.LayoutInformation layoutInfo = descriptorLayoutFragStorage.GetLayoutInfo();
var buffer = materialsCache.GetMaterialsBuffer();
descSet.SetBuffer(device, buffer, buffer.GetRequestedSize(), layoutInfo.Binding(), layoutInfo.DescriptorType());
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(Texture::GetImageView).toList();
descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device,DESCRIPTOR_ID_TEXT,descriptorLayoutTexture);
descriptorSet.SetImageArray(device,imageViews,textureSampler,0);
descSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device, DESCRIPTOR_ID_TEXT, descriptorLayoutTexture);
descSet.SetImageArray(device, imageViews, textureSampler, 0);
}
private static VkRenderingInfo CreateRenderInfo(VulkanContext VkCtx, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){
VkRenderingInfo Result;
SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D Extent = swapChain.GetSwapChainExtent();
VkRenderingInfo Result = VkRenderingInfo.calloc();
try(var MemStack = MemoryStack.stackPush()){
var RenderArea = VkRect2D.calloc(MemStack).extent(Extent);
Result = VkRenderingInfo.calloc()
.sType$Default()
Result.sType$Default()
.renderArea(RenderArea)
.layerCount(1)
.pColorAttachments(ColourAttachmentInfo)

View file

@ -5,6 +5,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
@ -32,6 +33,7 @@ import org.tinylog.Logger;
import java.nio.ByteBuffer;
import java.nio.LongBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -127,6 +129,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
));
BufferViewMatrices = VulkanUtils.CreateHostVisibleBuffers(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.MAX_IN_FLIGHT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_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){
@ -207,7 +210,8 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean AlphaToCoverage){
var vertexBufferStructure = new VertexBufferStructure();
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),COLOUR_FORMAT)
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{
MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT})
.SetDepthFormat(DEPTH_FORMAT)
.SetDepthWrite(DepthWrite)
.SetPushConstantRanges(
@ -292,7 +296,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
try(var MemStack = MemoryStack.stackPush()){
LongBuffer offsets = MemStack.mallocLong(1).put(0,0L);
LongBuffer vertexBuffer = MemStack.mallocLong(1);
Scene scene = instance.scene();
IScene scene = instance.scene();
List<Actor> Actors = scene.GetActors();
int ActorCount = Actors.size();
for(int i = 0; i < ActorCount; i++){

View file

@ -72,27 +72,27 @@ public class ImageView {
this.MipLevels = 1;
this.ViewType = VK_IMAGE_VIEW_TYPE_2D;
}
public ImageView.ImageViewData AspectMask(int aspectMask){
public ImageViewData AspectMask(int aspectMask){
this.AspectMask = aspectMask;
return this;
}
public ImageView.ImageViewData BaseArrayLayer(int baseArrayLayer){
public ImageViewData BaseArrayLayer(int baseArrayLayer){
this.BaseArrayLayer = baseArrayLayer;
return this;
}
public ImageView.ImageViewData Format(int format){
public ImageViewData Format(int format){
this.Format = format;
return this;
}
public ImageView.ImageViewData LayerCount(int layerCount){
public ImageViewData LayerCount(int layerCount){
this.LayerCount = layerCount;
return this;
}
public ImageView.ImageViewData MipLevels(int mipLevels){
public ImageViewData MipLevels(int mipLevels){
this.MipLevels = mipLevels;
return this;
}
public ImageView.ImageViewData ViewType(int viewType){
public ImageViewData ViewType(int viewType){
this.ViewType = viewType;
return this;
}

View file

@ -14,6 +14,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.util.shaderc.Shaderc;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.LongBuffer;
import java.util.Arrays;
@ -55,6 +56,8 @@ public class SwapChainRender {
pipeline = CreatePipeline(VkCtx,shaderModules,new DescriptorSetLayout[]{AttachmentDescriptorSetLayout});
Arrays.asList(shaderModules).forEach(s->s.CleanUp(VkCtx));
Logger.debug("Swap Chain Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline());
}
private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, Attachment attachment, TextureSampler sampler){
@ -84,7 +87,7 @@ public class SwapChainRender {
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){
var VertexBufferStruct = new EmptyVertexBufferStruct();
var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStruct.GetVertexInput(),VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStruct.GetVertexInput(),new int[]{VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()}).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var pipeline = new DefaultPipeline(VkCtx,BuildInfo);
VertexBufferStruct.CleanUp();
return pipeline;

View file

@ -39,7 +39,13 @@ public class VulkanInstance {
Logger.debug("Initialising Vulkan Instance");
try (MemoryStack MemStack = MemoryStack.stackPush()) {
ByteBuffer appShortName = MemStack.UTF8("Terrain4J");
var appInfo = VkApplicationInfo.calloc(MemStack).sType$Default().pApplicationName(appShortName).applicationVersion(1).pEngineName(appShortName).engineVersion(3).apiVersion(VK_API_VERSION_1_3);
var appInfo = VkApplicationInfo.calloc(MemStack)
.sType$Default()
.pApplicationName(appShortName)
.applicationVersion(1)
.pEngineName(appShortName)
.engineVersion(0)
.apiVersion(VK_API_VERSION_1_3);
//Vulkan operates in "Layers" and does minimal validation as it expects the developer to be competent, so we add these ourseves for better debugging
//refer to https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers for an explanation

View file

@ -28,6 +28,7 @@ public class VulkanUtils {
public enum OSType {WINDOWS, MACOS, LINUX, UNSUPPORTED}
public static final int FLOAT_SIZE = 4;
public static final int VEC3_SIZE = 3 * FLOAT_SIZE;
public static final int INT_SIZE = 4;
public static final int MATRIX4X4_SIZE = 16 * FLOAT_SIZE;
public static final int VEC4_SIZE = 4 * FLOAT_SIZE;