Last active
July 11, 2017 09:02
-
-
Save digz6666/48bb433c83801ea4b82fa194f05b4f02 to your computer and use it in GitHub Desktop.
OpenGL graph render
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mn.digz.lwjgl; | |
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.system.MemoryUtil.NULL; | |
import java.io.IOException; | |
import java.nio.DoubleBuffer; | |
import java.nio.FloatBuffer; | |
import java.nio.IntBuffer; | |
import java.util.ArrayList; | |
import java.util.List; | |
import mn.digz.lwjgl.model.GLColor; | |
import mn.digz.lwjgl.model.GLLine; | |
import mn.digz.lwjgl.model.GLPoint; | |
import mn.digz.lwjgl.model.GLTriangle; | |
import mn.digz.lwjgl.util.ShaderUtil; | |
import org.joml.Matrix4f; | |
import org.joml.Vector3f; | |
import org.lwjgl.BufferUtils; | |
import org.lwjgl.glfw.GLFWErrorCallback; | |
import org.lwjgl.glfw.GLFWFramebufferSizeCallback; | |
import org.lwjgl.glfw.GLFWKeyCallback; | |
import org.lwjgl.glfw.GLFWMouseButtonCallback; | |
import org.lwjgl.glfw.GLFWScrollCallback; | |
import org.lwjgl.glfw.GLFWVidMode; | |
import org.lwjgl.opengl.GL; | |
import org.lwjgl.opengl.GLUtil; | |
import org.lwjgl.system.Callback; | |
/** | |
* | |
* @author MethoD | |
*/ | |
public class OpenGLGraphRender { | |
private long window; | |
private int width = 1024; | |
private int height = 768; | |
private int program; | |
// view projection | |
private int viewProjMatrixUniform; | |
private Matrix4f viewProjMatrix = new Matrix4f(); | |
private FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16); | |
// view port | |
private IntBuffer viewportBuffer = BufferUtils.createIntBuffer(4); | |
private int[] viewport = new int[4]; | |
// vertices | |
private List<GLTriangle> vertices; | |
private FloatBuffer verticesBuffer; | |
private int vertexPositionAttribute; | |
private int vertexColorAttribute; | |
private int pointSize = 3 + 4; // x,y,z + r,g,b,a | |
private int step = Float.SIZE / 8; // byte per element | |
private int stride = step * pointSize; // need? | |
// edges | |
//private List<GLLine> edges; | |
// eye | |
private float eye_x = 0f; | |
private float eye_y = 0f; | |
private float eye_z = 7f; | |
// mouse | |
private DoubleBuffer mouseXBuffer = BufferUtils.createDoubleBuffer(1); | |
private DoubleBuffer mouseYBuffer = BufferUtils.createDoubleBuffer(1); | |
private GLFWErrorCallback errCallback; | |
private GLFWKeyCallback keyCallback; | |
private GLFWFramebufferSizeCallback fbCallback; | |
private Callback debugProc; | |
private void init() { | |
glfwSetErrorCallback(errCallback = GLFWErrorCallback.createPrint(System.err)); | |
if (!glfwInit()) | |
throw new IllegalStateException("Unable to initialize GLFW"); | |
glfwDefaultWindowHints(); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | |
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); | |
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); | |
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); | |
window = glfwCreateWindow(width, height, "Silhouette rendering with geometry shader", NULL, NULL); | |
if (window == NULL) { | |
throw new AssertionError("Failed to create the GLFW window"); | |
} | |
// resize callback | |
glfwSetFramebufferSizeCallback(window, fbCallback = new GLFWFramebufferSizeCallback() { | |
@Override | |
public void invoke(long window, int width, int height) { | |
if (width > 0 && height > 0 | |
&& (OpenGLGraphRender.this.width != width || OpenGLGraphRender.this.height != height)) { | |
OpenGLGraphRender.this.width = width; | |
OpenGLGraphRender.this.height = height; | |
} | |
} | |
}); | |
glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() { | |
@Override | |
public void invoke(long window, int key, int scancode, int action, int mods) { | |
if (action != GLFW_RELEASE) | |
return; | |
if (key == GLFW_KEY_ESCAPE) { | |
glfwSetWindowShouldClose(window, true); | |
} | |
if (key == GLFW_KEY_UP) { | |
eye_y += 0.5f; | |
} | |
if (key == GLFW_KEY_DOWN) { | |
eye_y -= 0.5f; | |
} | |
if (key == GLFW_KEY_LEFT) { | |
eye_x -= 0.5f; | |
} | |
if (key == GLFW_KEY_RIGHT) { | |
eye_x += 0.5f; | |
} | |
if (key == GLFW_KEY_UP || key == GLFW_KEY_DOWN || key == GLFW_KEY_LEFT || key == GLFW_KEY_RIGHT) { | |
updatePerspective(); | |
} | |
} | |
}); | |
// mouse click callback | |
glfwSetMouseButtonCallback(window, new GLFWMouseButtonCallback() { | |
@Override | |
public void invoke(long window, int button, int action, int mods) { | |
if (button == GLFW_MOUSE_BUTTON_1) { | |
glfwGetCursorPos(window, mouseXBuffer, mouseYBuffer); | |
double x = mouseXBuffer.get(0); | |
double y = mouseYBuffer.get(0); | |
System.out.println("clicked at: " + x + " - " + y); | |
Vector3f v3f = new Vector3f(); | |
viewProjMatrix.unproject((float)x, (float)y, 0f, viewport, v3f); | |
System.out.println("world coordinate: " + v3f.x + " - " + v3f.y); | |
// check if any shape clicked | |
for (GLTriangle glTriangle : vertices) { | |
if (glTriangle.contains(v3f.x, v3f.y)) { | |
System.out.println("clicked glTriangle"); | |
glTriangle.setPoint1Color(new GLColor(0.5f, 0.5f, 0f, 1.f)); | |
break; | |
} | |
} | |
} | |
} | |
}); | |
/*glfwSetCursorPosCallback(window, new GLFWCursorPosCallback() { | |
@Override | |
public void invoke(long window, double xpos, double ypos) { | |
} | |
});*/ | |
// scroll callback | |
glfwSetScrollCallback(window, new GLFWScrollCallback() { | |
@Override | |
public void invoke(long window, double xoffset, double yoffset) { | |
if (eye_z - yoffset > 0) { | |
eye_z -= yoffset; | |
} | |
updatePerspective(); | |
} | |
}); | |
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); | |
glfwSetWindowPos(window, (vidmode.width() - width) / 2, (vidmode.height() - height) / 2); | |
glfwMakeContextCurrent(window); | |
glfwSwapInterval(1); // enable v sync | |
glfwShowWindow(window); | |
} | |
private void createProgram() throws IOException { | |
int program = glCreateProgram(); | |
int vshader = ShaderUtil.createShader("mn/digz/lwjgl/shader/vs.glsl", GL_VERTEX_SHADER); | |
int fshader = ShaderUtil.createShader("mn/digz/lwjgl/shader/fs.glsl", GL_FRAGMENT_SHADER); | |
//int gshader = ShaderUtil.createShader("mn/digz/lwjgl/shader/gs.glsl", GL_GEOMETRY_SHADER_EXT); | |
glAttachShader(program, vshader); | |
glAttachShader(program, fshader); | |
//glAttachShader(program, gshader); | |
glLinkProgram(program); | |
int linked = glGetProgrami(program, GL_LINK_STATUS); | |
String programLog = glGetProgramInfoLog(program); | |
if (programLog != null && programLog.trim().length() > 0) { | |
System.err.println(programLog); | |
} | |
if (linked == 0) { | |
throw new AssertionError("Could not link program"); | |
} | |
this.program = program; | |
} | |
/** | |
* Initialize the shader program. | |
*/ | |
private void initProgram() { | |
glUseProgram(this.program); | |
viewProjMatrixUniform = glGetUniformLocation(this.program, "viewProjMatrix"); | |
glBindAttribLocation(program, 0, "vertexPosition"); | |
glBindAttribLocation(program, 1, "vertexColor"); | |
vertexPositionAttribute = glGetAttribLocation(program, "vertexPosition"); | |
vertexColorAttribute = glGetAttribLocation(program, "vertexColor"); | |
verticesBuffer = BufferUtils.createFloatBuffer(pointSize * 3 * 3); // point size * 3 points * 3 triangles = 21 floats per triangle | |
vertices = new ArrayList<>(3); | |
vertices.add(new GLTriangle( | |
new GLPoint(0f, 0f, 1f, 1f, 1f, 0f, 1f), | |
new GLPoint(2f, 0f, 1f, 1f, 0f, 1f, 1f), | |
new GLPoint(1f, 1.7f, 1f, 0f, 1f, 1f, 1f))); | |
vertices.add(new GLTriangle( | |
new GLPoint(4f, 4f, 1f, 1f, 1f, 0f, 1f), | |
new GLPoint(6f, 4f, 1f, 1f, 0f, 1f, 1f), | |
new GLPoint(5f, 5.7f, 1f, 0f, 1f, 1f, 1f))); | |
vertices.add(new GLTriangle( | |
new GLPoint(4f, 1f, 1f, 1f, 1f, 0f, 1f), | |
new GLPoint(6f, 1f, 1f, 1f, 0f, 1f, 1f), | |
new GLPoint(5f, 2.7f, 1f, 0f, 1f, 1f, 1f))); | |
int vbo = glGenBuffers(); | |
glBindBuffer(GL_ARRAY_BUFFER, vbo); | |
glEnableVertexAttribArray(vertexPositionAttribute); | |
glEnableVertexAttribArray(vertexColorAttribute); | |
glVertexAttribPointer(vertexPositionAttribute, 3, GL_FLOAT, false, stride, 0); | |
glVertexAttribPointer(vertexColorAttribute, 4, GL_FLOAT, false, stride, step * 3); | |
glGetIntegerv(GL_VIEWPORT, viewportBuffer); | |
viewportBuffer.get(viewport); | |
glUseProgram(0); | |
} | |
private void updatePerspective() { | |
glUseProgram(this.program); | |
viewProjMatrix | |
.setPerspective((float) Math.toRadians(30), (float) width / height, 0.01f, 500.0f) // define min and max planes | |
.lookAt(eye_x, eye_y, eye_z, | |
eye_x, eye_y, 0.0f, | |
0.0f, 2.0f, 0.0f); | |
glUniformMatrix4fv(viewProjMatrixUniform, false, viewProjMatrix.get(matrixBuffer)); | |
glUseProgram(0); | |
} | |
private void render() { | |
glUseProgram(this.program); | |
verticesBuffer.clear(); | |
vertices.forEach((glTriangle) -> { | |
verticesBuffer.put(glTriangle.toFloatArray()); | |
}); | |
verticesBuffer.flip(); | |
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW); | |
glDrawArrays(GL_TRIANGLES, 0, vertices.size() * 3); // 3 indices per triangle | |
glUseProgram(0); | |
} | |
private void loop() throws IOException { | |
GL.createCapabilities(); | |
debugProc = GLUtil.setupDebugMessageCallback(); | |
glClearColor(0.55f, 0.75f, 0.95f, 1.0f); | |
glEnable(GL_DEPTH_TEST); | |
/* Create all needed GL resources */ | |
createProgram(); | |
initProgram(); | |
updatePerspective(); | |
while (!glfwWindowShouldClose(window)) { | |
glfwPollEvents(); | |
glViewport(0, 0, width, height); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
//glMatrixMode(GL_PROJECTION); | |
//float aspect = (float)width/height; | |
//glLoadIdentity(); | |
//glOrtho(-aspect, aspect, -1, 1, -1, 1); | |
render(); | |
glfwSwapBuffers(window); | |
} | |
} | |
public void run() { | |
try { | |
init(); | |
loop(); | |
if (debugProc != null) | |
debugProc.free(); | |
errCallback.free(); | |
keyCallback.free(); | |
fbCallback.free(); | |
glfwDestroyWindow(window); | |
} catch (Throwable t) { | |
t.printStackTrace(); | |
} finally { | |
glfwTerminate(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment