«Ошибка C0000: синтаксическая ошибка, неожиданный конец $ на токене« <EOF>»» и не знаете, как продолжить - PullRequest
0 голосов
/ 24 января 2020

Я столкнулся с этой ошибкой при попытке использовать шейдер с базовым c треугольником с OpenGL. Он отображается только во время выполнения в консоли, когда я зарегистрировал данные, и не вызывает ошибки компиляции. LOG_ERROR в строке 35 шейдера. cpp - это то, что записывает ошибку. Я понятия не имею, как решить проблему.

шейдер. cpp

#include "engine_pch.h"
#include "shader.h"

#include "glad/glad.h"

namespace Engine {
    Shader::Shader(const std::string& vertexSrc, const std::string& fragmentSrc)
    {
        // Create an empty vertex shader handle
        GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

        // Send the vertex shader source code to GL
        // Note that std::string's .c_str is NULL character terminated.
        const GLchar* source = vertexSrc.c_str();
        glShaderSource(vertexShader, 1, &source, 0);

        // Compile the vertex shader
        glCompileShader(vertexShader);

        GLint isCompiled = 0;
        glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
        if (isCompiled == GL_FALSE)
        {
            GLint maxLength = 0;
            glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);

            // The maxLength includes the NULL character
            std::vector<GLchar> infoLog(maxLength);
            glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);

            // We don't need the shader anymore.
            glDeleteShader(vertexShader);

            // Use the infoLog as you see fit.
            LOG_ERROR("{0}", infoLog.data());
            // In this simple program, we'll just leave
            return;
        }

        // Create an empty fragment shader handle
        GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

        // Send the fragment shader source code to GL
        // Note that std::string's .c_str is NULL character terminated.
        source = fragmentSrc.c_str();
        glShaderSource(fragmentShader, 1, &source, 0);

        // Compile the fragment shader
        glCompileShader(fragmentShader);

        glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
        if (isCompiled == GL_FALSE)
        {
            GLint maxLength = 0;
            glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);

            // The maxLength includes the NULL character
            std::vector<GLchar> infoLog(maxLength);
            glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);

            // We don't need the shader anymore.
            glDeleteShader(fragmentShader);
            // Either of them. Don't leak shaders.
            glDeleteShader(vertexShader);

            // Use the infoLog as you see fit.
            LOG_ERROR("{0}", infoLog.data());
            // In this simple program, we'll just leave
            return;
        }

        // Vertex and fragment shaders are successfully compiled.
        // Now time to link them together into a program.
        // Get a program object.
        m_renderingID = glCreateProgram();
        GLuint program = m_renderingID;

        // Attach our shaders to our program
        glAttachShader(program, vertexShader);
        glAttachShader(program, fragmentShader);

        // Link our program
        glLinkProgram(program);

        // Note the different functions here: glGetProgram* instead of glGetShader*.
        GLint isLinked = 0;
        glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
        if (isLinked == GL_FALSE)
        {
            GLint maxLength = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

            // The maxLength includes the NULL character
            std::vector<GLchar> infoLog(maxLength);
            glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);

            // We don't need the program anymore.
            glDeleteProgram(program);
            // Don't leak shaders either.
            glDeleteShader(vertexShader);
            glDeleteShader(fragmentShader);

            // Use the infoLog as you see fit.

            // In this simple program, we'll just leave
            return;
        }

        // Always detach shaders after a successful link.
        glDetachShader(program, vertexShader);
        glDetachShader(program, fragmentShader);
    }
    Shader::~Shader()
    {
        glDeleteProgram(m_renderingID);
    }
    void Shader::bind() const
    {
        glUseProgram(m_renderingID);
    }
    void Shader::unbind() const
    {
        glUseProgram(0);
    }
}

shader.h

#pragma once

#include <string>

namespace Engine {

    class Shader {
    public:
        Shader(const std::string& vertexSrc, const std::string& fragmentSrc);
        ~Shader();

        void bind() const;
        void unbind() const;
    private:
        uint32_t m_renderingID;
    };
}

приложение. cpp

/** \file application.cpp
*/


#include "engine_pch.h"

#pragma region TempIncludes
// temp includes
#include <glad/glad.h>
#include <gl/GL.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#pragma endregion TempIncludes

#include "core/application.h"



namespace Engine {
    Application* Application::s_instance = nullptr;
    std::shared_ptr<Timestep> frameTimer(new Timestep());

    Application::Application()
    {

        if (s_instance == nullptr)
        {
            s_instance = this;
        }
        log::log();

        m_window = std::unique_ptr<Window>(Window::create());
        m_window->setEventCallback(std::bind(&Application::onEvent, this, std::placeholders::_1));

        glGenVertexArrays(1, &m_vertexArray);
        glBindVertexArray(m_vertexArray);

        glGenBuffers(1, &m_vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);

        float vertices[3 * 3] = {
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f
        };

        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);

        glGenBuffers(1, &m_indexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);

        unsigned int indices[3] = { 0, 1, 2 };
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


        std::string vertexSrc = R"(
        #version 440 core

        layout(location = 0) in vec3 position;

        void main(){
            gl_Position = vec4(position + 0.3, 1.0);
        )"
            ;

        std::string fragmentSrc = R"(
        #version 440 core

        layout(location = 0) out vec4 colour;

        void main(){
            colour = vec4(1.0, 0.2, 1.0, 1.0);
        )"
            ;

        m_shader = std::make_unique<Shader>(Shader(vertexSrc, fragmentSrc));
    }

    Application::~Application()
    {

    }



    void Application::run()
    {

        while (s_instance) {
            glClearColor(0.8, 0.4, 0, 1);
            glClear(GL_COLOR_BUFFER_BIT);

            m_shader->bind();
            glBindVertexArray(m_vertexArray);
            glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);

            glm::vec2 a = InputPoller::getMousePosition();
            float x = a.x;
            float y = a.y;
            LOG_INFO("{0}, {1}", x, y);

            m_window->onUpdate();


        }
    }

    void Application::onEvent(Event& e)
    {
        EventDispatcher dispatcher(e);
        dispatcher.dispatch<WindowCloseEvent>(std::bind(&Application::onClose, this, std::placeholders::_1));
        dispatcher.dispatch<WindowResizeEvent>(std::bind(&Application::onResize, this, std::placeholders::_1));
        dispatcher.dispatch<KeyPressedEvent>(std::bind(&Application::onKeyPress, this, std::placeholders::_1));
    }

    bool Application::onClose(WindowCloseEvent & e)
    {
        LOG_INFO("Closing Application");
        s_instance = false;
        return true;
    }

    bool Application::onResize(WindowResizeEvent & e)
    {
        LOG_INFO("Resize window to {0} * {1}", e.GetWidth(), e.GetHeight());
        return true;
    }

    bool Application::onKeyPress(KeyPressedEvent& e) {
        LOG_INFO(e.getKeyCode());
        return true;
    }

}

application.h

/** \file application.h
*/
#pragma once
#include "systems/log.h"
#include "core/timestep.h"
#include "systems/events/keyEvent.h"
#include "systems/events/MouseEvent.h"
#include "systems/events/WindowEvent.h"
#include "windows/window.h"
#include "Platform/win/winWindow.h"
#include "core/keyCodes.h"
#include "core/mouseCodes.h"
#include "systems/events/InputPoller.h"
#include "Platform/OpenGL/shader.h"
#include <glm/glm.hpp>

namespace Engine {

    /**
    \class Application
    Fundemental class of the engine. A singleton which runs the game loop infinitely.
    Provides ...
    */

    class Application
    {
    protected:
        Application(); //!< Constructor
    private:
        static Application* s_instance; //!< Singleton instance of the application
        std::unique_ptr<Window> m_window;
        unsigned int m_vertexArray, m_vertexBuffer, m_indexBuffer;
        std::unique_ptr<Shader> m_shader;
    public:
        virtual ~Application(); //!< Deconstructor
        inline static Application& getInstance() { return *s_instance; } //!< Instance getter from singleton pattern
        void run(); //!< Main loop
        void onEvent(Event& e);
        bool onClose(WindowCloseEvent& e);
        bool onResize(WindowResizeEvent& e);
        bool onKeyPress(KeyPressedEvent& e);
        inline Window& getWindow() { return *m_window; }
    };

    // To be defined in users code
    Application* startApplication(); //!< Function definition which provides an entry hook

}

РЕДАКТИРОВАТЬ: я понял, что код ошибки показывался из-за пропущенных '}' в основных функциях шейдеров. Однако теперь, даже если ошибка исчезла, шейдеры не влияют на мою визуализированную форму.

1 Ответ

1 голос
/ 24 января 2020

Проблема заключается в строке

m_shader = std::make_unique<Shader>(Shader(vertexSrc, fragmentSrc));

Установите точку останова в деструкторе Shader, чтобы выяснить, что происходит.
Что вы на самом деле делаете, это создаете временную Объект Shader и pass передаются конструктору копирования по умолчанию Shader. Временный объект уничтожается и вызывается glDeleteProgram(m_renderingID);.

std::make_unique<T> передает аргументы в конструктор T.
Для решения проблемы это должно быть:

m_shader = std::make_unique<Shader>(vertexSrc, fragmentSrc);
...