问题
I am trying to complete my first JOGL OpenGL program using shaders.
I am just starting with a simple Vertex shader which does a compilation error. The shader is expected to receive a vec2(0.5, 0.5)
which is basically (x,y) coordinates and it generates a proper vec4(x-1.0,y-1.0,0.0,1.0)
pixel.
The program actually displays the pixel, but it is not using the shader as the shader gives compilation error. How can I get more information on what is failing?
Nowhere in the JOGL API code is specified that specifically 3.30 wants to be used, not sure if that is relevant or not.
Java class which extends JFrame and implements GLEventListener. It contains the 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;
}
}
Main class invoking this JFrame class:
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 source:
#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);
}
As shown here, the program draws the pixel, but it is not using the shader as I get the following message:
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
What is wrong?
The output of the program:
回答1:
The source code lines were being submitted to the API without \n
.
This is the right readShader routine:
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 + "\n"));
} catch (IOException e) {
e.printStackTrace();
}
// CONVERT VECTOR TO ARRAY
Object[] objArray = lines.toArray();
String[] array = Arrays.copyOf(objArray, objArray.length, String[].class);
return array;
}
Notice the + "\n"
change.
来源:https://stackoverflow.com/questions/60098830/how-to-fix-this-opengl-error-unexpected-tokens-following-preprocessor-directiv