Camera and proper rendering

This commit is contained in:
Halbear 2026-06-07 21:40:21 +01:00
parent 3040800275
commit a8adf662ff
48 changed files with 65391 additions and 22367 deletions

View file

@ -133,7 +133,7 @@ public class Render {
resize(engineInstance);
return;
}
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,ImageIndex);
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,ImageIndex,CurrentFrame);
RecordingStop(CommandBuffer);
Submit(CommandBuffer, CurrentFrame, ImageIndex);
Resize = swapChain.PresentImage(PresentQueue, RenderCompleteSemaphores[ImageIndex],ImageIndex);

View file

@ -4,6 +4,7 @@ public interface GameLogic {
void cleanup();
InitData Initialise(EngineInstance engineInstance);
void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds);
void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds);
void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds);
void UpdateFastThread(EngineInstance engineInstance, long FrameDiffNanoSeconds);
}

View file

@ -35,7 +35,7 @@ public class ModelCompiler {
| aiProcess_Triangulate | aiProcess_FixInfacingNormals | aiProcess_CalcTangentSpace
| aiProcess_PreTransformVertices;
@Parameter(names = "-m", description = "Model Path", required = true)
@Parameter(names = "-model", description = "Model Path", required = true)
private String ModelPath;
public static void main(String[] args){
@ -50,8 +50,7 @@ public class ModelCompiler {
Logger.error("Error Compiling model",exception);
}
}
private void Process() throws IOException{
public static void Process(String ModelPath) throws IOException{
Logger.debug("Loading 3D Model Data from [{}]", ModelPath);
var ModelSourceFile = new File(ModelPath);
if (!ModelSourceFile.exists()) throw new RuntimeException("Model path does not exist->["+ModelPath+"]");
@ -86,7 +85,7 @@ public class ModelCompiler {
String CreateModelFile = ModelPath.substring(0,ModelPath.lastIndexOf('.')) + ".json";
Writer writer = new FileWriter(CreateModelFile);
var gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create();
var gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().create();
gson.toJson(model, writer);
writer.flush();
writer.close();
@ -102,7 +101,11 @@ public class ModelCompiler {
Logger.info("Generated Vertex File [{}] and Index File [{}]",BinaryData.GetVertexFilePath(),BinaryData.GetIndexFilePath());
}
private MaterialData ProcessMaterial(AIScene aiScene, AIMaterial aiMaterial, String ModelName, String BaseDirectory, int Position) throws IOException{
private void Process() throws IOException{
Process(ModelPath);
}
public static MaterialData ProcessMaterial(AIScene aiScene, AIMaterial aiMaterial, String ModelName, String BaseDirectory, int Position) throws IOException{
Vector4f diffuse = new Vector4f();
AIColor4D colour = AIColor4D.create();
@ -114,7 +117,7 @@ public class ModelCompiler {
return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,diffuse);
}
private MeshData ProcessMesh(AIMesh aiMesh, List<MaterialData> MaterialList, int MeshPosition, ModelBinaryData BinaryData) throws IOException {
public static MeshData ProcessMesh(AIMesh aiMesh, List<MaterialData> MaterialList, int MeshPosition, ModelBinaryData BinaryData) throws IOException {
List<Float> vertices = ProcessVertices(aiMesh);
List<Float> textureCoordinates = ProcessTextureCoords(aiMesh);
List<Integer> indices = ProcessIndices(aiMesh);
@ -155,7 +158,7 @@ public class ModelCompiler {
return meshData;
}
private static List<Float> ProcessTextureCoords(AIMesh aiMesh){
public static List<Float> ProcessTextureCoords(AIMesh aiMesh){
List<Float> TextureCoords = new ArrayList<>();
AIVector3D.Buffer aiTextureCoords = aiMesh.mTextureCoords(0);
int CoordinateCount = aiTextureCoords != null ? aiTextureCoords.remaining() : 0;
@ -167,7 +170,7 @@ public class ModelCompiler {
return TextureCoords;
}
private List<Integer> ProcessIndices(AIMesh aiMesh){
public static List<Integer> ProcessIndices(AIMesh aiMesh){
List<Integer> Indices = new ArrayList<>();
int FaceCount = aiMesh.mNumFaces();
AIFace.Buffer aiFaces = aiMesh.mFaces();
@ -181,7 +184,7 @@ public class ModelCompiler {
return Indices;
}
private List<Float> ProcessVertices(AIMesh aiMesh){
public static List<Float> ProcessVertices(AIMesh aiMesh){
List<Float> vertices = new ArrayList<>();
AIVector3D.Buffer aiVertices = aiMesh.mVertices();
while(aiVertices.remaining() > 0){
@ -193,7 +196,7 @@ public class ModelCompiler {
return vertices;
}
private String ProcessTexture(AIScene aiScene, AIMaterial aiMaterial, String BaseDirectory,int TextType ) throws IOException{
public static String ProcessTexture(AIScene aiScene, AIMaterial aiMaterial, String BaseDirectory,int TextType ) throws IOException{
String TexturePath;
try(var MemStack = MemoryStack.stackPush()){
int EmbeddedTextureCount = aiScene.mNumTextures();

View file

@ -17,6 +17,21 @@ public class ModelLoader { // Model Utility class kinda like a model version of
}
public static List<MaterialData> LoadMaterials(String[] Path){
var Result = new ArrayList<MaterialData>();
for(int i = 0; i < Path.length; i++) {
Logger.debug("Material loading step [{}], Loading Materials From [{}]", i, Path[i]);
try {
String content = new String(Files.readAllBytes(Paths.get(Path[i])));
var gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
Result.addAll(Arrays.asList(gson.fromJson(content, MaterialData[].class)));
} catch (Exception e) {
throw new RuntimeException(e);
}
Logger.debug("Loaded Material Data: [{}]", Result.toString());
}
return Result;
}
public static List<MaterialData> LoadMaterials(String Path){
Logger.debug("Loading Materials From [{}]",Path);
var Result = new ArrayList<MaterialData>();

View file

@ -1,25 +1,35 @@
package net.halbear.Terrain4J.EngineCore.Main;
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.Logic.GameLogic;
import net.halbear.Terrain4J.EngineCore.Logic.InitData;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData;
import org.joml.Vector2f;
import org.joml.Vector3f;
import org.tinylog.Logger;
import java.util.ArrayList;
import java.util.List;
import static org.lwjgl.glfw.GLFW.*;
public class GameCore implements GameLogic {
private final Vector3f rotatingAngle = new Vector3f(1, 1, 1);
private float angle = 0;
private static final float MOUSE_SENSITIVITY = 0.1f;
private static final float MOVEMENT_SPEED = 0.01f;
private final Vector3f rotatingAngle = new Vector3f(0, 1, 0);
private float angle = 180;
private List<Float> angles = new ArrayList<>();
private List<Vector3f> rotatingAngles = new ArrayList<>();
private List<Vector3f> Velocities = new ArrayList<>();
private Actor CubeActor;
private List<Actor> CubeActors = new ArrayList<>();
@ -34,31 +44,81 @@ public class GameCore implements GameLogic {
Scene scene = engineInstance.scene();
List<ModelData> models = new ArrayList<>();
ModelData SloopModel = ModelLoader.LoadModel("resources/Models/Cube/cube.json");
models.add(SloopModel);
Logger.trace(SloopModel.ID());
Actor SloopActor = new Actor("CubeEntity",SloopModel.ID(),new Vector3f(0.0f,0.0f,-10.0f));
angles.add(34F);
Velocities.add(new Vector3f(0,0,0));
CubeActors.add(SloopActor);
scene.AddActor(SloopActor);
models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json"));
models.add(ModelLoader.LoadModel("resources/models/Corvette/CorvetteOBJ.json"));
//models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json"));
models.add(ModelLoader.LoadModel("resources/models/melona/melona.json"));
models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json"));
for(int i = 0; i < 50000; i++) {
CubeActors.add(new Actor("CubeEntity" + i, models.get((int)Math.round(Math.min(Math.max((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)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2)));
}
CubeActors.forEach(scene::AddActor);
List<MaterialData> materials = new ArrayList<>(ModelLoader.LoadMaterials("resources/Models/Cube/cube_mat.json"));
List<MaterialData> materials = new ArrayList<>();
materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/CorvetteOBJ_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json"));
Camera camera = scene.GetCamera();
camera.SetPosition(0.0f, 0.0f, 0.0f);
camera.SetRotation((float) Math.toRadians(0.0f), (float) Math.toRadians(0.0f),0);
return new InitData(models,materials);
}
@Override
public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
Scene scene = engineInstance.scene();
Window window = engineInstance.window();
Camera camera = scene.GetCamera();
MouseListener MouseInput = window.getMouseInput();
if(MouseInput.isRightButtonPressed()){
Vector2f deltaPos = MouseInput.getDeltaPos();
camera.AddRotation((float)Math.toRadians(-deltaPos.y * MOUSE_SENSITIVITY),(float)Math.toRadians(-deltaPos.x * MOUSE_SENSITIVITY),0);
}
}
@Override
public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
Scene 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_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);
}
}
@Override
public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
float DeltaTime = (float)(FrameDiffNanoSeconds/16000000.0);
for(int i = 0; i < angles.size()/2; i++) {
angles.set(i, (angles.get(i) + 1.0f* DeltaTime) % 360);
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngle);
CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
angles.set(i, (angles.get(i) + 0.1f* DeltaTime) % 360);
Camera camera = engineInstance.scene().GetCamera();
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i));
//CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
CubeActors.get(i).UpdateModelMatrix();
}
}
@ -68,9 +128,9 @@ public class GameCore implements GameLogic {
float DeltaTime = (float)(FrameDiffNanoSeconds/16000000.0);
for(int i = angles.size()/2; i < angles.size(); i++) {
angles.set(i, (angles.get(i) + 1.0f* DeltaTime) % 360);
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngle);
CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
CubeActors.get(i).UpdateModelMatrix();
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i));
// CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
CubeActors.get(i).UpdateModelMatrix();
}
}
}

View file

@ -27,9 +27,11 @@ public class PrimaryRuntime {
private static long OriginalFrameAccuracy;
private static boolean CappedToTickRate = false;
public final CPUMonitor cpuProfiler;
private static GameLogic gameLogic;
public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
window = new Window(windowTitle);
gameLogic = appLogic;
engineInstance = new EngineInstance(window, new Scene(window));
InitData initData = appLogic.Initialise(engineInstance);
PrimaryThread = new MainThread(engineInstance, appLogic);
@ -59,6 +61,10 @@ public class PrimaryRuntime {
}
}
public void PrimaryRuntimeInputUpdate(long nsTimeDiff){
gameLogic.CameraInput(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff));
}
public void run(){
UpdateTickRateThreshold();
long InitialTime = System.nanoTime();
@ -85,6 +91,7 @@ public class PrimaryRuntime {
if (TickDiff >= TickRate) {
TickFrames++;
long nsTimeDiff = now - updateTime;
PrimaryRuntimeInputUpdate(nsTimeDiff);
updateTime = now;
TickDiff = 0;
}

View file

@ -0,0 +1,80 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import org.joml.Matrix4f;
import org.joml.Vector3f;
public class Camera {
private final Vector3f Direction;
private final Vector3f Position;
private final Vector3f Right;
private final Vector3f Rotation;
private final Vector3f Up;
private final Matrix4f ViewMatrix;
public Camera(){
Direction = new Vector3f();
Position = new Vector3f();
Right = new Vector3f();
Rotation = new Vector3f();
Up = new Vector3f();
ViewMatrix = new Matrix4f();
}
public void SetRotation(float x, float y, float z){Rotation.set(x,y,z); Recalculate();}
public void AddRotation(float x, float y, float z){Rotation.add(x,y,z); Recalculate();}
public void AddRotX(float x){Rotation.x += x; Recalculate();}
public void AddRotY(float y){Rotation.y += y; Recalculate();}
public void AddRotZ(float z){Rotation.z += z; Recalculate();}
public Vector3f GetRotation(){return Rotation;}
public void SetPosition(float x, float y, float z){Position.set(x,y,z); Recalculate();}
public void AddPosition(float x, float y, float z){Position.add(x,y,z);Recalculate(); }
public void AddPosX(float x){Position.x += x;Recalculate();}
public void AddPosY(float y){Position.y += y;Recalculate();}
public void AddPosZ(float z){Position.z += z;Recalculate();}
public Vector3f GetPosition(){return Position;}
public Matrix4f GetViewMatrix(){
return ViewMatrix;
}
public void MoveForward(float Distance){
ViewMatrix.positiveZ(Direction).negate().mul(Distance);
Position.add(Direction);
Recalculate();
}
public void MoveBackward(float Distance){
ViewMatrix.positiveZ(Direction).negate().mul(Distance);
Position.sub(Direction);
Recalculate();
}
public void MoveUp(float Distance){
ViewMatrix.positiveY(Up).negate().mul(Distance);
Position.sub(Up);
Recalculate();
}
public void MoveDown(float Distance){
ViewMatrix.positiveY(Up).negate().mul(Distance);
Position.add(Up);
Recalculate();
}
public void MoveLeft(float Distance){
ViewMatrix.positiveX(Right).negate().mul(Distance);
Position.add(Right);
Recalculate();
}
public void MoveRight(float Distance){
ViewMatrix.positiveX(Right).negate().mul(Distance);
Position.sub(Right);
Recalculate();
}
public void Recalculate(){
ViewMatrix.identity()
.rotateX(Rotation.x)
.rotateY(Rotation.y)
//.rotateZ(Rotation.z)
.translate(-Position.x, -Position.y, -Position.z);
}
}

View file

@ -11,14 +11,16 @@ public class Scene {
private final List<Actor> Actors;
private final Project3D Projection;
private final Camera camera;
public Scene(Window window) {
Actors = new ArrayList<>();
var EngConfig = EngineConfig.getInstance();
Projection = new Project3D(EngConfig.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(),
window.getWidth(), window.getHeight());
camera = new Camera();
}
public Camera GetCamera(){return camera;}
public void AddActor(Actor NewActor){Actors.add(NewActor);}
public List<Actor> GetActors(){return Actors;}
public Project3D GetProjection(){return Projection;}

View file

@ -0,0 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Main.Util.Maths;
public class T4Math {
public static double Log2(int n){
return Math.log(n) / Math.log(n);
}
}

View file

@ -14,7 +14,6 @@ public class MainThread extends EngineThread {
}
@Override
public void FrameEvent(long now, long InitialTime){
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime));
}
@Override
public void CycleEvent(){

View file

@ -24,6 +24,7 @@ public class RenderThread extends EngineThread {
}
@Override
public void FrameEvent(long now, long InitialTime){
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime));
render.render(PrimaryRuntime.GetEngineInstance());
}
@Override

View file

@ -1,18 +1,20 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.Util.Maths.T4Math;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
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.vulkan.VkBufferImageCopy;
import org.lwjgl.vulkan.*;
import java.nio.ByteBuffer;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.VK_ACCESS_2_NONE;
import static org.lwjgl.vulkan.VK13.vkCmdPipelineBarrier2;
public class Texture {
@ -22,6 +24,7 @@ public class Texture {
private final Image image;
private final ImageView imageView;
private boolean RecordedTransition;
private boolean Transparent;
private VulkanBuffer stgBuffer;
public Texture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int ImageFormat){
@ -29,17 +32,30 @@ public class Texture {
RecordedTransition = false;
Width = imageSrc.Width();
Height = imageSrc.Height();
SetTransparency(imageSrc.data());
int MipMapLevels = (int) Math.floor(T4Math.Log2(Math.min(Width, Height))) + 1;
CreateStgBuffer(VkCtx, imageSrc.data());
var ImageData = new Image.ImageData().Width(Width).Height(Height)
.Usage(VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
.Format(ImageFormat);
.Format(ImageFormat).MipMapLevels(MipMapLevels);
image = new Image(VkCtx, ImageData);
var ImageViewData = new ImageView.ImageViewData().Format(image.GetFormat())
.AspectMask(VK_IMAGE_ASPECT_COLOR_BIT);
.AspectMask(VK_IMAGE_ASPECT_COLOR_BIT).MipLevels(MipMapLevels);
imageView = new ImageView(VkCtx.GetDevice(), image.getVulkanImage(), ImageViewData, false);
}
public boolean HasTransparency(){return Transparent;}
public void SetTransparency(ByteBuffer data){
int PixelCount = data.capacity()/4;
int Offset = 0;
Transparent = false;
for(int i = 0; i < PixelCount; i++){
int alpha = (0xFF & data.get(Offset + 3));
if( alpha < 255){
Transparent = true;
}
Offset += 4;
}
}
public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data){
int Size = data.remaining();
stgBuffer = new VulkanBuffer(VkCtx, Size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
@ -58,13 +74,84 @@ public class Texture {
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);
RecordCopyBuffer(MemStack, commandBuffer, stgBuffer);
VulkanUtils.ImageBarrier(MemStack, commandBuffer.GetVulkanCommandBuffer(), image.getVulkanImage(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,VK_IMAGE_ASPECT_COLOR_BIT);
RecordGenerateMipMaps(MemStack, commandBuffer);
}
}
}
private void RecordGenerateMipMaps(MemoryStack MemStack, CommandBuffer commandBuffer){
VkImageSubresourceRange SubResourceRange = VkImageSubresourceRange.calloc(MemStack)
.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT)
.baseArrayLayer(0)
.levelCount(1)
.layerCount(1);
VkImageMemoryBarrier2.Buffer ImageMemoryBarrierBuffer = VkImageMemoryBarrier2.calloc(1,MemStack)
.sType$Default()
.image(image.getVulkanImage())
.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.subresourceRange(SubResourceRange);
VkDependencyInfo dependencyInfo = VkDependencyInfo.calloc(MemStack)
.sType$Default()
.pImageMemoryBarriers(ImageMemoryBarrierBuffer);
int MipMapWidth = Width;
int MipMapHeight = Height;
int MipMapLevels = image.GetMipLevels();
for(int i = 1; i < MipMapLevels; i++){
SubResourceRange.baseMipLevel(i - 1);
ImageMemoryBarrierBuffer.subresourceRange(SubResourceRange)
.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
.newLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
.srcStageMask(VK_PIPELINE_STAGE_TRANSFER_BIT)
.dstStageMask(VK_PIPELINE_STAGE_TRANSFER_BIT)
.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT)
.dstAccessMask(VK_ACCESS_TRANSFER_READ_BIT);
vkCmdPipelineBarrier2(commandBuffer.GetVulkanCommandBuffer(),dependencyInfo);
int auxi = i;
VkOffset3D srcOffset0 = VkOffset3D.calloc(MemStack).x(0).y(0).z(0);
VkOffset3D srcOffset1 = VkOffset3D.calloc(MemStack).x(MipMapWidth).y(MipMapHeight).z(1);
VkOffset3D dstOffset0 = VkOffset3D.calloc(MemStack).x(0).y(0).z(0);
VkOffset3D dstOffset1 = VkOffset3D.calloc(MemStack)
.x(MipMapWidth > 1 ? MipMapWidth/2 : 1).y(MipMapHeight > 1 ? MipMapHeight/2 : 1).z(1);
VkImageBlit.Buffer BlitBuffer = VkImageBlit.calloc(1,MemStack)
.srcOffsets(0,srcOffset0)
.srcOffsets(1,srcOffset1)
.srcSubresource(it -> it.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT)
.mipLevel(auxi - 1)
.baseArrayLayer(0)
.layerCount(1))
.dstOffsets(0,dstOffset0)
.dstOffsets(1,dstOffset1)
.dstSubresource(it -> it.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT)
.mipLevel(auxi)
.baseArrayLayer(0)
.layerCount(1));
vkCmdBlitImage(commandBuffer.GetVulkanCommandBuffer(),image.getVulkanImage(),VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
image.getVulkanImage(),VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,BlitBuffer,VK_FILTER_LINEAR);
ImageMemoryBarrierBuffer.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL).newLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.srcAccessMask(VK_ACCESS_TRANSFER_READ_BIT).dstAccessMask(VK_ACCESS_SHADER_READ_BIT);
ImageMemoryBarrierBuffer.srcStageMask(VK_PIPELINE_STAGE_TRANSFER_BIT).dstAccessMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
vkCmdPipelineBarrier2(commandBuffer.GetVulkanCommandBuffer(),dependencyInfo);
if(MipMapWidth > 1) MipMapWidth/=2;
if(MipMapHeight > 1) MipMapHeight/=2;
}
ImageMemoryBarrierBuffer.subresourceRange(it -> it.baseMipLevel(MipMapLevels - 1))
.oldLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
.newLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
.srcStageMask(VK_PIPELINE_STAGE_TRANSFER_BIT)
.dstAccessMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
.srcAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT)
.dstAccessMask(VK_ACCESS_SHADER_READ_BIT);
vkCmdPipelineBarrier2(commandBuffer.GetVulkanCommandBuffer(), dependencyInfo);
}
private void RecordCopyBuffer(MemoryStack MemStack, CommandBuffer commandBuffer, VulkanBuffer bufferData){
VkBufferImageCopy.Buffer Region = VkBufferImageCopy.calloc(1, MemStack)
.bufferOffset(0)
@ -77,6 +164,9 @@ public class Texture {
.layerCount(1)
).imageOffset(it->it.x(0).y(0).z(0))
.imageExtent(it->it.width(Width).height(Height).depth(1));
vkCmdCopyBufferToImage(commandBuffer.GetVulkanCommandBuffer(), bufferData.GetBuffer(), image.getVulkanImage(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, Region);
}
public void CleanUp(VulkanContext VkCtx){

View file

@ -54,20 +54,6 @@ public class Pipeline {
var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack)
.sType$Default()
.rasterizationSamples(VK_SAMPLE_COUNT_1_BIT);
VkPipelineDynamicStateCreateInfo VulkanPipelineDynamicStateCreateInfo = VkPipelineDynamicStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO)
.pDynamicStates(MemStack.ints(
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
));
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(false);
var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack)
.sType$Default()
.pAttachments(BlendAttributeState);
IntBuffer ColourFormats = MemStack.mallocInt(1);
ColourFormats.put(0,BuildInfo.GetColourFormat());
VkPipelineDepthStencilStateCreateInfo DepthStencil = null;
if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){
@ -80,12 +66,14 @@ public class Pipeline {
.stencilTestEnable(false);
}
var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack)
.sType$Default()
.colorAttachmentCount(1)
.pColorAttachmentFormats(ColourFormats);
if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());}
VkPipelineDynamicStateCreateInfo VulkanPipelineDynamicStateCreateInfo = VkPipelineDynamicStateCreateInfo.calloc(MemStack)
.sType$Default()
.pDynamicStates(MemStack.ints(
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
));
VkPushConstantRange.Buffer VkPushConstRangeBuffer = null;
PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges();
@ -100,13 +88,37 @@ public class Pipeline {
.size(pushConstantsRange.Size());
}
}
DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts();
int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0;
LongBuffer ppLayout = MemStack.mallocLong(LayoutCount);
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_SRC_ALPHA)
.dstAlphaBlendFactor(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()

View file

@ -14,12 +14,14 @@ public class PipelineBuildInfo {
private int DepthFormat;
private PushConstantsRange[] PushConstRanges;
private DescriptorSetLayout[] DescriptorSetLayouts;
private boolean useBlend;
public PipelineBuildInfo(ShaderModule[] shaderModules, VkPipelineVertexInputStateCreateInfo VertexInput, int ColourFormat){
this.ColourFormat = ColourFormat;
this.ShaderModules = shaderModules;
this.VertexInput = VertexInput;
DepthFormat = VK_FORMAT_UNDEFINED;
useBlend = true;
}
public DescriptorSetLayout[] GetDescriptorSetLayouts(){return DescriptorSetLayouts;}
@ -29,6 +31,14 @@ public class PipelineBuildInfo {
return this;
}
public boolean BlendingUsed(){
return useBlend;
}
public PipelineBuildInfo BlendingIsUsed(boolean useBlend) {
this.useBlend = useBlend;
return this;
}
public PipelineBuildInfo SetDepthFormat(int DepthFormat){
this.DepthFormat = DepthFormat;
return this;

View file

@ -10,6 +10,7 @@ import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo;
import org.lwjgl.vulkan.VkWriteDescriptorSet;
import java.nio.LongBuffer;
import java.util.ArrayList;
import java.util.List;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
@ -51,7 +52,12 @@ public class DescriptorSet {
}
}
public void SetImage(Device device, List<ImageView> imageViews, TextureSampler textureSampler, int BaseBinding){
public void SetImage(Device device, ImageView imageView, TextureSampler textureSampler, int BaseBinding){
List<ImageView> imageViews = new ArrayList<>();
imageViews.add(imageView);
SetImages(device, imageViews, textureSampler, BaseBinding);
}
public void SetImages(Device device, List<ImageView> imageViews, TextureSampler textureSampler, int BaseBinding){
try(var MemStack = MemoryStack.stackPush()){
int ImageCount = imageViews.size();
var DescriptorBuffer = VkWriteDescriptorSet.calloc(ImageCount,MemStack);

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Texture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
@ -49,14 +50,19 @@ public class MaterialsCache {
var Material = Materials.get(i);
String TexturePath = Material.TexturePath();
boolean ValidTexture = TexturePath != null && !TexturePath.isEmpty();
boolean TransparentTexture;
if(ValidTexture){
Logger.debug("Loading Texture [{}]",TexturePath);
textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB);
Texture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB);
TransparentTexture = newTexture.HasTransparency();
} else{
TransparentTexture = Material.DiffuseColour().w < 1.0f;
}
VulkanMaterial newMaterial = new VulkanMaterial(Material.ID());
VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture);
MaterialsMap.put(newMaterial.ID(), newMaterial);
Logger.trace(Material.toString());
Material.DiffuseColour().get(Offset, data);
data.position(Offset);
Material.DiffuseColour().get(data);
Logger.debug("Set Diffuse Colour -> [{}]",Material.DiffuseColour());
data.putInt(Offset + VulkanUtils.VEC4_SIZE, ValidTexture ? 1 : 0);
data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE, textureCache.GetPosition(TexturePath));
@ -66,6 +72,8 @@ public class MaterialsCache {
data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE * 3,0);
Offset += MATERIAL_SIZE;
}
data.position(0);
SrcBuffer.UnMapMemory(VkCtx);
transferBuffer.RecordTransferCommand(CmdBuffer);
CmdBuffer.EndRecording();

View file

@ -0,0 +1,4 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
public class ProceduralMesh {
}

View file

@ -1,4 +1,4 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
public record VulkanMaterial(String ID) {
public record VulkanMaterial(String ID, boolean HasTransparency) {
}

View file

@ -41,6 +41,7 @@ public class SceneRender {//dynamic rendering
private static final String DESCRIPTOR_ID_MAT = "SCN_DESC_ID_MAT";
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 int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE;
private final VulkanBuffer BufferProjectionMatrix;
private final DescriptorSetLayout descriptorLayoutFragStorage;
@ -69,15 +70,20 @@ public class SceneRender {//dynamic rendering
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String VERTEX_SHADER_FILE_GLSL = "resources/shaders/scene_vertex.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
private final VulkanBuffer[] BufferViewMatrices;
private final Pipeline VkPipeline;
public SceneRender(VulkanContext vulkanContext){
ClearValueDepth = VkClearValue.calloc().color(c->c.float32(0,1.0f));
ClearValueColour = VkClearValue.calloc().color(
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
//ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f));
ClearValueDepth = VkClearValue.calloc().depthStencil(c -> c.depth(1.0f).stencil());
AttDepth = createDepthAttachments(vulkanContext);
AttInfoDepth = createDepthAttachmentsInfo(vulkanContext, AttDepth, ClearValueDepth);
ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f));
AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour);
RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth);
ShaderModule[] shaderModules = SceneRender.CreateShaderModules(vulkanContext);
PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE));
descriptorLayoutVertexUniform = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@ -93,12 +99,16 @@ public class SceneRender {//dynamic rendering
descriptorLayoutTexture = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 0, TextureCache.MAX_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT
));
DescriptorSetLayout[] layouts = new DescriptorSetLayout[]{
descriptorLayoutVertexUniform,
descriptorLayoutVertexUniform,
descriptorLayoutFragStorage,
descriptorLayoutTexture
};
ShaderModule[] shaderModules = SceneRender.CreateShaderModules(vulkanContext);
VkPipeline = CreatePipeline(vulkanContext, shaderModules, new DescriptorSetLayout[]{
descriptorLayoutVertexUniform, descriptorLayoutFragStorage, descriptorLayoutFragStorage
});
//Continue Here
BufferViewMatrices = VulkanUtils.CreateHostVisibleBuffers(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.MAX_IN_FLIGHT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_VIEW, descriptorLayoutVertexUniform);
VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
}
@ -122,7 +132,7 @@ public class SceneRender {//dynamic rendering
var Attachments = VkRenderingAttachmentInfo.calloc()
.sType$Default()
.imageView(DepthAttachments[i].GetVkImageView().GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL)
.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE)
.clearValue(clearValue);
@ -134,7 +144,7 @@ public class SceneRender {//dynamic rendering
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx){
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_fragment_shader);
ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader);
}
return new ShaderModule[]{
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV),
@ -148,11 +158,12 @@ public class SceneRender {//dynamic rendering
VkCtx.GetSurface().GetSurfaceFormat().ImageFormat())
.SetDepthFormat(DEPTH_FORMAT)
.SetPushConstantRanges(
new PushConstantsRange[]{
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.MATRIX4X4_SIZE * 2),
new PushConstantsRange[]{
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.MATRIX4X4_SIZE),
new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT,VulkanUtils.MATRIX4X4_SIZE,VulkanUtils.INT_SIZE)
})
.SetDescriptorSetLayouts(DescriptorSetLayouts);
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(true);
var pipeline = new Pipeline(VkCtx, BuildInfo);
vertexBufferStructure.cleanup();
return pipeline;
@ -180,12 +191,12 @@ public class SceneRender {//dynamic rendering
if (B >0.0f&& Math.random() <0.7) B-=0.0005f;
else if (B <= 0.0f) Bb = true;
}
ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f));
AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour);
RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth);
//ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f));
//AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour);
//RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth);
}
public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int ImageIndex){
public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int ImageIndex, int CurrentFrame){
UpdateColours(vulkanContext);
try(var MemStack = MemoryStack.stackPush()){
SwapChain swapChain = vulkanContext.GetSwapChain();
@ -219,22 +230,38 @@ public class SceneRender {//dynamic rendering
vkCmdSetViewport(CommandHandle, 0, Viewport);
var Scissor = VkRect2D.calloc(1,MemStack)
.extent(it -> it.width(width).height(height))
.offset(it->it.x(0).y(0));
.offset(it->it.x(0).y(0));
vkCmdSetScissor(CommandHandle, 0, Scissor);
LongBuffer offsets = MemStack.mallocLong(1).put(0,0L);
LongBuffer vertexBuffer = MemStack.mallocLong(1);
Scene scene = engineInstance.scene();
List<Actor> Actors = scene.GetActors();
int ActorCount = Actors.size();
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0);
DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator();
LongBuffer DescriptorSets = MemStack.mallocLong(3)
LongBuffer DescriptorSets = MemStack.mallocLong(4)
.put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet())
.put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet())
.put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
.put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW).GetVkDescriptorSet())
.put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet())
.put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false);
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true);
vkCmdEndRendering(CommandHandle);
VulkanUtils.ImageBarrier(MemStack, CommandHandle, SwapChainImage,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_2_NONE,
VK_IMAGE_ASPECT_COLOR_BIT);
}
}
private void RenderActors(EngineInstance instance, VkCommandBuffer CommandHandle, ModelsCache modelsCache, MaterialsCache materialsCache, boolean Transparent){
try(var MemStack = MemoryStack.stackPush()){
LongBuffer offsets = MemStack.mallocLong(1).put(0,0L);
LongBuffer vertexBuffer = MemStack.mallocLong(1);
Scene scene = instance.scene();
List<Actor> Actors = scene.GetActors();
int ActorCount = Actors.size();
for(int i = 0; i < ActorCount; i++){
var Actor = Actors.get(i);
@ -250,22 +277,18 @@ public class SceneRender {//dynamic rendering
Logger.warn("Mesh [{}] in model [{}] does not have material",j,model.GetID());
continue;
}
SetPushConstants(CommandHandle, Actor.GetModelMatrix(),MaterialIndex);
vertexBuffer.put(0,VkMesh.VerticesBuffer().GetBuffer());
vkCmdBindVertexBuffers(CommandHandle,0,vertexBuffer,offsets);
vkCmdBindIndexBuffer(CommandHandle,VkMesh.IndicesBuffer().GetBuffer(),0,VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(CommandHandle,VkMesh.IndicesCount(),1,0,0,0);
if(vulkanMaterial.HasTransparency() == Transparent) {
SetPushConstants(CommandHandle, Actor.GetModelMatrix(), MaterialIndex);
vertexBuffer.put(0, VkMesh.VerticesBuffer().GetBuffer());
vkCmdBindVertexBuffers(CommandHandle, 0, vertexBuffer, offsets);
vkCmdBindIndexBuffer(CommandHandle, VkMesh.IndicesBuffer().GetBuffer(), 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(CommandHandle, VkMesh.IndicesCount(), 1, 0, 0, 0);
}
}
}
vkCmdEndRendering(CommandHandle);
VulkanUtils.ImageBarrier(MemStack, CommandHandle, SwapChainImage,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT,
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_2_NONE,
VK_IMAGE_ASPECT_COLOR_BIT);
}
}
private void SetPushConstants(VkCommandBuffer CmdHandle, Matrix4f ModelMatrix, int MaterialIndex){
ModelMatrix.get(0,PushConstBuffer);
PushConstBuffer.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex);
@ -328,6 +351,7 @@ public class SceneRender {//dynamic rendering
.imageView(swapChain.GetVulkanImageView(i).GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
.clearValue(CLearValue);
result[i] = Attachments;
}
@ -336,6 +360,7 @@ public class SceneRender {//dynamic rendering
public void cleanup(VulkanContext VkCtx){
VkPipeline.CleanUp(VkCtx);
Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free);
Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx));
Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free);
Arrays.asList(AttInfoDepth).forEach(VkRenderingAttachmentInfo::free);
Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free);

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Util;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorAllocator;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSet;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
@ -29,6 +30,21 @@ public class VulkanUtils {
matrix.get(Offset, matrixBuffer);
VkBuffer.UnMapMemory(VkCtx);
}
public static VulkanBuffer[] CreateHostVisibleBuffers(VulkanContext VkCtx, long BufferSize, int BufferCount, int Usage, String ID, DescriptorSetLayout layout){
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
Device device = VkCtx.GetDevice();
VulkanBuffer[] Result = new VulkanBuffer[BufferCount];
descriptorAllocator.AddDescriptorSets(device, ID, BufferCount, layout);
DescriptorSetLayout.LayoutInformation LayoutInfo = layout.GetLayoutInfo();
for(int i = 0; i < BufferCount; i++){
Result[i] = new VulkanBuffer(VkCtx, BufferSize, Usage, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(ID, i);
descriptorSet.SetBuffer(device, Result[i], Result[i].GetRequestedSize(), layout.GetLayoutInfo().Binding(),layout.GetLayoutInfo().DescriptorType());
}
return Result;
}
public static VulkanBuffer CreateHostVisibleBuffer(VulkanContext VkCtx, long BufferSize, int Usage, String ID, DescriptorSetLayout layout){
var Buffer = new VulkanBuffer(VkCtx, BufferSize, Usage, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
Device device = VkCtx.GetDevice();