More work on the engine
This commit is contained in:
@@ -18,12 +18,6 @@
|
||||
<attribute name="gradle_used_by_scope" value="graphics"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="bin/graphics" path="src/graphics/resources">
|
||||
<attributes>
|
||||
<attribute name="gradle_scope" value="graphics"/>
|
||||
<attribute name="gradle_used_by_scope" value="graphics"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="bin/math" path="src/math/java">
|
||||
<attributes>
|
||||
<attribute name="gradle_scope" value="math"/>
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import speiger.src.coreengine.assets.impl.parsers.Buffers;
|
||||
import speiger.src.coreengine.assets.impl.parsers.Checksums;
|
||||
import speiger.src.coreengine.assets.impl.parsers.Closables;
|
||||
import speiger.src.coreengine.assets.impl.parsers.Serialized;
|
||||
|
||||
@@ -26,5 +27,8 @@ public interface IAsset {
|
||||
public default JsonObject jsonObj() throws IOException { return parse(Serialized.JSON_OBJ); }
|
||||
public default JsonArray jsonArray() throws IOException { return parse(Serialized.JSON_ARRAY); }
|
||||
|
||||
public default String crc() throws IOException { return parse(Checksums.CRC); }
|
||||
public default String sha256() throws IOException { return parse(Checksums.SHA_256); }
|
||||
|
||||
public <T> T parse(IAssetParser<T> parser) throws IOException;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import speiger.src.collections.objects.utils.ObjectLists;
|
||||
@NullMarked
|
||||
public interface IAssetProvider extends AutoCloseable {
|
||||
@Nullable
|
||||
IAsset get(ID id);
|
||||
IAsset get(ID id);
|
||||
@Nullable
|
||||
MultiAsset getAll(ID id);
|
||||
Map<ID, IAsset> list(String folder, Predicate<ID> filter);
|
||||
|
||||
@@ -5,12 +5,15 @@ import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import speiger.src.collections.ints.functions.consumer.IntObjectConsumer;
|
||||
import speiger.src.collections.objects.collections.ObjectIterable;
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
import speiger.src.collections.objects.functions.consumer.ObjectObjectConsumer;
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.lists.ObjectList;
|
||||
import speiger.src.coreengine.assets.impl.parsers.Checksums;
|
||||
|
||||
public record MultiAsset(ObjectList<IAsset> assets) implements ObjectIterable<IAsset> {
|
||||
|
||||
@@ -26,6 +29,9 @@ public record MultiAsset(ObjectList<IAsset> assets) implements ObjectIterable<IA
|
||||
public IAsset get(int index) { return assets.get(index); }
|
||||
@Override
|
||||
public ObjectIterator<IAsset> iterator() { return assets.iterator(); }
|
||||
public String crc() { return map(Checksums.CRC, () -> "").reduce(new StringBuilder(), StringBuilder::append).toString(); }
|
||||
public String sha256() { return map(Checksums.SHA_256, () -> "").reduce(new StringBuilder(), StringBuilder::append).toString(); }
|
||||
|
||||
|
||||
public <T> ObjectIterable<T> map(IAssetParser<T> mapper, Supplier<T> defaultValue) {
|
||||
return assets.map(E -> {
|
||||
@@ -51,4 +57,19 @@ public record MultiAsset(ObjectList<IAsset> assets) implements ObjectIterable<IA
|
||||
public void forEachIndexed(IntObjectConsumer<IAsset> action) {
|
||||
assets.forEachIndexed(action);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MultiAsset combineNonNull(IAssetProvider provider, ID...ids) {
|
||||
ObjectList<IAsset> all = new ObjectArrayList<>();
|
||||
for(ID id : ids) {
|
||||
IAsset entry = provider.get(id);
|
||||
if(entry == null) return null;
|
||||
all.add(entry);
|
||||
}
|
||||
return new MultiAsset(all);
|
||||
}
|
||||
|
||||
public static MultiAsset combine(IAssetProvider provider, ID...ids) {
|
||||
return new MultiAsset(ObjectArrayList.wrap(ids).map(provider::get).filter(T -> T != null).pourAsList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package speiger.src.coreengine.assets.impl.parsers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import java.util.zip.CRC32C;
|
||||
|
||||
import speiger.src.coreengine.assets.api.IAssetParser;
|
||||
|
||||
public class Checksums {
|
||||
public static final IAssetParser<String> CRC = new CRC();
|
||||
public static final IAssetParser<String> SHA_256 = new SHA256();
|
||||
|
||||
public static class CRC implements IAssetParser<String> {
|
||||
@Override
|
||||
public String parse(Path path) throws IOException {
|
||||
Map<String, Object> files = Files.readAttributes(path, "crc");
|
||||
if(files.containsKey("crc")) return Long.toHexString(((Long)files.get("crc")) & 0xFFFFFFFFL);
|
||||
CRC32C crc = new CRC32C();
|
||||
crc.update(Files.readAllBytes(path));
|
||||
return Long.toHexString(crc.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static class SHA256 implements IAssetParser<String> {
|
||||
@Override
|
||||
public String parse(Path path) throws IOException {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
digest.update(Files.readAllBytes(path));
|
||||
return Base64.getEncoder().encodeToString(digest.digest());
|
||||
}
|
||||
catch(NoSuchAlgorithmException e) { e.printStackTrace(); }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package speiger.src.coreengine.graphics.api.core;
|
||||
|
||||
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
|
||||
import speiger.src.coreengine.graphics.api.mesh.Mesh;
|
||||
import speiger.src.coreengine.graphics.api.sampler.Sampler;
|
||||
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline;
|
||||
import speiger.src.coreengine.graphics.api.texture.Texture;
|
||||
import speiger.src.coreengine.graphics.api.utils.GraphicsResource;
|
||||
|
||||
public interface GraphicsCommandBuffer extends GraphicsResource {
|
||||
GraphicsCommandBuffer begin();
|
||||
GraphicsCommandBuffer setScissors(int x, int y, int width, int height);
|
||||
|
||||
GraphicsCommandBuffer pipeline(ShaderPipeline pipeline);
|
||||
GraphicsCommandBuffer mesh(Mesh mesh);
|
||||
GraphicsCommandBuffer texture(int set, int binding, Texture texture, Sampler sampler);
|
||||
GraphicsCommandBuffer uniform(int set, int binding, VertexBuffer buffer);
|
||||
|
||||
GraphicsCommandBuffer drawIndexed(int start, int count);
|
||||
|
||||
GraphicsCommandBuffer pushScissors(int x, int y, int width, int height);
|
||||
GraphicsCommandBuffer popScissors();
|
||||
GraphicsCommandBuffer end();
|
||||
|
||||
int commandCount();
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,5 @@
|
||||
package speiger.src.coreengine.graphics.api.core;
|
||||
|
||||
import speiger.src.coreengine.graphics.api.shader.RenderPass;
|
||||
import speiger.src.coreengine.graphics.api.target.RenderTarget;
|
||||
import speiger.src.coreengine.graphics.api.texture.Texture;
|
||||
import speiger.src.coreengine.graphics.api.utils.PushableResource;
|
||||
@@ -20,7 +19,8 @@ public interface GraphicsCommandQueue {
|
||||
|
||||
public void writeToTexture(Texture target, int x, int y, int width, int height, long source);
|
||||
public void readFromTexture(Texture source, int x, int y, int width, int height, long target);
|
||||
public RenderPass createRenderPass(RenderTarget target, DrawArea area);
|
||||
|
||||
public void submitCommands(GraphicsCommandBuffer buffer);
|
||||
|
||||
public record DrawArea(int x, int y, int width, int height) {
|
||||
public boolean fits(int x, int y, int width, int height) {
|
||||
|
||||
@@ -3,18 +3,22 @@ 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.mesh.Mesh;
|
||||
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.TextureSettings;
|
||||
import speiger.src.coreengine.graphics.api.utils.ExecutionType;
|
||||
import speiger.src.coreengine.rendering.input.window.Window;
|
||||
|
||||
public interface GraphicsDevice {
|
||||
public Window getWindow();
|
||||
public GraphicsSurface createSurface();
|
||||
public GraphicsCommandBuffer createBuffer(ExecutionType type);
|
||||
public GraphicsCommandQueue getQueue();
|
||||
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);
|
||||
public Mesh createMesh(Mesh.Builder builder, boolean autocreate);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package speiger.src.coreengine.graphics.api.mesh;
|
||||
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
|
||||
import speiger.src.coreengine.graphics.api.buffer.states.IndeciesType;
|
||||
import speiger.src.coreengine.graphics.api.utils.GraphicsResource;
|
||||
import speiger.src.coreengine.graphics.api.vertex.VertexLayout;
|
||||
|
||||
public abstract class Mesh implements GraphicsResource {
|
||||
protected final Int2ObjectMap<LayoutInfo> layouts;
|
||||
protected Int2ObjectMap<VertexBuffer> buffers;
|
||||
protected VertexBuffer indeciesBuffer;
|
||||
protected IndeciesType indeciesType;
|
||||
|
||||
public Mesh(Int2ObjectMap<LayoutInfo> layouts, Int2ObjectMap<VertexBuffer> buffers, VertexBuffer indeciesBuffer) {
|
||||
this.layouts = layouts;
|
||||
this.buffers = buffers;
|
||||
this.indeciesBuffer = indeciesBuffer;
|
||||
}
|
||||
|
||||
protected abstract void closeWithBuffers();
|
||||
|
||||
public Int2ObjectMap<LayoutInfo> layouts() {
|
||||
return layouts;
|
||||
}
|
||||
|
||||
public VertexBuffer indeciesBuffer() {
|
||||
return indeciesBuffer;
|
||||
}
|
||||
|
||||
public IndeciesType indeciesType() {
|
||||
return indeciesType;
|
||||
}
|
||||
|
||||
public VertexBuffer buffer(int binding) {
|
||||
return buffers.get(binding);
|
||||
}
|
||||
|
||||
public Mesh indexBuffer(VertexBuffer indexBuffer, IndeciesType indeciesType) {
|
||||
this.indeciesBuffer = indexBuffer;
|
||||
this.indeciesType = indeciesType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Mesh buffer(int binding, VertexBuffer buffer) {
|
||||
buffers.put(binding, buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
Int2ObjectMap<LayoutInfo> layouts = Int2ObjectMap.builder().linkedMap();
|
||||
boolean autoGenerate;
|
||||
|
||||
private Builder() {}
|
||||
|
||||
public Builder layout(VertexLayout layout) {
|
||||
return layout(layouts.size(), layout);
|
||||
}
|
||||
|
||||
public Builder layout(int index, VertexLayout layout) {
|
||||
return layout(index, layout, 0);
|
||||
}
|
||||
|
||||
public Builder layout(int index, VertexLayout layout, int instanceCount) {
|
||||
layouts.put(index, new LayoutInfo(layout, instanceCount));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public record LayoutInfo(VertexLayout layout, int instanceCount) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,12 @@
|
||||
package speiger.src.coreengine.graphics.api.shader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
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;
|
||||
public record BufferAttribute(String name, int index, int size, GraphicsDataType type, boolean normal) {
|
||||
public BufferAttribute {
|
||||
Objects.requireNonNull(name, "Attributes requires name");
|
||||
Objects.requireNonNull(type, "GraphicsDataType required");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package speiger.src.coreengine.graphics.api.shader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import speiger.src.coreengine.graphics.api.shader.states.DrawMode;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.PolygonMode;
|
||||
|
||||
public record RasterizerState(DrawMode mode, PolygonMode fillMode, boolean cullBack) {
|
||||
public static final RasterizerState DEFAULT = new RasterizerState(DrawMode.TRIANGLES, PolygonMode.FILL, true);
|
||||
public RasterizerState {
|
||||
Objects.requireNonNull(mode);
|
||||
Objects.requireNonNull(fillMode);
|
||||
}
|
||||
}
|
||||
@@ -5,120 +5,103 @@ 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.assets.api.ID;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.Bindings.TextureBinding;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.Bindings.UniformBinding;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.DrawMode;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.PolygonMode;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.ShaderType;
|
||||
import speiger.src.coreengine.graphics.api.texture.states.TextureType;
|
||||
|
||||
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 record ShaderPipeline(ID id, Map<ShaderType, ID> shaders, List<VertexBinding> attributes, List<UniformBinding> uniforms, List<TextureBinding> textures, RasterizerState rasterizer, 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(textures);
|
||||
Objects.requireNonNull(rasterizer);
|
||||
Objects.requireNonNull(colorTarget);
|
||||
Objects.requireNonNull(depthTarget);
|
||||
}
|
||||
|
||||
public static Builder builder(AssetLocation id) {
|
||||
public static Builder builder(ID id) {
|
||||
return new Builder(id);
|
||||
}
|
||||
|
||||
public Builder copy(AssetLocation id) {
|
||||
public Builder copy(ID 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;
|
||||
ID id;
|
||||
EnumMap<ShaderType, ID> shaders = new EnumMap<>(ShaderType.class);
|
||||
ObjectList<VertexBinding> attributes = new ObjectArrayList<>();
|
||||
ObjectList<UniformBinding> uniforms = new ObjectArrayList<>();
|
||||
ObjectList<TextureBinding> textures = new ObjectArrayList<>();
|
||||
RasterizerState rasterizer = RasterizerState.DEFAULT;
|
||||
ColorTarget colorTarget = ColorTarget.DEFAULT;
|
||||
DepthTarget depthTarget = DepthTarget.DEFAULT;
|
||||
|
||||
private Builder(AssetLocation id) {
|
||||
private Builder(ID id) {
|
||||
this.id = Objects.requireNonNull(id);
|
||||
|
||||
}
|
||||
|
||||
private Builder(AssetLocation id, ShaderPipeline line) {
|
||||
private Builder(ID 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));
|
||||
}
|
||||
attributes.addAll(line.attributes());
|
||||
uniforms.addAll(line.uniforms());
|
||||
samplers.addAll(line.samplers());
|
||||
drawMode = line.mode();
|
||||
fillMode = line.fillMode();
|
||||
cullBack = line.cullBack();
|
||||
textures.addAll(line.textures());
|
||||
rasterizer = line.rasterizer();
|
||||
colorTarget = line.colorTarget();
|
||||
depthTarget = line.depthTarget();
|
||||
}
|
||||
|
||||
public Builder withShader(ShaderType type, AssetLocation location) {
|
||||
public Builder withStage(ShaderType type, ID 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));
|
||||
public Builder withUniform(String name, int binding, int set, int bytes) {
|
||||
uniforms.add(new UniformBinding(name, binding, set, bytes));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withSampler(String sampler) {
|
||||
samplers.add(Objects.requireNonNull(sampler));
|
||||
public Builder withTexture(String name, int binding, int set, TextureType type) {
|
||||
textures.add(new TextureBinding(name, binding, set, type));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withDrawMode(DrawMode mode) {
|
||||
drawMode = Objects.requireNonNull(mode);
|
||||
public Builder withRasterizer(DrawMode draw, PolygonMode polygon, boolean cullBack) {
|
||||
rasterizer = new RasterizerState(draw, polygon, cullBack);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withFillMode(PolygonMode mode) {
|
||||
this.fillMode = Objects.requireNonNull(mode);
|
||||
return this;
|
||||
public AttributeBuilder withFormat() {
|
||||
return withFormat(attributes.size());
|
||||
}
|
||||
|
||||
public Builder withBackCulling(boolean cull) {
|
||||
this.cullBack = cull;
|
||||
return this;
|
||||
public AttributeBuilder withInstanceFormat() {
|
||||
return withFormat(attributes.size(), 1);
|
||||
}
|
||||
|
||||
public Builder withAttributeNames(String... names) {
|
||||
this.attributeNames.clear();
|
||||
this.attributeNames.addAll(names);
|
||||
return this;
|
||||
public AttributeBuilder withInstanceFormat(int instanceCount) {
|
||||
return withFormat(attributes.size(), instanceCount);
|
||||
}
|
||||
|
||||
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 AttributeBuilder withFormat(int bindingIndex) {
|
||||
return withFormat(bindingIndex, 0);
|
||||
}
|
||||
|
||||
public Builder clearBufferFormat(int index) {
|
||||
if(index < 0 || index >= 8) throw new IndexOutOfBoundsException(index);
|
||||
attributes.set(index, null);
|
||||
return this;
|
||||
public AttributeBuilder withFormat(int bindingIndex, int instanceCount) {
|
||||
return new AttributeBuilder(this, bindingIndex, instanceCount);
|
||||
}
|
||||
|
||||
public Builder withColorTarget(ColorTarget target) {
|
||||
@@ -133,7 +116,52 @@ public record ShaderPipeline(AssetLocation id, Map<ShaderType, AssetLocation> sh
|
||||
|
||||
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);
|
||||
return new ShaderPipeline(id, Collections.unmodifiableMap(shaders), attributes.unmodifiable(), uniforms.unmodifiable(), textures.unmodifiable(), Objects.requireNonNull(rasterizer, "A Rasterizer should be defined"), colorTarget, depthTarget);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AttributeBuilder {
|
||||
final Builder owner;
|
||||
final List<BufferAttribute> attributes = new ObjectArrayList<>();
|
||||
final int bindingIndex;
|
||||
final int instanceCount;
|
||||
int stride;
|
||||
|
||||
private AttributeBuilder(Builder owner, int bindingIndex, int instanceCount) {
|
||||
this.owner = owner;
|
||||
this.bindingIndex = bindingIndex;
|
||||
this.instanceCount = instanceCount;
|
||||
}
|
||||
|
||||
public AttributeBuilder attribute(String name, int index, int size) {
|
||||
return attribute(name, index, size, GraphicsDataType.FLOAT, false);
|
||||
}
|
||||
|
||||
public AttributeBuilder attribute(String name, int index, int size, GraphicsDataType type) {
|
||||
return attribute(name, index, size, type, false);
|
||||
}
|
||||
|
||||
public AttributeBuilder attribute(String name, int index, int size, GraphicsDataType type, boolean normalized) {
|
||||
attributes.add(new BufferAttribute(name, index, size, type, normalized));
|
||||
stride += type.size(size);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AttributeBuilder array(String baseName, int startIndex, int width, int size, GraphicsDataType type) {
|
||||
return array(baseName, startIndex, width, size, type, false);
|
||||
}
|
||||
|
||||
public AttributeBuilder array(String baseName, int startIndex, int width, int size, GraphicsDataType type, boolean normalized) {
|
||||
Objects.requireNonNull(baseName);
|
||||
for(int i = 0;i<width;i++) {
|
||||
attribute(baseName+" ["+i+"]", startIndex + i, size, type, normalized);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder endFormat() {
|
||||
owner.attributes.add(new VertexBinding(bindingIndex, stride, instanceCount, new ImmutableObjectList<>(attributes)));
|
||||
return owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package speiger.src.coreengine.graphics.api.shader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record VertexBinding(int bindingIndex, int stide, int instanceOffset, List<BufferAttribute> attributes) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package speiger.src.coreengine.graphics.api.shader.states;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import speiger.src.coreengine.graphics.api.texture.states.TextureType;
|
||||
|
||||
public class Bindings {
|
||||
public record UniformBinding(String name, int binding, int set, int bytes) {
|
||||
public UniformBinding {
|
||||
Objects.requireNonNull(name, "A name has to be provided");
|
||||
}
|
||||
}
|
||||
|
||||
public record TextureBinding(String name, int binding, int set, TextureType type) {
|
||||
public TextureBinding {
|
||||
Objects.requireNonNull(name, "A name has to be provided");
|
||||
Objects.requireNonNull(type, "A TextureType has to be provided");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+28
-27
@@ -2,48 +2,49 @@ 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),
|
||||
UNSIGNED_BYTE("u_byte", 1, PrimitiveType.BYTE, true),
|
||||
SHORT("short", 2, PrimitiveType.SHORT),
|
||||
UNSIGNED_SHORT("u_short", 2, PrimitiveType.SHORT, true, false),
|
||||
UNSIGNED_SHORT("u_short", 2, PrimitiveType.SHORT, true),
|
||||
INT("int", 4, PrimitiveType.INT),
|
||||
UNSIGNED_INT("u_int", 4, PrimitiveType.INT, true, false),
|
||||
UNSIGNED_INT("u_int", 4, PrimitiveType.INT, true),
|
||||
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_3_3_2("u_byte_3_3_2", 1, PrimitiveType.BYTE, false, true),
|
||||
UNSIGNED_2_3_3_REV("u_byte_2_3_3_rev", 1, PrimitiveType.BYTE, false, true),
|
||||
UNSIGNED_5_6_5("u_short_5_6_5", 2, PrimitiveType.SHORT, false, true),
|
||||
UNSIGNED_5_6_5_REV("u_short_5_6_5_rev", 2, PrimitiveType.SHORT, false, true),
|
||||
UNSIGNED_4_4_4_4("u_short_4_4_4_4", 2, PrimitiveType.SHORT, false, true),
|
||||
UNSIGNED_4_4_4_4_REV("u_short_4_4_4_4_rev", 2, PrimitiveType.SHORT, false, true),
|
||||
UNSIGNED_5_5_5_1("u_short_5_5_5_1", 2, PrimitiveType.SHORT, false, true),
|
||||
UNSIGNED_1_5_5_5_REV("u_short_1_5_5_5_rev", 2, PrimitiveType.SHORT, false, true),
|
||||
UNSIGNED_8_8_8_8("u_int_8_8_8_8", 4, PrimitiveType.INT, false, true),
|
||||
UNSIGNED_8_8_8_8_REV("u_int_8_8_8_8_rev", 4, PrimitiveType.INT, false, true),
|
||||
UNSIGNED_10_10_10_2("u_int_10_10_10_2", 4, PrimitiveType.INT, false, true),
|
||||
UNSIGNED_2_10_10_10_REV("u_int_2_10_10_10_rev", 4, PrimitiveType.INT, false, true),
|
||||
|
||||
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);
|
||||
UNSIGNED_INT_10F_11F_11F_REV("u_int_10_11_11_rev", 4, PrimitiveType.INT, false, true),
|
||||
UNSIGNED_INT_5_9_9_9_REV("u_int_5_9_9_9_rev", 4, PrimitiveType.INT, false, true);
|
||||
|
||||
String name;
|
||||
int byteSize;
|
||||
PrimitiveType type;
|
||||
boolean supportsIBO;
|
||||
boolean isCompound;
|
||||
boolean compound;
|
||||
|
||||
private GraphicsDataType(String name, int byteSize, PrimitiveType type, boolean supportsIBO, boolean isCompound) {
|
||||
private GraphicsDataType(String name, int byteSize, PrimitiveType type, boolean supportsIBO, boolean compound) {
|
||||
this.name = name;
|
||||
this.byteSize = byteSize;
|
||||
this.type = type;
|
||||
this.supportsIBO = supportsIBO;
|
||||
this.isCompound = isCompound;
|
||||
this.compound = compound;
|
||||
}
|
||||
|
||||
private GraphicsDataType(String name, int byteSize, PrimitiveType type, boolean isCompound) {
|
||||
this(name, byteSize, type, false, isCompound);
|
||||
private GraphicsDataType(String name, int byteSize, PrimitiveType type, boolean supportsIBO) {
|
||||
this(name, byteSize, type, supportsIBO, false);
|
||||
}
|
||||
|
||||
|
||||
private GraphicsDataType(String name, int byteSize, PrimitiveType type) {
|
||||
this(name, byteSize, type, false, false);
|
||||
@@ -61,16 +62,16 @@ public enum GraphicsDataType {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean isCompound() {
|
||||
return compound;
|
||||
}
|
||||
|
||||
public boolean supportsIBO() {
|
||||
return supportsIBO;
|
||||
}
|
||||
|
||||
public boolean isCompound() {
|
||||
return isCompound;
|
||||
}
|
||||
|
||||
public int size(int attributes) {
|
||||
return isCompound ? byteSize : attributes * byteSize;
|
||||
return compound ? byteSize : attributes * byteSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package speiger.src.coreengine.graphics.api.utils;
|
||||
|
||||
public enum ExecutionType {
|
||||
IMMEDIATE,
|
||||
RECORDED;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package speiger.src.coreengine.graphics.api.vertex;
|
||||
|
||||
public record VertexElement(int size, Usage usage)
|
||||
{
|
||||
public static enum Usage {
|
||||
POS,
|
||||
UV,
|
||||
COLOR,
|
||||
NORMAL,
|
||||
CUSTOM;
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package speiger.src.coreengine.graphics.api.vertex;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import speiger.src.collections.ints.lists.IntArrayList;
|
||||
import speiger.src.collections.ints.lists.IntList;
|
||||
import speiger.src.collections.objects.collections.ObjectIterable;
|
||||
import speiger.src.collections.objects.collections.ObjectIterator;
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.lists.ObjectList;
|
||||
import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap;
|
||||
import speiger.src.collections.objects.utils.ObjectIterators;
|
||||
import speiger.src.coreengine.graphics.api.shader.states.GraphicsDataType;
|
||||
import speiger.src.coreengine.graphics.api.vertex.VertexLayout.Element;
|
||||
|
||||
public class VertexLayout implements ObjectIterable<Element> {
|
||||
Object2ObjectMap<String, Element> mapped = Object2ObjectMap.builder().linkedMap();
|
||||
ObjectList<Element> elements = new ObjectArrayList<>();
|
||||
IntList offsets = new IntArrayList();
|
||||
int stride;
|
||||
int bytes;
|
||||
|
||||
private VertexLayout() {}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder(new VertexLayout());
|
||||
}
|
||||
|
||||
public int stride() { return stride; }
|
||||
public int size() { return elements.size(); }
|
||||
public int bytes() { return bytes; }
|
||||
public int offset(int index) { return offsets.getInt(index); }
|
||||
public Element get(int index) { return elements.get(index); }
|
||||
public boolean contains(String key) { return mapped.containsKey(key); }
|
||||
public ObjectList<Element> elements() { return elements.unmodifiable(); }
|
||||
@Override
|
||||
public ObjectIterator<Element> iterator() { return ObjectIterators.unmodifiable(elements.iterator()); }
|
||||
|
||||
private void add(Element element) {
|
||||
if(mapped.put(element.name(), element) != null) throw new IllegalStateException("Duplicated Names are not allowed");
|
||||
elements.add(element);
|
||||
offsets.add(stride);
|
||||
int size = element.size();
|
||||
stride += size;
|
||||
bytes += element.type().size(size);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
VertexLayout format;
|
||||
|
||||
private Builder(VertexLayout format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
public Builder element(String name, int index, int size, Usage usage) {
|
||||
return element(name, index, size, usage, GraphicsDataType.FLOAT, false);
|
||||
}
|
||||
|
||||
public Builder element(String name, int index, int size, Usage usage, GraphicsDataType type) {
|
||||
return element(name, index, size, usage, type, false);
|
||||
}
|
||||
|
||||
public Builder element(String name, int index, int size, Usage usage, GraphicsDataType type, boolean normalized) {
|
||||
format.add(new Element(name, index, size, usage, type, normalized));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder array(String baseName, int startIndex, int width, int size, Usage usage, GraphicsDataType type) {
|
||||
return array(baseName, startIndex, width, size, usage, type, false);
|
||||
}
|
||||
|
||||
public Builder array(String baseName, int startIndex, int width, int size, Usage usage, GraphicsDataType type, boolean normalized) {
|
||||
Objects.requireNonNull(baseName);
|
||||
for(int i = 0;i<width;i++) {
|
||||
element(baseName+" ["+i+"]", startIndex + i, size, usage, type, normalized);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public VertexLayout build() {
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
public record Element(String name, int index, int size, Usage usage, GraphicsDataType type, boolean normalized) {}
|
||||
|
||||
public enum Usage {
|
||||
POS, UV, COLOR, NORMAL, MATRIX, CUSTOM;
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL45;
|
||||
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
import speiger.src.coreengine.graphics.api.core.GraphicsCommandBuffer;
|
||||
import speiger.src.coreengine.graphics.api.core.GraphicsCommandQueue;
|
||||
import speiger.src.coreengine.graphics.api.shader.RenderPass;
|
||||
import speiger.src.coreengine.graphics.api.target.RenderTarget;
|
||||
import speiger.src.coreengine.graphics.api.target.ScreenTarget;
|
||||
import speiger.src.coreengine.graphics.api.target.TextureTarget;
|
||||
@@ -22,18 +22,17 @@ import speiger.src.coreengine.math.vector.floats.Vec4f;
|
||||
import speiger.src.coreengine.rendering.input.window.Window;
|
||||
|
||||
public class GLCommandQueue implements GraphicsCommandQueue {
|
||||
private static final int HAS_COLOR = 1;
|
||||
private static final int HAS_DEPTH = 2;
|
||||
private static final int HAS_BOTH = 3;
|
||||
GLGraphicsDevice device;
|
||||
FrameBufferCache fboCache = new FrameBufferCache();
|
||||
GLRenderPass activePass;
|
||||
RenderTarget renderTarget = ScreenTarget.INSTANCE;
|
||||
ScreenBuffer targetFBO;
|
||||
Vec4f clearColor = Vec4f.mutable(0F, 0F, 0F, 1F);
|
||||
double clearDepth = 0D;
|
||||
|
||||
public GLCommandQueue(GLGraphicsDevice device) {
|
||||
this.device = device;
|
||||
this.targetFBO = new ScreenBuffer(0, device.getWindow().width(), device.getWindow().height());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,23 +67,26 @@ public class GLCommandQueue implements GraphicsCommandQueue {
|
||||
private RenderTarget setRenderTarget(RenderTarget target) {
|
||||
if(this.renderTarget.equals(target)) return target;
|
||||
this.renderTarget = target;
|
||||
switch(target) {
|
||||
targetFBO = switch(target) {
|
||||
case ScreenTarget _ -> {
|
||||
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, 0);
|
||||
Window window = device.getWindow();
|
||||
GL11.glViewport(0, 0, window.width(), window.height());
|
||||
break;
|
||||
yield new ScreenBuffer(0, window.width(), window.height());
|
||||
}
|
||||
case TextureTarget(AssetLocation id, Texture color, Texture depth) -> {
|
||||
int fbo = fboCache.getOrCreateFBO(id);
|
||||
if(color != null) GL45.glNamedFramebufferTexture(fbo, GL30.GL_COLOR_ATTACHMENT0, ((GLTexture)color).id(), 0);
|
||||
if(depth != null) GL45.glNamedFramebufferTexture(fbo, GL30.GL_DEPTH_ATTACHMENT, ((GLTexture)depth).id(), 0);
|
||||
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, fbo);
|
||||
if(color != null) GL11.glViewport(0, 0, color.width(), color.height());
|
||||
else if(depth != null) GL11.glViewport(0, 0, depth.width(), depth.height());
|
||||
break;
|
||||
if(color != null) {
|
||||
GL45.glNamedFramebufferTexture(fbo, GL30.GL_COLOR_ATTACHMENT0, ((GLTexture)color).id(), 0);
|
||||
yield new ScreenBuffer(fbo, color.width(), color.height());
|
||||
}
|
||||
if(depth != null) {
|
||||
GL45.glNamedFramebufferTexture(fbo, GL30.GL_DEPTH_ATTACHMENT, ((GLTexture)depth).id(), 0);
|
||||
yield new ScreenBuffer(fbo, depth.width(), depth.height());
|
||||
}
|
||||
throw new IllegalArgumentException("No Color or Depth Provided");
|
||||
}
|
||||
}
|
||||
};
|
||||
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, targetFBO.fbo());
|
||||
GL11.glViewport(0, 0, targetFBO.width(), targetFBO.height());
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -112,50 +114,6 @@ public class GLCommandQueue implements GraphicsCommandQueue {
|
||||
public void readFromTexture(Texture source, int x, int y, int width, int height, long target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderPass createRenderPass(RenderTarget target, DrawArea area) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int hasState = 0;
|
||||
int frameBuffer = switch(target) {
|
||||
case ScreenTarget _ -> {
|
||||
Window window = device.getWindow();
|
||||
width = window.width();
|
||||
height = window.height();
|
||||
hasState = HAS_BOTH;
|
||||
yield 0;
|
||||
}
|
||||
case TextureTarget(AssetLocation id, Texture color, Texture depth) -> {
|
||||
int fbo = fboCache.getOrCreateFBO(id);
|
||||
if(color != null) {
|
||||
hasState |= HAS_COLOR;
|
||||
GL45.glNamedFramebufferTexture(fbo, GL30.GL_COLOR_ATTACHMENT0, ((GLTexture)color).id(), 0);
|
||||
}
|
||||
if(depth != null) {
|
||||
hasState |= HAS_DEPTH;
|
||||
GL45.glNamedFramebufferTexture(fbo, GL30.GL_DEPTH_ATTACHMENT, ((GLTexture)depth).id(), 0);
|
||||
}
|
||||
if(color != null) {
|
||||
width = color.width();
|
||||
height = color.height();
|
||||
}
|
||||
else if(depth != null) {
|
||||
width = depth.width();
|
||||
height = depth.height();
|
||||
}
|
||||
yield fbo;
|
||||
}
|
||||
};
|
||||
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, frameBuffer);
|
||||
GL11.glViewport(0, 0, width, height);
|
||||
boolean scissors = area != null && !area.fills(width, height);
|
||||
if(scissors) {
|
||||
GL11.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
GL11.glScissor(area.x(), area.y(), area.width(), area.height());
|
||||
}
|
||||
return (activePass = new GLRenderPass(this, area, scissors, (hasState & HAS_COLOR) != 0, (hasState & HAS_DEPTH) != 0, frameBuffer));
|
||||
}
|
||||
|
||||
private record PushableObject<T>(T original, T applying, Supplier<T> current, Consumer<T> apply) implements PushableResource {
|
||||
@Override
|
||||
public void close() {
|
||||
@@ -164,4 +122,11 @@ public class GLCommandQueue implements GraphicsCommandQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private record ScreenBuffer(int fbo, int width, int height) {}
|
||||
|
||||
@Override
|
||||
public void submitCommands(GraphicsCommandBuffer buffer) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -9,14 +9,17 @@ import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.opengl.GL43;
|
||||
import org.lwjgl.opengl.GL45;
|
||||
|
||||
import speiger.src.coreengine.assets.base.IAssetProvider;
|
||||
import speiger.src.coreengine.assets.api.IAssetProvider;
|
||||
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.GraphicsCommandBuffer;
|
||||
import speiger.src.coreengine.graphics.api.core.GraphicsDevice;
|
||||
import speiger.src.coreengine.graphics.api.mesh.Mesh;
|
||||
import speiger.src.coreengine.graphics.api.sampler.SamplerSettings;
|
||||
import speiger.src.coreengine.graphics.api.shader.ShaderPipeline;
|
||||
import speiger.src.coreengine.graphics.api.texture.TextureSettings;
|
||||
import speiger.src.coreengine.graphics.api.texture.states.SwizzleMask;
|
||||
import speiger.src.coreengine.graphics.api.utils.ExecutionType;
|
||||
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer;
|
||||
import speiger.src.coreengine.graphics.opengl.sampler.GLSampler;
|
||||
import speiger.src.coreengine.graphics.opengl.shader.ShaderInstance;
|
||||
@@ -44,6 +47,11 @@ public class GLGraphicsDevice implements GraphicsDevice {
|
||||
return new GLSurface(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsCommandBuffer createBuffer(ExecutionType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GLCommandQueue getQueue() {
|
||||
return queue;
|
||||
@@ -85,9 +93,12 @@ public class GLGraphicsDevice implements GraphicsDevice {
|
||||
return new GLSampler(Objects.requireNonNull(settings));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mesh createMesh(Mesh.Builder builder, boolean autocreate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ShaderInstance createShader(ShaderPipeline line, IAssetProvider provider) {
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package speiger.src.coreengine.graphics.opengl.mesh;
|
||||
|
||||
import org.lwjgl.opengl.GL45;
|
||||
|
||||
import speiger.src.collections.ints.maps.interfaces.Int2ObjectMap;
|
||||
import speiger.src.coreengine.graphics.api.buffer.VertexBuffer;
|
||||
import speiger.src.coreengine.graphics.api.mesh.Mesh;
|
||||
import speiger.src.coreengine.graphics.api.vertex.VertexLayout;
|
||||
import speiger.src.coreengine.graphics.api.vertex.VertexLayout.Element;
|
||||
import speiger.src.coreengine.graphics.opengl.buffer.GLVertexBuffer;
|
||||
import speiger.src.coreengine.graphics.opengl.utils.GLUtils;
|
||||
|
||||
public class GLMesh extends Mesh {
|
||||
int vao;
|
||||
boolean managed;
|
||||
|
||||
public GLMesh(Int2ObjectMap<LayoutInfo> layouts, Int2ObjectMap<VertexBuffer> buffers, VertexBuffer indeciesBuffer, boolean managed) {
|
||||
super(layouts, buffers, indeciesBuffer);
|
||||
this.managed = managed;
|
||||
vao = GL45.glCreateVertexArrays();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoved() { return vao == 0; }
|
||||
|
||||
@Override
|
||||
public Mesh buffer(int binding, VertexBuffer buffer) {
|
||||
super.buffer(binding, buffer);
|
||||
bind(binding);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void bind(int binding) {
|
||||
LayoutInfo info = layouts.get(binding);
|
||||
VertexLayout layout = info.layout();
|
||||
GLVertexBuffer buffer = (GLVertexBuffer)buffers.get(binding);
|
||||
GL45.glVertexArrayVertexBuffer(vao, binding, buffer.id(), 0, layout.bytes());
|
||||
if(info.instanceCount() > 0) GL45.glVertexArrayBindingDivisor(vao, binding, info.instanceCount());
|
||||
int index = 0;
|
||||
for(Element element : layout) {
|
||||
GL45.glVertexArrayAttribFormat(vao, element.index(), element.size(), GLUtils.toGL(element.type()), element.normalized(), layout.offset(index++));
|
||||
GL45.glVertexArrayAttribBinding(vao, element.index(), binding);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if(vao == 0) return;
|
||||
GL45.glDeleteVertexArrays(vao);
|
||||
vao = 0;
|
||||
if(!managed) return;
|
||||
if(indeciesBuffer != null) indeciesBuffer.remove();
|
||||
buffers.values().forEach(VertexBuffer::close);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeWithBuffers() {
|
||||
boolean wasManaged = managed;
|
||||
managed = true;
|
||||
close();
|
||||
managed = wasManaged;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@ 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.shader.states.GraphicsDataType;
|
||||
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;
|
||||
@@ -126,4 +127,31 @@ public class GLUtils {
|
||||
case NOTEQUAL -> GL11.GL_NOTEQUAL;
|
||||
};
|
||||
}
|
||||
|
||||
public static int toGL(GraphicsDataType type) {
|
||||
return switch(type) {
|
||||
case BYTE -> GL11.GL_BYTE;
|
||||
case UNSIGNED_BYTE -> GL11.GL_UNSIGNED_BYTE;
|
||||
case SHORT -> GL11.GL_SHORT;
|
||||
case UNSIGNED_SHORT -> GL11.GL_UNSIGNED_SHORT;
|
||||
case INT -> GL11.GL_INT;
|
||||
case UNSIGNED_INT -> GL11.GL_UNSIGNED_INT;
|
||||
case FLOAT -> GL11.GL_FLOAT;
|
||||
case DOUBLE -> GL11.GL_DOUBLE;
|
||||
case UNSIGNED_3_3_2 -> GL12.GL_UNSIGNED_BYTE_3_3_2;
|
||||
case UNSIGNED_2_3_3_REV -> GL12.GL_UNSIGNED_BYTE_2_3_3_REV;
|
||||
case UNSIGNED_5_6_5 -> GL12.GL_UNSIGNED_SHORT_5_6_5;
|
||||
case UNSIGNED_5_6_5_REV -> GL12.GL_UNSIGNED_SHORT_5_6_5_REV;
|
||||
case UNSIGNED_4_4_4_4 -> GL12.GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
case UNSIGNED_4_4_4_4_REV -> GL12.GL_UNSIGNED_SHORT_4_4_4_4_REV;
|
||||
case UNSIGNED_5_5_5_1 -> GL12.GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
case UNSIGNED_1_5_5_5_REV -> GL12.GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
case UNSIGNED_8_8_8_8 -> GL12.GL_UNSIGNED_INT_8_8_8_8;
|
||||
case UNSIGNED_8_8_8_8_REV -> GL12.GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
case UNSIGNED_10_10_10_2 -> GL12.GL_UNSIGNED_INT_10_10_10_2;
|
||||
case UNSIGNED_2_10_10_10_REV -> GL12.GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
case UNSIGNED_INT_10F_11F_11F_REV -> GL30.GL_UNSIGNED_INT_10F_11F_11F_REV;
|
||||
case UNSIGNED_INT_5_9_9_9_REV -> GL30.GL_UNSIGNED_INT_5_9_9_9_REV;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user