Hallo
Wahrscheinlich merk ich es nur nicht, weil ich seit Monaten nicht mehr richtig programmiert hab. Diese Sache mit dem Shader und der Weltgenerierung hat mir echt den Rest gegeben (Appropos, ich habs immer noch nicht raus, also wenn irgendwer helfen kann: Zum Thema). Aber nach diesem weiteren verzweifelten Hilferuf nun zu einem neuen Problem. Ich hab zur Ablenkung mal ein kleineres “Projektlein” angefangen. Ein 3D Funktionsplotter soll es werden. Doch irgendwie krieg ich die Basics eines GL Kontexts nicht mehr hin. Also, grundsätzlich schon, aber ich hab das Gefühl, dass irgendwas fehlt. Irgendwie funktioniert nämlich die Projektion nicht. Ich hab zu Anfang versucht 3 Linien für das Koordinatensystem zu zeichnen. Doch obwohl ich sie nur von 0 bis 1 (jeweils) zeichne, gehen sie jeweils bis zum Rand des GL Displays. Das kommt glaube ich daher, dass das nicht projeziert wird. Auch werden Linien die schräg oder ganz in Z Richtung verlaufen gar nicht angezeigt.
Das Projekt ist bisher relativ übersichtlich, ich hab mal alles in eine Datei zusammengeschrieben. Ist so ausführbar, aber ideal wär natürlich, wenn es direkt jemandem auffallen würde (Wie gesagt, ich glaub es ist ganz einfach).
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.swing.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.PixelFormat;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
public class Main {
public static void main(String[] args){
new Main();
}
private JFrame f;
private JTextField formelFeld;
private Canvas plotCanvas;
private JLabel formelAnzeige;
JSplitPane splitPane0;
int shader, plotVAO, plotIBO, indexCount;
private int modelMatrixLocation;
private int projectionMatrixLocation;
private FloatBuffer projectionMatrix;
private FloatBuffer modelMatrix;
//private Plot plot;
private int[] vaos = new int[3];
public Main(){
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
f = new JFrame("Plotter");
f.setBounds(1000, 225, 600, 450);
f.setLayout(new BorderLayout());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
formelFeld = new JTextField();
plotCanvas = new Canvas(){
private static final long serialVersionUID = 1L;
public final void addNotify() {
super.addNotify();
create3DEnvironment();
}
public final void removeNotify() {
Display.destroy();
super.removeNotify();
}
};;
formelAnzeige = new JLabel("Formeln");
splitPane0 = new JSplitPane();
splitPane0.setLeftComponent(formelAnzeige);
splitPane0.setRightComponent(new JPanel().add(plotCanvas));
JSplitPane splitPane = new JSplitPane();
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPane.setDividerLocation((int)(f.getHeight()*0.8311d));
splitPane.setRightComponent(formelFeld);
splitPane.setLeftComponent(splitPane0);
f.add(splitPane, BorderLayout.CENTER);
plotCanvas.setMinimumSize(new Dimension(0, 0));
plotCanvas.setFocusable(true);
plotCanvas.requestFocus();
plotCanvas.setIgnoreRepaint(true);
f.setVisible(true);
try {
shader = createDefaultShader();
} catch (IOException e) {
e.printStackTrace();
}
setUniformPositions();
createPlot();
renderLoop();
}
private void createPlot() {
float[] points1 = {
0, 0, 0,
1, 0, 0
};
FloatBuffer b1 = BufferUtils.createFloatBuffer(6);
b1.put(points1);
b1.flip();
int vbo1 = Main.createVBO(b1);
vaos[0] = glGenVertexArrays();
glBindVertexArray(vaos[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
float[] points2 = {
0, 0, 0,
0, 1, 0
};
FloatBuffer b2 = BufferUtils.createFloatBuffer(6);
b2.put(points2);
b2.flip();
int vbo2 = Main.createVBO(b2);
vaos[1] = glGenVertexArrays();
glBindVertexArray(vaos[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
float[] points3 = {
0, 0, 0,
0, 0, 1
};
FloatBuffer b3 = BufferUtils.createFloatBuffer(6);
b3.put(points3);
b3.flip();
int vbo3 = Main.createVBO(b3);
vaos[2] = glGenVertexArrays();
glBindVertexArray(vaos[2]);
glBindBuffer(GL_ARRAY_BUFFER, vbo3);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
}
private void setUniformPositions() {
modelMatrixLocation = GL20.glGetUniformLocation(shader, "model");
projectionMatrixLocation = GL20.glGetUniformLocation(shader, "projection");
}
private void renderLoop() {
matrixMultiply(modelMatrix, rotate(0, 0, 1, -45));
while(f.isVisible()){
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, 200, 200);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUseProgram(shader);
GL20.glUniformMatrix4(projectionMatrixLocation, false, projectionMatrix);
GL20.glUniformMatrix4(modelMatrixLocation, false, modelMatrix);
for(int vao : vaos){
glBindVertexArray(vao);
glDrawArrays(GL_LINES, 0, 2);
}
Display.update();
}
Display.destroy();
System.exit(0);
}
private void create3DEnvironment() {
try {
final int GL_MAJOR_VERSION = 3;
final int GL_MINOR_VERSION = 3;
final DisplayMode displayMode = new DisplayMode(plotCanvas.getWidth(), plotCanvas.getHeight());
final PixelFormat pixelFormat = new PixelFormat();
final ContextAttribs contextAttribs = new ContextAttribs(GL_MAJOR_VERSION, GL_MINOR_VERSION);
Display.setParent(plotCanvas);
Display.setDisplayMode(displayMode);
Display.create(pixelFormat, contextAttribs);
Display.setResizable(true);
Display.setVSyncEnabled(true);
} catch (LWJGLException e) {
e.printStackTrace();
}
projectionMatrix = createFloatBuffer(projection(75.0f, 1, 0.1f, 100.0f));
modelMatrix = createFloatBuffer(einheitsMatrix());
}
public static float[] einheitsMatrix(){
float[] m = new float[16];
m[0] = 1;
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = 1;
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = 1;
m[11] = 0;
m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1;
return m;
}
public static float[] projection(final float fovy, final float aspect, final float zNear, final float zFar) {
final double f = (1.0 / Math.tan(Math.toRadians(fovy / 2.0)));
final float[] m = new float[16];
m[0] = (float) (f / aspect);
m[5] = (float) (f);
m[10] = (zFar + zNear) / (zNear - zFar);
m[11] = (-1);
m[14] = (2 * zFar * zNear) / (zNear - zFar);
m[15] = 0;
return m;
}
public static FloatBuffer createFloatBuffer(float[] coords){
ByteBuffer vbb = ByteBuffer.allocateDirect(coords.length * 4);
vbb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(coords);
vertexBuffer.position(0);
return vertexBuffer;
}
public static int createVBO(FloatBuffer b){
int id = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, b, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return id;
}
public static int createIBO(IntBuffer b){
int id = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, b, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return id;
}
public static float[] rotate(float x, float y, float z, float angle) {
final float len = (float) Math.sqrt(x * x + y * y + z * z);
final float c = (float) Math.cos(Math.toRadians(angle));
final float s = (float) Math.sin(Math.toRadians(angle));
x = x / len;
y = y / len;
z = z / len;
final float[] m = new float[16];
m[0] = x * x * (1 - c) + c;
m[1] = y * x * (1 - c) + z * s;
m[2] = x * z * (1 - c) - y * s;
m[4] = x * y * (1 - c) - z * s;
m[5] = y * y * (1 - c) + c;
m[6] = y * z * (1 - c) + x * s;
m[8] = x * z * (1 - c) + y * s;
m[9] = y * z * (1 - c) - x * s;
m[10] = z * z * (1 - c) + c;
m[15] = 1;
return m;
}
public static float[] scale(float x, float y, float z){
float[] mat = new float[16];
mat[0] = x;
mat[1] = 0;
mat[2] = 0;
mat[3] = 0;
mat[4] = 0;
mat[5] = y;
mat[6] = 0;
mat[7] = 0;
mat[8] = 0;
mat[9] = 0;
mat[10] = z;
mat[11] = 0;
mat[12] = 0;
mat[13] = 0;
mat[14] = 0;
mat[15] = 1;
return mat;
}
public static void matrixMultiply(FloatBuffer b1, float[] o) {
float[] m = new float[b1.capacity()];
for(int i = 0; i < m.length; i++){
m** = b1.get(i);
}
final float[] result = new float[16];
result[0] = m[0] * o[0] + m[4] * o[1] + m[8] * o[2] + m[12] * o[3];
result[1] = m[1] * o[0] + m[5] * o[1] + m[9] * o[2] + m[13] * o[3];
result[2] = m[2] * o[0] + m[6] * o[1] + m[10] * o[2] + m[14] * o[3];
result[3] = m[3] * o[0] + m[7] * o[1] + m[11] * o[2] + m[15] * o[3];
result[4] = m[0] * o[4] + m[4] * o[5] + m[8] * o[6] + m[12] * o[7];
result[5] = m[1] * o[4] + m[5] * o[5] + m[9] * o[6] + m[13] * o[7];
result[6] = m[2] * o[4] + m[6] * o[5] + m[10] * o[6] + m[14] * o[7];
result[7] = m[3] * o[4] + m[7] * o[5] + m[11] * o[6] + m[15] * o[7];
result[8] = m[0] * o[8] + m[4] * o[9] + m[8] * o[10] + m[12] * o[11];
result[9] = m[1] * o[8] + m[5] * o[9] + m[9] * o[10] + m[13] * o[11];
result[10] = m[2] * o[8] + m[6] * o[9] + m[10] * o[10] + m[14] * o[11];
result[11] = m[3] * o[8] + m[7] * o[9] + m[11] * o[10] + m[15] * o[11];
result[12] = m[0] * o[12] + m[4] * o[13] + m[8] * o[14] + m[12] * o[15];
result[13] = m[1] * o[12] + m[5] * o[13] + m[9] * o[14] + m[13] * o[15];
result[14] = m[2] * o[12] + m[6] * o[13] + m[10] * o[14] + m[14] * o[15];
result[15] = m[3] * o[12] + m[7] * o[13] + m[11] * o[14] + m[15] * o[15];
b1.clear();
b1.put(result);
b1.flip();
}
public static String readFromFile(String datei) throws IOException{
String text;
BufferedReader br = new BufferedReader(new InputStreamReader(ShaderManager.class.getClassLoader().getResourceAsStream(datei)));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
text = sb.toString();
}finally {
br.close();
}
return text;
}
public static int createDefaultShader() throws IOException{
final int vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, readFromFile("default.vertex"));
glCompileShader(vs);
if (GL_FALSE == glGetShaderi(vs, GL_COMPILE_STATUS)) {
final int length = glGetShaderi(vs, GL_INFO_LOG_LENGTH);
final String log = glGetShaderInfoLog(vs, length);
throw new RuntimeException("Fehler: "+vs+" "+log);
}
final int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, readFromFile("default.fragment"));
glCompileShader(fs);
if (GL_FALSE == glGetShaderi(fs, GL_COMPILE_STATUS)) {
final int length = glGetShaderi(fs, GL_INFO_LOG_LENGTH);
final String log = glGetShaderInfoLog(fs, length);
throw new RuntimeException("Fehler: "+fs+" "+log);
}
final int handle = glCreateProgram();
glAttachShader(handle, vs);
glAttachShader(handle, fs);
glLinkProgram(handle);
if (GL_FALSE == glGetProgrami(handle, GL_LINK_STATUS)) {
final int length = glGetProgrami(handle, GL_INFO_LOG_LENGTH);
final String log = glGetProgramInfoLog(handle, length);
throw new RuntimeException("Fehler beim Programm: "+handle+" "+log);
}
return handle;
}
}
Die einfachsten Shader:
#version 330
layout (location = 0) in vec3 in_Position;
uniform mat4 projection;
uniform mat4 model;
void main(){
vec4 pos = projection*model*vec4(in_Position, 0);
gl_Position = pos;
}
#version 330
out vec4 outColor;
void main(){
outColor = vec4(1, 0, 0, 1);
}