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

标签 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) 不要那样做更新

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

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

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

4) 使用一个顶点缓冲对象来声明你的顶点属性(比如位置)

5) 声明一个 boolean 标志变量 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我的

关于java - 如何在 JOGL 中编辑顶点着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39402825/

相关文章:

java - 重定向和平衡 Java 输出流量

java - 从java运行git,git提示输入用户名和密码,为什么?

c++ - 改变静态数组的大小

c++ - 在 C++、Windows 7 中包含 OpenGL 库

java - 生成球体顶点、索引和法线?

java - IllegalStateException - 没有最后一次调用可用的模拟

c++ - Python 依赖,windows (CMake)

java - 如何使用 for 循环生成简单地形 [voxel]

c++ - 无法创建/采样 3D 纹理 (Qt/OpenGL)

java - super.onStop() 的意义何在?