Opengl Particles

achso, das parameterlose create() ist ohne context attribs, verstehe ^^

Hm, die loopTest methode will trotztdem noch nicht funktionieren… hast du sie dir mal angesehen?

Okay, hab die fehler selbst gefunden.
erstens firstBuffer statt firstVao gebindet, außerdem transform feedback
beendet vor dem render durchlauf… läuft also jetzt, danke :slight_smile:

Genau, wenn man dann den Shader noch ein wenig anpasst, sieht man auch dauerhaft was.



import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL30.GL_TRANSFORM_FEEDBACK_BUFFER;

import java.nio.FloatBuffer;

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.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.PixelFormat;


public class TransformFeedbackPorting {

    private final int floatSizeInBytes = Float.SIZE / 8;
    private final int argumentCount = 3;
    private int firstVao, secondVao;
    private int firstBuffer, secondBuffer;


    public TransformFeedbackPorting() throws LWJGLException {

        final DisplayMode displayMode = new DisplayMode(800, 600);
        final PixelFormat pixelFormat = new PixelFormat();
        final ContextAttribs contextAttribs = new ContextAttribs(3, 1);
        Display.setDisplayMode(displayMode);
        Display.create(pixelFormat, contextAttribs);
        Display.setVSyncEnabled(true); // <--

        final String vertexShaderContent = ""
                + "#version 150                          
"
                + "in float vIn;                         
"
                + "out float vOut;                       
"
                + "void main(){                          
"
                + "  vOut = vIn + 0.005f;                
" // <--
                + "  if(vOut > 1){ vOut = -1; }          
" // <--
                + "  gl_Position = vec4(vIn, 0, 0, 1);   
"
                + "}";
        final int vshaderId = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vshaderId, vertexShaderContent);
        GL20.glCompileShader(vshaderId);
        checkCompileErrors(vshaderId);

        final String fragmentShaderContent = ""
                + "#version 150                          
"
                + "out vec4 outColor;                    
"
                + "void main(){                          
"
                + "  outColor = vec4(1, 0, 0, 1);        
"
                + "}";
        final int fshaderId = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fshaderId, fragmentShaderContent);
        GL20.glCompileShader(fshaderId);
        checkCompileErrors(fshaderId);

        final int programId = GL20.glCreateProgram();
        GL20.glAttachShader(programId, vshaderId);
        GL20.glAttachShader(programId, fshaderId);

        GL30.glTransformFeedbackVaryings(programId, new String[] { "vOut" }, GL30.GL_INTERLEAVED_ATTRIBS);

        GL20.glLinkProgram(programId);
        checkLinkErrors(programId);
        GL20.glUseProgram(programId);


        secondVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(secondVao);

        secondBuffer = GL15.glGenBuffers();

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, secondBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, argumentCount * floatSizeInBytes, GL15.GL_STREAM_DRAW);

        GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatSizeInBytes);

        final int inputvert = GL20.glGetAttribLocation(programId, "vIn");
        GL20.glEnableVertexAttribArray(inputvert);
        GL20.glVertexAttribPointer(inputvert, 1, GL11.GL_FLOAT, false, 4, 0);


        firstVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(firstVao);


        final FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(argumentCount);

        System.out.println("-- filling buffer");
        for (int i = 0; i < argumentCount; i++) {
            final float value = (float) (((i) / (double) argumentCount) * 0.5 - 0.5);
            System.out.println(value);
            dataBuffer.put(value);
        }
        dataBuffer.rewind();
        System.out.println("-- finished initialization
");


        firstBuffer = GL15.glGenBuffers();

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, firstBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, dataBuffer, GL15.GL_STREAM_DRAW);

        GL20.glEnableVertexAttribArray(inputvert);
        GL20.glVertexAttribPointer(inputvert, 1, GL11.GL_FLOAT, false, 4, 0);

        testLoop();

        // testStepByStep();
    }


    private void testLoop() {

        while (!Display.isCloseRequested()) {
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            // in buffer2 soll output geschrieben werden
            GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatSizeInBytes);
            GL30.glBeginTransformFeedback(GL11.GL_POINTS);
            // von buffer1 (vao1) soll gelesen also gerendert werden
            GL30.glBindVertexArray(firstVao); // <--
            GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
            GL30.glEndTransformFeedback(); // <--

            Display.update();

            // switch alles (vao und buffer id's)
            int temp = secondVao;
            secondVao = firstVao;
            firstVao = temp;
            temp = secondBuffer;
            secondBuffer = firstBuffer;
            firstBuffer = temp;
        }
    }


    private void testStepByStep() {

        /** run 1 **/
        GL30.glBindBufferRange(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatSizeInBytes);
        GL30.glBeginTransformFeedback(GL11.GL_POINTS);
        GL30.glBindVertexArray(firstVao);
        GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
        GL30.glEndTransformFeedback();


        FloatBuffer result = BufferUtils.createFloatBuffer(argumentCount);
        GL15.glGetBufferSubData(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, result);
        System.out.println("-- data in transform feedback buffer: ");
        for (int i = 0; i < result.capacity(); i++)
            System.out.println(result.get(i));
        System.out.println("-- end, preparing second run..
");

        /** run 2 **/
        GL30.glBindBufferRange(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, firstBuffer, 0, argumentCount * floatSizeInBytes);
        GL30.glBeginTransformFeedback(GL11.GL_POINTS);
        GL30.glBindVertexArray(secondVao);
        GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
        GL30.glEndTransformFeedback();

        result = BufferUtils.createFloatBuffer(argumentCount);
        GL15.glGetBufferSubData(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, result);
        System.out.println("-- data in transform feedback buffer after round 2: ");
        for (int i = 0; i < result.capacity(); i++)
            System.out.println(result.get(i));
        System.out.println("-- end, preparing third run..
");

        /** run 3 **/
        GL30.glBindBufferRange(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatSizeInBytes);
        GL30.glBeginTransformFeedback(GL11.GL_POINTS);
        GL30.glBindVertexArray(firstVao);
        GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
        GL30.glEndTransformFeedback();

        result = BufferUtils.createFloatBuffer(argumentCount);
        GL15.glGetBufferSubData(GL30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, result);
        System.out.println("-- data in transform feedback buffer after round 3: ");
        for (int i = 0; i < result.capacity(); i++)
            System.out.println(result.get(i));
        System.out.println("-- end.
");
    }


    private void checkCompileErrors(final int shaderId) {

        if (GL_FALSE == glGetShaderi(shaderId, GL_COMPILE_STATUS)) {
            final int length = glGetShaderi(shaderId, GL_INFO_LOG_LENGTH);
            final String log = glGetShaderInfoLog(shaderId, length);
            throw new RuntimeException(log);
        }
    }


    private void checkLinkErrors(final int programId) {

        if (GL_FALSE == glGetProgrami(programId, GL_LINK_STATUS)) {
            final int length = glGetProgrami(programId, GL_INFO_LOG_LENGTH);
            final String log = glGetProgramInfoLog(programId, length);
            throw new RuntimeException(log);
        }
    }


    public static void main(final String[] args) throws LWJGLException {

        try {
            new TransformFeedbackPorting();
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

Gruß
Fancy

wenn ich so eine partikel animation jetzt hab… die auf der gpu läuft… ergibt es dann sinn, die zeit auch dort hochzuladen?
also die zeit zwischen den frames? soetwas wie

uniform float delta;

und dann am anfang jeden frames diese delta zeit setzen? Ist es überhaupt sinnvoll, bei uniforms die die ganze zeit
verändert werden sollen, das jeden frame zu machen?

*** Edit ***

und… wir hatten das thema des entfernens mal…

geht das nur so? Oder habe ich eine andere möglichkeit, partikel zu „löschen“ ?

*** Edit ***

wenn ich die output variable einfach nicht mehr beschreibe, wird der buffer dadurch ja nicht leer oder so…

Ja, ein delta zu übertragen ist sinnvoll und notwendig, wenn die Animation auf allen Rechnern gleich schnell laufen soll. Allerdings bietet es sich an, das nicht als einzelne uniform Variable zu machen, sondern besser als UBO zusammen mit allen anderen Werten die sich regelmäßig ändern, wie zum Beispiel die ModelView Matrix.

Beim Transform Feedback behalten die Elemente im Buffer ihre Reihenfolge, so das Du auch ohne Geometrie Shader die jeweils ältesten Partikel verwerfen kannst. Beispiel:

            GL30.glBindVertexArray(newVao); 
            GL11.glDrawArrays(GL11.GL_POINTS, 0, 1);
            GL30.glBindVertexArray(firstVao); 
            GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount - 1);

Würde dazu führen das vorne im Buffer ein neues Element eingefügt wird und das letzte Element verschwindet. Unabhängig davon kannst Du ein Element natürlich zu einem beliebigen Zeitpunkt unsichtbar machen, so das es aussieht als würde es direkt entfernt, auch wenn es noch im Buffer vorhanden ist.

Mit dem Geometrie Shader kannst Du hingegen ein Primitiv (Punkt, Dreieck) wirklich verwerfen. Das wird dann nicht in den Transform Feedback Buffer geschrieben. Entsprechend rücken alle anderen Elemente dann eine Position nach vorne. Dann brauchst Du allerdings auch ein Query (GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) um festzustellen wie viele gültige Elemente überhaupt im Buffer vorhanden sind.

Gruß
Fancy

Okay, danke. Mal schauen ob ich das hinbekomme.

Ich habe jetzt ein neues denkproblem…
Angenommen ich erweitere ein partikel um 2 werte… zum Beispiel:

position, lebenszeit, alpha.

so. ich würde jetzt einen vec3 im shader definieren, als input. position in gl_Position benutzen,
den rest einfach so wieder in den output schreiben wie es war, zB vOut = vec3(position + 0.1, lifetime, alpha);
Rendern will ich nach wie vor GL_POINTS.

In glVertexAttribPointer müsste ich als size ja 1 angeben, weil nur 1 float zum rendern verwendet wird.
stride müsste dennoch 3 * floatSizeInBytes sein, richtig? offset 0.

wenn ich jetzt rendere rufe ich nach wie vor glDrawArrays(GL_POINTS, 0, count) auf, richtig?

Das Problem: dann muss ich in glBeginTransformFeedback() auch GL_POINTS übergeben. sonst läuft das ja nicht, laut doc.
aber dann kann ich ja kein vec3 mehr in den transform feedback buffer schreiben, sondern nur noch einzelne floats… wie löse ich das also?

Nicht laufendes kskb:

 
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL30.GL_TRANSFORM_FEEDBACK_BUFFER;

import java.nio.FloatBuffer;

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.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL31;
import org.lwjgl.opengl.PixelFormat;
 
public class TransformFeedbackPorting {
 
	private int programId;
	private int floatSizeInBytes = Float.SIZE / 8;
	private int argumentCount = 3, floatsPerArgument = 2;
	private int firstVao, secondVao;
	private int firstBuffer, secondBuffer;
	
	public TransformFeedbackPorting() throws LWJGLException {
//    	AGLDisplay d = new AGLDisplay(AGLDisplayCap.NONE);
    	Display.setDisplayMode(new DisplayMode(800, 600));
    	Display.create(new PixelFormat(), new ContextAttribs(3, 1));
    	String vertexShaderContent = 
    			"#version 150
"+
    			"in vec2 vIn;
"+
    			"layout(std140) uniform GlobalValues {
"+
    			"float delta;
"+
    			"float globalTime;
"+
				"};
"+
				"out float vOut;
"+
				"void main(){
"+
				"float posx = vIn.x;
"+
				"float amplitude = vIn.y;
"+
				"if(posx >= 1.0f){vOut = vec2(-1.0f, amplitude);}
"+
				"else{vOut = vec2(posx + 1f * delta, amplitude);}
"+
				"gl_Position = vec4(posx, amplitude * sin(5.0f * posx), 0, 1);
"+
				"}";
    	final int vshaderId = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vshaderId, vertexShaderContent);
        GL20.glCompileShader(vshaderId);
        checkCompileErrors(vshaderId);
        
        String fragmentShaderContent = 
        		"#version 150
"+
        		"out vec4 outColor;
"+
        		"void main(){
"+
        		"outColor = vec4(1, 0, 0, 1);
"+
				"}";
        final int fshaderId = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fshaderId, fragmentShaderContent);
        GL20.glCompileShader(fshaderId);
        checkCompileErrors(fshaderId);
        
        programId = GL20.glCreateProgram();
        GL20.glAttachShader(programId, vshaderId);
        GL20.glAttachShader(programId, fshaderId);
        
        GL30.glTransformFeedbackVaryings(programId, new String[] { "vOut" }, GL30.GL_INTERLEAVED_ATTRIBS);
        
        GL20.glLinkProgram(programId);
        checkLinkErrors(programId);
        GL20.glUseProgram(programId);
 
        
        final int inputvert = GL20.glGetAttribLocation(programId, "vIn");
        
        secondVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(secondVao);
        
        secondBuffer = GL15.glGenBuffers();
        
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, secondBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, argumentCount * floatsPerArgument * floatSizeInBytes, GL15.GL_DYNAMIC_READ);
        
        GL20.glEnableVertexAttribArray(inputvert);
        GL20.glVertexAttribPointer(inputvert, 1, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 0 * floatSizeInBytes);
        
        GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatsPerArgument * floatSizeInBytes);

        
        firstVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(firstVao);
 
        final FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(argumentCount * floatsPerArgument);
       
        System.out.println("-- filling buffer");
        for(int i = 0; i < argumentCount; i++){
        	float value = (float) (((i) / (double) argumentCount) * 0.5);
        	System.out.println(value);
        	dataBuffer.put(value);
//        	dataBuffer.put((float) Math.random() * 0.5f + 0.3f);
        	dataBuffer.put(1);
        }
        dataBuffer.flip();
        System.out.println("-- finished initialization
");
        
        
        firstBuffer = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, firstBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, dataBuffer, GL15.GL_DYNAMIC_DRAW);
        
        GL20.glEnableVertexAttribArray(inputvert);
        GL20.glVertexAttribPointer(inputvert, 1, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 0 * floatSizeInBytes);
        
        GL11.glPointSize(10);
        
        testLoop();
    } 
       
    private void testLoop(){
    	long thisFrame, lastFrame = System.currentTimeMillis();
    	float delta, time = 0;
    	
    	int globalDataUBO = GL31.glGetUniformBlockIndex(programId, "GlobalValues");
    	int uniformBufferId = GL15.glGenBuffers();
    	GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uniformBufferId);
    	GL15.glBufferData(GL31.GL_UNIFORM_BUFFER, 2 * floatSizeInBytes, GL15.GL_STREAM_DRAW);
    	FloatBuffer globalData = BufferUtils.createFloatBuffer(2);
    	GL31.glUniformBlockBinding(programId, globalDataUBO, 0);
    	GL30.glBindBufferRange(GL31.GL_UNIFORM_BUFFER, 0, uniformBufferId, 0, 2 * floatSizeInBytes);
    	
    	while(!Display.isCloseRequested()){
	        thisFrame = System.currentTimeMillis();
	        delta = (thisFrame - lastFrame) / (float) 1e3;
	        lastFrame = thisFrame;
	        time += delta;
    		
	        globalData.put(delta);
	        globalData.put(time);
	        globalData.flip();
	        //GL20.glUniform1f(deltaUniformLocation, delta);
	        GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uniformBufferId);
	        GL15.glBufferSubData(GL31.GL_UNIFORM_BUFFER, 0, globalData);
	        
    		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
	        //in buffer2 soll output geschrieben werden
	        GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatsPerArgument * floatSizeInBytes);
	        GL30.glBeginTransformFeedback(GL11.GL_POINTS);
	        //von buffer1 (vao1) soll gelesen also gerendert werden
	        GL30.glBindVertexArray(firstVao);
	        GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
	        GL30.glEndTransformFeedback();
	        Display.update();
	        
	        //switch alles (vao und buffer id's)
	        int temp = secondVao;
	        secondVao = firstVao;
	        firstVao = temp;
	        temp = secondBuffer;
	        secondBuffer = firstBuffer;
	        firstBuffer = temp;
        }
    }
       
    private void checkCompileErrors(int shaderId){
    	if (GL_FALSE == glGetShaderi(shaderId, GL_COMPILE_STATUS)){
            final int length = glGetShaderi(shaderId, GL_INFO_LOG_LENGTH);
            final String log = glGetShaderInfoLog(shaderId, length);
            throw new RuntimeException(log);
        }
    }
    
    private void checkLinkErrors(int programId){
    	if (GL_FALSE == glGetProgrami(programId, GL_LINK_STATUS)) {
            final int length = glGetProgrami(programId, GL_INFO_LOG_LENGTH);
            final String log = glGetProgramInfoLog(programId, length);
            throw new RuntimeException(log);
        }
    }
 
    public static void main(final String[] args) throws LWJGLException {
        try{
        	new TransformFeedbackPorting();
        }
        catch(Exception e){
        	e.printStackTrace();
        }
    }
}``` 

ich verstehe nicht wo der fehler ist.. auf jeden fall liegt es daran das ich versuche mehrere (hier 2) werte hin und her zu schreiben,
aber nur mit dem einen zu rendern... ohne das funktioniert es nämlich

GL_POINTS bedeutet lediglich das ein Primitiv (hier der Punkt) aus genau einem einzigen Vertex besteht. Bei GL_TRIANGLES währen es z.B. drei Vertices. Wie viele Attribute ein Vertex hat ist dabei beliebig. In Deinem Beispiel definierst Du in vec2 vIn;, das sind dann eben zwei float Werte für jeden Vertex. Entsprechend musst Du glVertexAttribPointer(inputvert, 2, GL_FLOAT,... setzen.



import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL30.GL_TRANSFORM_FEEDBACK_BUFFER;

import java.nio.FloatBuffer;

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.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL31;
import org.lwjgl.opengl.PixelFormat;


public class TransformFeedbackPorting {

    private final int programId;
    private final int floatSizeInBytes = Float.SIZE / 8;
    private final int argumentCount = 10, floatsPerArgument = 2;
    private int firstVao, secondVao;
    private int firstBuffer, secondBuffer;


    public TransformFeedbackPorting() throws LWJGLException {

        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create(new PixelFormat(), new ContextAttribs(3, 1));
        final String vertexShaderContent = ""
                + "#version 150                                                     
"
                + "in vec2 vIn;                                                     
"
                + "layout(std140) uniform GlobalValues {                            
"
                + "  float delta;                                                   
"
                + "  float globalTime;                                              
"
                + "};                                                               
"
                + "out vec2 vOut;                                                   
" // <--
                + "void main(){                                                     
"
                + "  float posx = vIn.x;                                            
"
                + "  float amplitude = vIn.y;                                       
"
                + "  if(posx >= 1.0f){vOut = vec2(-1.0f, amplitude);}               
"
                + "  else{vOut = vec2(posx + 1f * delta, amplitude);}               
"
                + "  gl_Position = vec4(posx, amplitude * sin(5.0f * posx), 0, 1);  
"
                + "}";
        final int vshaderId = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vshaderId, vertexShaderContent);
        GL20.glCompileShader(vshaderId);
        checkCompileErrors(vshaderId);

        final String fragmentShaderContent = ""
                + "#version 150                                                     
"
                + "out vec4 outColor;                                               
"
                + "void main(){                                                     
"
                + "  outColor = vec4(1, 0, 0, 1);                                   
"
                + "}";
        final int fshaderId = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fshaderId, fragmentShaderContent);
        GL20.glCompileShader(fshaderId);
        checkCompileErrors(fshaderId);

        programId = GL20.glCreateProgram();
        GL20.glAttachShader(programId, vshaderId);
        GL20.glAttachShader(programId, fshaderId);

        GL30.glTransformFeedbackVaryings(programId, new String[] { "vOut" }, GL30.GL_INTERLEAVED_ATTRIBS);

        GL20.glLinkProgram(programId);
        checkLinkErrors(programId);
        GL20.glUseProgram(programId);


        final int inputvert = GL20.glGetAttribLocation(programId, "vIn");

        secondVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(secondVao);

        secondBuffer = GL15.glGenBuffers();

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, secondBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, argumentCount * floatsPerArgument * floatSizeInBytes, GL15.GL_STREAM_DRAW); // < --

        GL20.glEnableVertexAttribArray(inputvert);
        GL20.glVertexAttribPointer(inputvert, 2, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 0 * floatSizeInBytes); // <--

        GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatsPerArgument * floatSizeInBytes);


        firstVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(firstVao);

        final FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(argumentCount * floatsPerArgument);

        System.out.println("-- filling buffer");
        for (int i = 0; i < argumentCount; i++) {
            final float value = (float) (((i) / (double) argumentCount) * 0.5);
            System.out.println(value);
            dataBuffer.put(value);
            // dataBuffer.put((float) Math.random() * 0.5f + 0.3f);
            dataBuffer.put(0.5f);
        }
        dataBuffer.flip();
        System.out.println("-- finished initialization
");


        firstBuffer = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, firstBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, dataBuffer, GL15.GL_STREAM_DRAW); // < --

        GL20.glEnableVertexAttribArray(inputvert);
        GL20.glVertexAttribPointer(inputvert, 2, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 0 * floatSizeInBytes); // < --

        GL11.glPointSize(10);

        testLoop();
    }


    private void testLoop() {

        long thisFrame, lastFrame = System.currentTimeMillis();
        float delta, time = 0;

        final int globalDataUBO = GL31.glGetUniformBlockIndex(programId, "GlobalValues");
        final int uniformBufferId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uniformBufferId);
        GL15.glBufferData(GL31.GL_UNIFORM_BUFFER, 2 * floatSizeInBytes, GL15.GL_STREAM_DRAW);
        final FloatBuffer globalData = BufferUtils.createFloatBuffer(2);
        GL31.glUniformBlockBinding(programId, globalDataUBO, 0);
        GL30.glBindBufferRange(GL31.GL_UNIFORM_BUFFER, 0, uniformBufferId, 0, 2 * floatSizeInBytes);

        while (!Display.isCloseRequested()) {
            thisFrame = System.currentTimeMillis();
            delta = (thisFrame - lastFrame) / (float) 1e3;
            lastFrame = thisFrame;
            time += delta;

            globalData.put(delta);
            globalData.put(time);
            globalData.flip();
            // GL20.glUniform1f(deltaUniformLocation, delta);
            GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uniformBufferId);
            GL15.glBufferSubData(GL31.GL_UNIFORM_BUFFER, 0, globalData);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            // in buffer2 soll output geschrieben werden
            GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatsPerArgument * floatSizeInBytes);
            GL30.glBeginTransformFeedback(GL11.GL_POINTS);
            // von buffer1 (vao1) soll gelesen also gerendert werden
            GL30.glBindVertexArray(firstVao);
            GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
            GL30.glEndTransformFeedback();
            Display.update();

            // switch alles (vao und buffer id's)
            int temp = secondVao;
            secondVao = firstVao;
            firstVao = temp;
            temp = secondBuffer;
            secondBuffer = firstBuffer;
            firstBuffer = temp;
        }
    }


    private void checkCompileErrors(final int shaderId) {

        if (GL_FALSE == glGetShaderi(shaderId, GL_COMPILE_STATUS)) {
            final int length = glGetShaderi(shaderId, GL_INFO_LOG_LENGTH);
            final String log = glGetShaderInfoLog(shaderId, length);
            throw new RuntimeException(log);
        }
    }


    private void checkLinkErrors(final int programId) {

        if (GL_FALSE == glGetProgrami(programId, GL_LINK_STATUS)) {
            final int length = glGetProgrami(programId, GL_INFO_LOG_LENGTH);
            final String log = glGetProgramInfoLog(programId, length);
            throw new RuntimeException(log);
        }
    }


    public static void main(final String[] args) throws LWJGLException {

        try {
            new TransformFeedbackPorting();
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

Gruß
Fancy

och mist… vergessen von float auf vec2 zu ändern… wieso bekomm ich denn da keinen glsl error??

ja das ist mir klar. Wenn ich Punkte zeichnen will, benutze ich GL_POINTS weil damit sage, dass zum zeichnen immer genau ein float verwendet werden soll, richtig?
Aber welchen sinn ergibt es dann, das beginTransformFeedback() auch GL_POINTS übergeben haben will, obwohl in den transform feedback buffer ja mehr als GL_POINTS geschrieben werden?

also sage ich bei vertexAttribPointer lediglich wie ein attribut aussieht, und nichts darüber, was zum zeichnen verwendet wird, oder wie? Also size 2, weil ich da ein vec2 hab…

danke dir, wieder einiges etwas besser verstanden ^^
opengl kann echt mindf*** sein…

Ich bekomme an der Stelle eine Fehlermeldung:

java.lang.RuntimeException: 0:11(19): error: value of type vec2 cannot be assigned to variable of type float
0:12(7): error: value of type vec2 cannot be assigned to variable of type float

	at temp.TransformFeedbackPorting.checkCompileErrors(TransformFeedbackPorting.java:182)
	at temp.TransformFeedbackPorting.<init>(TransformFeedbackPorting.java:60)
	at temp.TransformFeedbackPorting.main(TransformFeedbackPorting.java:200)

Nein. in float blub ist ein (Vertex-) Attribut, genau wie etwa in vec4 pos, in float weight, in vec3 color, in mat4 morph, usw… Davon kann es immer beliebig viele geben. Egal ob GL_POINTS oder was anderes. Egal ob gezeichnet oder nicht.

Allgemein: Eine Geometrische Struktur besteht aus Primitiven (GL_POINTS, GL_TRIANGLES, …). Jedes Primitiv besteht aus einem oder mehreren Vertices. Ein Vertex (Einzahl von Vertices) ist so etwas wie ein Eckpunkt oder eine Datenstruktur die diesen Eckpunkt beschreibt. Die Elemente dieser Datenstruktur sind dann eben die (Vertex-) Attribute. Der Vertex Shader wird für jedes Vertex genau ein mal aufgerufen.

Also:

  • Ein Punkt besteht aus genau einem Vertex. Das Vertex kann aber beliebig viele Attribute haben.
  • Ein Dreieck besteht aus drei Vertices. Jedes dieser Vertices hat wiederum mehrere Attribute.

glVertexAttribPointer macht genau das was der Name suggeriert, es stellt eine Verbindung zwischen einem Vertexattribut und einem Buffer(-teil) her. Size 2 weil ein vec2 aus zwei floats besteht.

Beispiel, Dein KSKB umgebaut auf zwei separate float Attribute:



import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_INFO_LOG_LENGTH;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL30.GL_TRANSFORM_FEEDBACK_BUFFER;

import java.nio.FloatBuffer;

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.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL31;
import org.lwjgl.opengl.PixelFormat;


public class TransformFeedbackPorting {

    private final int programId;
    private final int floatSizeInBytes = Float.SIZE / 8;
    private final int argumentCount = 10, floatsPerArgument = 2;
    private int firstVao, secondVao;
    private int firstBuffer, secondBuffer;


    public TransformFeedbackPorting() throws LWJGLException {

        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create(new PixelFormat(), new ContextAttribs(3, 1));
        final String vertexShaderContent = ""
                + "#version 150                                                           
"
                + "in float inPosX;                                                       
" // <--
                + "in float inAmplitude;                                                  
" // <--
                + "layout(std140) uniform GlobalValues {                                  
"
                + "  float delta;                                                         
"
                + "  float globalTime;                                                    
"
                + "};                                                                     
"
                + "out float outPosX;                                                     
" // <--
                + "out float outAmplitude;                                                
" // <--
                + "void main(){                                                           
"
                + "  if(inPosX >= 1.0f){outPosX = -1.0f;}                                 
" // <--
                + "  else{outPosX = inPosX + 1f * delta;}                                 
" // <--
                + "  outAmplitude = inAmplitude;                                          
" // <--
                + "  gl_Position = vec4(inPosX, inAmplitude * sin(5.0f * inPosX), 0, 1);  
" // <--
                + "}";
        final int vshaderId = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
        GL20.glShaderSource(vshaderId, vertexShaderContent);
        GL20.glCompileShader(vshaderId);
        checkCompileErrors(vshaderId);

        final String fragmentShaderContent = ""
                + "#version 150                                                     
"
                + "out vec4 outColor;                                               
"
                + "void main(){                                                     
"
                + "  outColor = vec4(1, 0, 0, 1);                                   
"
                + "}";
        final int fshaderId = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
        GL20.glShaderSource(fshaderId, fragmentShaderContent);
        GL20.glCompileShader(fshaderId);
        checkCompileErrors(fshaderId);

        programId = GL20.glCreateProgram();
        GL20.glAttachShader(programId, vshaderId);
        GL20.glAttachShader(programId, fshaderId);

        GL30.glTransformFeedbackVaryings(programId, new String[] { "outPosX", "outAmplitude" }, GL30.GL_INTERLEAVED_ATTRIBS); // << --

        GL20.glLinkProgram(programId);
        checkLinkErrors(programId);
        GL20.glUseProgram(programId);


        final int inPosXLocation = GL20.glGetAttribLocation(programId, "inPosX"); // << --
        final int inAmplitudeLocation = GL20.glGetAttribLocation(programId, "inAmplitude"); // << --

        secondVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(secondVao);

        secondBuffer = GL15.glGenBuffers();

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, secondBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, argumentCount * floatsPerArgument * floatSizeInBytes, GL15.GL_STREAM_DRAW);

        GL20.glEnableVertexAttribArray(inPosXLocation);
        GL20.glVertexAttribPointer(inPosXLocation, 1, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 0 * floatSizeInBytes); // <--

        GL20.glEnableVertexAttribArray(inAmplitudeLocation); // <--
        GL20.glVertexAttribPointer(inAmplitudeLocation, 1, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 1 * floatSizeInBytes); // <--

        GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatsPerArgument * floatSizeInBytes);


        firstVao = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(firstVao);

        final FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(argumentCount * floatsPerArgument);

        System.out.println("-- filling buffer");
        for (int i = 0; i < argumentCount; i++) {
            final float value = (float) (((i) / (double) argumentCount) * 0.5);
            System.out.println(value);
            dataBuffer.put(value);
            // dataBuffer.put((float) Math.random() * 0.5f + 0.3f);
            dataBuffer.put(0.5f);
        }
        dataBuffer.flip();
        System.out.println("-- finished initialization
");


        firstBuffer = GL15.glGenBuffers();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, firstBuffer);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, dataBuffer, GL15.GL_STREAM_DRAW);

        GL20.glEnableVertexAttribArray(inPosXLocation);
        GL20.glVertexAttribPointer(inPosXLocation, 1, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 0 * floatSizeInBytes); // <--

        GL20.glEnableVertexAttribArray(inAmplitudeLocation); // <--
        GL20.glVertexAttribPointer(inAmplitudeLocation, 1, GL11.GL_FLOAT, false, floatsPerArgument * floatSizeInBytes, 1 * floatSizeInBytes); // <--

        GL11.glPointSize(10);

        testLoop();
    }


    private void testLoop() {

        long thisFrame, lastFrame = System.currentTimeMillis();
        float delta, time = 0;

        final int globalDataUBO = GL31.glGetUniformBlockIndex(programId, "GlobalValues");
        final int uniformBufferId = GL15.glGenBuffers();
        GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uniformBufferId);
        GL15.glBufferData(GL31.GL_UNIFORM_BUFFER, 2 * floatSizeInBytes, GL15.GL_STREAM_DRAW);
        final FloatBuffer globalData = BufferUtils.createFloatBuffer(2);
        GL31.glUniformBlockBinding(programId, globalDataUBO, 0);
        GL30.glBindBufferRange(GL31.GL_UNIFORM_BUFFER, 0, uniformBufferId, 0, 2 * floatSizeInBytes);

        while (!Display.isCloseRequested()) {
            thisFrame = System.currentTimeMillis();
            delta = (thisFrame - lastFrame) / (float) 1e3;
            lastFrame = thisFrame;
            time += delta;

            globalData.put(delta);
            globalData.put(time);
            globalData.flip();
            // GL20.glUniform1f(deltaUniformLocation, delta);
            GL15.glBindBuffer(GL31.GL_UNIFORM_BUFFER, uniformBufferId);
            GL15.glBufferSubData(GL31.GL_UNIFORM_BUFFER, 0, globalData);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            // in buffer2 soll output geschrieben werden
            GL30.glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, secondBuffer, 0, argumentCount * floatsPerArgument * floatSizeInBytes);
            GL30.glBeginTransformFeedback(GL11.GL_POINTS);
            // von buffer1 (vao1) soll gelesen also gerendert werden
            GL30.glBindVertexArray(firstVao);
            GL11.glDrawArrays(GL11.GL_POINTS, 0, argumentCount);
            GL30.glEndTransformFeedback();
            Display.update();

            // switch alles (vao und buffer id's)
            int temp = secondVao;
            secondVao = firstVao;
            firstVao = temp;
            temp = secondBuffer;
            secondBuffer = firstBuffer;
            firstBuffer = temp;
        }
    }


    private void checkCompileErrors(final int shaderId) {

        if (GL_FALSE == glGetShaderi(shaderId, GL_COMPILE_STATUS)) {
            final int length = glGetShaderi(shaderId, GL_INFO_LOG_LENGTH);
            final String log = glGetShaderInfoLog(shaderId, length);
            throw new RuntimeException(log);
        }
    }


    private void checkLinkErrors(final int programId) {

        if (GL_FALSE == glGetProgrami(programId, GL_LINK_STATUS)) {
            final int length = glGetProgrami(programId, GL_INFO_LOG_LENGTH);
            final String log = glGetProgramInfoLog(programId, length);
            throw new RuntimeException(log);
        }
    }


    public static void main(final String[] args) throws LWJGLException {

        try {
            new TransformFeedbackPorting();
        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
}

Gruß
Fancy