Проблема при попытке открыть файл с ifstream с помощью CMake - PullRequest
0 голосов
/ 04 марта 2019

/ * Определяет класс шейдеров.* /

Я разрабатываю приложение на C ++ с OpenGL и CMake.Структура моих каталогов:

  • tanx
    • CMakeLists.txt
    • ext (содержит GLFW и рад)
    • src
      • TanX.cpp
      • TanX.h
      • математика (содержит несколько математических методов; не очень подходит для моей задачи)
      • шейдер
        • шейдер.h
        • vertex.glsl
        • фрагмент.glsl
        • CMakeLists.txt

Shader.h в основном предназначен для чтения источников вершинных и фрагментных шейдеров из файлов, их компиляции и связывания с программой Shader.Это выглядит так:

#ifndef _SHADER_H
#define _SHADER_H

#include <string>
#include <exception>
#include <fstream>
#include <glad.h>


class shader_exception :std::exception {
private:
    const char* text;
public:
    shader_exception(const char* text)
        : text(text) {}
    virtual const char* what() const {
        return text;
    }
};

class Shader {
private:
    std::string* vertex_source = new std::string();
    std::string* fragment_source = new std::string();
    unsigned int vao, vbo, vertex_shader, fragment_shader, program;
public:
    Shader(const char* vertex_source_path, const char* fragment_source_path) {
        std::ifstream file_reader;
        file_reader.open(vertex_source_path);
        std::string line;

        if (file_reader.is_open()) {
            while (getline(file_reader, line)) {
                vertex_source->append(line + "\n");
            }
            file_reader.close();
        }
        else 
            throw shader_exception("Could not open vertex shader source file");

        file_reader.open(fragment_source_path);  // this is where I get an unhandled exception dialog box
        if (file_reader.is_open()) {
            while (getline(file_reader, line)) {
                fragment_source->append(line + "\n");
            }
            file_reader.close();
        }
        else
            throw shader_exception("Could not open fragment shader file");
        const char** vertex_source_c = (const char**)malloc(vertex_source->size());
        *vertex_source_c = vertex_source->c_str();
        const char** fragment_source_c = (const char**)malloc(fragment_source->size());

        *fragment_source_c = fragment_source->c_str();
        vertex_shader = glCreateShader(GL_VERTEX_SHADER);

        glShaderSource(vertex_shader, 1, vertex_source_c, NULL);
        glCompileShader(vertex_shader);

        int success;
        glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
        char infoLog[512];
        if (!success) {
            glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
            throw shader_exception(infoLog);
        }

        glShaderSource(fragment_shader, 1, fragment_source_c, NULL);
        glCompileShader(fragment_shader);
        glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
        if (!success) {
            glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog);
            throw shader_exception(infoLog);
        }

        program = glCreateProgram();
        glAttachShader(program, vertex_shader);
        glAttachShader(program, fragment_shader);
        glLinkProgram(program);
        glGetProgramiv(program, GL_LINK_STATUS, &success);
        if (!success) {
            glGetProgramInfoLog(program, 512, NULL, infoLog);
            throw shader_exception(infoLog);
        }

        glDeleteShader(vertex_shader);
        glDeleteShader(fragment_shader);
    }

    Shader() = delete;

    void use() 
    {
        glUseProgram(program);
    }

    ~Shader() {
        glDeleteProgram(program);
    }
};

#endif

В TanX.cpp я пытаюсь создать объект шейдера следующим образом:

Shader shader("vertex.glsl", "fragment.glsl");

Как видите, исходные файлы шейдера я бынравится использовать vertex.glsl и фрагмент.glsl, которые находятся в папке "Shader".Чтобы сделать их пригодными для использования в ifstream, файл CMakeLists.txt в папке Shader выглядит следующим образом (это один из упомянутых вариантов здесь , чтобы сделать файлы пригодными для использования в программе):

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/vertex.glsl ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fragment.glsl ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)

Файл CMakeLists.txt верхнего уровня также содержит

add_subdirectory("TanX/src/Shader")

, так что файл CMakeLists.txt в шейдере выполняется.

Проблема заключается в том, что при попыткеЗапустив мой код в Visual Studio, я получаю необработанное исключение в файле Shader.h в строке 45 (где он пытается открыть фрагмент.glsl).Это исключение shader_exception, поэтому, по-видимому, открытие vertex.glsl не удалось.Сведения о диалоговом окне «Исключение необработано»: «Необработанное исключение по адресу 0x00007FFF43E4A388 в TanX.exe: исключение Microsoft C ++: возникло исключение shader_exception в ячейке памяти 0x00000028896FF608.».Теперь у меня есть два вопроса

1) Что мне нужно сделать, чтобы ifstream открыл vertex.glsl (а затем фрагмента.glsl)?
2) Почему я даже получаю необработанное исключениеошибка, разве не должно завершиться создание объекта Shader, как только возникнет исключение, и это приведет к тому, что программа даже не достигнет строки 45?

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Проблема была в том, куда я положил файлы.Я помещаю их в папку bin в папке Shader, но, поскольку она реализована в заголовке, правильное место - папка bin в папке верхнего уровня.

0 голосов
/ 04 марта 2019

Сразу же, это ...

Shader* shader;
try {
    *shader = Shader("vertex.glsl", "fragment.glsl");
}

... - неопределенное поведение, потому что вы разыменовываете неинициализированный указатель (т. Е. Вы не выделили никакого хранилища для Shaderобъект).Возможно, это не единственная проблема, но это критическая проблема, которую необходимо устранить, прежде чем вы сможете продолжить отладку (поскольку поведение программы впоследствии непредсказуемо).

Возможно, вы хотели написать:

shader = new Shader(...);

(И на самом деле вы должны использовать std::unique_ptr для этого, а не пустой указатель, но это выходит за рамки первоначального вопроса. Среди других преимуществ, это делает этот видошибки легче обнаружить и избежать.)


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

По моим подсчетам, строка 45 - это ...

}

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

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