From 7339ca69a713c04c6eff5682fac096125280155e Mon Sep 17 00:00:00 2001 From: DaniTheSkunk <> Date: Fri, 18 Nov 2022 22:37:00 +0000 Subject: [PATCH] started 3d code --- com/danitheskunk/skunkworks/BaseGame.java | 9 ++ com/danitheskunk/skunkworks/IWindow.java | 12 ++- com/danitheskunk/skunkworks/Mat4f.java | 68 ++++++++++++++ com/danitheskunk/skunkworks/Test3D.java | 24 +++++ com/danitheskunk/skunkworks/Vec3f.java | 25 ++++++ .../backends/gl/RenderContext3D.java | 24 +++++ .../skunkworks/backends/gl/Window.java | 88 +++++++++++++++---- .../skunkworks/gfx/BaseRenderContext3D.java | 7 ++ .../skunkworks/gfx/IRenderContext3D.java | 7 ++ 9 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 com/danitheskunk/skunkworks/Mat4f.java create mode 100644 com/danitheskunk/skunkworks/Test3D.java create mode 100644 com/danitheskunk/skunkworks/Vec3f.java create mode 100644 com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java create mode 100644 com/danitheskunk/skunkworks/gfx/BaseRenderContext3D.java create mode 100644 com/danitheskunk/skunkworks/gfx/IRenderContext3D.java diff --git a/com/danitheskunk/skunkworks/BaseGame.java b/com/danitheskunk/skunkworks/BaseGame.java index 8451f3d..fe340fc 100644 --- a/com/danitheskunk/skunkworks/BaseGame.java +++ b/com/danitheskunk/skunkworks/BaseGame.java @@ -6,6 +6,7 @@ import com.danitheskunk.skunkworks.audio.nodes.Mixer; import com.danitheskunk.skunkworks.audio.nodes.Node; import com.danitheskunk.skunkworks.audio.nodes.SamplePlayer; import com.danitheskunk.skunkworks.gfx.IRenderContext; +import com.danitheskunk.skunkworks.gfx.IRenderContext3D; import com.danitheskunk.skunkworks.gfx.ITexture; import com.danitheskunk.skunkworks.gfx.font.IFont; import com.danitheskunk.skunkworks.nodes.NodeRoot; @@ -48,15 +49,23 @@ public abstract class BaseGame { //todo: frame rate control rootNode.tick(); update(1.0 / 60.0); + var rc3d = window.renderStart3D(); + render3D(rc3d); + window.renderFinish3D(rc3d); var rc = window.renderStart(); renderPre(rc); rootNode.render(rc); render(rc); window.renderFinish(rc); + + window.runScaler(); audioEngine.refill(); } } + protected void render3D(IRenderContext3D rc3d) { + } + protected void init() { } diff --git a/com/danitheskunk/skunkworks/IWindow.java b/com/danitheskunk/skunkworks/IWindow.java index 6439c7d..56747a3 100644 --- a/com/danitheskunk/skunkworks/IWindow.java +++ b/com/danitheskunk/skunkworks/IWindow.java @@ -1,9 +1,6 @@ package com.danitheskunk.skunkworks; -import com.danitheskunk.skunkworks.gfx.IRenderContext; -import com.danitheskunk.skunkworks.gfx.ITexture; -import com.danitheskunk.skunkworks.gfx.Image; -import com.danitheskunk.skunkworks.gfx.NineSlice; +import com.danitheskunk.skunkworks.gfx.*; import com.danitheskunk.skunkworks.gfx.font.IFont; import java.util.List; @@ -31,6 +28,13 @@ public interface IWindow { IRenderContext renderStart(); + void renderFinish3D(IRenderContext3D context); + + IRenderContext3D renderStart3D(); + + //needs to be run after rendering + void runScaler(); + void setDebug(boolean on); boolean shouldClose(); diff --git a/com/danitheskunk/skunkworks/Mat4f.java b/com/danitheskunk/skunkworks/Mat4f.java new file mode 100644 index 0000000..d7a861f --- /dev/null +++ b/com/danitheskunk/skunkworks/Mat4f.java @@ -0,0 +1,68 @@ +package com.danitheskunk.skunkworks; + +public final class Mat4f { + private final double[] data; + + public Mat4f() { + data = new double[16]; + set(0, 0, 1.0); + set(1, 1, 1.0); + set(2, 2, 1.0); + set(3, 3, 1.0); + } + + public double get(int x, int y) { + return data[x + y * 4]; + } + + public void set(int x, int y, double val) { + data[x + y * 4] = val; + } + + public double[] asArray() { + return data; + } + + public float[] asFloatArray() { + var arr = new float[16]; + for(int i = 0; i < 16; ++i) { + arr[i] = (float)data[i]; + } + return arr; + } + + public static Mat4f perspective( + double fovy, double aspect, double zNear, double zFar + ) { + /* + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + */ + + /* + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + */ + var mat = new Mat4f(); + double tanHalfFovy = Math.tan(fovy / 2.0); + mat.set(0, 0, 1.0 / (aspect * tanHalfFovy)); + mat.set(1, 1, 1.0 / tanHalfFovy); + /* + mat.set(2, 2, - (zFar + zNear) / (zFar - zNear)); + mat.set(2, 3, -1.0); + mat.set(3, 2, -(2.0 * zFar * zNear) / (zFar - zNear)); + */ + mat.set(2, 2, zFar / (zFar - zNear)); + mat.set(2, 3, 1.0); + mat.set(3, 2, -(zFar * zNear) / (zFar - zNear)); + //mat.set(3, 3, 0); + return mat; + } +} diff --git a/com/danitheskunk/skunkworks/Test3D.java b/com/danitheskunk/skunkworks/Test3D.java new file mode 100644 index 0000000..1e308a9 --- /dev/null +++ b/com/danitheskunk/skunkworks/Test3D.java @@ -0,0 +1,24 @@ +package com.danitheskunk.skunkworks; + +import com.danitheskunk.skunkworks.gfx.IRenderContext; +import com.danitheskunk.skunkworks.gfx.IRenderContext3D; + +public class Test3D extends BaseGame { + public Test3D() { + super(new Vec2i(1920, 1080), "Skunkworks 3d test"); + } + + static public void main(String[] args) { + new Test3D().run(); + } + + @Override + protected void render3D(IRenderContext3D rc) { + rc.renderTriangle(new Vec3f(-10, -10, 0), + new Vec3f(10, -10, 0), + new Vec3f(10, 10, -1) + + + ); + } +} diff --git a/com/danitheskunk/skunkworks/Vec3f.java b/com/danitheskunk/skunkworks/Vec3f.java new file mode 100644 index 0000000..6a9cbd4 --- /dev/null +++ b/com/danitheskunk/skunkworks/Vec3f.java @@ -0,0 +1,25 @@ +package com.danitheskunk.skunkworks; + +public final class Vec3f { + public static Vec3f ZERO = new Vec3f(0, 0, 0); + public static Vec3f ONE = new Vec3f(1, 1, 1); + private final double x, y, z; + + public Vec3f(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java b/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java new file mode 100644 index 0000000..3e5ea1c --- /dev/null +++ b/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java @@ -0,0 +1,24 @@ +package com.danitheskunk.skunkworks.backends.gl; + +import com.danitheskunk.skunkworks.Vec3f; +import com.danitheskunk.skunkworks.gfx.BaseRenderContext3D; +import static org.lwjgl.opengl.GL46.*; + +public class RenderContext3D extends BaseRenderContext3D { + @Override + public void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3) { + glBegin(GL_TRIANGLES); + + glVertex3d(p1.getX(), p1.getY(), p1.getZ()); + glVertex3d(p2.getX(), p2.getY(), p2.getZ()); + glVertex3d(p3.getX(), p3.getY(), p3.getZ()); + + /* + glVertex3f((float) p1.getX(), (float) p1.getY(), (float) p1.getZ()); + glVertex3f((float) p2.getX(), (float) p2.getY(), (float) p2.getZ()); + glVertex3f((float) p3.getX(), (float) p3.getY(), (float) p3.getZ()); + */ + + glEnd(); + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/Window.java b/com/danitheskunk/skunkworks/backends/gl/Window.java index 534e802..9cabceb 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Window.java +++ b/com/danitheskunk/skunkworks/backends/gl/Window.java @@ -2,6 +2,7 @@ package com.danitheskunk.skunkworks.backends.gl; import com.danitheskunk.skunkworks.*; import com.danitheskunk.skunkworks.gfx.IRenderContext; +import com.danitheskunk.skunkworks.gfx.IRenderContext3D; import com.danitheskunk.skunkworks.gfx.ITexture; import com.danitheskunk.skunkworks.gfx.Image; import org.lwjgl.glfw.GLFWErrorCallback; @@ -46,7 +47,28 @@ public class Window extends BaseWindow { } } """; - + private static String vertexSource3D = """ + #version 450 + layout(location = 0) in vec3 pos; + //layout(location = 1) in ivec2 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; + } + """; + private static String fragmentSource3D = """ + #version 450 + layout(location = 1) in vec2 texCoord; + //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); + } + """; private static String vertexSourceScaler = """ #version 450 layout(location = 0) in vec2 pos; @@ -75,8 +97,10 @@ public class Window extends BaseWindow { } """; private final Program program; + private final Program program3D; private final Program programScaler; private final RenderContext renderContext; + private final RenderContext3D renderContext3D; private final Vec2i size; private Vec2i windowSize; private final TextureAtlas textureAtlas; @@ -87,6 +111,7 @@ public class Window extends BaseWindow { private final int framebufferTex; private boolean[] stateMouseClicked; private boolean[] stateMouseDown; + private Mat4f projection; public Window(Vec2i size, String title, Engine engine) { super(engine); @@ -113,7 +138,7 @@ public class Window extends BaseWindow { GL.createCapabilities(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0.0f, size.getX(), size.getY(), 0.0f, 0.0f, 1.0f); + //glOrtho(0.0f, size.getX(), size.getY(), 0.0f, 0.0f, 1.0f); glEnable(GL_COLOR); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -148,8 +173,11 @@ public class Window extends BaseWindow { textureAtlas = new TextureAtlas(); program = new Program(vertexSource, fragmentSource); + program3D = new Program(vertexSource3D, fragmentSource3D); programScaler = new Program(vertexSourceScaler, fragmentSourceScaler); + projection = Mat4f.perspective(Math.PI / 2, 16.0 / 9.0, 0.1, 100.0); + renderContext = new RenderContext(size, textureAtlas, program.getAttribLocation("texCoord"), @@ -157,6 +185,9 @@ public class Window extends BaseWindow { program.getUniformLocation("texSize"), program.getUniformLocation("tint") ); + + renderContext3D = new RenderContext3D(); + glProgramUniform2f(program.program, program.getUniformLocation("windowSize"), size.getX(), @@ -235,6 +266,46 @@ public class Window extends BaseWindow { true ); } + } + + @Override + public IRenderContext renderStart() { + program.use(); + textureAtlas.bind(); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glViewport(0, 0, size.getX(), size.getY()); + textureAtlas.update(); + glClearColor(0.f, 0.f, 0.f, 0.0f); + glClear(GL_DEPTH_BUFFER_BIT); + //glBegin(GL_TRIANGLES); + return renderContext; + } + + public void renderFinish3D(IRenderContext3D context) { + + } + + @Override + public IRenderContext3D renderStart3D() { + program3D.use(); + textureAtlas.bind(); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glViewport(0, 0, size.getX(), size.getY()); + textureAtlas.update(); + glClearColor(0.f, 1.f, 0.f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //glBegin(GL_TRIANGLES); + glUniformMatrix4fv( + program3D.getUniformLocation("projection"), + true, + projection.asFloatArray() + ); + + return renderContext3D; + } + + @Override + public void runScaler() { //glEnd(); glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -320,19 +391,6 @@ public class Window extends BaseWindow { glfwSwapBuffers(window); } - @Override - public IRenderContext renderStart() { - program.use(); - textureAtlas.bind(); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - glViewport(0, 0, size.getX(), size.getY()); - textureAtlas.update(); - glClearColor(0.f, 0.f, 0.f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - program.use(); - //glBegin(GL_TRIANGLES); - return renderContext; - } @Override public void setDebug(boolean on) { diff --git a/com/danitheskunk/skunkworks/gfx/BaseRenderContext3D.java b/com/danitheskunk/skunkworks/gfx/BaseRenderContext3D.java new file mode 100644 index 0000000..91443b5 --- /dev/null +++ b/com/danitheskunk/skunkworks/gfx/BaseRenderContext3D.java @@ -0,0 +1,7 @@ +package com.danitheskunk.skunkworks.gfx; + +import com.danitheskunk.skunkworks.Mat4f; + +abstract public class BaseRenderContext3D implements IRenderContext3D { + +} diff --git a/com/danitheskunk/skunkworks/gfx/IRenderContext3D.java b/com/danitheskunk/skunkworks/gfx/IRenderContext3D.java new file mode 100644 index 0000000..a58c0a5 --- /dev/null +++ b/com/danitheskunk/skunkworks/gfx/IRenderContext3D.java @@ -0,0 +1,7 @@ +package com.danitheskunk.skunkworks.gfx; + +import com.danitheskunk.skunkworks.Vec3f; + +public interface IRenderContext3D { + void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3); +}