Finishing more work on textures/fonts

This commit is contained in:
Speiger 2024-07-20 18:03:35 +02:00
parent cc5267378d
commit 30e63d79a2
4 changed files with 57 additions and 10 deletions

View File

@ -14,6 +14,7 @@ import speiger.src.coreengine.rendering.input.devices.FileDrop;
import speiger.src.coreengine.rendering.input.devices.Joystick; import speiger.src.coreengine.rendering.input.devices.Joystick;
import speiger.src.coreengine.rendering.input.devices.Keyboard; import speiger.src.coreengine.rendering.input.devices.Keyboard;
import speiger.src.coreengine.rendering.input.devices.Mouse; import speiger.src.coreengine.rendering.input.devices.Mouse;
import speiger.src.coreengine.rendering.input.events.KeyEvent;
import speiger.src.coreengine.rendering.input.window.Window; import speiger.src.coreengine.rendering.input.window.Window;
import speiger.src.coreengine.rendering.input.window.WindowManager; import speiger.src.coreengine.rendering.input.window.WindowManager;
import speiger.src.coreengine.rendering.models.buffers.BufferAttribute; import speiger.src.coreengine.rendering.models.buffers.BufferAttribute;
@ -23,10 +24,12 @@ import speiger.src.coreengine.rendering.shader.SimpleShader;
import speiger.src.coreengine.rendering.shader.uniform.base.TextureUniform; import speiger.src.coreengine.rendering.shader.uniform.base.TextureUniform;
import speiger.src.coreengine.rendering.tesselation.buffer.VertexBuilder; import speiger.src.coreengine.rendering.tesselation.buffer.VertexBuilder;
import speiger.src.coreengine.rendering.tesselation.format.VertexTypes; import speiger.src.coreengine.rendering.tesselation.format.VertexTypes;
import speiger.src.coreengine.rendering.textures.custom.Drawable;
import speiger.src.coreengine.rendering.textures.custom.DynamicTexture; import speiger.src.coreengine.rendering.textures.custom.DynamicTexture;
import speiger.src.coreengine.rendering.utils.GLStateTracker; import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.rendering.utils.values.GLDataType; import speiger.src.coreengine.rendering.utils.values.GLDataType;
import speiger.src.coreengine.rendering.utils.values.GLMode; import speiger.src.coreengine.rendering.utils.values.GLMode;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureFormat;
import speiger.src.coreengine.utils.eventbus.EventBus; import speiger.src.coreengine.utils.eventbus.EventBus;
import speiger.src.coreengine.utils.helpers.IOUtils; import speiger.src.coreengine.utils.helpers.IOUtils;
@ -67,6 +70,17 @@ public class NewInputTest {
texture.process(true); texture.process(true);
window.visible(true); window.visible(true);
bus.register(KeyEvent.Key.class, T -> {
if(T.key() == GLFW.GLFW_KEY_T) {
T.cancel();
texture.bind();
Drawable drawable = new Drawable(GLTextureFormat.RGBA, 8, 8);
drawable.fill(0, 0, 8, 8, 255, 255, 0, 255);
drawable.upload(6, 6, 2, 2, 4, 4);
drawable.close();
}
});
VertexBuilder builder = new VertexBuilder(255); VertexBuilder builder = new VertexBuilder(255);
builder.start(GLMode.TRIANGLES, VertexTypes.TESTING); builder.start(GLMode.TRIANGLES, VertexTypes.TESTING);
builder.pos(-0.5F, -0.5F, 0).tex(0F, 1F).rgba(-1).endVertex(); builder.pos(-0.5F, -0.5F, 0).tex(0F, 1F).rgba(-1).endVertex();

View File

@ -99,6 +99,7 @@ public class TextureMetadata {
for(int i = 0,m=list.size();i<m;i++) { for(int i = 0,m=list.size();i<m;i++) {
if(BitUtil.intKey(list.getLong(i)) == id) { if(BitUtil.intKey(list.getLong(i)) == id) {
list.removeLong(i--); list.removeLong(i--);
m--;
} }
} }
return this; return this;

View File

@ -1,11 +1,17 @@
package speiger.src.coreengine.rendering.textures.custom; package speiger.src.coreengine.rendering.textures.custom;
import org.lwjgl.opengl.GL46;
import org.lwjgl.stb.STBImage; import org.lwjgl.stb.STBImage;
import org.lwjgl.stb.STBTTFontinfo;
import org.lwjgl.stb.STBTruetype;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import speiger.src.coreengine.math.misc.ColorSpaces; import speiger.src.coreengine.math.misc.ColorSpaces;
import speiger.src.coreengine.rendering.utils.GLFunctions;
import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.rendering.utils.values.GLDataType;
import speiger.src.coreengine.rendering.utils.values.IGLValue;
import speiger.src.coreengine.rendering.utils.values.IGLValue.ITextureComponentFormat; import speiger.src.coreengine.rendering.utils.values.IGLValue.ITextureComponentFormat;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureType;
public class Drawable implements IDrawable, AutoCloseable { public class Drawable implements IDrawable, AutoCloseable {
ITextureComponentFormat format; ITextureComponentFormat format;
@ -20,6 +26,7 @@ public class Drawable implements IDrawable, AutoCloseable {
} }
public Drawable(ITextureComponentFormat format, int width, int height, long pixels, boolean isSTB) { public Drawable(ITextureComponentFormat format, int width, int height, long pixels, boolean isSTB) {
this.format = format;
this.width = width; this.width = width;
this.height = height; this.height = height;
this.pixels = pixels; this.pixels = pixels;
@ -55,12 +62,34 @@ public class Drawable implements IDrawable, AutoCloseable {
protected void ensureValid(int x, int y) { protected void ensureValid(int x, int y) {
if(x < 0 || y < 0) throw new ArrayIndexOutOfBoundsException("Index out of bounds: X=["+x+"], Y=["+y+"]"); if(x < 0 || y < 0) throw new ArrayIndexOutOfBoundsException("Index out of bounds: X=["+x+"], Y=["+y+"]");
if(x >= width || y >= height) throw new ArrayIndexOutOfBoundsException("Index out of bounds: X=["+x+"], Y=["+y+"], width=["+width+"], height=["+height+"]"); if(x > width || y > height) throw new ArrayIndexOutOfBoundsException("Index out of bounds: X=["+x+"], Y=["+y+"], width=["+width+"], height=["+height+"]");
if(pixels == 0L) throw new IllegalStateException("Pixel Data doesn't exist"); if(pixels == 0L) throw new IllegalStateException("Pixel Data doesn't exist");
} }
public void upload(int texture, int level, int x, int y, int texX, int texY, int width, int height) { public void drawFont(STBTTFontinfo info, int glyth, int sourceX, int sourceY, int targetX, int targetY, int width, int height, float scaleX, float scaleY) {
ensureValid(targetX, targetY);
ensureValid(targetX + width, targetY + height);
if(components != 1) throw new IllegalStateException("Format has to be 1 component");
STBTruetype.nstbtt_MakeGlyphBitmapSubpixel(info.address(), pixels + offset(targetX, targetY), width, height, width(), scaleX, scaleY, sourceX, sourceY, glyth);
}
public void upload(int targetX, int targetY, int sourceX, int sourceY, int width, int height) {
upload(GLTextureType.TEXTURE_2D, 0, targetX, targetY, sourceX, sourceY, width, height);
}
public void upload(IGLValue textureType, int level, int targetX, int targetY, int sourceX, int sourceY, int width, int height) {
ensureValid(sourceX, sourceY);
ensureValid(sourceX + width, sourceY + height);
GLStateTracker tracker = GLStateTracker.instance();
tracker.unpack_row_length.set(width());
tracker.unpack_alignment.set(format.components());
tracker.unpack_skip_pixel.set(sourceX);
tracker.unpack_skip_rows.set(sourceY);
GLFunctions.upload2DSubImage(textureType, level, targetX, targetY, width, height, format, GLDataType.UNSIGNED_BYTE, pixels);
tracker.unpack_row_length.setDefault();
tracker.unpack_skip_pixel.setDefault();
tracker.unpack_skip_rows.setDefault();
tracker.unpack_alignment.setDefault();
} }
@Override @Override
@ -103,8 +132,10 @@ public class Drawable implements IDrawable, AutoCloseable {
if(components != 4) throw new IllegalStateException("Format has to be 4 components"); if(components != 4) throw new IllegalStateException("Format has to be 4 components");
ensureValid(x, y); ensureValid(x, y);
ensureValid(x+width, y+height); ensureValid(x+width, y+height);
for(int xOff = 0;xOff<width;xOff++) {
for(int yOff = 0;yOff<height;yOff++) { for(int yOff = 0;yOff<height;yOff++) {
MemoryUtil.memSet(offset(x, y+yOff), data, width * 4L); MemoryUtil.memPutInt(this.pixels + offset(x+xOff, y+yOff), data);
}
} }
} }
@ -119,27 +150,27 @@ public class Drawable implements IDrawable, AutoCloseable {
public int getR(int index) { public int getR(int index) {
if(!format.hasRed()) throw new IllegalArgumentException("Format doesn't support Red/Luminance"); if(!format.hasRed()) throw new IllegalArgumentException("Format doesn't support Red/Luminance");
ensureValid(index); ensureValid(index);
return MemoryUtil.memGetByte(index * 4L); return MemoryUtil.memGetByte(index * components + format.redOffset());
} }
@Override @Override
public int getG(int index) { public int getG(int index) {
if(!format.hasGreen()) throw new IllegalArgumentException("Format doesn't support Green"); if(!format.hasGreen()) throw new IllegalArgumentException("Format doesn't support Green");
ensureValid(index); ensureValid(index);
return MemoryUtil.memGetByte(index * 4L + 1L); return MemoryUtil.memGetByte(index * components + format.greenOffset());
} }
@Override @Override
public int getB(int index) { public int getB(int index) {
if(!format.hasBlue()) throw new IllegalArgumentException("Format doesn't support Blue"); if(!format.hasBlue()) throw new IllegalArgumentException("Format doesn't support Blue");
ensureValid(index); ensureValid(index);
return MemoryUtil.memGetByte(index * 4L + 2L); return MemoryUtil.memGetByte(index * components + format.blueOffset());
} }
@Override @Override
public int getA(int index) { public int getA(int index) {
if(!format.hasAlpha()) throw new IllegalArgumentException("Format doesn't support Alpha"); if(!format.hasAlpha()) throw new IllegalArgumentException("Format doesn't support Alpha");
ensureValid(index); ensureValid(index);
return MemoryUtil.memGetByte(index * 4L + 3L); return MemoryUtil.memGetByte(index * components + format.alphaOffset());
} }
} }

View File

@ -99,6 +99,7 @@ public class EventBus
} }
protected Listeners getListeners(Class<? extends Event> event) { protected Listeners getListeners(Class<? extends Event> event) {
//TODO this is abusing undefined behavior!
return listeners.computeIfAbsent(event, T -> { return listeners.computeIfAbsent(event, T -> {
if(T == Event.class) return new Listeners(); if(T == Event.class) return new Listeners();
else return new Listeners(getListeners(castClass(event.getSuperclass()))); else return new Listeners(getListeners(castClass(event.getSuperclass())));