Я пытаюсь завершить свою первую программу JOGL OpenGL, используя шейдеры.
Я только начинаю с простого шейдера Vertex, который делает ошибку компиляции. Ожидается, что шейдер получит vec2(0.5, 0.5)
, который является в основном (x, y) координатами, и он генерирует правильный vec4(x-1.0,y-1.0,0.0,1.0)
пиксель.
Программа фактически отображает пиксель, но не использует шейдер как шейдер выдает ошибку компиляции. Как я могу получить больше информации о том, что не работает?
Нигде в коде API JOGL не указано, что именно 3.30 хочет использоваться, не уверен, что это актуально или нет.
Java класс, который расширяет JFrame и реализует GLEventListener. Он содержит GLCanvas:
package openglexample1;
import com.jogamp.common.nio.Buffers;
import static com.jogamp.opengl.GL.GL_NO_ERROR;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.glu.GLU;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Vector;
import java.util.stream.Stream;
import javax.swing.JFrame;
public class WindowD extends JFrame implements GLEventListener {
/**
* @return the glcanvas
*/
public GLCanvas getGlcanvas() {
return glcanvas;
}
//getting the capabilities object of GL3 profile
final private GLProfile profile;
final private GLCapabilities capabilities;
final private GLCanvas glcanvas;
// GL PROGAM
private int glProgram;
// VAO AND VBOs
private int vao[] = new int[1]; // VAO GROUPS VBOs, ONLY ONE USED
private int vbo[] = new int[2]; // 2 VBOs FOR 2 SQUARES
public WindowD() {
// OpenGL CAPABILITIES
profile = GLProfile.get(GLProfile.GL3);
capabilities = new GLCapabilities(profile);
// CANVAS
glcanvas = new GLCanvas(capabilities);
glcanvas.addGLEventListener(this);
glcanvas.setSize(400, 400);
// JFRAME
this.getContentPane().add(glcanvas);
this.setSize(this.getContentPane().getPreferredSize());
}
@Override
public void display(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
// USE PROGRAM
gl.glUseProgram(glProgram);
// USE VBOs
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo[0]);
gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, false, 0, 0); // associate 0th vertex attribute with active buffer
gl.glEnableVertexAttribArray(0); // enable the 0th vertex attribute
// DRAW POINT
gl.glDrawArrays(GL3.GL_POINTS, 0, 1);
}
@Override
public void init(GLAutoDrawable drawable) {
GL3 gl = drawable.getGL().getGL3();
// CREATE PROGRAM
glProgram = gl.glCreateProgram();
// CREATE VERTEX SHADER
int vertexShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
// COMPILATION STATUS
int[ ] vertCompiled = new int[1];
// LOAD SOURCE CODE
String[] vertexShaderSource = readShader("VertexShader1.glsl");
gl.glShaderSource(vertexShader, vertexShaderSource.length, vertexShaderSource, null, 0);
checkOpenGLError(); // can use returned boolean
gl.glGetShaderiv(vertexShader, GL3.GL_COMPILE_STATUS, vertCompiled, 0);
gl.glCompileShader(vertexShader);
if (vertCompiled[0] == 1)
{
System.out.println(". . . vertex compilation success.");
} else {
System.out.println(". . . vertex compilation failed.");
printShaderLog(vertexShader);
}
// ATTACH VERTEX SHADER TO PROGRAM, LINK AND DELETE SHADERS
gl.glAttachShader(glProgram, vertexShader);
gl.glLinkProgram(glProgram);
gl.glDeleteShader(vertexShader);
// CREATE VAO
gl.glGenVertexArrays(1, vao, 0);
gl.glBindVertexArray(vao[0]);
// COORDINATES SQUARES
float[] coordinatesSquare1 = new float[]{0.5f, 0.5f};
//float[] coordinatesSquare2 = new float[]{-0.5f, -0.5f};
// CREATE VBOs
gl.glGenBuffers(1, vbo, 0);
// POPULATE VBO 1 FOR SQUARE 1
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo[0]);
FloatBuffer bufferSquare1 = Buffers.newDirectFloatBuffer(coordinatesSquare1);
gl.glBufferData(gl.GL_ARRAY_BUFFER, bufferSquare1.limit()*4, bufferSquare1, gl.GL_STATIC_DRAW);
}
@Override
public void dispose(GLAutoDrawable drawable) {
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
System.out.println("reshape");
this.display(drawable);
}
private String[] readShader(String filename) {
Vector<String> lines = new Vector<String>();
try (Stream<String> stream = Files.lines(Paths.get(filename))) {
stream.forEach(x -> lines.add(x));
} catch (IOException e) {
e.printStackTrace();
}
// CONVERT VECTOR TO ARRAY
Object[] objArray = lines.toArray();
String[] array = Arrays.copyOf(objArray, objArray.length, String[].class);
return array;
}
private void printShaderLog(int shader) {
GL3 gl = (GL3) GLContext.getCurrentGL();
int[ ] len = new int[1];
int[ ] chWrittn = new int[1];
byte[ ] log = null;
// determine the length of the shader compilation log
gl.glGetShaderiv(shader, GL3.GL_INFO_LOG_LENGTH, len, 0);
if (len[0] > 0)
{
log = new byte[len[0]];
gl.glGetShaderInfoLog(shader, len[0], chWrittn, 0, log, 0);
System.out.println("Shader Info Log: ");
for (int i = 0; i < log.length; i++)
{
System.out.print((char) log[i]);
}
}
}
void printProgramLog(int prog) {
GL3 gl = (GL3) GLContext.getCurrentGL();
int[ ] len = new int[1];
int[ ] chWrittn = new int[1];
byte[ ] log = null;
// determine the length of the program linking log
gl.glGetProgramiv(prog,GL3.GL_INFO_LOG_LENGTH,len, 0);
if (len[0] > 0)
{
log = new byte[len[0]];
gl.glGetProgramInfoLog(prog, len[0], chWrittn, 0,log, 0);
System.out.println("Program Info Log: ");
for (int i = 0; i < log.length; i++)
{
System.out.print((char) log[i]);
}
}
}
boolean checkOpenGLError() {
GL3 gl = (GL3) GLContext.getCurrentGL();
boolean foundError = false;
GLU glu = new GLU();
int glErr = gl.glGetError();
while (glErr != GL_NO_ERROR) {
System.err.println("glError: " + glu.gluErrorString(glErr));
foundError = true;
glErr = gl.glGetError();
}
return foundError;
}
}
Основной класс, вызывающий этот класс JFrame:
package openglexample1;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.WindowConstants;
public class OpenGLExample3 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TEST WINDOW
WindowD basicFrame3 = new WindowD();
basicFrame3.setTitle("WindowD");
basicFrame3.setLocation(400,400);
basicFrame3.setVisible(true);
basicFrame3.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
Vertex shader Источник GLSL:
#version 330 core
layout (location = 0) in vec2 squareCenterPosition;
void main()
{
gl_Position = vec4(squareCenterPosition.x - 1.0, squareCenterPosition.y -1.0, 0.0, 1.0);
}
Как показано здесь, программа dr aws pixel, но она не использует шейдер, так как я получаю следующее сообщение:
run:
. . . vertex compilation failed.
Shader Info Log:
ERROR: 2:1: '#version' : syntax error
ERROR: 2:1: '#version' : syntax error
ERROR: 2:1: '' : syntax error: unexpected tokens following preprocessor directive - expected a newline
Что не так?
Вывод программы:
![enter image description here](https://i.stack.imgur.com/LV8Xh.png)