Slowly implementing new render pipeline

This commit is contained in:
Speiger 2026-06-04 14:02:38 +02:00
parent c1f6c5ec10
commit 340d8ff463
40 changed files with 1198 additions and 89 deletions

View File

@ -12,18 +12,6 @@ eclipse {
classpath { classpath {
downloadJavadoc = true downloadJavadoc = true
downloadSources = 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) it.isDirectory() ? it : zipTree(it)
} }
} }
exclude('**/*.LIST')
exclude('**/module-info.class')
duplicatesStrategy = DuplicatesStrategy.INCLUDE duplicatesStrategy = DuplicatesStrategy.INCLUDE
} }

View File

@ -2,18 +2,27 @@ package speiger.src.coreengine.graphics.api.buffer;
import java.nio.Buffer; import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List;
import org.lwjgl.system.MemoryUtil; 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 { public abstract class VertexBuffer implements GraphicsResource {
protected final BufferType type;
protected final BufferState usage; protected final BufferState usage;
protected int size; protected int size;
public VertexBuffer(BufferState usage, int size) { public VertexBuffer(BufferType type, BufferState usage) {
this.type = type;
this.usage = usage; this.usage = usage;
this.size = size; }
public BufferType type() {
return type;
} }
public BufferState usage() { public BufferState usage() {
@ -24,6 +33,9 @@ public abstract class VertexBuffer implements GraphicsResource {
return size; return size;
} }
public abstract VertexBuffer bind();
public abstract VertexBuffer unbind();
public abstract VertexBuffer allocate(int totalBytes); public abstract VertexBuffer allocate(int totalBytes);
public abstract VertexBuffer set(long pointer, int totalBytes); public abstract VertexBuffer set(long pointer, int totalBytes);
public VertexBuffer set(ByteBuffer buffer) { public VertexBuffer set(ByteBuffer buffer) {
@ -35,10 +47,17 @@ public abstract class VertexBuffer implements GraphicsResource {
return fill(MemoryUtil.memAddress(buffer), buffer.remaining(), offset); 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) { 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<IntObjectPair<byte[]>> data) { return fill(0, data); }
public abstract VertexBuffer fill(int offset, List<IntObjectPair<byte[]>> data);
public abstract VertexBuffer shrink(int newSize);
public abstract VertexBuffer grow(int newSize);
public abstract VertexBuffer shift(int source, int dest, int length);
} }

View File

@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.buffer; package speiger.src.coreengine.graphics.api.buffer.states;
public enum BufferState { public enum BufferState {
STATIC_DRAW, STATIC_DRAW,

View File

@ -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;
}

View File

@ -5,5 +5,6 @@ import speiger.src.coreengine.rendering.input.window.Window;
public interface Graphics { public interface Graphics {
public String getName(); public String getName();
public void setupWindowArguments();
public GraphicsDevice createDevice(Window window); public GraphicsDevice createDevice(Window window);
} }

View File

@ -1,5 +1,17 @@
package speiger.src.coreengine.graphics.api.core; 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 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);
} }

View File

@ -1,12 +1,18 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.graphics.api.core;
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer; 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.graphics.api.texture.Texture;
import speiger.src.coreengine.rendering.input.window.Window; import speiger.src.coreengine.graphics.api.texture.TextureSettings;
public interface GraphicsDevice { public interface GraphicsDevice {
public GraphicsSurface createSurface(Window window); public GraphicsSurface createSurface();
public GraphicsCommandQueue getQueue(); public GraphicsCommandQueue getQueue();
public VertexBuffer createBuffer(); public VertexBuffer createBuffer(BufferType type, BufferState state);
public Texture createTexture(); public VertexBuffer createBuffer(BufferType type, BufferState state, int allocatedBytes);
public Texture createTexture(TextureSettings data, int width, int height);
public Sampler createSampler(SamplerSettings settings);
} }

View File

@ -2,4 +2,6 @@ package speiger.src.coreengine.graphics.api.core;
public interface GraphicsSurface { public interface GraphicsSurface {
public void setVsync(boolean value); public void setVsync(boolean value);
public void beginFrame();
public void finishFrame();
} }

View File

@ -1,7 +1,9 @@
package speiger.src.coreengine.graphics.api.sampler; package speiger.src.coreengine.graphics.api.sampler;
public abstract class Sampler { import speiger.src.coreengine.graphics.api.utils.GraphicsResource;
SamplerSettings settings;
public abstract class Sampler implements GraphicsResource {
protected SamplerSettings settings;
public Sampler(SamplerSettings settings) { public Sampler(SamplerSettings settings) {
this.settings = settings; this.settings = settings;

View File

@ -1,5 +1,60 @@
package speiger.src.coreengine.graphics.api.sampler; 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<BorderMode> 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"));
}
}
} }

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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<BlendFunction> 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);
}
}

View File

@ -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);
}
}

View File

@ -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<ShaderType, AssetLocation> shaders, List<List<BufferAttribute>> attributes, List<String> attributeNames, Set<String> uniforms, Set<String> 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<ShaderType, AssetLocation> shaders = new EnumMap<>(ShaderType.class);
ObjectList<String> attributeNames = new ObjectArrayList<>();
@SuppressWarnings("unchecked")
ObjectList<List<BufferAttribute>> attributes = ObjectArrayList.wrap(new List[8]);
ObjectSet<String> uniforms = new ObjectOpenHashSet<>();
ObjectSet<String> 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<m;i++) {
attributes.set(i, line.attributes().get(i));
}
uniforms.addAll(line.uniforms());
samplers.addAll(line.samplers());
drawMode = line.mode();
fillMode = line.fillMode();
cullBack = line.cullBack();
colorTarget = line.colorTarget();
depthTarget = line.depthTarget();
}
public Builder withShader(ShaderType type, AssetLocation location) {
shaders.put(Objects.requireNonNull(type, "Shouldn't be null"), Objects.requireNonNull(location, "Resource shouldn't be null"));
return this;
}
public Builder withUniform(String uniform) {
uniforms.add(Objects.requireNonNull(uniform));
return this;
}
public Builder withSampler(String sampler) {
samplers.add(Objects.requireNonNull(sampler));
return this;
}
public Builder withDrawMode(DrawMode mode) {
drawMode = Objects.requireNonNull(mode);
return this;
}
public Builder withFillMode(PolygonMode mode) {
this.fillMode = Objects.requireNonNull(mode);
return this;
}
public Builder withBackCulling(boolean cull) {
this.cullBack = cull;
return this;
}
public Builder withAttributeNames(String... names) {
this.attributeNames.clear();
this.attributeNames.addAll(names);
return this;
}
public Builder withBufferFormat(int index, BufferAttribute...attributes) {
if(index < 0 || index >= 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);
}
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
};
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,7 @@
package speiger.src.coreengine.graphics.api.shader.states;
public enum PolygonMode {
POINT,
LINE,
FILL;
}

View File

@ -0,0 +1,10 @@
package speiger.src.coreengine.graphics.api.shader.states;
public enum PrimitiveType {
BYTE,
SHORT,
INT,
LONG,
FLOAT,
DOUBLE;
}

View File

@ -0,0 +1,9 @@
package speiger.src.coreengine.graphics.api.shader.states;
public enum ShaderType {
VERTEX,
FRAGMENT,
GEOMETRY,
TESSELATION_CONTROL,
TESSELATION_EVALUATION;
}

View File

@ -1,12 +1,24 @@
package speiger.src.coreengine.graphics.api.texture; 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 { public abstract class Texture implements GraphicsResource {
final TextureSettings settings; final TextureSettings settings;
int width;
int height;
public Texture(TextureSettings settings) { public Texture(TextureSettings settings, int width, int height) {
this.settings = settings; this.settings = settings;
this.width = width;
this.height = height;
}
public int width() {
return width;
}
public int height() {
return height;
} }
public TextureSettings settings() { public TextureSettings settings() {

View File

@ -1,6 +1,5 @@
package speiger.src.coreengine.graphics.api.texture; package speiger.src.coreengine.graphics.api.texture;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; 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.TextureFormat;
import speiger.src.coreengine.graphics.api.texture.states.TextureType; 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<Optional<SwizzleMask>> swizzle, Optional<StencilType> stencilType) { public record TextureSettings(TextureType type, TextureFormat internal, TextureFormat external, boolean generateMipmapping, OptionalInt baseLevel, OptionalInt maxLevel, ImmutableObjectList<Optional<SwizzleMask>> swizzle, Optional<StencilType> 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 Builder copy() { return new Builder(this); }
public static Builder builder() { return new Builder(); } public static Builder builder() { return new Builder(); }

View File

@ -1,6 +1,6 @@
package speiger.src.coreengine.graphics.api.texture.states; package speiger.src.coreengine.graphics.api.texture.states;
public enum StencilType { public enum StencilType {
DEPTH_COMPONENT, GL_COMPARE_REF_TO_TEXTURE,
STENCIL_INDEX GL_NONE
} }

View File

@ -0,0 +1,12 @@
package speiger.src.coreengine.graphics.api.utils;
public enum AlphaFunction {
NEVER,
LESS,
EQUAL,
LEQUAL,
GREATER,
NOTEQUAL,
GEQUAL,
ALWAYS;
}

View File

@ -1,4 +1,4 @@
package speiger.src.coreengine.graphics.api.core; package speiger.src.coreengine.graphics.api.utils;
public interface GraphicsResource extends AutoCloseable { public interface GraphicsResource extends AutoCloseable {
public boolean isRemoved(); public boolean isRemoved();

View File

@ -0,0 +1,6 @@
package speiger.src.coreengine.graphics.api.utils;
public interface PushableResource extends AutoCloseable {
@Override
public void close();
}

View File

@ -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;
}
}

View File

@ -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<VertexElement> {
Object2ObjectMap<String, VertexElement> mappedElements = new Object2ObjectLinkedOpenHashMap<>();
ObjectList<VertexElement> elements = new ObjectArrayList<>();
Set<Usage> 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<Entry<String, VertexElement>> entrySet() { return mappedElements.object2ObjectEntrySet().unmodifiable(); }
@Override
public Iterator<VertexElement> 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;
}
}
}

View File

@ -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<IntObjectPair<byte[]>> 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<byte[]> 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;
}
}

View File

@ -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);
}
}

View File

@ -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<Optional<SwizzleMask>> 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));
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
};
}
}