package de.sky.agl3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.Callbacks;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.vector.Matrix4f;
public class Lwjgl3Test {
public static long windowId;
private int shaderProgramId;
private static GLFWErrorCallback errorCallbak;
public Lwjgl3Test(){
long windowId = createWindow();
GLContext.createFromCurrent();
shaderProgramId = createShaderProgram();
createAndUploadMatrices();
ArrayList<RenderObject> renderObjects = new ArrayList<>();
RenderObject triangle = new RenderObject(new float[]{
-1.0f, 1.0f, 0,
1.0f, 1.0f, 0,
0.0f, -0.5f, 0
});
renderObjects.add(triangle);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_NEAREST);
while(GLFW.glfwWindowShouldClose(windowId) == GL11.GL_FALSE){
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(0.1f, 0, 0.2f, 0);
renderObjects.forEach((o) -> o.render());
GLFW.glfwSwapBuffers(windowId);
GLFW.glfwPollEvents();
}
}
private void createAndUploadMatrices(){
float top = 10.0f, bottom = -top, right = 10.0f, left = -right;
projectionMatrix.m00 = 2 / (right - left);
projectionMatrix.m03 = -(right + left) / (right - left);
projectionMatrix.m11 = 2 / (top - bottom);
projectionMatrix.m13 = -(top + bottom) / (top - bottom);
projectionMatrix.m22 = -2 / (far - near);
FloatBuffer projectionBuffer = BufferUtils.createFloatBuffer(16);
projectionMatrix.store(projectionBuffer);
projectionBuffer.flip();
int projectionLocation = GL20.glGetUniformLocation(shaderProgramId, "projection");
GL20.glUniformMatrix4fv(projectionLocation, false, projectionBuffer);
Matrix4f cameraMatrix = new Matrix4f();
FloatBuffer cameraBuffer = BufferUtils.createFloatBuffer(16);
cameraMatrix.store(cameraBuffer);
cameraBuffer.flip();
int cameraLocation = GL20.glGetUniformLocation(shaderProgramId, "camera");
GL20.glUniformMatrix4fv(cameraLocation, false, cameraBuffer);
}
private int createShaderProgram(){
String vertexShaderCode = null;
String fragmentShaderCode = null;
try{
vertexShaderCode = readResource("shader/vertex.shader");
fragmentShaderCode = readResource("shader/fragment.shader");
}
catch(IOException e){
e.printStackTrace();
}
int shaderProgramId = GL20.glCreateProgram();
int vertexShaderId = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexShaderId, vertexShaderCode);
GL20.glCompileShader(vertexShaderId);
GL20.glAttachShader(shaderProgramId, vertexShaderId);
int fragmentShaderId = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentShaderId, fragmentShaderCode);
GL20.glCompileShader(fragmentShaderId);
GL20.glAttachShader(shaderProgramId, fragmentShaderId);
GL20.glLinkProgram(shaderProgramId);
GL20.glUseProgram(shaderProgramId);
return shaderProgramId;
}
private String readResource(String name) throws IOException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder content = new StringBuilder();
String line;
while((line = reader.readLine()) != null){
content.append(line);
content.append("\n");
}
return content.toString();
}
private long createWindow(){
errorCallbak = Callbacks.errorCallbackPrint(System.err);
GLFW.glfwSetErrorCallback(errorCallbak);
int glfwInitResult = GLFW.glfwInit();
if(glfwInitResult == GL11.GL_FALSE){
throw new IllegalStateException("error on glfw init");
}
windowId = GLFW.glfwCreateWindow(800, 600, "hello world!", 0, MemoryUtil.NULL);
if(windowId == MemoryUtil.NULL){
throw new IllegalStateException("error on creating window");
}
ByteBuffer videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
int monitorWidth = GLFWvidmode.width(videoMode);
int monitorHeight = GLFWvidmode.height(videoMode);
GLFW.glfwSetWindowPos(windowId, (monitorWidth - 800) / 2, (monitorHeight - 600) / 2);
GLFW.glfwMakeContextCurrent(windowId);
GLFW.glfwSwapInterval(0);
GLFW.glfwShowWindow(windowId);
return windowId;
}
class RenderObject {
private int primitiveCount;
private int vertexArrayId;
public RenderObject(float verticies3d[]){
int vertexBufferId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferId);
FloatBuffer verticiesData = BufferUtils.createFloatBuffer(verticies3d.length);
verticiesData.put(verticies3d);
verticiesData.flip();
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticiesData, GL15.GL_STATIC_DRAW);
vertexArrayId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vertexArrayId);
int inVertexId = GL20.glGetAttribLocation(shaderProgramId, "vertexPosition");
GL20.glEnableVertexAttribArray(inVertexId);
GL20.glVertexAttribPointer(inVertexId, 3, GL11.GL_FLOAT, false, 3 * Float.SIZE / 8, 0);
primitiveCount = verticies3d.length / 3 / 3;
}
public void render(){
GL30.glBindVertexArray(vertexArrayId);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, primitiveCount);
}
}
public static void main(String[] args){
new Lwjgl3Test();
}
}