diff --git a/build.gradle b/build.gradle index e8641a2..c5f792e 100644 --- a/build.gradle +++ b/build.gradle @@ -12,18 +12,6 @@ eclipse { classpath { downloadJavadoc = true downloadSources = true - file { - whenMerged { cp -> - cp.entries.forEach { entry -> - // Target the core LWJGL modules - if (entry.kind == 'lib' && entry.path.contains('org.lwjgl')) { - // Dynamically add a JPMS modular export rule to the Eclipse compiler - def rule = new org.gradle.plugins.ide.eclipse.model.AccessRule('accessible', 'org/lwjgl/system/**') - entry.accessRules.add(rule) - } - } - } - } } } @@ -87,8 +75,6 @@ jar { it.isDirectory() ? it : zipTree(it) } } - exclude('**/*.LIST') - exclude('**/module-info.class') duplicatesStrategy = DuplicatesStrategy.INCLUDE } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/VertexBuffer.java b/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/VertexBuffer.java index 439a20d..6d84b2d 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/VertexBuffer.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/VertexBuffer.java @@ -2,18 +2,27 @@ package speiger.src.coreengine.graphics.api.buffer; import java.nio.Buffer; import java.nio.ByteBuffer; +import java.util.List; import org.lwjgl.system.MemoryUtil; -import speiger.src.coreengine.graphics.api.core.GraphicsResource; +import speiger.src.collections.ints.misc.pairs.IntObjectPair; +import speiger.src.coreengine.graphics.api.buffer.states.BufferState; +import speiger.src.coreengine.graphics.api.buffer.states.BufferType; +import speiger.src.coreengine.graphics.api.utils.GraphicsResource; public abstract class VertexBuffer implements GraphicsResource { + protected final BufferType type; protected final BufferState usage; protected int size; - public VertexBuffer(BufferState usage, int size) { + public VertexBuffer(BufferType type, BufferState usage) { + this.type = type; this.usage = usage; - this.size = size; + } + + public BufferType type() { + return type; } public BufferState usage() { @@ -24,6 +33,9 @@ public abstract class VertexBuffer implements GraphicsResource { return size; } + public abstract VertexBuffer bind(); + public abstract VertexBuffer unbind(); + public abstract VertexBuffer allocate(int totalBytes); public abstract VertexBuffer set(long pointer, int totalBytes); public VertexBuffer set(ByteBuffer buffer) { @@ -35,10 +47,17 @@ public abstract class VertexBuffer implements GraphicsResource { return fill(MemoryUtil.memAddress(buffer), buffer.remaining(), offset); } - public abstract VertexBuffer read(long pointer, int totalbytes, int offset); + public abstract VertexBuffer read(long pointer, int totalBytes, int offset); public VertexBuffer read(Buffer buffer, int totalBytes, int offset) { - return read(MemoryUtil.memAddress(buffer), totalBytes, offset); + read(MemoryUtil.memAddress(buffer), totalBytes, offset); + buffer.flip(); + return this; } + public VertexBuffer fill(List> data) { return fill(0, data); } + public abstract VertexBuffer fill(int offset, List> data); + public abstract VertexBuffer shrink(int newSize); + public abstract VertexBuffer grow(int newSize); + public abstract VertexBuffer shift(int source, int dest, int length); } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/BufferState.java b/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/states/BufferState.java similarity index 68% rename from src/graphics/java/speiger/src/coreengine/graphics/api/buffer/BufferState.java rename to src/graphics/java/speiger/src/coreengine/graphics/api/buffer/states/BufferState.java index bdf07e6..3a69591 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/BufferState.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/states/BufferState.java @@ -1,4 +1,4 @@ -package speiger.src.coreengine.graphics.api.buffer; +package speiger.src.coreengine.graphics.api.buffer.states; public enum BufferState { STATIC_DRAW, diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/states/BufferType.java b/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/states/BufferType.java new file mode 100644 index 0000000..9da4a92 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/buffer/states/BufferType.java @@ -0,0 +1,17 @@ +package speiger.src.coreengine.graphics.api.buffer.states; + +public enum BufferType { + ARRAY_BUFFER, + ELEMENT_BUFFER, + UNIFORM_BUFFER, + DRAW_INDIRECT_BUFFER, + TEXTURE_BUFFER, + PIXEL_PACK_BUFFER, + PIXEL_UNPACK_BUFFER, + TRANSFORM_FEEDBACK_BUFFER, + COPY_READ_BUFFER, + COPY_WRITE_BUFFER, + ATOMIC_COUNTER_BUFFER, + DISPATCH_INDIRECT_BUFFER, + SHADER_STORAGE_BUFFER; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/core/Graphics.java b/src/graphics/java/speiger/src/coreengine/graphics/api/core/Graphics.java index cc2e2ae..199a6cd 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/core/Graphics.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/core/Graphics.java @@ -5,5 +5,6 @@ import speiger.src.coreengine.rendering.input.window.Window; public interface Graphics { public String getName(); + public void setupWindowArguments(); public GraphicsDevice createDevice(Window window); } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsCommandQueue.java b/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsCommandQueue.java index 58f8d79..4fd6278 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsCommandQueue.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsCommandQueue.java @@ -1,5 +1,17 @@ package speiger.src.coreengine.graphics.api.core; +import speiger.src.coreengine.graphics.api.texture.Texture; +import speiger.src.coreengine.graphics.api.utils.PushableResource; +import speiger.src.coreengine.math.vector.floats.Vec4f; + public interface GraphicsCommandQueue { + public static final int CLEAR_COLOR = 1; + public static final int CLEAR_DEPTH = 2; + public PushableResource pushClearColor(Vec4f color); + public PushableResource pushClearDepth(double value); -} + public void clearTexture(Texture texture, int clearParam); + public void clearTexture(Texture texture, int x, int y, int width, int height, int clearParam); + + +} \ No newline at end of file diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsDevice.java b/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsDevice.java index 24314df..6007bb3 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsDevice.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsDevice.java @@ -1,12 +1,18 @@ package speiger.src.coreengine.graphics.api.core; import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; +import speiger.src.coreengine.graphics.api.buffer.states.BufferState; +import speiger.src.coreengine.graphics.api.buffer.states.BufferType; +import speiger.src.coreengine.graphics.api.sampler.Sampler; +import speiger.src.coreengine.graphics.api.sampler.SamplerSettings; import speiger.src.coreengine.graphics.api.texture.Texture; -import speiger.src.coreengine.rendering.input.window.Window; +import speiger.src.coreengine.graphics.api.texture.TextureSettings; public interface GraphicsDevice { - public GraphicsSurface createSurface(Window window); + public GraphicsSurface createSurface(); public GraphicsCommandQueue getQueue(); - public VertexBuffer createBuffer(); - public Texture createTexture(); + public VertexBuffer createBuffer(BufferType type, BufferState state); + public VertexBuffer createBuffer(BufferType type, BufferState state, int allocatedBytes); + public Texture createTexture(TextureSettings data, int width, int height); + public Sampler createSampler(SamplerSettings settings); } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsSurface.java b/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsSurface.java index bb5dbf6..fe3ef72 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsSurface.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsSurface.java @@ -2,4 +2,6 @@ package speiger.src.coreengine.graphics.api.core; public interface GraphicsSurface { public void setVsync(boolean value); + public void beginFrame(); + public void finishFrame(); } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/Sampler.java b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/Sampler.java index cac7dd3..78ab295 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/Sampler.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/Sampler.java @@ -1,7 +1,9 @@ package speiger.src.coreengine.graphics.api.sampler; -public abstract class Sampler { - SamplerSettings settings; +import speiger.src.coreengine.graphics.api.utils.GraphicsResource; + +public abstract class Sampler implements GraphicsResource { + protected SamplerSettings settings; public Sampler(SamplerSettings settings) { this.settings = settings; diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/SamplerSettings.java b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/SamplerSettings.java index 8a7e186..9dc31a0 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/SamplerSettings.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/SamplerSettings.java @@ -1,5 +1,60 @@ package speiger.src.coreengine.graphics.api.sampler; -public class SamplerSettings { +import java.util.Objects; +import java.util.Optional; + +import speiger.src.coreengine.graphics.api.sampler.states.BorderMode; +import speiger.src.coreengine.graphics.api.sampler.states.SampleMode; + +public record SamplerSettings(BorderMode wrapS, BorderMode wrapT, Optional wrapR, SampleMode minSample, SampleMode magSample) { + public SamplerSettings { + Objects.requireNonNull(wrapS); + Objects.requireNonNull(wrapT); + Objects.requireNonNull(wrapR); + Objects.requireNonNull(minSample); + Objects.requireNonNull(magSample); + } + + public static class Builder { + BorderMode wrapS; + BorderMode wrapT; + BorderMode wrapR; + SampleMode minSample; + SampleMode magSample; + + public Builder wrapS(BorderMode mode) { + wrapS = Objects.requireNonNull(mode); + return this; + } + + public Builder wrapT(BorderMode mode) { + wrapT = Objects.requireNonNull(mode); + return this; + } + + public Builder wrapR(BorderMode mode) { + wrapR = mode; + return this; + } + + public Builder minSample(SampleMode mode) { + minSample = Objects.requireNonNull(mode); + return this; + } + + public Builder magSample(SampleMode mode) { + if(mode != SampleMode.LINEAR && mode != SampleMode.NEAREST) throw new IllegalArgumentException("["+mode+"] is not supported in mag filter"); + magSample = Objects.requireNonNull(mode); + return this; + } + + public SamplerSettings build() { + return new SamplerSettings(Objects.requireNonNull(wrapS, "X Wrap should be defined"), + Objects.requireNonNull(wrapT, "Y Wrap should be defined"), + Optional.ofNullable(wrapR), + Objects.requireNonNull(minSample, "Min Sample should be defined"), + Objects.requireNonNull(magSample, "Mag Sample should be defined")); + } + } } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/states/BorderMode.java b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/states/BorderMode.java new file mode 100644 index 0000000..77c3465 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/states/BorderMode.java @@ -0,0 +1,9 @@ +package speiger.src.coreengine.graphics.api.sampler.states; + +public enum BorderMode { + CLAMP_TO_EDGE, + CLAMP_TO_BORDER, + MIRRORED_REPEAT, + REPEAT, + MIRROR_CLAMP_TO_EDGE; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/states/SampleMode.java b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/states/SampleMode.java new file mode 100644 index 0000000..f85e07a --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/sampler/states/SampleMode.java @@ -0,0 +1,10 @@ +package speiger.src.coreengine.graphics.api.sampler.states; + +public enum SampleMode { + NEAREST, + LINEAR, + NEAREST_MIPMAP_NEAREST, + LINEAR_MIPMAP_NEAREST, + NEAREST_MIPMAP_LINEAR, + LINEAR_MIPMAP_LINEAR; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/BufferAttribute.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/BufferAttribute.java new file mode 100644 index 0000000..3476470 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/BufferAttribute.java @@ -0,0 +1,32 @@ +package speiger.src.coreengine.graphics.api.shader; + +import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType; + +public record BufferAttribute(int index, int size, GraphicsDataType type, boolean normal, int instancedAmount) { + public BufferAttribute(int index, int size) { + this(index, size, GraphicsDataType.FLOAT, false, 0); + } + + public BufferAttribute(int index, int size, GraphicsDataType type) { + this(index, size, type, false, 0); + } + + public BufferAttribute(int index, int size, GraphicsDataType type, boolean normal) { + this(index, size, type, normal, 0); + } + + public BufferAttribute(int index, int size, GraphicsDataType type, int instancedAmount) { + this(index, size, type, false, instancedAmount); + } + + public static BufferAttribute[] array(int startIndex, int width, int size, GraphicsDataType type) { return array(startIndex, width, size, type, false, 0); } + public static BufferAttribute[] array(int startIndex, int width, int size, GraphicsDataType type, boolean normal) { return array(startIndex, width, size, type, normal, 0); } + public static BufferAttribute[] array(int startIndex, int width, int size, GraphicsDataType type, int instanceAmount) { return array(startIndex, width, size, type, false, instanceAmount); } + public static BufferAttribute[] array(int startIndex, int width, int size, GraphicsDataType type, boolean normal, int instancedAmount) { + BufferAttribute[] attributes = new BufferAttribute[width]; + for(int i = 0;i < width;i++) { + attributes[i] = new BufferAttribute(startIndex + i, size, type, normal, instancedAmount); + } + return attributes; + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/ColorTarget.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/ColorTarget.java new file mode 100644 index 0000000..529b15c --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/ColorTarget.java @@ -0,0 +1,24 @@ +package speiger.src.coreengine.graphics.api.shader; + +import java.util.Objects; +import java.util.Optional; + +import speiger.src.coreengine.graphics.api.shader.states.BlendFunction; + +public record ColorTarget(Optional blend, int writeMask) { + public static final int RED = 1; + public static final int GREEN = 2; + public static final int BLUE = 4; + public static final int ALPHA = 8; + public static final int ALL = 15; + public static final ColorTarget DEFAULT = new ColorTarget(null); + + public ColorTarget { + Objects.requireNonNull(blend); + if(writeMask < 0 || writeMask > ALL) throw new IllegalArgumentException("WriteMask has to be within 0-15"); + } + + public ColorTarget(BlendFunction function) { + this(Optional.ofNullable(function), ALL); + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/DepthTarget.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/DepthTarget.java new file mode 100644 index 0000000..c02ddb4 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/DepthTarget.java @@ -0,0 +1,13 @@ +package speiger.src.coreengine.graphics.api.shader; + +import java.util.Objects; + +import speiger.src.coreengine.graphics.api.utils.AlphaFunction; + +public record DepthTarget(AlphaFunction function, boolean write) { + public static final DepthTarget DEFAULT = new DepthTarget(AlphaFunction.GEQUAL, true); + + public DepthTarget { + Objects.requireNonNull(function); + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/ShaderPipeline.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/ShaderPipeline.java new file mode 100644 index 0000000..38c5132 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/ShaderPipeline.java @@ -0,0 +1,139 @@ +package speiger.src.coreengine.graphics.api.shader; + +import java.util.Collections; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import speiger.src.collections.objects.lists.ImmutableObjectList; +import speiger.src.collections.objects.lists.ObjectArrayList; +import speiger.src.collections.objects.lists.ObjectList; +import speiger.src.collections.objects.sets.ObjectOpenHashSet; +import speiger.src.collections.objects.sets.ObjectSet; +import speiger.src.coreengine.assets.AssetLocation; +import speiger.src.coreengine.graphics.api.shader.states.DrawMode; +import speiger.src.coreengine.graphics.api.shader.states.PolygonMode; +import speiger.src.coreengine.graphics.api.shader.states.ShaderType; + +public record ShaderPipeline(AssetLocation id, Map shaders, List> attributes, List attributeNames, Set uniforms, Set samplers, DrawMode mode, PolygonMode fillMode, boolean cullBack, ColorTarget colorTarget, DepthTarget depthTarget) { + + public ShaderPipeline { + Objects.requireNonNull(id); + if(shaders.isEmpty()) throw new IllegalStateException("Shaders isn't allowed to be empty"); + Objects.requireNonNull(uniforms); + Objects.requireNonNull(samplers); + Objects.requireNonNull(mode); + Objects.requireNonNull(fillMode); + Objects.requireNonNull(colorTarget); + Objects.requireNonNull(depthTarget); + } + + public static Builder builder(AssetLocation id) { + return new Builder(id); + } + + public Builder copy(AssetLocation id) { + return new Builder(id, this); + } + + public static class Builder { + AssetLocation id; + EnumMap shaders = new EnumMap<>(ShaderType.class); + ObjectList attributeNames = new ObjectArrayList<>(); + @SuppressWarnings("unchecked") + ObjectList> attributes = ObjectArrayList.wrap(new List[8]); + ObjectSet uniforms = new ObjectOpenHashSet<>(); + ObjectSet samplers = new ObjectOpenHashSet<>(); + DrawMode drawMode; + PolygonMode fillMode = PolygonMode.FILL; + boolean cullBack = true; + ColorTarget colorTarget = ColorTarget.DEFAULT; + DepthTarget depthTarget = DepthTarget.DEFAULT; + + private Builder(AssetLocation id) { + this.id = Objects.requireNonNull(id); + + } + + private Builder(AssetLocation id, ShaderPipeline line) { + this(id); + shaders.putAll(line.shaders()); + attributeNames.addAll(line.attributeNames()); + for(int i = 0,m=line.attributes().size();i= 8) throw new IndexOutOfBoundsException(index); + this.attributes.set(index, new ImmutableObjectList<>(attributes)); + return this; + } + + public Builder clearBufferFormat(int index) { + if(index < 0 || index >= 8) throw new IndexOutOfBoundsException(index); + attributes.set(index, null); + return this; + } + + public Builder withColorTarget(ColorTarget target) { + this.colorTarget = Objects.requireNonNull(target); + return this; + } + + public Builder withDepthTarget(DepthTarget target) { + this.depthTarget = Objects.requireNonNull(target); + return this; + } + + public ShaderPipeline build() { + if(shaders.isEmpty()) throw new IllegalStateException("Shaders must be provided in a Shader Pipeline"); + return new ShaderPipeline(id, Collections.unmodifiableMap(shaders), attributes.unmodifiable(), attributeNames.unmodifiable(), uniforms.unmodifiable(), samplers.unmodifiable(), Objects.requireNonNull(drawMode, "Draw Mode has to be defined"), fillMode, cullBack, colorTarget, depthTarget); + } + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/BlendFactor.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/BlendFactor.java new file mode 100644 index 0000000..60956f3 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/BlendFactor.java @@ -0,0 +1,19 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public enum BlendFactor { + ZERO, + ONE, + CONSTANT_COLOR, + CONSTANT_ALPHA, + SRC_COLOR, + SRC_ALPHA, + DST_COLOR, + DST_ALPHA, + ONE_MINUS_SRC_COLOR, + ONE_MINUS_SRC_ALPHA, + ONE_MINUS_DST_COLOR, + ONE_MINUS_DST_ALPHA, + ONE_MINUS_CONSTANT_COLOR, + ONE_MINUS_CONSTANT_ALPHA, + SRC_ALPHA_SATURATE; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/BlendFunction.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/BlendFunction.java new file mode 100644 index 0000000..535c599 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/BlendFunction.java @@ -0,0 +1,7 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public record BlendFunction(BlendFactor colorSource, BlendFactor alphaSource, BlendFactor colorTarget, BlendFactor alphaTarget) { + public BlendFunction(BlendFactor source, BlendFactor target) { + this(source, BlendFactor.ONE, target, BlendFactor.ZERO); + } +} \ No newline at end of file diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/DrawMode.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/DrawMode.java new file mode 100644 index 0000000..24ee582 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/DrawMode.java @@ -0,0 +1,34 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public enum DrawMode { + POINT(1), + LINES(2), + LINE_STRIP(2, true), + LINE_LOOP(2, true), + TRIANGLES(3), + TRIANGLE_STRIP(3, true), + TRIANGLE_FAN(3, true), + QUADS(4); + + int length; + boolean isConnective; + + private DrawMode(int length) { + this(length, false); + } + + private DrawMode(int length, boolean isConnective) { + this.length = length; + this.isConnective = isConnective; + } + + public int primitiveLength() { return length; } + public boolean isConnective() { return isConnective; } + public int indeciesCount(int vertecies) { + return switch(this) { + case POINT, LINE_STRIP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN -> vertecies; + case LINES, QUADS -> vertecies / 4 * 6; + default -> 0; + }; + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/GraphicsDataType.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/GraphicsDataType.java new file mode 100644 index 0000000..fb7f5ff --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/GraphicsDataType.java @@ -0,0 +1,76 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public enum GraphicsDataType { + BYTE("byte", 1, PrimitiveType.BYTE), + UNSIGNED_BYTE("u_byte", 1, PrimitiveType.BYTE, true, false), + SHORT("short", 2, PrimitiveType.SHORT), + UNSIGNED_SHORT("u_short", 2, PrimitiveType.SHORT, true, false), + INT("int", 4, PrimitiveType.INT), + UNSIGNED_INT("u_int", 4, PrimitiveType.INT, true, false), + FLOAT("float", 4, PrimitiveType.FLOAT), + DOUBLE("double", 8, PrimitiveType.DOUBLE), + + //CompressedTypes + UNSIGNED_3_3_2("u_byte_3_3_2", 1, PrimitiveType.BYTE), + UNSIGNED_2_3_3_REV("u_byte_2_3_3_rev", 1, PrimitiveType.BYTE), + UNSIGNED_5_6_5("u_short_5_6_5", 2, PrimitiveType.SHORT), + UNSIGNED_5_6_5_REV("u_short_5_6_5_rev", 2, PrimitiveType.SHORT), + UNSIGNED_4_4_4_4("u_short_4_4_4_4", 2, PrimitiveType.SHORT), + UNSIGNED_4_4_4_4_REV("u_short_4_4_4_4_rev", 2, PrimitiveType.SHORT), + UNSIGNED_5_5_5_1("u_short_5_5_5_1", 2, PrimitiveType.SHORT), + UNSIGNED_1_5_5_5_REV("u_short_1_5_5_5_rev", 2, PrimitiveType.SHORT), + UNSIGNED_8_8_8_8("u_int_8_8_8_8", 4, PrimitiveType.INT), + UNSIGNED_8_8_8_8_REV("u_int_8_8_8_8_rev", 4, PrimitiveType.INT), + UNSIGNED_10_10_10_2("u_int_10_10_10_2", 4, PrimitiveType.INT), + UNSIGNED_2_10_10_10_REV("u_int_2_10_10_10_rev", 4, PrimitiveType.INT), + + UNSIGNED_INT_10F_11F_11F_REV("u_int_10_11_11_rev", 4, PrimitiveType.INT), + UNSIGNED_INT_5_9_9_9_REV("u_int_5_9_9_9_rev", 4, PrimitiveType.INT); + + String name; + int byteSize; + PrimitiveType type; + boolean supportsIBO; + boolean isCompound; + + private GraphicsDataType(String name, int byteSize, PrimitiveType type, boolean supportsIBO, boolean isCompound) { + this.name = name; + this.byteSize = byteSize; + this.type = type; + this.supportsIBO = supportsIBO; + this.isCompound = isCompound; + } + + private GraphicsDataType(String name, int byteSize, PrimitiveType type, boolean isCompound) { + this(name, byteSize, type, false, isCompound); + } + + private GraphicsDataType(String name, int byteSize, PrimitiveType type) { + this(name, byteSize, type, false, false); + } + + public String idName() { + return name; + } + + public int byteSize() { + return byteSize; + } + + public PrimitiveType type() { + return type; + } + + public boolean supportsIBO() { + return supportsIBO; + } + + public boolean isCompound() { + return isCompound; + } + + public int size(int attributes) { + return isCompound ? byteSize : attributes * byteSize; + } + +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/PolygonMode.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/PolygonMode.java new file mode 100644 index 0000000..569c7ef --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/PolygonMode.java @@ -0,0 +1,7 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public enum PolygonMode { + POINT, + LINE, + FILL; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/PrimitiveType.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/PrimitiveType.java new file mode 100644 index 0000000..4b8bc0f --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/PrimitiveType.java @@ -0,0 +1,10 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public enum PrimitiveType { + BYTE, + SHORT, + INT, + LONG, + FLOAT, + DOUBLE; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/ShaderType.java b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/ShaderType.java new file mode 100644 index 0000000..d589ebd --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/shader/states/ShaderType.java @@ -0,0 +1,9 @@ +package speiger.src.coreengine.graphics.api.shader.states; + +public enum ShaderType { + VERTEX, + FRAGMENT, + GEOMETRY, + TESSELATION_CONTROL, + TESSELATION_EVALUATION; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/texture/Texture.java b/src/graphics/java/speiger/src/coreengine/graphics/api/texture/Texture.java index 4130b21..8105ae4 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/texture/Texture.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/texture/Texture.java @@ -1,12 +1,24 @@ package speiger.src.coreengine.graphics.api.texture; -import speiger.src.coreengine.graphics.api.core.GraphicsResource; +import speiger.src.coreengine.graphics.api.utils.GraphicsResource; public abstract class Texture implements GraphicsResource { final TextureSettings settings; + int width; + int height; - public Texture(TextureSettings settings) { + public Texture(TextureSettings settings, int width, int height) { this.settings = settings; + this.width = width; + this.height = height; + } + + public int width() { + return width; + } + + public int height() { + return height; } public TextureSettings settings() { diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/texture/TextureSettings.java b/src/graphics/java/speiger/src/coreengine/graphics/api/texture/TextureSettings.java index 41d3969..10945a2 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/texture/TextureSettings.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/texture/TextureSettings.java @@ -1,6 +1,5 @@ package speiger.src.coreengine.graphics.api.texture; -import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.OptionalInt; @@ -11,7 +10,17 @@ import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask; import speiger.src.coreengine.graphics.api.texture.states.TextureFormat; import speiger.src.coreengine.graphics.api.texture.states.TextureType; -public record TextureSettings(TextureType type, TextureFormat internal, TextureFormat external, boolean generateMipmapping, OptionalInt baseLevel, OptionalInt maxLevel, List> swizzle, Optional stencilType) { +public record TextureSettings(TextureType type, TextureFormat internal, TextureFormat external, boolean generateMipmapping, OptionalInt baseLevel, OptionalInt maxLevel, ImmutableObjectList> swizzle, Optional stencilType) { + + public TextureSettings { + Objects.requireNonNull(type, "Texture Type shouldn't be null"); + Objects.requireNonNull(internal, "Internal Format shouldn't be null"); + Objects.requireNonNull(external, "External Format shouldn't be null"); + Objects.requireNonNull(baseLevel); + Objects.requireNonNull(maxLevel); + Objects.requireNonNull(swizzle); + Objects.requireNonNull(stencilType); + } public Builder copy() { return new Builder(this); } public static Builder builder() { return new Builder(); } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/texture/states/StencilType.java b/src/graphics/java/speiger/src/coreengine/graphics/api/texture/states/StencilType.java index 032a2b4..36c6ea8 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/texture/states/StencilType.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/texture/states/StencilType.java @@ -1,6 +1,6 @@ package speiger.src.coreengine.graphics.api.texture.states; public enum StencilType { - DEPTH_COMPONENT, - STENCIL_INDEX + GL_COMPARE_REF_TO_TEXTURE, + GL_NONE } diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/utils/AlphaFunction.java b/src/graphics/java/speiger/src/coreengine/graphics/api/utils/AlphaFunction.java new file mode 100644 index 0000000..d6bcf99 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/utils/AlphaFunction.java @@ -0,0 +1,12 @@ +package speiger.src.coreengine.graphics.api.utils; + +public enum AlphaFunction { + NEVER, + LESS, + EQUAL, + LEQUAL, + GREATER, + NOTEQUAL, + GEQUAL, + ALWAYS; +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsResource.java b/src/graphics/java/speiger/src/coreengine/graphics/api/utils/GraphicsResource.java similarity index 72% rename from src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsResource.java rename to src/graphics/java/speiger/src/coreengine/graphics/api/utils/GraphicsResource.java index 4674765..f9b4e2c 100644 --- a/src/graphics/java/speiger/src/coreengine/graphics/api/core/GraphicsResource.java +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/utils/GraphicsResource.java @@ -1,4 +1,4 @@ -package speiger.src.coreengine.graphics.api.core; +package speiger.src.coreengine.graphics.api.utils; public interface GraphicsResource extends AutoCloseable { public boolean isRemoved(); diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/utils/PushableResource.java b/src/graphics/java/speiger/src/coreengine/graphics/api/utils/PushableResource.java new file mode 100644 index 0000000..95e98ad --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/utils/PushableResource.java @@ -0,0 +1,6 @@ +package speiger.src.coreengine.graphics.api.utils; + +public interface PushableResource extends AutoCloseable { + @Override + public void close(); +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/vertex/VertexElement.java b/src/graphics/java/speiger/src/coreengine/graphics/api/vertex/VertexElement.java new file mode 100644 index 0000000..55c46ac --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/vertex/VertexElement.java @@ -0,0 +1,12 @@ +package speiger.src.coreengine.graphics.api.vertex; + +public record VertexElement(int size, Usage usage) +{ + public static enum Usage { + POS, + UV, + COLOR, + NORMAL, + CUSTOM; + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/api/vertex/VertexFormat.java b/src/graphics/java/speiger/src/coreengine/graphics/api/vertex/VertexFormat.java new file mode 100644 index 0000000..8496e84 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/api/vertex/VertexFormat.java @@ -0,0 +1,78 @@ +package speiger.src.coreengine.graphics.api.vertex; + +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; + +import speiger.src.collections.ints.lists.IntArrayList; +import speiger.src.collections.ints.lists.IntList; +import speiger.src.collections.objects.lists.ObjectArrayList; +import speiger.src.collections.objects.lists.ObjectList; +import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap; +import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap; +import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap.Entry; +import speiger.src.collections.objects.utils.ObjectIterators; +import speiger.src.coreengine.graphics.api.vertex.VertexElement.Usage; + +public class VertexFormat implements Iterable { + Object2ObjectMap mappedElements = new Object2ObjectLinkedOpenHashMap<>(); + ObjectList elements = new ObjectArrayList<>(); + Set types = EnumSet.noneOf(Usage.class); + IntList offsets = new IntArrayList(); + int totalOffset; + + private VertexFormat() {} + + private VertexFormat(VertexFormat vertexList) { + elements.addAll(vertexList.elements); + offsets.addAll(vertexList.offsets); + totalOffset = vertexList.totalOffset; + } + + public static Builder builder() { + return new Builder(); + } + + public static Builder builder(VertexFormat format) { + return new Builder(format); + } + + private void add(String name, VertexElement element) { + if(mappedElements.put(name, element) != null) throw new IllegalStateException("Duplicated Names are not allowed"); + elements.add(element); + offsets.add(totalOffset); + totalOffset += element.size(); + types.add(element.usage()); + } + + public int totalOffset() { return totalOffset; } + public int size() { return elements.size(); } + public VertexElement get(int index) { return elements.get(index); } + public int offset(int index) { return offsets.getInt(index); } + public Iterable> entrySet() { return mappedElements.object2ObjectEntrySet().unmodifiable(); } + @Override + public Iterator iterator() { return ObjectIterators.unmodifiable(elements.iterator()); } + public boolean hasType(Usage type) { return types.contains(type); } + public boolean hasName(String name) { return mappedElements.containsKey(name); } + + public static class Builder { + VertexFormat format; + + public Builder() { + format = new VertexFormat(); + } + + public Builder(VertexFormat prev) { + format = new VertexFormat(prev); + } + + public Builder add(String name, VertexElement element) { + format.add(name, element); + return this; + } + + public VertexFormat build() { + return format; + } + } +} \ No newline at end of file diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/buffer/GLVertexBuffer.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/buffer/GLVertexBuffer.java new file mode 100644 index 0000000..e299f49 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/buffer/GLVertexBuffer.java @@ -0,0 +1,139 @@ +package speiger.src.coreengine.graphics.opengl.buffer; + +import java.nio.ByteBuffer; +import java.util.List; + +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL45; +import org.lwjgl.system.MemoryUtil; + +import speiger.src.collections.ints.misc.pairs.IntObjectPair; +import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; +import speiger.src.coreengine.graphics.api.buffer.states.BufferState; +import speiger.src.coreengine.graphics.api.buffer.states.BufferType; +import speiger.src.coreengine.graphics.opengl.utils.GLUtils; +import speiger.src.coreengine.rendering.utils.AllocationTracker; +import speiger.src.coreengine.utils.io.GameLog; + +public class GLVertexBuffer extends VertexBuffer { + int id; + public GLVertexBuffer(BufferType type, BufferState usage) { + super(type, usage); + id = GL45.glCreateBuffers(); + } + + public GLVertexBuffer(BufferType type, BufferState usage, int totalBytes) { + super(type, usage); + id = GL45.glCreateBuffers(); + bind().allocate(totalBytes).unbind(); + } + + public int id() { + return id; + } + + @Override + public boolean isRemoved() { + return id == 0; + } + + @Override + public void remove() { + if(id == 0) return; + GL15.glDeleteBuffers(id); + id = 0; + } + + @Override + public GLVertexBuffer bind() { + GL15.glBindBuffer(GLUtils.toGL(type), id); + return this; + } + + @Override + public GLVertexBuffer unbind() { + GL15.glBindBuffer(GLUtils.toGL(type), 0); + return this; + } + + @Override + public GLVertexBuffer allocate(int totalBytes) { + this.size = totalBytes; + GL45.glNamedBufferData(id, totalBytes, GLUtils.toGL(usage)); + return this; + } + + @Override + public GLVertexBuffer set(long pointer, int totalBytes) { + this.size = totalBytes; + GL45.nglNamedBufferData(id, totalBytes, pointer, GLUtils.toGL(usage)); + return this; + } + + @Override + public GLVertexBuffer fill(long pointer, int totalBytes, int offset) { + GL45.nglNamedBufferSubData(id, offset, totalBytes, pointer); + return this; + } + + @Override + public GLVertexBuffer read(long pointer, int totalBytes, int offset) { + GL45.nglGetNamedBufferSubData(id, offset, totalBytes, pointer); + return this; + } + + @Override + public GLVertexBuffer fill(int offset, List> data) { + if(data.size() > 0) { + ByteBuffer buffer = GL45.glMapNamedBuffer(id, GL15.GL_WRITE_ONLY); + for(int i = 0,m = data.size();i < m;i++) { + IntObjectPair entry = data.get(i); + buffer.position(entry.getIntKey() + offset); + buffer.put(entry.getValue()); + } + buffer.flip(); + if(!GL45.glUnmapNamedBuffer(id)) GameLog.info("Memory Corruption?"); + } + return this; + } + + @Override + public GLVertexBuffer shrink(int newSize) { + if(size <= newSize) throw new IllegalArgumentException("New Size ["+newSize+"] is bigger then the buffer ["+size+"]"); + ByteBuffer buffer = GL45.glMapNamedBuffer(id, GL15.GL_READ_WRITE); + if(size != buffer.remaining()) throw new IllegalStateException("Grow Function found inconsisten data: Found=["+buffer.remaining()+"], Expected=["+size+"]"); + ByteBuffer newBuff = MemoryUtil.memAlloc(newSize); + MemoryUtil.memCopy(MemoryUtil.memAddress(buffer), MemoryUtil.memAddress(newBuff), newSize); + newBuff.position(newSize).flip(); + GL45.glUnmapNamedBuffer(id); + + set(MemoryUtil.memAddress(newBuff), newSize); + MemoryUtil.memFree(newBuff); + return this; + } + + @Override + public GLVertexBuffer grow(int newSize) { + if(size >= newSize) throw new IllegalArgumentException("New Size ["+newSize+"] is smaller then the buffer ["+size+"]"); + ByteBuffer buffer = GL45.glMapNamedBuffer(id, GL15.GL_READ_ONLY); + if(size != buffer.remaining()) throw new IllegalStateException("Grow Function found inconsisten data: Found=["+buffer.remaining()+"], Expected=["+size+"]"); + ByteBuffer newBuff = MemoryUtil.memAlloc(newSize); + MemoryUtil.memCopy(MemoryUtil.memAddress(buffer), MemoryUtil.memAddress(newBuff), size); + newBuff.position(newSize).flip(); + GL45.glUnmapNamedBuffer(id); + + set(MemoryUtil.memAddress(newBuff), newSize); + MemoryUtil.memFree(newBuff); + return this; + } + + @Override + public GLVertexBuffer shift(int source, int dest, int length) { + if(source < 0 || source + length >= size) throw new ArrayIndexOutOfBoundsException(); + if(dest < 0 || dest + length >= size) throw new ArrayIndexOutOfBoundsException(); + GL45.glCopyNamedBufferSubData(id, id, source, dest, length); + AllocationTracker.INSTANCE.addGPUBytes(length*2); + return this; + } + +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLGraphics.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLGraphics.java new file mode 100644 index 0000000..8e531c8 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLGraphics.java @@ -0,0 +1,28 @@ +package speiger.src.coreengine.graphics.opengl.core; + +import org.lwjgl.glfw.GLFW; + +import speiger.src.coreengine.graphics.api.core.Graphics; +import speiger.src.coreengine.rendering.input.window.Window; + +public class GLGraphics implements Graphics { + + @Override + public String getName() { + return "OpenGL"; + } + + @Override + public void setupWindowArguments() { + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4); + GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 0); + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE); + GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE); + } + + @Override + public GLGraphicsDevice createDevice(Window window) { + return new GLGraphicsDevice(window); + } + +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLGraphicsDevice.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLGraphicsDevice.java new file mode 100644 index 0000000..31a3f36 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLGraphicsDevice.java @@ -0,0 +1,79 @@ +package speiger.src.coreengine.graphics.opengl.core; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.lwjgl.opengl.GL12; +import org.lwjgl.opengl.GL33; +import org.lwjgl.opengl.GL43; +import org.lwjgl.opengl.GL45; + +import speiger.src.coreengine.graphics.api.buffer.states.BufferState; +import speiger.src.coreengine.graphics.api.buffer.states.BufferType; +import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue; +import speiger.src.coreengine.graphics.api.core.GraphicsDevice; +import speiger.src.coreengine.graphics.api.core.GraphicsSurface; +import speiger.src.coreengine.graphics.api.sampler.SamplerSettings; +import speiger.src.coreengine.graphics.api.texture.TextureSettings; +import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask; +import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer; +import speiger.src.coreengine.graphics.opengl.sampler.GLSampler; +import speiger.src.coreengine.graphics.opengl.texture.GLTexture; +import speiger.src.coreengine.graphics.opengl.utils.GLFunctions; +import speiger.src.coreengine.graphics.opengl.utils.GLUtils; +import speiger.src.coreengine.rendering.input.window.Window; + +public class GLGraphicsDevice implements GraphicsDevice { + Window owner; + + public GLGraphicsDevice(Window owner) { + this.owner = owner; + } + + @Override + public GraphicsSurface createSurface() { + return new GLSurface(owner); + } + + @Override + public GraphicsCommandQueue getQueue() { + return null; + } + + @Override + public GLVertexBuffer createBuffer(BufferType type, BufferState state) { + return new GLVertexBuffer(Objects.requireNonNull(type), Objects.requireNonNull(state)); + } + + @Override + public GLVertexBuffer createBuffer(BufferType type, BufferState state, int allocatedBytes) { + if(allocatedBytes <= 0) throw new IllegalArgumentException("Allocated bytes are invalid"); + return new GLVertexBuffer(Objects.requireNonNull(type), Objects.requireNonNull(state), allocatedBytes); + } + + @Override + public GLTexture createTexture(TextureSettings settings, int width, int height) { + if(width < 0) throw new IllegalArgumentException("Width ["+width+"] is invalid"); + if(height < 0) throw new IllegalArgumentException("Height ["+height+"] is invalid"); + int id = GLFunctions.createTexture(settings.type()); + settings.stencilType().ifPresent(T -> GL45.glTextureParameteri(id, GL43.GL_DEPTH_STENCIL_TEXTURE_MODE, GLUtils.toGL(T))); + settings.baseLevel().ifPresent(T -> GL45.glTextureParameteri(id, GL12.GL_TEXTURE_BASE_LEVEL, T)); + settings.maxLevel().ifPresent(T -> GL45.glTextureParameteri(id, GL12.GL_TEXTURE_MAX_LEVEL, T)); + if(settings.hasSwizzle()) { + List> masks = settings.swizzle(); + GL45.glTextureParameterIiv(id, GL33.GL_TEXTURE_SWIZZLE_RGBA, new int[] { + GLUtils.toGL(masks.get(0).orElse(SwizzleMask.RED)), + GLUtils.toGL(masks.get(1).orElse(SwizzleMask.GREEN)), + GLUtils.toGL(masks.get(2).orElse(SwizzleMask.BLUE)), + GLUtils.toGL(masks.get(3).orElse(SwizzleMask.ALPHA)), + }); + } + return new GLTexture(settings, id, width, height); + } + + @Override + public GLSampler createSampler(SamplerSettings settings) { + return new GLSampler(Objects.requireNonNull(settings)); + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLSurface.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLSurface.java new file mode 100644 index 0000000..679dcec --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/core/GLSurface.java @@ -0,0 +1,31 @@ +package speiger.src.coreengine.graphics.opengl.core; + +import org.lwjgl.glfw.GLFW; + +import speiger.src.coreengine.graphics.api.core.GraphicsSurface; +import speiger.src.coreengine.rendering.input.window.Window; + +public class GLSurface implements GraphicsSurface { + Window window; + + public GLSurface(Window window) { + this.window = window; + } + + @Override + public void setVsync(boolean value) { + window.vsync(value); + } + + @Override + public void beginFrame() { + GLFW.glfwPollEvents(); + } + + @Override + public void finishFrame() { + window.handleInput(); + window.finishFrame(); + } + +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/sampler/GLSampler.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/sampler/GLSampler.java new file mode 100644 index 0000000..8f37ae8 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/sampler/GLSampler.java @@ -0,0 +1,41 @@ +package speiger.src.coreengine.graphics.opengl.sampler; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; +import org.lwjgl.opengl.GL33; +import org.lwjgl.opengl.GL45; + +import speiger.src.coreengine.graphics.api.sampler.Sampler; +import speiger.src.coreengine.graphics.api.sampler.SamplerSettings; +import speiger.src.coreengine.graphics.opengl.utils.GLUtils; + +public class GLSampler extends Sampler { + int id; + + public GLSampler(SamplerSettings settings) { + super(settings); + init(); + } + + protected void init() { + this.id = GL45.glCreateSamplers(); + GL45.glSamplerParameteri(id, GL11.GL_TEXTURE_WRAP_S, GLUtils.toGL(settings.wrapS())); + GL45.glSamplerParameteri(id, GL11.GL_TEXTURE_WRAP_T, GLUtils.toGL(settings.wrapT())); + settings.wrapR().ifPresent(T -> GL45.glSamplerParameteri(id, GL12.GL_TEXTURE_WRAP_R, GLUtils.toGL(T))); + GL45.glSamplerParameteri(id, GL11.GL_TEXTURE_WRAP_S, GLUtils.toGL(settings.wrapS())); + GL45.glSamplerParameteri(id, GL11.GL_TEXTURE_MIN_FILTER, GLUtils.toGL(settings.minSample())); + GL45.glSamplerParameteri(id, GL11.GL_TEXTURE_MAG_FILTER, GLUtils.toGL(settings.magSample())); + } + + @Override + public boolean isRemoved() { + return id == 0; + } + + @Override + public void remove() { + if(id == 0) return; + GL33.glDeleteSamplers(id); + } + +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/texture/GLTexture.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/texture/GLTexture.java new file mode 100644 index 0000000..bdbe199 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/texture/GLTexture.java @@ -0,0 +1,27 @@ +package speiger.src.coreengine.graphics.opengl.texture; + +import speiger.src.coreengine.graphics.api.texture.Texture; +import speiger.src.coreengine.graphics.api.texture.TextureSettings; +import speiger.src.coreengine.graphics.opengl.utils.GLFunctions; + +public class GLTexture extends Texture { + int id; + + public GLTexture(TextureSettings settings, int id, int width, int height) { + super(settings, width, height); + this.id = id; + } + + @Override + public boolean isRemoved() { + return id == 0; + } + + @Override + public void remove() { + if(id == 0) return; + GLFunctions.deleteTextures(id); + id = 0; + } + +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/utils/GLFunctions.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/utils/GLFunctions.java new file mode 100644 index 0000000..e406c76 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/utils/GLFunctions.java @@ -0,0 +1,17 @@ +package speiger.src.coreengine.graphics.opengl.utils; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL45; + +import speiger.src.coreengine.graphics.api.texture.states.TextureType; + +public class GLFunctions { + + public static int createTexture(TextureType type) { + return GL45.glCreateTextures(GLUtils.toGL(type)); + } + + public static void deleteTextures(int... id) { + GL11.glDeleteTextures(id); + } +} diff --git a/src/graphics/java/speiger/src/coreengine/graphics/opengl/utils/GLUtils.java b/src/graphics/java/speiger/src/coreengine/graphics/opengl/utils/GLUtils.java new file mode 100644 index 0000000..fea9405 --- /dev/null +++ b/src/graphics/java/speiger/src/coreengine/graphics/opengl/utils/GLUtils.java @@ -0,0 +1,129 @@ +package speiger.src.coreengine.graphics.opengl.utils; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL14; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL21; +import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GL31; +import org.lwjgl.opengl.GL32; +import org.lwjgl.opengl.GL40; +import org.lwjgl.opengl.GL42; +import org.lwjgl.opengl.GL43; +import org.lwjgl.opengl.GL44; + +import speiger.src.coreengine.graphics.api.buffer.states.BufferState; +import speiger.src.coreengine.graphics.api.buffer.states.BufferType; +import speiger.src.coreengine.graphics.api.sampler.states.BorderMode; +import speiger.src.coreengine.graphics.api.sampler.states.SampleMode; +import speiger.src.coreengine.graphics.api.texture.states.StencilType; +import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask; +import speiger.src.coreengine.graphics.api.texture.states.TextureType; +import speiger.src.coreengine.graphics.api.utils.AlphaFunction; + +public class GLUtils { + //Buffer Begin + + public static int toGL(BufferType type) { + return switch(type) { + case ARRAY_BUFFER -> GL15.GL_ARRAY_BUFFER; + case ELEMENT_BUFFER -> GL15.GL_ELEMENT_ARRAY_BUFFER; + case UNIFORM_BUFFER -> GL31.GL_UNIFORM_BUFFER; + case DRAW_INDIRECT_BUFFER -> GL40.GL_DRAW_INDIRECT_BUFFER; + case TEXTURE_BUFFER -> GL31.GL_TEXTURE_BUFFER; + case PIXEL_PACK_BUFFER -> GL21.GL_PIXEL_PACK_BUFFER; + case PIXEL_UNPACK_BUFFER -> GL21.GL_PIXEL_UNPACK_BUFFER; + case TRANSFORM_FEEDBACK_BUFFER -> GL30.GL_TRANSFORM_FEEDBACK_BUFFER; + case COPY_READ_BUFFER -> GL31.GL_COPY_READ_BUFFER; + case COPY_WRITE_BUFFER -> GL31.GL_COPY_WRITE_BUFFER; + case ATOMIC_COUNTER_BUFFER -> GL42.GL_ATOMIC_COUNTER_BUFFER; + case DISPATCH_INDIRECT_BUFFER -> GL43.GL_DISPATCH_INDIRECT_BUFFER; + case SHADER_STORAGE_BUFFER -> GL43.GL_SHADER_STORAGE_BUFFER; + }; + } + + public static int toGL(BufferState state) { + return switch(state) { + case STATIC_DRAW -> GL15.GL_STATIC_DRAW; + case STATIC_READ -> GL15.GL_STATIC_READ; + case STATIC_COPY -> GL15.GL_STATIC_COPY; + case STREAM_DRAW -> GL15.GL_STREAM_DRAW; + case STREAM_READ -> GL15.GL_STREAM_READ; + case STREAM_COPY -> GL15.GL_STREAM_COPY; + case DYNAMIC_DRAW -> GL15.GL_DYNAMIC_DRAW; + case DYNAMIC_READ -> GL15.GL_DYNAMIC_READ; + case DYNAMIC_COPY -> GL15.GL_DYNAMIC_COPY; + }; + } + + //Texture Begin + + public static int toGL(TextureType type) { + return switch(type) { + case TEXTURE_1D -> GL11.GL_TEXTURE_1D; + case TEXTURE_1D_ARRAY -> GL30.GL_TEXTURE_1D_ARRAY; + case TEXTURE_2D -> GL11.GL_TEXTURE_2D; + case TEXTURE_2D_ARRAY -> GL30.GL_TEXTURE_2D_ARRAY; + case TEXTURE_2D_MULTISAMPLE -> GL32.GL_TEXTURE_2D_MULTISAMPLE; + case TEXTURE_2D_MULTISAMPLE_ARRAY -> GL32.GL_TEXTURE_2D_MULTISAMPLE_ARRAY; + case TEXTURE_3D -> GL12.GL_TEXTURE_3D; + case TEXTURE_CUBE_MAP -> GL32.GL_TEXTURE_CUBE_MAP; + case TEXTURE_CUBE_MAP_ARRAY -> GL40.GL_TEXTURE_CUBE_MAP_ARRAY; + case TEXTURE_RECTANGLE -> GL31.GL_TEXTURE_RECTANGLE; + case TEXTURE_BUFFER -> GL31.GL_TEXTURE_BUFFER; + }; + } + + public static int toGL(SwizzleMask mask) { + return switch(mask) { + case RED -> GL11.GL_RED; + case GREEN -> GL11.GL_GREEN; + case BLUE -> GL11.GL_BLUE; + case ALPHA -> GL11.GL_ALPHA; + case ZERO -> GL11.GL_ZERO; + case ONE -> GL11.GL_ONE; + + }; + } + + public static int toGL(StencilType type) { + return type == StencilType.GL_COMPARE_REF_TO_TEXTURE ? GL30.GL_COMPARE_REF_TO_TEXTURE : GL11.GL_NONE; + } + + //Sampler begin + public static int toGL(BorderMode mode) { + return switch(mode) { + case CLAMP_TO_BORDER -> GL13.GL_CLAMP_TO_BORDER; + case CLAMP_TO_EDGE -> GL12.GL_CLAMP_TO_EDGE; + case MIRRORED_REPEAT -> GL14.GL_MIRRORED_REPEAT; + case MIRROR_CLAMP_TO_EDGE -> GL44.GL_MIRROR_CLAMP_TO_EDGE; + case REPEAT -> GL11.GL_REPEAT; + }; + } + + public static int toGL(SampleMode mode) { + return switch(mode) { + case LINEAR -> GL11.GL_LINEAR; + case LINEAR_MIPMAP_LINEAR -> GL11.GL_LINEAR_MIPMAP_LINEAR; + case LINEAR_MIPMAP_NEAREST -> GL11.GL_LINEAR_MIPMAP_NEAREST; + case NEAREST -> GL11.GL_NEAREST; + case NEAREST_MIPMAP_LINEAR -> GL11.GL_NEAREST_MIPMAP_LINEAR; + case NEAREST_MIPMAP_NEAREST -> GL11.GL_NEAREST_MIPMAP_NEAREST; + }; + } + + public static int toGL(AlphaFunction type) { + return switch(type) { + case ALWAYS -> GL11.GL_ALWAYS; + case EQUAL -> GL11.GL_EQUAL; + case GEQUAL -> GL11.GL_GEQUAL; + case GREATER -> GL11.GL_GREATER; + case LEQUAL -> GL11.GL_LEQUAL; + case LESS -> GL11.GL_LESS; + case NEVER -> GL11.GL_NEVER; + case NOTEQUAL -> GL11.GL_NOTEQUAL; + }; + } +} diff --git a/src/main/java/speiger/src/coreengine/rendering/shader/ShaderCache.java b/src/main/java/speiger/src/coreengine/rendering/shader/ShaderCache.java index ac7a42f..f01b09c 100644 --- a/src/main/java/speiger/src/coreengine/rendering/shader/ShaderCache.java +++ b/src/main/java/speiger/src/coreengine/rendering/shader/ShaderCache.java @@ -1,54 +1,54 @@ -package speiger.src.coreengine.rendering.shader; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.FileTime; - -import org.lwjgl.system.MemoryUtil; - -public class ShaderCache { - public static final ShaderCache INSTANCE = new ShaderCache(); - private Path cache; - - public void init(Path cache) { - this.cache = cache; - if(Files.notExists(cache)) { - try { Files.createDirectories(cache); } - catch(IOException e) { - e.printStackTrace(); - this.cache = null; - } - } - } - - public boolean hasCache() { - return cache != null; - } - - public ByteBuffer readFromCache(String location, FileTime latestSource) { - try { return readFromCacheUnsafe(location, latestSource); } - catch(Exception e) { e.printStackTrace(); } - return null; - } - - private ByteBuffer readFromCacheUnsafe(String location, FileTime latestSource) throws IOException { - if(cache == null) return null; - Path path = cache.resolve(location+".bin"); - if(Files.exists(path)) { - if(Files.getLastModifiedTime(path).compareTo(latestSource) <= 0) return null; - byte[] data = Files.readAllBytes(path); - return MemoryUtil.memAlloc(data.length).put(data).flip(); - } - return null; - } - - public void storeInCache(String location, byte[] data) { - if(cache == null) return; - try { Files.write(cache.resolve(location+".bin"), data); } - catch(Exception e) { - e.printStackTrace(); - } - } -} +package speiger.src.coreengine.rendering.shader; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; + +import org.lwjgl.system.MemoryUtil; + +public class ShaderCache { + public static final ShaderCache INSTANCE = new ShaderCache(); + private Path cache; + + public void init(Path cache) { + this.cache = cache; + if(Files.notExists(cache)) { + try { Files.createDirectories(cache); } + catch(IOException e) { + e.printStackTrace(); + this.cache = null; + } + } + } + + public boolean hasCache() { + return cache != null; + } + + public ByteBuffer readFromCache(String location, FileTime latestSource) { + try { return readFromCacheUnsafe(location, latestSource); } + catch(Exception e) { e.printStackTrace(); } + return null; + } + + private ByteBuffer readFromCacheUnsafe(String location, FileTime latestSource) throws IOException { + if(cache == null) return null; + Path path = cache.resolve(location+".bin"); + if(Files.exists(path)) { + if(Files.getLastModifiedTime(path).compareTo(latestSource) <= 0) return null; + byte[] data = Files.readAllBytes(path); + return MemoryUtil.memAlloc(data.length).put(data).flip(); + } + return null; + } + + public void storeInCache(String location, byte[] data) { + if(cache == null) return; + try { Files.write(cache.resolve(location+".bin"), data); } + catch(Exception e) { + e.printStackTrace(); + } + } +}