camera, shade, textures, basic window with cubes

This commit is contained in:
Bixilon 2021-01-02 21:11:18 +01:00
parent cf8c6c5f7c
commit d06bba2eb6
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
10 changed files with 443 additions and 72 deletions

View File

@ -0,0 +1,4 @@
Relative Chunk position: 3x 0-15 (3x 4bit = 12bit)
Side: 0-6 (3 bits)
Light level: 1x 0-15 (4bit)
Texture index: ?

26
pom.xml
View File

@ -127,6 +127,13 @@
<lwjgl.version>3.2.3</lwjgl.version>
</properties>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
@ -207,6 +214,10 @@
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-opengl</artifactId>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-stb</artifactId>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl</artifactId>
@ -227,5 +238,20 @@
<artifactId>lwjgl-opengl</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-stb</artifactId>
<classifier>${lwjgl.natives}</classifier>
</dependency>
<dependency>
<groupId>org.l33tlabs.twl</groupId>
<artifactId>pngdecoder</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.github.kotlin-graphics</groupId>
<artifactId>glm</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,86 @@
package de.bixilon.minosoft.gui.rendering
import glm_.glm
import glm_.mat4x4.Mat4
import glm_.vec3.Vec3
import org.lwjgl.glfw.GLFW
import kotlin.math.cos
import kotlin.math.sin
class Camera(private var fov: Float, private val windowId: Long) {
private var mouseSensitivity = 0.1
private var movementSpeed = 7
private var cameraFront = Vec3(0.0f, 0.0f, -1.0f)
private var cameraPosition = Vec3(0.0f, 0.0f, 3.0f)
private var lastMouseX = 0.0
private var lastMouseY = 0.0
private var yaw = 0.0
private var pitch = 0.0
fun mouseCallback(xPos: Double, yPos: Double) {
var xOffset = xPos - this.lastMouseX
var yOffset = this.lastMouseY - yPos // reversed since y-coordinates go from bottom to top
lastMouseX = xPos
lastMouseY = yPos
xOffset *= mouseSensitivity
yOffset *= mouseSensitivity
yaw += xOffset
pitch += yOffset
// make sure that when pitch is out of bounds, screen doesn't get flipped
if (this.pitch > 89.0) {
this.pitch = 89.0
} else if (this.pitch < -89.0) {
this.pitch = -89.0
}
cameraFront = Vec3((cos(glm.radians(yaw)) * cos(glm.radians(pitch))).toFloat(), sin(glm.radians(pitch)).toFloat(), (sin(glm.radians(yaw)) * cos(glm.radians(pitch))).toFloat()).normalize()
}
fun handleInput(deltaTime: Double) {
val cameraSpeed = movementSpeed * deltaTime
val currentY = cameraPosition.y
if (GLFW.glfwGetKey(windowId, GLFW.GLFW_KEY_W) == GLFW.GLFW_PRESS) {
cameraPosition = cameraPosition + cameraFront * cameraSpeed
}
if (GLFW.glfwGetKey(windowId, GLFW.GLFW_KEY_S) == GLFW.GLFW_PRESS) {
cameraPosition = cameraPosition - cameraFront * cameraSpeed
}
if (GLFW.glfwGetKey(windowId, GLFW.GLFW_KEY_A) == GLFW.GLFW_PRESS) {
cameraPosition = cameraPosition - (cameraFront.cross(CAMERA_UP_VEC3).normalize()) * cameraSpeed
}
if (GLFW.glfwGetKey(windowId, GLFW.GLFW_KEY_D) == GLFW.GLFW_PRESS) {
cameraPosition = cameraPosition + (cameraFront.cross(CAMERA_UP_VEC3).normalize()) * cameraSpeed
}
this.cameraPosition.y = currentY // stay on xz line when moving (aka. no clip)
if (GLFW.glfwGetKey(windowId, GLFW.GLFW_KEY_LEFT_SHIFT) == GLFW.GLFW_PRESS) {
cameraPosition = cameraPosition - CAMERA_UP_VEC3 * cameraSpeed
}
if (GLFW.glfwGetKey(windowId, GLFW.GLFW_KEY_SPACE) == GLFW.GLFW_PRESS) {
cameraPosition = cameraPosition + CAMERA_UP_VEC3 * cameraSpeed
}
}
fun calculateProjectionMatrix(screenWidth: Int, screenHeight: Int, shader: Shader) {
shader.use().setMat4("projection", calculateProjectionMatrix(screenWidth, screenHeight))
}
private fun calculateProjectionMatrix(screenWidth: Int, screenHeight: Int): Mat4 {
return glm.perspective(glm.radians(fov), screenWidth.toFloat() / screenHeight.toFloat(), 0.1f, 100f)
}
fun calculateViewMatrix(shader: Shader) {
shader.use().setMat4("view", calculateViewMatrix())
}
private fun calculateViewMatrix(): Mat4 {
return glm.lookAt(cameraPosition, cameraPosition + cameraFront, CAMERA_UP_VEC3)
}
fun setFOV(fov: Float) {
this.fov = fov
}
companion object {
private val CAMERA_UP_VEC3 = Vec3(0.0f, 1.0f, 0.0f)
}
}

View File

@ -13,6 +13,5 @@ public class DummyRender {
renderWindow.init();
renderWindow.startLoop();
renderWindow.exit();
}
}

View File

@ -1,10 +1,13 @@
package de.bixilon.minosoft.gui.rendering;
import de.bixilon.minosoft.gui.rendering.exceptions.ShaderLoadingException;
import glm_.glm;
import glm_.mat4x4.Mat4;
import glm_.vec3.Vec3;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.GLFWWindowSizeCallback;
import org.lwjgl.opengl.*;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryStack;
import java.io.IOException;
@ -14,7 +17,8 @@ import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.system.MemoryStack.stackPush;
@ -22,46 +26,74 @@ import static org.lwjgl.system.MemoryUtil.NULL;
public class RenderWindow {
float[] vertices = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
private final float[] vertices = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
int[] indices = { // note that we start from 0!
0, 1, 3, // first Triangle
1, 2, 3 // second Triangle
private final Vec3[] cubePositions = {
new Vec3(0.0f, 0.0f, 0.0f),
new Vec3(2.0f, 5.0f, -15.0f),
new Vec3(-1.5f, -2.2f, -2.5f),
new Vec3(-3.8f, -2.0f, -12.3f),
new Vec3(2.4f, -0.4f, -3.5f),
new Vec3(-1.7f, 3.0f, -7.5f),
new Vec3(1.3f, -2.0f, -2.5f),
new Vec3(1.5f, 2.0f, -2.5f),
new Vec3(1.5f, 0.2f, -1.5f),
new Vec3(-1.3f, 1.0f, -1.5f)
};
boolean polygonEnabled;
private long window;
private int screenWidth = 800;
private int screenHeight = 600;
private float visibilityLevel;
private boolean polygonEnabled;
private Shader shader;
private Texture texture0;
private Texture texture1;
private long windowId;
private static int loadShaders() throws ShaderLoadingException, IOException {
int vertexShader = ShaderUtil.createShader("/vertex.glsl", ARBVertexShader.GL_VERTEX_SHADER_ARB);
int fragmentShader = ShaderUtil.createShader("/fragment.glsl", ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
private double deltaTime; // time between current frame and last frame
private double lastFrame;
int shaderId = ARBShaderObjects.glCreateProgramObjectARB();
if (shaderId == NULL) {
throw new ShaderLoadingException();
}
ARBShaderObjects.glAttachObjectARB(shaderId, vertexShader);
ARBShaderObjects.glAttachObjectARB(shaderId, fragmentShader);
ARBShaderObjects.glLinkProgramARB(shaderId);
if (ARBShaderObjects.glGetObjectParameteriARB(shaderId, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
throw new ShaderLoadingException(OpenGLUtil.getLogInfo(shaderId));
}
ARBShaderObjects.glValidateProgramARB(shaderId);
if (ARBShaderObjects.glGetObjectParameteriARB(shaderId, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
throw new ShaderLoadingException(OpenGLUtil.getLogInfo(shaderId));
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderId;
}
private Camera camera;
public void init() {
// Setup an error callback. The default implementation
@ -82,38 +114,42 @@ public class RenderWindow {
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
// Create the window
this.window = glfwCreateWindow(800, 600, "Hello World!", NULL, NULL);
if (this.window == NULL) {
this.windowId = glfwCreateWindow(this.screenWidth, this.screenHeight, "Hello World!", NULL, NULL);
if (this.windowId == NULL) {
glfwTerminate();
throw new RuntimeException("Failed to create the GLFW window");
}
this.camera = new Camera(45f, this.windowId);
glfwSetWindowSizeCallback(this.window, new GLFWWindowSizeCallback() {
glfwSetWindowSizeCallback(this.windowId, new GLFWWindowSizeCallback() {
@Override
public void invoke(long window, int width, int height) {
glViewport(0, 0, width, height);
RenderWindow.this.screenWidth = width;
RenderWindow.this.screenHeight = height;
RenderWindow.this.camera.calculateProjectionMatrix(RenderWindow.this.screenWidth, RenderWindow.this.screenHeight, RenderWindow.this.shader);
}
});
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(this.window, (window, key, scancode, action, mods) -> {
if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
glfwSetKeyCallback(this.windowId, (window, key, scancode, action, mods) -> {
if (action != GLFW_RELEASE) {
return;
}
if (key == GLFW_KEY_P && action == GLFW_RELEASE) {
if (this.polygonEnabled) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
} else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
this.polygonEnabled = !this.polygonEnabled;
return;
switch (key) {
case GLFW_KEY_ESCAPE -> glfwSetWindowShouldClose(this.windowId, true);
case GLFW_KEY_P -> switchPolygonMode();
}
});
glfwSetInputMode(this.windowId, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(this.windowId, ((window, xPos, yPos) -> this.camera.mouseCallback(xPos, yPos)));
// Get the thread stack and push a new frame
try (MemoryStack stack = stackPush()) {
@ -121,33 +157,33 @@ public class RenderWindow {
IntBuffer pHeight = stack.mallocInt(1); // int*
// Get the window size passed to glfwCreateWindow
glfwGetWindowSize(this.window, pWidth, pHeight);
glfwGetWindowSize(this.windowId, pWidth, pHeight);
// Get the resolution of the primary monitor
GLFWVidMode videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center the window
glfwSetWindowPos(this.window, (videoMode.width() - pWidth.get(0)) / 2, (videoMode.height() - pHeight.get(0)) / 2);
glfwSetWindowPos(this.windowId, (videoMode.width() - pWidth.get(0)) / 2, (videoMode.height() - pHeight.get(0)) / 2);
} // the stack frame is popped automatically
// Make the OpenGL context current
glfwMakeContextCurrent(this.window);
glfwMakeContextCurrent(this.windowId);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(this.window);
glfwShowWindow(this.windowId);
GL.createCapabilities();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glEnable(GL_DEPTH_TEST);
}
public void startLoop() throws IOException, ShaderLoadingException {
int vAO = glGenVertexArrays();
int vBO = glGenBuffers();
int eBO = glGenBuffers();
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(vAO);
@ -155,12 +191,13 @@ public class RenderWindow {
glBindBuffer(GL_ARRAY_BUFFER, vBO);
glBufferData(GL_ARRAY_BUFFER, this.vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this.indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * Float.BYTES, 0L);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * Float.BYTES, 0L);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * Float.BYTES, (3 * Float.BYTES));
glEnableVertexAttribArray(1);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -171,34 +208,98 @@ public class RenderWindow {
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
this.texture0 = new Texture("/textures/emerald_block.png");
this.texture0.load();
this.texture1 = new Texture("/textures/brown_wool.png");
this.texture1.load();
int shaderId = loadShaders();
this.shader = new Shader("vertex.glsl", "fragment.glsl");
this.shader.load();
this.shader.use();
this.shader.setInt("texture0", 0);
this.shader.setInt("texture1", 1);
this.shader.setFloat("visibility", this.visibilityLevel);
this.camera.calculateProjectionMatrix(this.screenWidth, this.screenHeight, this.shader);
this.camera.calculateViewMatrix(this.shader);
while (!glfwWindowShouldClose(this.windowId)) {
while (!glfwWindowShouldClose(this.window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glUseProgram(shaderId);
double currentFrame = glfwGetTime();
this.deltaTime = currentFrame - this.lastFrame;
this.lastFrame = currentFrame;
this.camera.calculateViewMatrix(this.shader);
this.texture0.use(GL_TEXTURE0);
this.texture1.use(GL_TEXTURE1);
this.shader.use();
glBindVertexArray(vAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawElements(GL_TRIANGLES, this.indices.length, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(this.window); // swap the color buffers
for (int i = 0; i < this.cubePositions.length; i++) {
float angle = 50.0f * (i + 1) * (float) glfwGetTime();
Mat4 model = new Mat4().translate(this.cubePositions[i]).rotate(glm.INSTANCE.radians(angle), new Vec3(i / 0.5f + 0.1f, i / 0.3f + 0.1f, i / 0.1f + 0.1f));
this.shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glfwSwapBuffers(this.windowId); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
handleInput();
this.camera.handleInput(this.deltaTime);
}
}
public void exit() {
// Free the window callbacks and destroy the window
glfwFreeCallbacks(this.window);
glfwDestroyWindow(this.window);
glfwFreeCallbacks(this.windowId);
glfwDestroyWindow(this.windowId);
// Terminate GLFW and free the error callback
glfwTerminate();
glfwSetErrorCallback(null).free();
}
private void switchPolygonMode() {
glPolygonMode(GL_FRONT_AND_BACK, (this.polygonEnabled ? GL_LINE : GL_FILL));
this.polygonEnabled = !this.polygonEnabled;
}
private void handleInput() {
if (glfwGetKey(this.windowId, GLFW_KEY_UP) == GLFW_PRESS) {
this.shader.use();
this.visibilityLevel += 0.1f;
if (this.visibilityLevel > 1.0f) {
this.visibilityLevel = 1.0f;
}
this.shader.setFloat("visibility", this.visibilityLevel);
}
if (glfwGetKey(this.windowId, GLFW_KEY_DOWN) == GLFW_PRESS) {
this.shader.use();
this.visibilityLevel -= 0.1f;
if (this.visibilityLevel < 0.0f) {
this.visibilityLevel = 0.0f;
}
this.shader.setFloat("visibility", this.visibilityLevel);
}
}
}

View File

@ -0,0 +1,86 @@
package de.bixilon.minosoft.gui.rendering;
import de.bixilon.minosoft.gui.rendering.exceptions.ShaderLoadingException;
import glm_.mat4x4.Mat4;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL11;
import java.io.IOException;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.system.MemoryUtil.NULL;
public class Shader {
private static Shader usedShader;
private final String vertex;
private final String fragment;
private int programId;
public Shader(String vertex, String fragment) {
this.vertex = vertex;
this.fragment = fragment;
}
public int load() throws ShaderLoadingException, IOException {
int vertexShader = ShaderUtil.createShader(this.vertex, ARBVertexShader.GL_VERTEX_SHADER_ARB);
int fragmentShader = ShaderUtil.createShader(this.fragment, ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
this.programId = ARBShaderObjects.glCreateProgramObjectARB();
if (this.programId == NULL) {
throw new ShaderLoadingException();
}
ARBShaderObjects.glAttachObjectARB(this.programId, vertexShader);
ARBShaderObjects.glAttachObjectARB(this.programId, fragmentShader);
ARBShaderObjects.glLinkProgramARB(this.programId);
if (ARBShaderObjects.glGetObjectParameteriARB(this.programId, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
throw new ShaderLoadingException(OpenGLUtil.getLogInfo(this.programId));
}
ARBShaderObjects.glValidateProgramARB(this.programId);
if (ARBShaderObjects.glGetObjectParameteriARB(this.programId, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
throw new ShaderLoadingException(OpenGLUtil.getLogInfo(this.programId));
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return this.programId;
}
public int getProgramId() {
return this.programId;
}
public Shader use() {
if (usedShader != this) {
glUseProgram(this.programId);
usedShader = this;
}
return this;
}
public int getUniformLocation(String variableName) {
return glGetUniformLocation(this.programId, variableName);
}
public void setFloat(String name, float value) {
glUniform1f(getUniformLocation(name), value);
}
public void setInt(String name, int value) {
glUniform1i(getUniformLocation(name), value);
}
public void set4f(String variableName, float[] floats) {
glUniformMatrix4fv(glGetUniformLocation(this.programId, variableName), false, floats);
}
public void setMat4(String variableName, Mat4 mat4) {
glUniformMatrix4fv(glGetUniformLocation(this.programId, variableName), false, mat4.to(BufferUtils.createFloatBuffer(16)));
}
}

View File

@ -18,7 +18,7 @@ public class ShaderUtil {
throw new ShaderLoadingException();
}
ARBShaderObjects.glShaderSourceARB(shaderId, Util.readAsset("/rendering/shader" + shaderPath));
ARBShaderObjects.glShaderSourceARB(shaderId, Util.readAsset("/rendering/shader/" + shaderPath));
ARBShaderObjects.glCompileShaderARB(shaderId);
if (ARBShaderObjects.glGetObjectParameteriARB(shaderId, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) {

View File

@ -0,0 +1,49 @@
package de.bixilon.minosoft.gui.rendering;
import de.matthiasmann.twl.utils.PNGDecoder;
import org.lwjgl.BufferUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.glGenerateMipmap;
public class Texture {
private final String texturePath;
private int textureId;
public Texture(String texturePath) {
this.texturePath = texturePath;
}
public int load() throws IOException {
this.textureId = glGenTextures();
glBindTexture(GL_TEXTURE_2D, this.textureId);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// load and generate the texture
PNGDecoder decoder = new PNGDecoder(OpenGLUtil.class.getResourceAsStream(this.texturePath));
ByteBuffer buffer = BufferUtils.createByteBuffer(decoder.getWidth() * decoder.getHeight() * 4);
decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
buffer.flip();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
glGenerateMipmap(GL_TEXTURE_2D);
return this.textureId;
}
public int getTextureId() {
return this.textureId;
}
public void use(int textureMode) {
glActiveTexture(textureMode); // activate the texture unit first before binding texture
glBindTexture(GL_TEXTURE_2D, this.textureId);
}
}

View File

@ -1,6 +1,16 @@
#version 330 core
out vec4 FragColor;
in vec3 vertexColor;
in vec2 TexCoord;
// texture sampler
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform float visibility;
void main() {
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
vec2 newTextCoord = vec2(TexCoord.x, -TexCoord.y);
FragColor = mix(texture(texture0, newTextCoord), texture(texture1, newTextCoord), visibility);
}

View File

@ -1,6 +1,16 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec3 vertexColor;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}