From 324a081fc9bf44ccf8ce2319efd61069d4d9ab31 Mon Sep 17 00:00:00 2001 From: DaniTheSkunk <> Date: Wed, 23 Nov 2022 08:03:20 +0000 Subject: [PATCH] rendering vrm model semi correctly :) --- com/danitheskunk/skunkworks/Test3D.java | 70 +++++++++++++++++-- com/danitheskunk/skunkworks/Vec2f.java | 4 ++ .../backends/gl/RenderContext3D.java | 59 ++++++++++++---- .../skunkworks/backends/gl/Window.java | 44 ++++++++++-- .../skunkworks/gfx/threedee/Mesh.java | 43 +++++++++--- 5 files changed, 185 insertions(+), 35 deletions(-) diff --git a/com/danitheskunk/skunkworks/Test3D.java b/com/danitheskunk/skunkworks/Test3D.java index 2d4974d..a748433 100644 --- a/com/danitheskunk/skunkworks/Test3D.java +++ b/com/danitheskunk/skunkworks/Test3D.java @@ -1,12 +1,16 @@ package com.danitheskunk.skunkworks; +import com.danitheskunk.skunkworks.gfx.ITexture; +import com.danitheskunk.skunkworks.gfx.Image; import com.danitheskunk.skunkworks.gfx.threedee.IRenderContext3D; import com.danitheskunk.skunkworks.gfx.threedee.Mesh; -import org.lwjgl.assimp.AIMesh; -import org.lwjgl.assimp.Assimp; +import org.lwjgl.assimp.*; + +import java.nio.IntBuffer; public class Test3D extends BaseGame { private Mesh[] meshes; + public Test3D() { super(new Vec2i(1920, 1080), "Skunkworks 3d test"); System.out.printf("assimp version: %d.%d.%d\n", @@ -15,6 +19,7 @@ public class Test3D extends BaseGame { Assimp.aiGetVersionPatch() ); var path = "C:\\stream\\models\\Dani.glb"; + //path = "C:\\stream\\models\\Amber_Arakada_V5_Blendshape.glb"; var bytes = engine.loadBytes(path); var flags = Assimp.aiProcess_Triangulate; flags |= Assimp.aiProcess_OptimizeGraph; @@ -26,19 +31,74 @@ public class Test3D extends BaseGame { throw new RuntimeException("couldn't load model because: " + Assimp.aiGetErrorString()); } + + int numMaterials = ai.mNumMaterials(); + var matTex = new int[numMaterials]; + var matPB = ai.mMaterials(); + for(int i = 0; i < numMaterials; ++i) { + var aiMat = AIMaterial.create(matPB.get(i)); + var texCount = Assimp.aiGetMaterialTextureCount(aiMat, + Assimp.aiTextureType_DIFFUSE + ); + var tpath = AIString.calloc(); + var tex = Assimp.aiGetMaterialTexture(aiMat, + Assimp.aiTextureType_DIFFUSE, + 0, + tpath, + (IntBuffer) null, + null, + null, + null, + null, + null + ); + var tpathstr = tpath.dataString(); + matTex[i] = tpathstr.startsWith("*") ? + Integer.parseInt(tpathstr.substring( + 1)) : -1; + System.out.printf("tex count: %d, path: %s\n", + texCount, + tpath.dataString() + ); + } + + int numTextures = ai.mNumTextures(); + var textures = new ITexture[numTextures]; + var texPB = ai.mTextures(); + for(int i = 0; i < numTextures; ++i) { + var aiTex = AITexture.create(texPB.get(i)); + var img = new Image(aiTex.pcDataCompressed()); + var tex = window.loadTexture(img); + textures[i] = tex; + System.out.printf("tex %dx%d\n", img.getWidth(), img.getHeight()); + } + + var numMeshes = ai.mNumMeshes(); - var meshespb = ai.mMeshes(); + var meshPB = ai.mMeshes(); meshes = new Mesh[numMeshes]; int faces = 0; for(int i = 0; i < numMeshes; ++i) { - var aiMesh = AIMesh.create(meshespb.get(i)); + var aiMesh = AIMesh.create(meshPB.get(i)); var mesh = Mesh.fromAIMesh(aiMesh); + var tex = aiMesh.mMaterialIndex(); + if(tex >= 0) { + mesh.setTexture(textures[matTex[tex]]); + } meshes[i] = mesh; System.out.println(aiMesh.mNumFaces()); faces += aiMesh.mNumFaces(); } - System.out.printf("numMeshes: %d, faces: %d\n", numMeshes, faces); + + + //window.setDebug(true); + + System.out.printf("numMeshes: %d, faces: %d, textures: %d\n", + numMeshes, + faces, + numTextures + ); } static public void main(String[] args) { diff --git a/com/danitheskunk/skunkworks/Vec2f.java b/com/danitheskunk/skunkworks/Vec2f.java index b9ba1a6..667efee 100644 --- a/com/danitheskunk/skunkworks/Vec2f.java +++ b/com/danitheskunk/skunkworks/Vec2f.java @@ -30,6 +30,10 @@ public final class Vec2f { return new Vec2f(a.x * b, a.y * b); } + public static Vec2f mul(Vec2f a, Vec2f b) { + return new Vec2f(a.x * b.x, a.y * b.y); + } + public static Vec2f sub(Vec2f a, Vec2f b) { return new Vec2f(a.x - b.x, a.y - b.y); } diff --git a/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java b/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java index 85d95a5..c3048a8 100644 --- a/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java +++ b/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java @@ -1,5 +1,6 @@ package com.danitheskunk.skunkworks.backends.gl; +import com.danitheskunk.skunkworks.Vec2f; import com.danitheskunk.skunkworks.Vec3f; import com.danitheskunk.skunkworks.gfx.threedee.BaseRenderContext3D; import com.danitheskunk.skunkworks.gfx.threedee.Mesh; @@ -7,6 +8,49 @@ import com.danitheskunk.skunkworks.gfx.threedee.Mesh; import static org.lwjgl.opengl.GL46.*; public class RenderContext3D extends BaseRenderContext3D { + private TextureAtlas textureAtlas; + private final int texCoordIndex; + + public RenderContext3D(int texCoordIndex) { + this.texCoordIndex = texCoordIndex; + } + + + @Override + public void renderMesh(Mesh mesh) { + var tex = (Texture) mesh.getTexture(); + + var texArea = tex.getTexArea(); + var texOff = Vec2f.div(texArea.getPos(), textureAtlas.getSize()); + var texMult = Vec2f.div(texArea.getSize(), textureAtlas.getSize()); + + + glBegin(GL_TRIANGLES); + for(int i = 0; i < mesh.getTriangleCount(); ++i) { + var tri = mesh.getTriangle(i); + var p1 = mesh.getVertex(tri.getX()); + var p2 = mesh.getVertex(tri.getY()); + var p3 = mesh.getVertex(tri.getZ()); + var t1 = mesh.getUV(tri.getX()); + var t2 = mesh.getUV(tri.getY()); + var t3 = mesh.getUV(tri.getZ()); + //t1 = new Vec2f(t1.getX(), 1.0 - t1.getY()); + //t2 = new Vec2f(t2.getX(), 1.0 - t2.getY()); + //t3 = new Vec2f(t3.getX(), 1.0 - t3.getY()); + t1 = Vec2f.add(texOff, Vec2f.mul(texMult, t1)); + t2 = Vec2f.add(texOff, Vec2f.mul(texMult, t2)); + t3 = Vec2f.add(texOff, Vec2f.mul(texMult, t3)); + + glVertexAttrib2d(texCoordIndex, t1.getX(), t1.getY()); + glVertex3d(p1.getX(), p1.getY()-0.5, p1.getZ()+0.5); + glVertexAttrib2d(texCoordIndex, t2.getX(), t2.getY()); + glVertex3d(p2.getX(), p2.getY()-0.5, p2.getZ()+0.5); + glVertexAttrib2d(texCoordIndex, t3.getX(), t3.getY()); + glVertex3d(p3.getX(), p3.getY()-0.5, p3.getZ()+0.5); + } + glEnd(); + } + @Override public void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3) { glBegin(GL_TRIANGLES); @@ -24,18 +68,7 @@ public class RenderContext3D extends BaseRenderContext3D { glEnd(); } - @Override - public void renderMesh(Mesh mesh) { - glBegin(GL_TRIANGLES); - for(int i = 0; i < mesh.getTriangleCount(); ++i) { - var tri = mesh.getTriangle(i); - var p1 = mesh.getVertex(tri.getX()); - var p2 = mesh.getVertex(tri.getY()); - var p3 = mesh.getVertex(tri.getZ()); - glVertex3d(p1.getX(), p1.getY(), p1.getZ()); - glVertex3d(p2.getX(), p2.getY(), p2.getZ()); - glVertex3d(p3.getX(), p3.getY(), p3.getZ()); - } - glEnd(); + public void setTextureAtlas(TextureAtlas textureAtlas) { + this.textureAtlas = textureAtlas; } } diff --git a/com/danitheskunk/skunkworks/backends/gl/Window.java b/com/danitheskunk/skunkworks/backends/gl/Window.java index d922aec..c8d10b4 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Window.java +++ b/com/danitheskunk/skunkworks/backends/gl/Window.java @@ -39,12 +39,13 @@ public class Window extends BaseWindow { private static final String fragmentSource3D = """ #version 450 layout(location = 1) in vec2 texCoord; - //layout(binding = 0) uniform sampler2D tex; + layout(binding = 0) uniform sampler2D tex; out vec4 color; void main() { //color = vec4(vec2(texCoord).x/1000.f, 0.2f, 0.7f, 1.0f); - //color = texture(tex, texCoord); - color = vec4(1.0, texCoord.x / 2, 1.0, 1.0); + color = texture(tex, texCoord); + //color = vec4(0.0, texCoord.xy, 1.0); + //color = vec4(1.0, texCoord.x / 2, 1.0, 1.0); } """; private static final String fragmentSourceScaler = """ @@ -77,12 +78,12 @@ public class Window extends BaseWindow { private static final String vertexSource3D = """ #version 450 layout(location = 0) in vec3 pos; - //layout(location = 1) in ivec2 texCoord; + layout(location = 1) in vec2 texCoord; layout(location = 2) uniform mat4 projection; layout(location = 1) out vec2 out_texCoord; void main() { gl_Position = projection * vec4(pos, 1.0f); - out_texCoord.x = pos.z; + out_texCoord = texCoord; } """; private static final String vertexSourceScaler = """ @@ -98,6 +99,7 @@ public class Window extends BaseWindow { """; private final int framebuffer; private final int framebufferTex; + private final int framebufferDepthTex; private final Program program; private final Program program3D; private final Program programScaler; @@ -143,6 +145,8 @@ public class Window extends BaseWindow { glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + //glDepthFunc(GL_GREATER); glfwSetWindowSizeCallback(window, this::windowSizeCallback); glfwSetMouseButtonCallback(window, this::mouseButtonCallback); @@ -169,6 +173,27 @@ public class Window extends BaseWindow { framebufferTex, 0 ); + + framebufferDepthTex = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, framebufferDepthTex); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT, + size.getX(), + size.getY(), + 0, + GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, + 0 + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glFramebufferTexture(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + framebufferDepthTex, + 0 + ); + glDrawBuffers(GL_COLOR_ATTACHMENT0); textureAtlas = new TextureAtlas(); @@ -186,7 +211,8 @@ public class Window extends BaseWindow { program.getUniformLocation("tint") ); - renderContext3D = new RenderContext3D(); + renderContext3D = new RenderContext3D(program.getAttribLocation("texCoord")); + renderContext3D.setTextureAtlas(textureAtlas); glProgramUniform2f(program.program, program.getUniformLocation("windowSize"), @@ -348,11 +374,13 @@ public class Window extends BaseWindow { public void runScaler() { //glEnd(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, windowSize.getX(), windowSize.getY()); + programScaler.use(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, framebufferTex); glProgramUniform2f(programScaler.program, @@ -428,6 +456,8 @@ public class Window extends BaseWindow { glEnd(); + + glfwSwapBuffers(window); } diff --git a/com/danitheskunk/skunkworks/gfx/threedee/Mesh.java b/com/danitheskunk/skunkworks/gfx/threedee/Mesh.java index 83ebdae..065229e 100644 --- a/com/danitheskunk/skunkworks/gfx/threedee/Mesh.java +++ b/com/danitheskunk/skunkworks/gfx/threedee/Mesh.java @@ -1,19 +1,24 @@ package com.danitheskunk.skunkworks.gfx.threedee; +import com.danitheskunk.skunkworks.Vec2f; import com.danitheskunk.skunkworks.Vec3f; import com.danitheskunk.skunkworks.Vec3i; +import com.danitheskunk.skunkworks.gfx.ITexture; import org.lwjgl.assimp.AIMesh; import java.util.ArrayList; import java.util.List; public class Mesh { + private ITexture texture; private List triangles; + private List uv; private List vertices; public Mesh() { vertices = new ArrayList<>(); triangles = new ArrayList<>(); + uv = new ArrayList<>(); } public static Mesh fromAIMesh(AIMesh aiMesh) { @@ -24,6 +29,7 @@ public class Mesh { var vertexBuffer = aiMesh.mVertices(); var faceBuffer = aiMesh.mFaces(); + var texCoordsBuffer = aiMesh.mTextureCoords(0); while(vertexBuffer.remaining() > 0) { var vert = vertexBuffer.get(); @@ -39,6 +45,12 @@ public class Mesh { var indices = face.mIndices(); mesh.addTriangle(indices.get(0), indices.get(1), indices.get(2)); } + + while(texCoordsBuffer.remaining() > 0) { + var uv = texCoordsBuffer.get(); + mesh.addUV(new Vec2f(uv.x(), 1.0 - uv.y())); + } + return mesh; } @@ -46,24 +58,35 @@ public class Mesh { triangles.add(new Vec3i(v1, v2, v3)); } + public void addUV(Vec2f uv) { + this.uv.add(uv); + } + public void addVertex(Vec3f vertex) { vertices.add(vertex); } - public int getTriangleCount() { - return triangles.size(); - } - - public int getVertexCount() { - return vertices.size(); - } - - public Vec3f getVertex(int idx) { - return vertices.get(idx); + public ITexture getTexture() { + return texture; } public Vec3i getTriangle(int idx) { return triangles.get(idx); } + public int getTriangleCount() { + return triangles.size(); + } + + public Vec2f getUV(int idx) { + return uv.get(idx); + } + + public Vec3f getVertex(int idx) { + return vertices.get(idx); + } + + public void setTexture(ITexture texture) { + this.texture = texture; + } }