如何在JOGL中编辑顶点着色器

时间:2016-09-09 02:15:58

标签: java c++ opengl glsl jogl

所以我正在开发一个基本上只是翻译三角形顶点的Java / Jogl应用程序。到目前为止,我能够让三角形从左向右移动,但我无法弄清楚如何编辑顶点着色器,以便当我单击一个按钮时,三角形开始上下移动而不是左右移动。

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.nio.*;
import javax.swing.*;
import static com.jogamp.opengl.GL4.*;

import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
import graphicslib3D.GLSLUtils;

import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.Vector;

public class a1 extends JFrame implements GLEventListener
{   
    private GLCanvas myCanvas;
    private int rendering_program;
    private int vao[] = new int[1];
    private GLSLUtils util = new GLSLUtils();
    private Button button1, button2;

    private float x = 0.0f;
    private float y = 0.0f;
    private float inc = 0.01f;
    private float incy = 0.01f;
    private int click = 1;

public a1()
{   setTitle("Chapter2 - program2");
    setSize(600, 400);
    myCanvas = new GLCanvas();
    myCanvas.addGLEventListener(this);
    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(myCanvas, BorderLayout.CENTER);

    JPanel sidePanel = new JPanel();
    sidePanel.setLayout(new BoxLayout(sidePanel, BoxLayout.Y_AXIS));
    button1 = new Button("button");
    button2 = new Button("button2");
    sidePanel.add(button1);
    sidePanel.add(button2);
    getContentPane().add(sidePanel, BorderLayout.WEST);

    button2.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            click = 1;

        }
    });

    setVisible(true);
    FPSAnimator animator = new FPSAnimator(myCanvas, 30);
    animator.start();
}

public void display(GLAutoDrawable drawable)
{   GL4 gl = (GL4) GLContext.getCurrentGL();
    gl.glUseProgram(rendering_program);
    gl.glPointSize(50.0f);

    float bkg[] = {0.0f, 0.0f, 0.0f, 1.0f};
    FloatBuffer bkgBuffer = Buffers.newDirectFloatBuffer(bkg);
    gl.glClearBufferfv(GL_COLOR, 0, bkgBuffer);

    x+=inc;
    y+=incy;
    if(x > 1.0f) inc = -0.01f;
    if(x < -1.0f) inc = 0.01f;

    if(y > 1.0f) incy = -0.01f;
    if(y< -1.0f) incy = 0.01f;


    int offset_loc = gl.glGetUniformLocation(rendering_program, "inc");
    int offset_y = gl.glGetUniformLocation(rendering_program, "incy");
    int flag = gl.glGetUniformLocation(rendering_program, "flag");

    gl.glProgramUniform1f(rendering_program, offset_loc, x);
    gl.glProgramUniform1f(rendering_program, offset_y, y);
    gl.glProgramUniform1f(rendering_program, flag, click);
    gl.glDrawArrays(GL_TRIANGLES,0,3);
}


public void init(GLAutoDrawable drawable)
{   GL4 gl = (GL4) GLContext.getCurrentGL();
    rendering_program = createShaderProgram();
    gl.glGenVertexArrays(vao.length, vao, 0);
    gl.glBindVertexArray(vao[0]);
}

private int createShaderProgram()
{
    GL4 gl = (GL4) GLContext.getCurrentGL();
    int[] vertCompiled = new int[1];
    int[] fragCompiled = new int[1];
    int[] linked = new int[1];

    String vshaderSource[] = readShaderSource("src/vert.shader");
    String fshaderSource[] = readShaderSource("src/frag.shader");

    int vShader = gl.glCreateShader(GL_VERTEX_SHADER);
    gl.glShaderSource(vShader, vshaderSource.length, vshaderSource, null, 0);
    gl.glCompileShader(vShader);

    util.checkOpenGLError();
    gl.glGetShaderiv(vShader, GL_COMPILE_STATUS, vertCompiled, 0);
    if(vertCompiled[0] == 1)
    {
        System.out.println("vertex compilation success");
    }else{
        System.out.println("vertex compilation failed");
        util.printShaderLog(vShader);
    }
    int fShader = gl.glCreateShader(GL_FRAGMENT_SHADER);
    gl.glShaderSource(fShader, fshaderSource.length, fshaderSource, null, 0);
    gl.glCompileShader(fShader);

    util.checkOpenGLError();
    gl.glGetShaderiv(fShader, GL_COMPILE_STATUS, fragCompiled, 0);
    if(fragCompiled[0] == 1)
    {
        System.out.println("fragment compilation success");
    }else{
        System.out.println("fragment compilation failed");
        util.printShaderLog(fShader);
    }

    int vfprogram = gl.glCreateProgram();
    gl.glAttachShader(vfprogram, vShader);
    gl.glAttachShader(vfprogram, fShader);
    gl.glLinkProgram(vfprogram);

    util.checkOpenGLError();
    gl.glGetProgramiv(vfprogram, GL_LINK_STATUS, linked, 0);
    if(linked[0] == 1)
    {
        System.out.println("linking succeeded");
    }else{
        System.out.println("linking failed");
        util.printProgramLog(vfprogram);
    }
    //gl.glDeleteShader(vShader);
    //gl.glDeleteShader(fShader);
    return vfprogram;
}

public static void main(String[] args) { new a1(); }
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
public void dispose(GLAutoDrawable drawable) {}

private String[] readShaderSource(String filename)
{
    Vector<String> lines = new Vector<String>();
    Scanner sc;
    try
    {
        sc = new Scanner(new File(filename));
    }catch (IOException e)
    {
        System.err.println("IOException reading file: " + e);
        return null;
    }
    while(sc.hasNext())
    {
        lines.addElement(sc.nextLine());
    }
    String[] program = new String[lines.size()];
    for(int i=0; i<lines.size(); i++)
    {
        program[i] = (String) lines.elementAt(i)+ "\n";
    }
    return program;
}
}

#version 430
uniform float inc;
void main(void)
{

  if(gl_VertexID == 0) gl_Position = vec4(0.25, -0.25+inc, 0.0, 1.0);
  else if(gl_VertexID == 1) gl_Position = vec4(-0.25, -0.25+inc, 0.0, 1.0);
  else gl_Position = vec4(0.25, 0.25+inc, 0.0, 1.0);

}

如何编辑顶点着色器,以便在单击按钮时顶点的位置发生变化,三角形开始上下移动而不是从左到右?

1 个答案:

答案 0 :(得分:2)

1)不要像那样进行更新

2)不要使用int数组作为OpenGL资源(vao),更喜欢直接整数缓冲区,例如可以使用GLBuffers.newDirectIntBuffer(1);作为vao ..

3)不要使用FPSAnimator,而是使用Animator

4)不要每次在display()方法(bkgBuffer)中初始化新的直接缓冲区,只需在变量声明或init()中执行一次。您还应该处置任何直接缓冲区,因为它不能保证它们将被垃圾收集器删除。我有一个小班here。然而,更好的是Gouessej here的实施。

4)使用顶点缓冲区对象声明顶点属性(如位置)

5)声明一个布尔标志变量update来触发更新。

button2.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        update = 1;
    }
});

public void display(GLAutoDrawable drawable) {   

    GL4 gl = (GL4) GLContext.getCurrentGL();

    if(update) {
        update = false;
        ...
    }
}

现在你有两种可能性:

  • 直接更新顶点

        gl3.glBindBuffer(GL_ARRAY_BUFFER, bufferName.get(Buffer.VERTEX));
        gl3.glBufferSubData(GL_ARRAY_BUFFER, 0, vertexBuffer.capacity(), vertexBuffer);
        gl3.glBindBuffer(GL_ARRAY_BUFFER, 0);
    

并且您的顶点着色器可能类似于

#version 430    
layout (location = POSITION) in vec2 position;
void main(void)
{    
    gl_Position = vec4(position, 0, 1);
}
  • 只更新将要乘以顶点的矩阵

    gl3.glBindBuffer(GL_UNIFORM_BUFFER, bufferName.get(Buffer.TRANSFORM));
    gl3.glBufferSubData(GL_UNIFORM_BUFFER, 0, Mat4.SIZE, matBuffer);
    gl3.glBindBuffer(GL_UNIFORM_BUFFER, 0);
    

在这种情况下,顶点可能是

#version 430    
layout (location = POSITION) in vec2 position;

layout (binding = TRANSFORM) uniform Transform
{
    mat4 mat;
};

void main(void)
{    
    gl_Position = mat * vec4(position, 0, 1);
}

如果您需要进一步的帮助,请不要犹豫,寻求帮助。 如需灵感,请参阅我的hello triangle