Как исправить эту ошибку OpenGL? «неожиданные токены после директивы препроцессора - ожидается новая строка» - PullRequest
1 голос
/ 06 февраля 2020

Я пытаюсь завершить свою первую программу 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

1 Ответ

3 голосов
/ 06 февраля 2020

Строки исходного кода были отправлены в API без \n.

Это правильная процедура readShader:

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;
} 

Обратите внимание на изменение + "\n".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...