LWJGL - Shader & Farbe (modernes OpenGL)

Hallo Forum,

Ich versuche zurzeit das moderne OpenGl (3+) ohne Fixed-Functions zu lernen. Nun wollte ich mithilfe dieses Tutorials Shader und Farbe zu meinen Objekten hinzufügen. Das Tutorial ist ursprünglich für C++.
Leider funktioniert jetzt aufeinmal gar nichts mehr, der Fenster in dem gerendert wird bleibt einfach schwarz, ohne Errors. ???:L

Auch vor den Shadern und der Farbe, hat etwas nicht ganz gestimmt. Anstelle des erwarteten weißen Dreieck auf schwarzem Grund, kam ein GRAUES Dreieck heraus. Ich hatte aber gehofft, dass sich das gibt sobald ich Farbe hinzufüge.

Im Code markiere ich alle neuen Zeilen der Hauptklasse mit einem voramgestellten /new/. Ansonsten sind die Klassen “Shader” und “ShaderProgramm” neu.

Hoffe ihr habt eine Idee was ich falsch mache.

Hier mein Code

Main.java

Hier der Code
[spoiler]```

package oneric.level.main;

import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import oneric.gl.shader.Shader;
import oneric.gl.shader.ShaderProgramm;
import oneric.importer.obj.Model;
import oneric.importer.obj.OBJLoader;
import oneric.util.GLHelper;

import org.lwjgl.BufferUtils;
//import org.lwjgl.opengl.GL11;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

import static org.lwjgl.opengl.GL11.;
import static org.lwjgl.opengl.GL15.
;
import static org.lwjgl.opengl.GL20.;
import static org.lwjgl.opengl.GL30.
;

public class Main {

private static Level level;



static int[] ids;
static int length;
static int textureID;
static IntBuffer vboIDs;
static int vaoID;
static int shProID;

public static void main(String[] args) {
	
	setUpDisplay();
	setUpOpenGL();
	
	
	level = loadLevel("res/Level.lev");
	
	float[] verTri = new float[9];
	
	verTri[0] = -0.4F; verTri[1] = 0.1F; verTri[2] = 0F;
	verTri[3] = 0.4F; verTri[4] = 0.1F; verTri[5] = 0F;
	verTri[6] = 0.F; verTri[7] = 0.7F; verTri[8] = 0F;
	
	FloatBuffer vertexTri = BufferUtils.createFloatBuffer(9);
	vertexTri.put(verTri);
	vertexTri.flip();
	
	verTri = null;
	
	/*new*/FloatBuffer colourTri = BufferUtils.createFloatBuffer(9);
	
	/*new*/colourTri.put(0, 1F); colourTri.put(1, 0F); colourTri.put(2, 0F);
	/*new*/colourTri.put(3, 0F); colourTri.put(4, 1F); colourTri.put(5, 0F);
	/*new*/colourTri.put(6, 0F); colourTri.put(7, 0F); colourTri.put(8, 1F);
	
	/*new*/colourTri.flip();
	
	
	vaoID = glGenVertexArrays();
	/*new*/vboIDs = BufferUtils.createIntBuffer(2);
	/** vorher: int vboID = glGenBuffers() */glGenBuffers(vboIDs);
	
	
	glBindVertexArray(vaoID);
	
	glBindBuffer(GL_ARRAY_BUFFER, vboIDs.get(0));
	glBufferData(GL_ARRAY_BUFFER, vertexTri, GL_STATIC_DRAW);
	glEnableVertexAttribArray(0); 
	glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); 
	
	/*new*/glBindBuffer(GL_ARRAY_BUFFER, vboIDs.get(1)); 
	/*new*/glBufferData(GL_ARRAY_BUFFER, colourTri, GL_STATIC_DRAW); 
	/*new*/glEnableVertexAttribArray(1); 
	/*new*/glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0); 
	
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);
	
	/*new*/Shader shVertex = new Shader();
	/*new*/Shader shFragment = new Shader();
	
	/*new*/try {
	/*new*/	shVertex.loadShader("res/shaders/shader.vert", GL_VERTEX_SHADER);
	/*new*/	shFragment.loadShader("res/shaders/shader.frag", GL_FRAGMENT_SHADER);
	/*new*/} catch (IOException e1) {
	/*new*/	e1.printStackTrace();
	/*new*/}
	
	/*new*/ShaderProgramm spMain = new ShaderProgramm();
	
	/*new*/spMain.createProgramm();
	/*new*/spMain.addShaderToProgramm(shVertex);
	/*new*/spMain.addShaderToProgramm(shFragment);
	
	/*new*/spMain.linkProgramm();
	/*new*/spMain.useProgramm();
	/*new*/shProID = spMain.getProgrammID();
	
	
	 
	  

	   
	
	// Der try-catch Block ist nicht wichtig, nur ein Überbleibsel von vorherigen tests
	try {
		Model mod = OBJLoader.loadModel(new File("res/Landscape.obj"));
		ids = OBJLoader.createVBO(mod);
		
		length = mod.faces.size() * 3;
		textureID = GLHelper.loadImage("res/Landscape.png");
		
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} 
	
	while(!Display.isCloseRequested())
	{
		render();
		
		Display.update();
		Display.sync(120);
	}

}





public static Level loadLevel(String location)
{
	return null;
}


/**
 * Sets up the basic Display
 * */
private static void setUpDisplay() {
	
    try {
    	
        Display.setDisplayMode(/*Display.getDesktopDisplayMode()*/new DisplayMode(512, 512));
        Display.setVSyncEnabled(true);
        Display.setTitle("Level: ");
        //Display.setFullscreen(true);
        Display.create();
    } catch (LWJGLException e) {
        System.err.println("The display wasn't initialized correctly. :(");
        Display.destroy();
        System.exit(1);
    }
}

/**
 * Sets up OpenGl so it's ready to use
 * */
private static void setUpOpenGL()
{
	
	GL11.glShadeModel(GL11.GL_SMOOTH);
	GL11.glEnable(GL11.GL_DEPTH_TEST);
	GL11.glEnable(GL11.GL_LIGHTING);
	GL11.glEnable(GL11.GL_LIGHT0);
	
	//GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, asFlippedFloatBuffer(new float[]{0.05f, 0.05f, 0.05f, 1f}));
	//GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, asFlippedFloatBuffer(new float[]{1.0F, 1.0F, 1.0F,1F}));
	GL11.glEnable(GL11.GL_CULL_FACE);
	GL11.glCullFace(GL11.GL_BACK);
	
	GL11.glEnable(GL11.GL_COLOR_MATERIAL);
	GL11.glColorMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE);
	
	glEnable(GL_TEXTURE_2D);
	
}




private static void render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glLoadIdentity();
    
    //glEnable(GL_TEXTURE_2D);

    
	/*new*/ glUseProgram(shProID);
    glBindVertexArray(vaoID);
    /**glEnableVertexAttribArray(0); 
    
    glBindBuffer(GL_ARRAY_BUFFER, vboIDs.get(0));
    glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);*/
    glDrawArrays(GL_TRIANGLES, 0, 3); 
    
   
}

}




Shader.java

Hier der Code
[spoiler]```

package oneric.gl.shader;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL11.*;

public class Shader {
	
	private int id;
	private int type;
	private boolean isLoaded;
	
	public Shader()
	{
		isLoaded = false;
	}
	
	public boolean loadShader(String file, int a_type) throws IOException
	{
		StringBuilder shaderSource = new StringBuilder();
		BufferedReader reader = new BufferedReader(new FileReader(file));
		
		String line;
		
		while((line = reader.readLine()) != null)
		{
			shaderSource.append(line).append('
');
		}
		reader.close();
		
		///////
		
		id = glCreateShader(a_type);
		
		glShaderSource(id, shaderSource);
		glCompileShader(id);
		
		if(glGetShaderi(id, GL_COMPILE_STATUS) == GL_FALSE) return false;
		
		this.type = a_type;
		this.isLoaded = true;
		
		return true;
		
	}
	
	public void deleteShader()
	{
		if(isLoaded) return;
		glDeleteShader(id);
		this.isLoaded = false;
	}
	
	public boolean isLoaded()
	{
		return this.isLoaded;
	}
	
	public int getShaderID()
	{
		return this.id;
	}
	
	public int getType()
	{
		return this.type;
	}
	
	

}


```[/spoiler]


ShaderProgramm.java

Hier der Code
[spoiler]```

package oneric.gl.shader;

import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL11.*;

public class ShaderProgramm {
	
	private int id;
	private boolean isLinked;
	
	public ShaderProgramm()
	{
		isLinked = false;
	}
	
	
	public void createProgramm()
	{
		id = glCreateProgram();
	}
	
	public void deleteProgramm()
	{
		if(!this.isLinked) return;
		
		glDeleteProgram(id);
		this.isLinked =  false;
	}
	
	public boolean addShaderToProgramm(Shader shader)
	{
		if(!shader.isLoaded()) return false;
		
		glAttachShader(id, shader.getShaderID());
		return true;
	}
	
	public boolean linkProgramm()
	{
		glLinkProgram(id);
		
		this.isLinked = (glGetProgrami(id, GL_LINK_STATUS) == GL_TRUE);
		return this.isLinked;
		
	}
	
	public void useProgramm()
	{
		if(this.isLinked) glUseProgram(id);
	}
	
	public int getProgrammID()
	{
		return this.id;
	}

}


```[/spoiler]


shader.vert

Hier der Code
[spoiler]```
#version 330 

layout (location = 0) in vec3 inPosition; 
layout (location = 1) in vec3 inColor; 

smooth out vec3 theColor; 

void main() 
{ 
   gl_Position = vec4(inPosition, 1.0); 
   theColor = inColor; 
}
```[/spoiler]


shader.frag

Hier der Code
[spoiler]```
#version 330 

smooth in vec3 theColor; 
out vec4 outputColor; 

void main() 
{ 
   outputColor = vec4(theColor, 1.0); 
}
```[/spoiler]


Schonmal danke im Vorraus :)


Mfg,

~Oneric

Moin,

so wie Du den colourTri Buffer füllst, funktioniert das mit dem colourTri.flip() nicht (das limit stimmt nicht). Ändere die Zeile einfach in colourTri.rewind() dann geht es.

Viele Grüße
Fancy

Das funktioniert super danke :smiley:

Aber noch eine Verständnisfrage:
Was ist an der Befüllung des Buffers so anders als bei vertexTri (die vertexs), wo flip() problemlos funktioniert ? Soweit ich das verstanden habe sollte put(float[] src) das gleiche sein wie eine for()-Schleife mit vielen put(float f) Aufrufen.

Mfg
Oneric

Genau, wenn Du put(float) genutzt hättest, hätte es auch funktioniert! :wink:

Der FloatBuffer hat intern einen „Zeiger“ auf die aktuelle Position. Bei put(float) und put(float[]) wird auf die aktuelle Position geschrieben und der „Zeiger“ entsprechend weiterbewegt. Oben in Deinem Beispiel verwendest Du aber put(index, float), dabei wird der „Zeiger“ nicht weiterbewegt. Durch das flip() wird das Limit des Buffers auf die aktuelle Position gesetzt, die ist aber eben noch 0. Dadurch werden beim glBufferData() genau 0 Byte übertragen und das ganze funktioniert nicht mehr.

Viele Grüße
Fancy

Ahhhh… :idea:

Danke ! Jetzt verstehe ich das auch besser

Mfg
Oneric