Rodgems
Rodgems

Reputation: 45

'Error C0000: syntax error, unexpected $end at token "<EOF>"' and unsure how to proceed

I've run into this error while attempting to use a shader with a basic triangle with OpenGL. It only shows up during run time in the console when I've logged the data, and causes no compile error. The LOG_ERROR in line 35 of shader.cpp is what is recording the error. I have no idea how to fix the issue.

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

application.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

}

EDIT: I realised the error code was showing up because of missed '}' in the main functions of the shaders. However, now, even with the error gone, the shaders are not effecting my rendered shape.

Upvotes: 0

Views: 761

Answers (1)

Rabbid76
Rabbid76

Reputation: 211268

The issue is the line

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

Put a breakpoint in the destructor of Shader to investigate what happens.
What you actually do is to create a temporary Shader object and pass is to the default copy constructor of Shader. The temporary object is destroyed and glDeleteProgram(m_renderingID); is called.

std::make_unique<T> passe the arguments to the constructor of T.
To solve the issue it has to be:

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

Upvotes: 1

Related Questions