implemented texture atlas
This commit is contained in:
parent
7c3ee28ba5
commit
f0e92638af
13
Test.java
13
Test.java
|
@ -4,10 +4,11 @@ public class Test {
|
|||
public static void main(String[] args) {
|
||||
var engine = new Engine();
|
||||
var window = engine.openWindow(1280, 720, "Skunkworks");
|
||||
var img2 = engine.loadImage("C:\\art\\pixel stuff.png");
|
||||
var img = engine.loadImage("C:\\Users\\dani\\Videos\\Screenshot 2022-06-25 17-00-59.png");
|
||||
//var img = engine.loadImage("C:\\art\\kyoko.png");
|
||||
var tex = window.loadTexture("C:\\Users\\dani\\Videos\\Screenshot 2022-06-25 17-00-59.png");
|
||||
System.out.println(img.getPixel(new Vec2i(60, 60)));
|
||||
var tex2 = window.loadTexture("C:\\art\\pixel stuff.png");
|
||||
//img.drawImage(img2, Vec2i.ZERO);
|
||||
var tex = window.loadTexture(img);
|
||||
|
||||
while(!window.shouldClose()) {
|
||||
window.tick();
|
||||
|
@ -17,9 +18,13 @@ public class Test {
|
|||
// new Color(150, 200, 250)
|
||||
//);
|
||||
renderContext.drawTextureRectangle(
|
||||
new Recti(100, 100, 100, 100),
|
||||
new Recti(0, 0, 1280, 720),
|
||||
tex
|
||||
);
|
||||
renderContext.drawTextureRectangle(
|
||||
new Recti(new Vec2i(200, 100), tex2.getSize()),
|
||||
tex2
|
||||
);
|
||||
window.renderFinish(renderContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,11 @@ package com.danitheskunk.skunkworks;
|
|||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
public class GLRenderContext implements IRenderContext{
|
||||
private GLTextureAtlas atlas;
|
||||
|
||||
public GLRenderContext(GLTextureAtlas atlas) {
|
||||
this.atlas = atlas;
|
||||
}
|
||||
@Override
|
||||
public void drawRectangle(Recti rect, Color color) {
|
||||
var tl = rect.getTopLeft();
|
||||
|
@ -36,11 +41,18 @@ public class GLRenderContext implements IRenderContext{
|
|||
|
||||
@Override
|
||||
public void drawTextureRectangle(Recti rect, ITexture texture, Color color) {
|
||||
var tex = (GLTexture)texture;
|
||||
|
||||
var tl = rect.getTopLeft();
|
||||
var tr = rect.getTopRight();
|
||||
var bl = rect.getBottomLeft();
|
||||
var br = rect.getBottomRight();
|
||||
|
||||
var ttl = Vec2i.divf(tex.getTexArea().getTopLeft(), atlas.getSize());
|
||||
var ttr = Vec2i.divf(tex.getTexArea().getTopRight(), atlas.getSize());
|
||||
var tbl = Vec2i.divf(tex.getTexArea().getBottomLeft(), atlas.getSize());
|
||||
var tbr = Vec2i.divf(tex.getTexArea().getBottomRight(), atlas.getSize());
|
||||
|
||||
glColor4f(
|
||||
color.getR() / 255.0f,
|
||||
color.getG() / 255.0f,
|
||||
|
@ -49,18 +61,18 @@ public class GLRenderContext implements IRenderContext{
|
|||
);
|
||||
|
||||
//counter clockwise triangles
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glTexCoord2d(tbl.getX(), tbl.getY());
|
||||
glVertex2i(bl.getX(), bl.getY());
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glTexCoord2d(ttr.getX(), ttr.getY());
|
||||
glVertex2i(tr.getX(), tr.getY());
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glTexCoord2d(ttl.getX(), ttl.getY());
|
||||
glVertex2i(tl.getX(), tl.getY());
|
||||
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glTexCoord2d(ttr.getX(), ttr.getY());
|
||||
glVertex2i(tr.getX(), tr.getY());
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glTexCoord2d(tbl.getX(), tbl.getY());
|
||||
glVertex2i(bl.getX(), bl.getY());
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glTexCoord2d(tbr.getX(), tbr.getY());
|
||||
glVertex2i(br.getX(), bl.getY());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,22 @@ package com.danitheskunk.skunkworks;
|
|||
|
||||
public class GLTexture implements ITexture {
|
||||
private Recti texArea;
|
||||
Image img; //for re-blitting onto texture atlas
|
||||
|
||||
GLTexture(Recti texArea) {
|
||||
GLTexture(Recti texArea, Image img) {
|
||||
this.texArea = texArea;
|
||||
this.img = img;
|
||||
}
|
||||
|
||||
//setters
|
||||
@Override
|
||||
public Vec2i getSize() { return this.img.getSize(); }
|
||||
void setTexArea(Recti texArea) {
|
||||
this.texArea = texArea;
|
||||
}
|
||||
|
||||
|
||||
public Recti getTexArea() {
|
||||
return texArea;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package com.danitheskunk.skunkworks;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.stb.STBRPContext;
|
||||
import org.lwjgl.stb.STBRectPack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
@ -26,14 +29,63 @@ class GLTextureAtlas {
|
|||
|
||||
ITexture addTexture(Image img) {
|
||||
//todo: do the actual texture stuff
|
||||
this.img = img;
|
||||
update();
|
||||
var texture = new GLTexture(new Recti(new Vec2i(0, 0), img.getSize()));
|
||||
//this.img = img;
|
||||
var texture = new GLTexture(new Recti(new Vec2i(0, 0), img.getSize()), img);
|
||||
textures.add(texture);
|
||||
repack();
|
||||
updateImage();
|
||||
uploadToGpu();
|
||||
return texture;
|
||||
}
|
||||
|
||||
void update() {
|
||||
void doubleAtlasSize() {
|
||||
img = new Image(Vec2i.mul(img.getSize(), 2));
|
||||
System.out.printf("Resized atlas to %dx%d\n", img.getSize().getX(), img.getSize().getY());
|
||||
}
|
||||
|
||||
void repack() {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int height;
|
||||
|
||||
textures.sort(new TextureHeightComparator().reversed());
|
||||
height = textures.get(0).img.getHeight();
|
||||
|
||||
for(var tex : textures) {
|
||||
//texture larger than atlas? resize atlas and try again
|
||||
if(tex.img.getHeight() > img.getHeight() || tex.img.getWidth() > img.getWidth()) {
|
||||
doubleAtlasSize();
|
||||
repack();
|
||||
return;
|
||||
}
|
||||
|
||||
//row full? start the next row
|
||||
if(img.getWidth() - x < tex.img.getWidth()) {
|
||||
x = 0;
|
||||
y += height;
|
||||
height = tex.img.getHeight();
|
||||
|
||||
//not enough space for new row? resize atlas and try again
|
||||
if(y + height > tex.img.getHeight()) {
|
||||
doubleAtlasSize();
|
||||
repack();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//take space, advance to right
|
||||
tex.setTexArea(new Recti(new Vec2i(x, y), tex.img.getSize()));
|
||||
x += tex.img.getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
void updateImage() {
|
||||
for(var tex : textures) {
|
||||
img.drawImage(tex.img, tex.getTexArea().getPos());
|
||||
}
|
||||
}
|
||||
|
||||
void uploadToGpu() {
|
||||
var buf = BufferUtils.createByteBuffer(img.getData().length);
|
||||
buf.put(img.getData());
|
||||
buf.flip();
|
||||
|
@ -50,4 +102,16 @@ class GLTextureAtlas {
|
|||
buf
|
||||
);
|
||||
}
|
||||
|
||||
public Vec2i getSize() {
|
||||
return img.getSize();
|
||||
}
|
||||
|
||||
private class TextureHeightComparator implements Comparator<GLTexture> {
|
||||
@Override
|
||||
public int compare(GLTexture o1, GLTexture o2) {
|
||||
return o1.img.getHeight() - o2.img.getHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ public class GLWindow implements IWindow {
|
|||
glEnable(GL_COLOR);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
renderContext = new GLRenderContext();
|
||||
textureAtlas = new GLTextureAtlas();
|
||||
renderContext = new GLRenderContext(textureAtlas);
|
||||
|
||||
shouldClose = false;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package com.danitheskunk.skunkworks;
|
||||
|
||||
public interface ITexture {
|
||||
|
||||
Vec2i getSize();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue