Проблема компиляции шейдера OpenGL-неожиданный EOF

поэтому я решил попробовать написать простое приложение OpenGL с помощью Java, просто чтобы посмотреть, как оно по сравнению с другими моими усилиями, и я столкнулся с проблемой, когда мои шейдеры отказываются компилироваться. Они действительно не могли получить намного проще, вот мой вершинный шейдер, чтобы продемонстрировать, что я имею в виду:

//Minimal vertex shader

#version 330

in vec3 in_Position;
in vec3 in_Color;
out vec3 var_Color;

void main(void)
{
    gl_Position = vec4(in_Position, 1.0);
    var_Color = in_Color;
}

шейдер фрагментов так же прост, поэтому я не буду утруждать себя его публикацией, если кто-то не попросит об этом. Когда я проверяю журналы, я получаю следующую ошибку (для обоих шейдеры):

(0) : error C0000: syntax error, unexpected $end at token "<EOF>"

Я не уверен, что это актуально... но я разрабатываю Linux (Ubuntu 11.04) с использованием Java. Единственными библиотеками, которые я использую, являются JOGL (для Привязок openGL) и стандартная библиотека Java (если это даже считается...) Моя видеокарта-это Nvidia GeForce 9600M GS, и я проверил расширения, и она имеет полную поддержку OpenGL 3.3.

помогите мне переполнение стека, вы моя единственная надежда.

EDIT:

по запросу, вот функция это отвечает за загрузку и компиляцию источника шейдеров. Кроме того, когда дело доходит до GLSL, я супер n00b, поэтому я действительно не знаю, что искать, чтобы убедиться, что все отформатировано правильно для OpenGL. Ссылка на недавний (т. е. дело с OpenGL 3.x)учебник по этому вопросу будет оценен.

private int CreateCompiledShader(File source, int shader, GL3 gl){
        int shaderloc = gl.glCreateShader(shader);

        BufferedReader input = null;
        ArrayList<String> lines = new ArrayList<String>();
        ArrayList<Integer> lengths = new ArrayList<Integer>();
        try{
            input = new BufferedReader(new FileReader(source));
            String buffer;

            while(input.ready()){
                buffer = input.readLine();
                lines.add(buffer);
                lengths.add(buffer.length());
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(input != null){
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        int[] iLengths = new int[lengths.size()];
        for(int i = 0; i < lengths.size(); i++){
        iLengths[i] = lengths.get(i).intValue();
        }

        gl.glShaderSource(shaderloc, lines.size(), lines.toArray(new String[0]), iLengths, 0);
        gl.glCompileShader(shaderloc);

        int error = gl.glGetError();
        if(error != GL3.GL_NO_ERROR){
            Logger.log(new GLU().gluErrorString(error), Logger.ERROR, "Shader compilation");
        }

        return shaderloc;
    }

в стороне, оператор if ближе к концу, где я проверяю glGetError ()не на самом деле, когда ошибка ловится, этого не происходит, пока выполнение возвращается к вызывающей функции, и я проверяю журналы шейдеров. Может быть, это важно, но, с другой стороны, я тоже могу быть бессвязным.

3 ответов


хорошо, теперь я вижу проблему. Ваш код загрузки не работает. Но не волнуйтесь; многие люди путаются, когда видят, что glShaderSource принимает массив строк. Я предполагаю, что вы видели, как кто-то писал свои шейдеры на C/C++ следующим образом:

const char *myShader[] = {
    "#version 330\n",
    "\n",
    "in vec3 in_position;\n",
    ...
};

и они загрузили шейдер с,glShaderSource(shader, ARRAY_COUNT(myShader), myShader, NULL, 0);

хотя это законно, это не совсем то, для чего предназначена эта функция. Поскольку GLSL не имеет механизма #include, glShaderSource может принимать несколько строк. Каждый строка должна быть файл Shader. Затем компилятор шейдеров эффективно объединяет строки вместе, как это делает #include перед компиляцией.

Теперь, из-за этого, вы можете иметь каждую строку в виде отдельной строки. Однако оглянитесь назад, что этот код C / C++. Посмотрим, что в конце каждой строки? Этот " n " персонаж.

что это не в конце строк, которые вы загружаете. Потому что я уверен, что BufferedReader.с readline ли не держите конец строки. Таким образом, ваш шейдер выглядит так:

//Minimal vertex shader#version 330in vec3 in_Position;in vec3 in_Color;out vec3 var_Color;...

весь ваш шейдер рассматривается как один большой однострочный комментарий. Отсюда неожиданный EOF: OpenGL никогда не видел ничего компилировать;)

вы не должны читать файл построчно. Просто загрузите все это в одну строку. Затем передайте его OpenGL. Кроме того, вы можете посмотреть этот предыдущий ответ о JOGL; он должен показать вам, как это сделать правильно (хотя я надеюсь, что BufferedReader будет иметь какой-то способ прочитать весь файл как строку, а не строку за строкой.


хотя ответ уже был предоставлен и принят peen, я просто напишу здесь, как я бы предпочел:

// Create shader from one or multiple source files
private int CreateCompiledShader(File[] source_files, int shader, GL3 gl){
    int shaderloc = gl.glCreateShader(shader);
    int nSources = source_files.size();

    // the number of shader sources it known from the beginning
    // so we can allocate the arrays right here
    String[] sources = new String[nSources];
    int[] sources_lengths = new int[nSources];
    for(int i = 0; i < nSources; i++) {
        // We don't need a buffered reader as we're reading the file as a whole
        FileReader input = new FileReader(source_file[i]);
        String buffer;

        buffer = input.read();
        sources[i] = buffer;
        sources_lengths[i] = buffer.length();

        if(input != null){
            input.close();
        }
    }

    // Frankly I really don't understand why you have to pass sources_lengths here
    // It would take only 3 LOC in the binding's code
    // to extract that from the sources array, Oh, well...
    gl.glShaderSource(shaderloc, nSources, sources, sources_lengths, 0);
    gl.glCompileShader(shaderloc);

    // Actually if glGetError() returns an error you must call it in a loop
    // as OpenGL errors can accumulate, and you have to pop them all from the list.
    int error = gl.glGetError();
    if(error != GL3.GL_NO_ERROR){
        Logger.log(new GLU().gluErrorString(error), Logger.ERROR, "Shader compilation");
    }

    return shaderloc;
}

Я взял на себя смелость удалить все блоки try/catch/finally, так как они были немного неуместны: если чтение любого исходного файла не удается, загрузка шейдеров не может завершиться, поэтому нет смысла продолжать изящно. Способ propper справиться с этим будет большим блоком try/catch, который очищает объекты OpenGL компиляции шейдеров, не завершается.


попробуйте переместить комментарий после объявления #version. Это не должно иметь значения, но могут быть ошибки водителя.

кроме того, попробуйте поместить дополнительную пустую строку в конце файла. Опять же, просто чтобы убедиться.

наконец, убедитесь, что вы на самом деле загружаете строку правильно. Проверьте это в отладчике. И убедитесь, что вы правильно передаете строку OpenGL. Как выглядит этот код?