Hallo,
ich habe mich in letzter Zeit wieder mit LWJGL auseinandergesetzt und dazu dieses Tutorial genutzt.
Mein Programm soll ein rotes Dreieck auf einen cyan-farbigen Hintergrund zeichnen. Hier mein Code:
(Die TriangleTest.class wird einmal in der main()-Methode erstellt)
TriangleTest.class
[spoiler]
package de.turakar.lwjgl_tests.triangle;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
public class TriangleTest implements Runnable {
private Thread thread;
private boolean stop;
private Triangle triangle;
public TriangleTest() {
thread = new Thread(this, "LWJGLThread");
thread.start();
}
@Override
public void run() {
stop = false;
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("Triangle");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
stop();
}
init();
while(!stop) {
render();
Display.update();
Display.sync(60);
if(Display.isCloseRequested()) {
stop();
}
}
destroy();
Display.destroy();
}
private void init() {
GL11.glViewport(0, 0, 800, 600);
GL11.glClearColor(0f, 0.8f, 1f, 1f);
triangle = new Triangle();
triangle.init();
}
private void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
triangle.render();
}
private void destroy() {
triangle.destroy();
}
private void stop() {
stop = true;
}
}
[/spoiler]
Triangle.class
[spoiler]
package de.turakar.lwjgl_tests.triangle;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
/**
* A example class for the use of VBOs and Shaders.
* @author Turakar
*/
public class Triangle {
private int vboHandle;
private int program;
/**
* This method creates and initializes the buffer and the shader.
*/
public void init() {
// define vertices
float[] verticesArray = new float[] {
200f, 200f, 0f,
600f, 200f, 0f,
200f, 600f, 0f
};
FloatBuffer vertices = ByteBuffer.allocateDirect(verticesArray.length * (Float.SIZE / 8)).asFloatBuffer();
vertices.put(verticesArray);
vertices.flip();
// generate buffer
IntBuffer handleBuffer = ByteBuffer.allocateDirect(1 * (Integer.SIZE / 8)).asIntBuffer();
GL15.glGenBuffers(handleBuffer);
vboHandle = handleBuffer.get();
// write to buffer
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// create the shaders
int vertexShader = createShader(GL20.GL_VERTEX_SHADER, "res/shaders/simple_vertex.shader");
int fragmentShader = createShader(GL20.GL_FRAGMENT_SHADER, "res/shaders/simple_fragment.shader");
program = createProgram(vertexShader, fragmentShader);
}
/**
* This method creates a shader.
* @param type the gl constant (e.g. GL_FRAGMENT_SHADER)
* @param sourcePath the path of the file with the shader´s source
* @return the shader handle
*/
private int createShader(int type, String sourcePath) {
// create the Shader
int shader = GL20.glCreateShader(type);
// load the file
try {
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[1];
FileInputStream sourceStream = new FileInputStream(sourcePath);
while(sourceStream.read(buffer) > 0) {
sb.append((char) buffer[0]);
}
sourceStream.close();
// set the shader´s source
GL20.glShaderSource(shader, sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
// compile
GL20.glCompileShader(shader);
// check the status
int status = GL20.glGetShaderi(shader, GL20.GL_COMPILE_STATUS);
if(status == GL11.GL_FALSE) {
// get the log
int logLength = GL20.glGetShaderi(shader, GL20.GL_INFO_LOG_LENGTH);
String log = GL20.glGetShaderInfoLog(shader, logLength);
// throw an error
throw new RuntimeException("Shader in file " + sourcePath + "wasn´t compiled correctly! Log:
" + log);
} else {
// get the log
// int logLength = GL20.glGetShaderi(shader, GL20.GL_INFO_LOG_LENGTH);
// String log = GL20.glGetShaderInfoLog(shader, logLength);
// System.out.println(log);
}
return shader;
}
/**
* This method creates a program and links the shaders to it.
* @param handles
* @return the handle of the program
*/
private int createProgram(int... handles) {
// create program
int program = GL20.glCreateProgram();
// attach the shaders
for(int handle : handles) {
GL20.glAttachShader(program, handle);
}
// link the program
GL20.glLinkProgram(program);
// error checking
int status = GL20.glGetProgrami(program, GL20.GL_LINK_STATUS);
if(status == GL11.GL_FALSE) {
// get the log
int logLength = GL20.glGetProgrami(program, GL20.GL_INFO_LOG_LENGTH);
String log = GL20.glGetProgramInfoLog(program, logLength);
// throw an error
throw new RuntimeException("Program wasn´t linked correctly! Log:
" + log);
} else {
// // get the log
// int logLength = GL20.glGetProgrami(program, GL20.GL_INFO_LOG_LENGTH);
// String log = GL20.glGetProgramInfoLog(program, logLength);
// System.out.println(log);
}
// detach the shaders
for(int handle : handles) {
GL20.glDetachShader(program, handle);
}
return program;
}
/**
* This method renders the Triangle.
*/
public void render() {
// set the program
GL20.glUseProgram(program);
// bind buffer
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboHandle);
// set attributes
GL20.glEnableVertexAttribArray(0);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, (long) 0);
// render
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
// unbind
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL20.glUseProgram(0);
}
/**
* This method deletes the buffer and the shader program.
*/
public void destroy() {
//delete buffer
GL15.glDeleteBuffers(vboHandle);
}
}
[/spoiler]
simple_vertex.shader
[spoiler]
#version 330
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
[/spoiler]
simple_fragment.shader
[spoiler]
#version 330
out vec4 outputColor;
void main()
{
outputColor = vec4(1.0f, 0f, 0f, 1.0f);
}
[/spoiler]
Die momentan installierte LWJGL-Version ist 4.0.0.
EDIT: Folgende Sachen habe ich geprüft:
- die Shaders werden richtigf aus der Datei geladen
- der Buffer wird korrekt mit Daten befüllt
- Code mindestens fünf mal durchgelsesen und keinen Fehler gefunden
- gl_FragColor statt out wert genutzt