diff --git a/.idea/Helium-Engine.iml b/.idea/Helium-Engine.iml index 0913bd0..01c1264 100644 --- a/.idea/Helium-Engine.iml +++ b/.idea/Helium-Engine.iml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/.idea/libraries/snakeyaml_1_9.xml b/.idea/libraries/snakeyaml_1_9.xml new file mode 100644 index 0000000..39c4439 --- /dev/null +++ b/.idea/libraries/snakeyaml_1_9.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/resources/objects/plane.mesh b/resources/objects/plane.mesh new file mode 100644 index 0000000..b6db697 --- /dev/null +++ b/resources/objects/plane.mesh @@ -0,0 +1,59 @@ + +type: color +vertices: + - + vertex: + - -20 + - -0.5000001 + - 20 + texture: + - 0 + - 0 + color: + - 0 + - 0 + - 1 + - + vertex: + - -20 + - -0.5000001 + - -20 + texture: + - 0 + - 1 + color: + - 0 + - 0 + - 1 + - + vertex: + - 20 + - -0.5000001 + - -20 + texture: + - 1 + - 1 + color: + - 1 + - 0 + - 1 + - + vertex: + - 20 + - -0.5000001 + - 20 + texture: + - 1 + - 0 + color: + - 1 + - 0 + - 1 +cull: + - 0 + - 1 + - 3 + - 3 + - 1 + - 2 +texture: "resources/textures/thonk.png" diff --git a/src/Game.java b/src/Game.java index 6e6cd77..2f71b83 100644 --- a/src/Game.java +++ b/src/Game.java @@ -1,11 +1,7 @@ -abstract public class Game { - abstract public void setup() throws Exception; - abstract public void loop() throws Exception; - abstract public void close() throws Exception; - - public void run() throws Exception { - setup(); - loop(); - } +public interface Game { + void setup() throws Exception; + void loop() throws Exception; + void close() throws Exception; + void run() throws Exception; } diff --git a/src/Test.java b/src/Test.java index 46de1d9..01bef0f 100644 --- a/src/Test.java +++ b/src/Test.java @@ -3,13 +3,15 @@ import org.hl.engine.io.Display; import org.hl.engine.io.Input; import org.hl.engine.math.lalg.Vector3f; import org.hl.engine.math.lalg.Vector2f; -import org.hl.engine.objects.FirstPersonCamera; import org.hl.engine.objects.GameObject; +import org.hl.engine.objects.ThirdPersonCamera; +import org.hl.engine.utils.FileUtils; import org.lwjgl.glfw.GLFW; +import java.io.IOException; -public class Test extends Game { +public class Test implements Game { // Defining original parts of the game public final static int WIDTH = 1280, HEIGHT = 760; public final String windowName = "Game!"; @@ -18,18 +20,7 @@ public class Test extends Game { public Renderer renderer; public Shader shader; - public Mesh plane = new Mesh(new Vertex[] { - new Vertex(new Vector3f(-20, -0.5000001f, 20), new Vector2f(0, 0)), - new Vertex(new Vector3f(-20, -0.5000001f, -20), new Vector2f(0, 1)), - new Vertex(new Vector3f(20, -0.5000001f, -20), new Vector2f(1, 1)), - new Vertex(new Vector3f(20, -0.5000001f, 20), new Vector2f(1, 0)), - }, new int[] { - 0, 1, 3, - 3, 1, 2 - - }, new Material(new Texture("resources/textures/thonk.png"))); - - public Mesh mesh = new Mesh(new Vertex[] { + public Mesh cube = new Mesh(new Vertex[] { //Back face new Vertex(new Vector3f(-0.5f, 0.5f, -0.5f), new Vector2f(0.0f, 0.0f)), new Vertex(new Vector3f(-0.5f, -0.5f, -0.5f), new Vector2f(0.0f, 1.0f)), @@ -89,15 +80,24 @@ public class Test extends Game { //Bottom face 20, 21, 23, 23, 21, 22 - }, new Material(new Texture("resources/textures/b.png"))); + }, new Material(new Texture("resources/textures/b.png")), "texture"); public boolean lockToggle = false; - public GameObject testObject = new GameObject(mesh, new Vector3f(0, 0, 0 ), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); + public GameObject[] gameObjects = new GameObject[500]; - public GameObject testingPlane = new GameObject(plane, new Vector3f(0, 0, 0 ), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); + public GameObject cubeObject = new GameObject(cube, new Vector3f(0, 0, 0 ), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); + + //public GameObject planeObject = new GameObject(plane, new Vector3f(0, 0, 0 ), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); + + public GameObject planeObject = new GameObject("resources/objects/plane.mesh", new Vector3f(0, 0, 0 ), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); + + + public ThirdPersonCamera camera = new ThirdPersonCamera(new Vector3f(0, 0, 5), new Vector3f(0, 0, 0), cubeObject, 0.5f, 5, 0.1f, 20f, true, true, true); + + public Test() throws Exception { + } - public FirstPersonCamera camera = new FirstPersonCamera(new Vector3f(0, 0, 1), new Vector3f(0, 0, 0), 0.05f, 0.15f); public void run() throws Exception { setup(); @@ -109,7 +109,7 @@ public class Test extends Game { } - public void loop(){ + public void loop() throws Exception { //First updating @@ -119,8 +119,10 @@ public class Test extends Game { camera.update(); } if (i.buttonPress(GLFW.GLFW_MOUSE_BUTTON_LEFT)) { - lockToggle = !lockToggle; - display.mouseState(lockToggle); + if (!lockToggle) { + lockToggle = true; + display.mouseState(true); + } } else if (i.isKeyDown(GLFW.GLFW_KEY_ESCAPE)) { lockToggle = false; display.mouseState(lockToggle); @@ -133,19 +135,27 @@ public class Test extends Game { // Now Render! - // rendering the mesh - renderer.renderMesh(testObject, camera); - renderer.renderMesh(testingPlane, camera); + // rendering the cube and plane + renderer.renderMesh(cubeObject, camera); + renderer.renderMesh(planeObject, camera); //swap buffers so the new one will appear + + for (GameObject gameObject : gameObjects) { + renderer.renderMesh(gameObject, camera); + } + display.swapBuffers(); } public void setup() throws Exception { + //First, set up the display display = new Display(WIDTH, HEIGHT, windowName, 70, 0.1f, 1000f); display.create(); + + // Open the shaders shader = new Shader(Shader.VERTEXSHADER, Shader.FRAGSHADER); @@ -155,13 +165,21 @@ public class Test extends Game { // Changing the background color display.setBackgroundColor(0.53f, .81f, 0.92f); - // Creating / displaying the mesh - mesh.create(); - plane.create(); + // Creating / displaying the cube and plane + planeObject.create(); // Creating the shader shader.create(); + + for (int i = 0; i < gameObjects.length; i ++) { + gameObjects[i] = new GameObject(cube, new Vector3f( (float)Math.random()*50 - 25 , (float)Math.random()*50, (float)Math.random()*50 - 25), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); + } + + for (GameObject gameObject : gameObjects) { + gameObject.create(); + } + // Creating the input i = new Input(display); @@ -174,9 +192,12 @@ public class Test extends Game { public void close() { // Removing everything display.destroy(); - mesh.destroy(); shader.destroy(); - plane.destroy(); + cubeObject.destroy(); + planeObject.destroy(); + for (GameObject gameObject : gameObjects) { + gameObject.destroy(); + } } public static void main(String[] args) throws Exception { diff --git a/src/org/hl/engine/graphics/Mesh.java b/src/org/hl/engine/graphics/Mesh.java index f994db9..f7188eb 100644 --- a/src/org/hl/engine/graphics/Mesh.java +++ b/src/org/hl/engine/graphics/Mesh.java @@ -15,12 +15,19 @@ public class Mesh { private int[] indices; private int vertexArrayObject, positionBufferObject, indicesBufferObject, colorBufferObject, textureBufferObject; private Material material; + private boolean type; // A group of vertices combined based on the indexes - public Mesh(Vertex[] vertices, int[] indices, Material material) { + public Mesh(Vertex[] vertices, int[] indices, Material material, String type) throws Exception { this.vertices = vertices; this.indices = indices; this.material = material; + if (!type.equals("texture") && !type.equals("color")) { + throw new Exception("Type must be either texture or color. "); + } + this.type = type.equals("texture"); + + } @@ -140,4 +147,8 @@ public class Mesh { return bufferID; } + + public boolean isType() { + return type; + } } diff --git a/src/org/hl/engine/graphics/Renderer.java b/src/org/hl/engine/graphics/Renderer.java index 33f7ae6..2048b72 100644 --- a/src/org/hl/engine/graphics/Renderer.java +++ b/src/org/hl/engine/graphics/Renderer.java @@ -34,6 +34,7 @@ public class Renderer { shader.bind(); + shader.setUniform("type", object.getMesh().isType()); shader.setUniform("projection", display.getProjectionMatrix()); shader.setUniform("view", Matrix4f.view(camera.getPosition(), camera.getRotation())); shader.setUniform("model", Matrix4f.transform(object.getPosition(), object.getRotation(), object.getScale())); diff --git a/src/org/hl/engine/graphics/Vertex.java b/src/org/hl/engine/graphics/Vertex.java index 4ef06df..b599295 100644 --- a/src/org/hl/engine/graphics/Vertex.java +++ b/src/org/hl/engine/graphics/Vertex.java @@ -11,17 +11,23 @@ public class Vertex { private Vector3f position; private Vector3f color; private Vector2f textureCoords; - - - public Vertex (Vector3f position, Vector3f color, Vector2f textureCoords) { - this.position = position; - this.color = color; - this.textureCoords = textureCoords; - } + private boolean type; public Vertex(Vector3f position, Vector2f textureCoords) { this.position = position; - this.color = new Vector3f(1.0F, 1.0F, 1.0F); + this.textureCoords = textureCoords; + this.color = new Vector3f(1, 1, 1); + } + + public Vertex(Vector3f position, Vector3f color) { + this.position = position; + this.color = color; + this.textureCoords = new Vector2f(0, 0); + } + + public Vertex(Vector3f position, Vector3f color, Vector2f textureCoords) { + this.position = position; + this.color = color; this.textureCoords = textureCoords; } @@ -38,4 +44,7 @@ public class Vertex { return textureCoords; } + public boolean isType() { + return type; + } } diff --git a/src/org/hl/engine/io/Display.java b/src/org/hl/engine/io/Display.java index 06ad435..9fc554d 100644 --- a/src/org/hl/engine/io/Display.java +++ b/src/org/hl/engine/io/Display.java @@ -138,9 +138,13 @@ public class Display { //System.exit(1); throw new Exception("Failed to initialize GLFW! "); } - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + if(System.getProperty("os.name").contains("Mac")) { + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + } else { + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + } glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL11.GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); diff --git a/src/org/hl/engine/objects/Camera.java b/src/org/hl/engine/objects/Camera.java index bc73103..a368a9a 100644 --- a/src/org/hl/engine/objects/Camera.java +++ b/src/org/hl/engine/objects/Camera.java @@ -16,7 +16,7 @@ public class Camera { return position; } - public void setPosition(Vector3f position) { + public void setPosition(Vector3f position) throws Exception { this.position = position; } @@ -24,7 +24,7 @@ public class Camera { return rotation; } - public void setRotation(Vector3f rotation) { + public void setRotation(Vector3f rotation) throws Exception { this.rotation = rotation; } diff --git a/src/org/hl/engine/objects/FirstPersonCamera.java b/src/org/hl/engine/objects/FirstPersonCamera.java index 6714916..590cdf1 100644 --- a/src/org/hl/engine/objects/FirstPersonCamera.java +++ b/src/org/hl/engine/objects/FirstPersonCamera.java @@ -25,7 +25,7 @@ public class FirstPersonCamera extends Camera { this.i = i; } - public void update () { + public void update () throws Exception { newMouseX = i.getMouseX(); newMouseY = i.getMouseY(); diff --git a/src/org/hl/engine/objects/FixedCamera.java b/src/org/hl/engine/objects/FixedCamera.java new file mode 100644 index 0000000..5e0a0f6 --- /dev/null +++ b/src/org/hl/engine/objects/FixedCamera.java @@ -0,0 +1,19 @@ +package org.hl.engine.objects; + +import org.hl.engine.math.lalg.Vector3f; + +public class FixedCamera extends Camera { + public FixedCamera(Vector3f position, Vector3f rotation) { + super(position, rotation); + } + + @Override + public void setRotation(Vector3f rotation) throws Exception { + throw new Exception("You cannot rotate a fixed camera! "); + } + + @Override + public void setPosition(Vector3f rotation) throws Exception { + throw new Exception("You cannot move a fixed camera! "); + } +} diff --git a/src/org/hl/engine/objects/GameObject.java b/src/org/hl/engine/objects/GameObject.java index a6b1432..5c1a119 100644 --- a/src/org/hl/engine/objects/GameObject.java +++ b/src/org/hl/engine/objects/GameObject.java @@ -1,7 +1,20 @@ package org.hl.engine.objects; +import org.hl.engine.graphics.Material; import org.hl.engine.graphics.Mesh; +import org.hl.engine.graphics.Texture; +import org.hl.engine.graphics.Vertex; +import org.hl.engine.math.lalg.Vector2f; import org.hl.engine.math.lalg.Vector3f; +import org.hl.engine.objects.yloaders.YMesh; +import org.hl.engine.objects.yloaders.YPoint; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.Objects; + public class GameObject { private Vector3f position, rotation, scale; @@ -14,6 +27,65 @@ public class GameObject { this.mesh = mesh; } + public GameObject(String meshFileName, Vector3f position, Vector3f rotation, Vector3f scale) throws Exception { + if (!meshFileName.endsWith(".mesh")) { + throw new Exception("Wrong file type! "); + } + Yaml yaml = new Yaml(); + FileInputStream inputStream = new FileInputStream(meshFileName); + YMesh yMesh = yaml.loadAs(inputStream, YMesh.class); + Integer[] cull = yMesh.getCull().toArray(new Integer[yMesh.getCull().size()]); + String type = yMesh.getType(); + String texture = yMesh.getTexture(); + YPoint[] vertices = yMesh.getVertices().toArray(new YPoint[yMesh.getVertices().size()]); + Vertex[] meshFormat = new Vertex[vertices.length]; + + for (YPoint vertex : vertices) { + if (vertex.getVertex().size() != 3) { + throw new Exception("Incorrect number of coordinates. "); + } + if (vertex.getColor().size() != 3) { + throw new Exception("Incorrect number of color values. "); + } + if (vertex.getTexture().size() != 2) { + throw new Exception("Incorrect number of texture coordinates. "); + } + } + if (!type.equals("texture") && !type.equals("color")) { + throw new Exception("Incorrect type. Type can only be texture or color. "); + } + + for (int i = 0; i < vertices.length; i ++) { + Vertex value = new Vertex( + new Vector3f(vertices[i].getVertex().get(0), vertices[i].getVertex().get(1), vertices[i].getVertex().get(2)), + new Vector3f(vertices[i].getColor().get(0), vertices[i].getColor().get(1), vertices[i].getColor().get(2)), + new Vector2f(vertices[i].getTexture().get(0), vertices[i].getTexture().get(1)) + + ); + meshFormat[i] = value; + + } + int[] indices = new int[cull.length]; + for (int j = 0; j < cull.length; j ++) { + indices[j] = cull[j]; + } + + this.mesh = new Mesh(meshFormat, indices, new Material(new Texture(texture)), type); + this.position = position; + this.scale = scale; + this.rotation = rotation; + + } + + + public void create() { + mesh.create(); + } + + public void destroy() { + mesh.destroy(); + } + public Vector3f getPosition() { return position; } @@ -41,4 +113,20 @@ public class GameObject { public void setScale(Vector3f scale) { this.scale = scale; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GameObject that = (GameObject) o; + return Objects.equals(getPosition(), that.getPosition()) && + Objects.equals(getRotation(), that.getRotation()) && + Objects.equals(getScale(), that.getScale()) && + Objects.equals(getMesh(), that.getMesh()); + } + + @Override + public int hashCode() { + return Objects.hash(getPosition(), getRotation(), getScale(), getMesh()); + } } diff --git a/src/org/hl/engine/objects/ThirdPersonCamera.java b/src/org/hl/engine/objects/ThirdPersonCamera.java new file mode 100644 index 0000000..aa7322b --- /dev/null +++ b/src/org/hl/engine/objects/ThirdPersonCamera.java @@ -0,0 +1,128 @@ +package org.hl.engine.objects; + +import org.hl.engine.io.Input; +import org.hl.engine.math.lalg.Vector3f; +import org.lwjgl.glfw.GLFW; + +public class ThirdPersonCamera extends Camera { + + private GameObject object; + private Input i; + private float distance; + private float angle = 0; + private float horizAngle = 0; + private float vertAngle = 0; + private float moveSpeed; + private float sensitivity; + private float near; + private float far; + private boolean clickToMove; + private boolean clickToZoom; + private boolean zoomEnabled; + + private double oldMouseX, oldMouseY = 0; + private double newMouseX, newMouseY; + + public ThirdPersonCamera(Vector3f position, Vector3f rotation, GameObject object, float sensitivity, float distance, float near, float far, boolean clickToMove, boolean clickToZoom, boolean zoomEnabled) { + super(position, rotation); + this.object = object; + this.sensitivity = sensitivity; + this.clickToMove = clickToMove; + this.clickToZoom = clickToZoom; + this.zoomEnabled = zoomEnabled; + this.near = near; + this.far = far; + this.distance = distance; + } + + public void create(Input i) throws Exception { + + this.i = i; + setRotation(getRotation()); + setPosition(getPosition()); + } + + + public void update() throws Exception { + + near = 0.1f; + + newMouseX = i.getMouseX(); + newMouseY = i.getMouseY(); + + + float dx = (float) ((float)newMouseX - oldMouseX); + float dy = (float) ((float)newMouseY - oldMouseY); + + if (clickToMove && clickToZoom) { + if (i.isButtonDown(GLFW.GLFW_MOUSE_BUTTON_LEFT)) { + vertAngle -= dy * sensitivity; + horizAngle += dx * sensitivity; + } + + if (i.isButtonDown(GLFW.GLFW_MOUSE_BUTTON_RIGHT) && zoomEnabled) { + if (distance > 0) { + distance += dy * sensitivity; + } else { + distance = near; + } + } + } else if (clickToMove) { + + if (i.isButtonDown(GLFW.GLFW_MOUSE_BUTTON_LEFT)) { + vertAngle -= dy * sensitivity; + horizAngle += dx * sensitivity; + } + if (zoomEnabled) { + if (distance > 0) { + distance += dy * sensitivity; + } else { + distance = near; + } + } + + } else if (clickToZoom) { + + vertAngle -= dy * sensitivity; + horizAngle += dx * sensitivity; + + if (i.isButtonDown(GLFW.GLFW_MOUSE_BUTTON_RIGHT) && zoomEnabled) { + if (distance > 0) { + distance += dy * sensitivity; + } else { + distance = near; + } + } + + } else { + + vertAngle -= dy * sensitivity; + horizAngle += dx * sensitivity; + if (zoomEnabled) { + if (distance > 0) { + distance += dy * sensitivity; + } else { + distance = near; + } + } + + } + + + oldMouseX = newMouseX; + oldMouseY = newMouseY; + + float horizDistance = (float) (distance * Math.cos(Math.toRadians(vertAngle))); + float vertDistance = (float) (distance * Math.sin(Math.toRadians(vertAngle))); + + float xOffset = (float) (horizDistance * Math.sin(Math.toRadians(-horizAngle))); + float zOffset = (float) (horizDistance * Math.cos(Math.toRadians(-horizAngle))); + + setPosition(new Vector3f(object.getPosition().getX() + xOffset, object.getPosition().getY() - vertDistance, object.getPosition().getZ() + zOffset)); + setRotation(new Vector3f(-vertAngle, horizAngle,0)); + + i.reset(); + + + } +} diff --git a/src/org/hl/engine/objects/TopDownCamera.java b/src/org/hl/engine/objects/TopDownCamera.java new file mode 100644 index 0000000..b9faacd --- /dev/null +++ b/src/org/hl/engine/objects/TopDownCamera.java @@ -0,0 +1,9 @@ +package org.hl.engine.objects; + +import org.hl.engine.math.lalg.Vector3f; + +public class TopDownCamera extends FixedCamera { + public TopDownCamera(Vector3f position) { + super(position, new Vector3f(90, 0, 0)); + } +} diff --git a/src/org/hl/engine/objects/yloaders/YMesh.java b/src/org/hl/engine/objects/yloaders/YMesh.java new file mode 100644 index 0000000..a7f283b --- /dev/null +++ b/src/org/hl/engine/objects/yloaders/YMesh.java @@ -0,0 +1,42 @@ +package org.hl.engine.objects.yloaders ; + +import java.util.ArrayList; + +public class YMesh implements java.io.Serializable { + private String type; + private ArrayList vertices; + private ArrayList cull; + private String texture; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ArrayList getVertices() { + return vertices; + } + + public void setVertices(ArrayList vertices) { + this.vertices = vertices; + } + + public ArrayList getCull() { + return cull; + } + + public void setCull(ArrayList cull) { + this.cull = cull; + } + + public String getTexture() { + return texture; + } + + public void setTexture(String texture) { + this.texture = texture; + } +} diff --git a/src/org/hl/engine/objects/yloaders/YPoint.java b/src/org/hl/engine/objects/yloaders/YPoint.java new file mode 100644 index 0000000..89a0bc1 --- /dev/null +++ b/src/org/hl/engine/objects/yloaders/YPoint.java @@ -0,0 +1,33 @@ +package org.hl.engine.objects.yloaders; + +import java.util.ArrayList; + +public class YPoint implements java.io.Serializable { + private ArrayList vertex; + private ArrayList texture; + private ArrayList color; + + public ArrayList getVertex() { + return vertex; + } + + public void setVertex(ArrayList vertex) { + this.vertex = vertex; + } + + public ArrayList getTexture() { + return texture; + } + + public void setTexture(ArrayList texture) { + this.texture = texture; + } + + public ArrayList getColor() { + return color; + } + + public void setColor(ArrayList color) { + this.color = color; + } +} diff --git a/src/resources/shaders/mainFragment.glsl b/src/resources/shaders/mainFragment.glsl index 8bbda4e..645fb89 100644 --- a/src/resources/shaders/mainFragment.glsl +++ b/src/resources/shaders/mainFragment.glsl @@ -2,11 +2,16 @@ in vec3 passColor; in vec2 passTextureCoord; +uniform int type; out vec4 outColor; uniform sampler2D tex; void main() { - outColor = texture(tex, passTextureCoord); + if (type == 1) { + outColor = texture(tex, passTextureCoord); + } else { + outColor = vec4(passColor, 1.0); + } } diff --git a/src/resources/shaders/mainVertex.glsl b/src/resources/shaders/mainVertex.glsl index 2ae7ecf..fd4c629 100644 --- a/src/resources/shaders/mainVertex.glsl +++ b/src/resources/shaders/mainVertex.glsl @@ -7,15 +7,18 @@ layout(location = 2) in vec2 textureCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; +uniform int type; layout(location = 0) out vec3 passColor; layout(location = 1) out vec2 passTextureCoord; +layout(location = 2) out int passType; void main() { gl_Position = projection * view * model * vec4(position, 1.0); passColor = color; + passType = type; passTextureCoord = textureCoord; } \ No newline at end of file