所以我正在开发一个基本上只是翻译三角形顶点的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);
}
如何编辑顶点着色器,以便在单击按钮时顶点的位置发生变化,三角形开始上下移动而不是从左到右?
答案 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