rendering vrm model semi correctly :)

This commit is contained in:
DaniTheSkunk 2022-11-23 08:03:20 +00:00
parent 40e1956098
commit 324a081fc9
5 changed files with 185 additions and 35 deletions

View File

@ -1,12 +1,16 @@
package com.danitheskunk.skunkworks; 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.IRenderContext3D;
import com.danitheskunk.skunkworks.gfx.threedee.Mesh; import com.danitheskunk.skunkworks.gfx.threedee.Mesh;
import org.lwjgl.assimp.AIMesh; import org.lwjgl.assimp.*;
import org.lwjgl.assimp.Assimp;
import java.nio.IntBuffer;
public class Test3D extends BaseGame { public class Test3D extends BaseGame {
private Mesh[] meshes; private Mesh[] meshes;
public Test3D() { public Test3D() {
super(new Vec2i(1920, 1080), "Skunkworks 3d test"); super(new Vec2i(1920, 1080), "Skunkworks 3d test");
System.out.printf("assimp version: %d.%d.%d\n", System.out.printf("assimp version: %d.%d.%d\n",
@ -15,6 +19,7 @@ public class Test3D extends BaseGame {
Assimp.aiGetVersionPatch() Assimp.aiGetVersionPatch()
); );
var path = "C:\\stream\\models\\Dani.glb"; var path = "C:\\stream\\models\\Dani.glb";
//path = "C:\\stream\\models\\Amber_Arakada_V5_Blendshape.glb";
var bytes = engine.loadBytes(path); var bytes = engine.loadBytes(path);
var flags = Assimp.aiProcess_Triangulate; var flags = Assimp.aiProcess_Triangulate;
flags |= Assimp.aiProcess_OptimizeGraph; flags |= Assimp.aiProcess_OptimizeGraph;
@ -26,19 +31,74 @@ public class Test3D extends BaseGame {
throw new RuntimeException("couldn't load model because: " + throw new RuntimeException("couldn't load model because: " +
Assimp.aiGetErrorString()); 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 numMeshes = ai.mNumMeshes();
var meshespb = ai.mMeshes(); var meshPB = ai.mMeshes();
meshes = new Mesh[numMeshes]; meshes = new Mesh[numMeshes];
int faces = 0; int faces = 0;
for(int i = 0; i < numMeshes; ++i) { 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 mesh = Mesh.fromAIMesh(aiMesh);
var tex = aiMesh.mMaterialIndex();
if(tex >= 0) {
mesh.setTexture(textures[matTex[tex]]);
}
meshes[i] = mesh; meshes[i] = mesh;
System.out.println(aiMesh.mNumFaces()); System.out.println(aiMesh.mNumFaces());
faces += 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) { static public void main(String[] args) {

View File

@ -30,6 +30,10 @@ public final class Vec2f {
return new Vec2f(a.x * b, a.y * b); 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) { public static Vec2f sub(Vec2f a, Vec2f b) {
return new Vec2f(a.x - b.x, a.y - b.y); return new Vec2f(a.x - b.x, a.y - b.y);
} }

View File

@ -1,5 +1,6 @@
package com.danitheskunk.skunkworks.backends.gl; package com.danitheskunk.skunkworks.backends.gl;
import com.danitheskunk.skunkworks.Vec2f;
import com.danitheskunk.skunkworks.Vec3f; import com.danitheskunk.skunkworks.Vec3f;
import com.danitheskunk.skunkworks.gfx.threedee.BaseRenderContext3D; import com.danitheskunk.skunkworks.gfx.threedee.BaseRenderContext3D;
import com.danitheskunk.skunkworks.gfx.threedee.Mesh; import com.danitheskunk.skunkworks.gfx.threedee.Mesh;
@ -7,6 +8,49 @@ import com.danitheskunk.skunkworks.gfx.threedee.Mesh;
import static org.lwjgl.opengl.GL46.*; import static org.lwjgl.opengl.GL46.*;
public class RenderContext3D extends BaseRenderContext3D { 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 @Override
public void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3) { public void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3) {
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);
@ -24,18 +68,7 @@ public class RenderContext3D extends BaseRenderContext3D {
glEnd(); glEnd();
} }
@Override public void setTextureAtlas(TextureAtlas textureAtlas) {
public void renderMesh(Mesh mesh) { this.textureAtlas = textureAtlas;
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();
} }
} }

View File

@ -39,12 +39,13 @@ public class Window extends BaseWindow {
private static final String fragmentSource3D = """ private static final String fragmentSource3D = """
#version 450 #version 450
layout(location = 1) in vec2 texCoord; layout(location = 1) in vec2 texCoord;
//layout(binding = 0) uniform sampler2D tex; layout(binding = 0) uniform sampler2D tex;
out vec4 color; out vec4 color;
void main() { void main() {
//color = vec4(vec2(texCoord).x/1000.f, 0.2f, 0.7f, 1.0f); //color = vec4(vec2(texCoord).x/1000.f, 0.2f, 0.7f, 1.0f);
//color = texture(tex, texCoord); color = texture(tex, texCoord);
color = vec4(1.0, texCoord.x / 2, 1.0, 1.0); //color = vec4(0.0, texCoord.xy, 1.0);
//color = vec4(1.0, texCoord.x / 2, 1.0, 1.0);
} }
"""; """;
private static final String fragmentSourceScaler = """ private static final String fragmentSourceScaler = """
@ -77,12 +78,12 @@ public class Window extends BaseWindow {
private static final String vertexSource3D = """ private static final String vertexSource3D = """
#version 450 #version 450
layout(location = 0) in vec3 pos; 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 = 2) uniform mat4 projection;
layout(location = 1) out vec2 out_texCoord; layout(location = 1) out vec2 out_texCoord;
void main() { void main() {
gl_Position = projection * vec4(pos, 1.0f); gl_Position = projection * vec4(pos, 1.0f);
out_texCoord.x = pos.z; out_texCoord = texCoord;
} }
"""; """;
private static final String vertexSourceScaler = """ private static final String vertexSourceScaler = """
@ -98,6 +99,7 @@ public class Window extends BaseWindow {
"""; """;
private final int framebuffer; private final int framebuffer;
private final int framebufferTex; private final int framebufferTex;
private final int framebufferDepthTex;
private final Program program; private final Program program;
private final Program program3D; private final Program program3D;
private final Program programScaler; private final Program programScaler;
@ -143,6 +145,8 @@ public class Window extends BaseWindow {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
//glDepthFunc(GL_GREATER);
glfwSetWindowSizeCallback(window, this::windowSizeCallback); glfwSetWindowSizeCallback(window, this::windowSizeCallback);
glfwSetMouseButtonCallback(window, this::mouseButtonCallback); glfwSetMouseButtonCallback(window, this::mouseButtonCallback);
@ -169,6 +173,27 @@ public class Window extends BaseWindow {
framebufferTex, framebufferTex,
0 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); glDrawBuffers(GL_COLOR_ATTACHMENT0);
textureAtlas = new TextureAtlas(); textureAtlas = new TextureAtlas();
@ -186,7 +211,8 @@ public class Window extends BaseWindow {
program.getUniformLocation("tint") program.getUniformLocation("tint")
); );
renderContext3D = new RenderContext3D(); renderContext3D = new RenderContext3D(program.getAttribLocation("texCoord"));
renderContext3D.setTextureAtlas(textureAtlas);
glProgramUniform2f(program.program, glProgramUniform2f(program.program,
program.getUniformLocation("windowSize"), program.getUniformLocation("windowSize"),
@ -348,11 +374,13 @@ public class Window extends BaseWindow {
public void runScaler() { public void runScaler() {
//glEnd(); //glEnd();
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, windowSize.getX(), windowSize.getY()); glViewport(0, 0, windowSize.getX(), windowSize.getY());
programScaler.use(); programScaler.use();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 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); glBindTexture(GL_TEXTURE_2D, framebufferTex);
glProgramUniform2f(programScaler.program, glProgramUniform2f(programScaler.program,
@ -428,6 +456,8 @@ public class Window extends BaseWindow {
glEnd(); glEnd();
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }

View File

@ -1,19 +1,24 @@
package com.danitheskunk.skunkworks.gfx.threedee; package com.danitheskunk.skunkworks.gfx.threedee;
import com.danitheskunk.skunkworks.Vec2f;
import com.danitheskunk.skunkworks.Vec3f; import com.danitheskunk.skunkworks.Vec3f;
import com.danitheskunk.skunkworks.Vec3i; import com.danitheskunk.skunkworks.Vec3i;
import com.danitheskunk.skunkworks.gfx.ITexture;
import org.lwjgl.assimp.AIMesh; import org.lwjgl.assimp.AIMesh;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Mesh { public class Mesh {
private ITexture texture;
private List<Vec3i> triangles; private List<Vec3i> triangles;
private List<Vec2f> uv;
private List<Vec3f> vertices; private List<Vec3f> vertices;
public Mesh() { public Mesh() {
vertices = new ArrayList<>(); vertices = new ArrayList<>();
triangles = new ArrayList<>(); triangles = new ArrayList<>();
uv = new ArrayList<>();
} }
public static Mesh fromAIMesh(AIMesh aiMesh) { public static Mesh fromAIMesh(AIMesh aiMesh) {
@ -24,6 +29,7 @@ public class Mesh {
var vertexBuffer = aiMesh.mVertices(); var vertexBuffer = aiMesh.mVertices();
var faceBuffer = aiMesh.mFaces(); var faceBuffer = aiMesh.mFaces();
var texCoordsBuffer = aiMesh.mTextureCoords(0);
while(vertexBuffer.remaining() > 0) { while(vertexBuffer.remaining() > 0) {
var vert = vertexBuffer.get(); var vert = vertexBuffer.get();
@ -39,6 +45,12 @@ public class Mesh {
var indices = face.mIndices(); var indices = face.mIndices();
mesh.addTriangle(indices.get(0), indices.get(1), indices.get(2)); 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; return mesh;
} }
@ -46,24 +58,35 @@ public class Mesh {
triangles.add(new Vec3i(v1, v2, v3)); triangles.add(new Vec3i(v1, v2, v3));
} }
public void addUV(Vec2f uv) {
this.uv.add(uv);
}
public void addVertex(Vec3f vertex) { public void addVertex(Vec3f vertex) {
vertices.add(vertex); vertices.add(vertex);
} }
public int getTriangleCount() { public ITexture getTexture() {
return triangles.size(); return texture;
}
public int getVertexCount() {
return vertices.size();
}
public Vec3f getVertex(int idx) {
return vertices.get(idx);
} }
public Vec3i getTriangle(int idx) { public Vec3i getTriangle(int idx) {
return triangles.get(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;
}
} }