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

Binary file not shown.

View file

@ -0,0 +1,15 @@
{
"ID": "CorvetteOBJ",
"Meshes": [
{
"ID": "cube_0",
"MaterialID": "CorvetteOBJ-mat-1",
"OffsetVertex": 0,
"VertexSize": 452640,
"OffsetIndex": 0,
"IndexSize": 151488
}
],
"VertexPath": "resources/models/Corvette/CorvetteOBJ.vtx",
"IndexPath": "resources/models/Corvette/CorvetteOBJ.idx"
}

View file

@ -0,0 +1,4 @@
# Made in Blockbench 5.1.4
newmtl m_64480dc7-fc68-f52d-eb18-7368900ee2a3
map_Kd corvetteclass.png
newmtl none

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -0,0 +1,32 @@
[
{
"ID": "CorvetteOBJ-mat-0",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "CorvetteOBJ-mat-1",
"TexturePath": "resources\\models\\Corvette\\corvetteclass.png",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "CorvetteOBJ-mat-2",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

View file

@ -0,0 +1,15 @@
{
"ID": "MetroLeadCar",
"Meshes": [
{
"ID": "DoorForward_0",
"MaterialID": "MetroLeadCar-mat-1",
"OffsetVertex": 0,
"VertexSize": 186900,
"OffsetIndex": 0,
"IndexSize": 58032
}
],
"VertexPath": "resources/models/Metro/OBJ/MetroLeadCar.vtx",
"IndexPath": "resources/models/Metro/OBJ/MetroLeadCar.idx"
}

View file

@ -0,0 +1,4 @@
# Made in Blockbench 5.1.4
newmtl m_6a204395-c016-b66d-c397-a01625c2ee08
map_Kd MetroCarLeadDefault.png
newmtl none

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -0,0 +1,32 @@
[
{
"ID": "MetroLeadCar-mat-0",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "MetroLeadCar-mat-1",
"TexturePath": "resources\\models\\Metro\\OBJ\\MetroCarLeadDefault.png",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "MetroLeadCar-mat-2",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
}
]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

View file

@ -1,4 +0,0 @@
# Made in Blockbench 5.1.4
newmtl m_1306cabb-1c39-88cc-7a28-6065072778b2
map_Kd SloopBluePaintedSpruce.png
newmtl none

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -1,15 +0,0 @@
{
"ID": "cube",
"Meshes": [
{
"ID": "cubemtl_0",
"MaterialID": "cube-mat-1",
"OffsetVertex": 0,
"VertexSize": 480,
"OffsetIndex": 0,
"IndexSize": 144
}
],
"VertexPath": "resources/models/cube/cube.vtx",
"IndexPath": "resources/models/cube/cube.idx"
}

View file

@ -1,5 +0,0 @@
newmtl cubemtl
Kd 0.00 0.00 0.00
Ka 0.59 0.45 0.35
Ks 0.59 0.45 0.35
map_Kd cube.png

View file

@ -1,88 +0,0 @@
mtllib cube.mtl
o cube
v -0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 0.500000 0.500000
v 0.500000 0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
v -0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v 0.500000 -0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
vt 0.000000 1.000000
vt 0.250000 1.000000
vt 0.000000 0.500000
vt 0.250000 0.500000
vt 0.250000 1.000000
vt 0.500000 1.000000
vt 0.250000 0.500000
vt 0.500000 0.500000
vt 0.500000 1.000000
vt 0.750000 1.000000
vt 0.500000 0.500000
vt 0.750000 0.500000
vt 0.750000 1.000000
vt 1.000000 1.000000
vt 0.750000 0.500000
vt 1.000000 0.500000
vt 0.000000 0.000000
vt 0.250000 0.000000
vt 0.000000 0.500000
vt 0.250000 0.500000
vt 0.250000 0.500000
vt 0.500000 0.500000
vt 0.250000 0.000000
vt 0.500000 0.000000
vn 0.000000 0.000000 1.000000
vn -1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 0.000000 -1.000000
g cubemtl
usemtl cubemtl
f 1/3/1 2/1/1 4/4/1
f 2/1/1 3/2/1 4/4/1
f 5/8/2 6/6/2 8/7/2
f 6/6/2 7/5/2 8/7/2
f 9/11/3 10/9/3 12/12/3
f 10/9/3 12/12/3 11/10/3
f 13/15/4 14/13/4 15/16/4
f 14/13/4 16/14/4 15/16/4
f 17/19/5 18/17/5 19/20/5
f 18/17/5 20/18/5 19/20/5
f 21/24/6 22/22/6 24/23/6
f 22/22/6 23/21/6 24/23/6

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

View file

@ -1,22 +0,0 @@
[
{
"ID": "cube-mat-0",
"TexturePath": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
}
},
{
"ID": "cube-mat-1",
"TexturePath": "resources/models/cube/cube.png",
"DiffuseColour": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 1.0
}
}
]

View file

@ -12,11 +12,11 @@ struct Material{
uint padding[2];
};
layout(set = 1, binding = 0) readonly buffer MaterialUniform{
layout(set = 2, binding = 0) readonly buffer MaterialUniform{
Material materials[];
} matUniform;
layout(set = 2, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
layout(set = 3, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
layout(push_constant) uniform pc{
layout(offset = 64) uint materialIdx;

View file

@ -2,6 +2,7 @@
layout(location = 0) in vec3 inPos;
layout(location = 1) in vec2 inTextCoords;
layout(location = 0) out vec2 outTextCoords;
@ -9,12 +10,16 @@ layout(set = 0, binding = 0) uniform ProjUniform{
mat4 matrix;
} projUniform;
layout(set = 1, binding = 0) uniform ViewUniform{
mat4 matrix;
} viewUniform;
layout(push_constant) uniform pc{
mat4 modelMatrix;
} push_constants;
void main()
{
gl_Position = projUniform.matrix * push_constants.modelMatrix * vec4(inPos,1);
gl_Position = projUniform.matrix * viewUniform.matrix * push_constants.modelMatrix * vec4(inPos,1);
outTextCoords = inTextCoords;
}

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,8 +128,8 @@ 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).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),
@ -149,10 +159,11 @@ public class SceneRender {//dynamic rendering
.SetDepthFormat(DEPTH_FORMAT)
.SetPushConstantRanges(
new PushConstantsRange[]{
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.MATRIX4X4_SIZE * 2),
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();
@ -222,19 +233,35 @@ public class SceneRender {//dynamic rendering
.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,6 +277,7 @@ public class SceneRender {//dynamic rendering
Logger.warn("Mesh [{}] in model [{}] does not have material",j,model.GetID());
continue;
}
if(vulkanMaterial.HasTransparency() == Transparent) {
SetPushConstants(CommandHandle, Actor.GetModelMatrix(), MaterialIndex);
vertexBuffer.put(0, VkMesh.VerticesBuffer().GetBuffer());
vkCmdBindVertexBuffers(CommandHandle, 0, vertexBuffer, offsets);
@ -257,15 +285,10 @@ public class SceneRender {//dynamic rendering
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();