简体   繁体   English

收到“错误编译:0:1(1): 错误:语法错误,意外的 $end” C++、GLSL、着色器文件

[英]Receiving a "Error compiling: 0:1(1): error: syntax error, unexpected $end" C++, GLSL, shader files

Here is my shader.cpp.这是我的 shader.cpp。 In my AddShader function, I am able to pass the vertex and fragment shader fine if it is hardcoded as a string with '\\n' and '\\' at the end of it.在我的 AddShader 函数中,如果将顶点和片段着色器硬编码为末尾带有'\\n''\\'的字符串,我就可以很好地传递它。 However when I try to load them from a file I receive the error in the title.但是,当我尝试从文件加载它们时,我收到标题中的错误。 I have read titles similar to my problem, but they did not help.我读过与我的问题类似的标题,但它们没有帮助。

#include "shader.h"

Shader::Shader()
{
  m_shaderProg = 0;
}

Shader::~Shader()
{
  for (std::vector<GLuint>::iterator it = m_shaderObjList.begin() ; it != m_shaderObjList.end() ; it++)
  {
    glDeleteShader(*it);
  }

  if (m_shaderProg != 0)
  {
    glDeleteProgram(m_shaderProg);
    m_shaderProg = 0;
  }
}

bool Shader::Initialize()
{
  m_shaderProg = glCreateProgram();

  if (m_shaderProg == 0)
  {
    std::cerr << "Error creating shader program\n";
    return false;
  }

  return true;
}

std::string Shader::readFile(GLenum ShaderType)
{
  std::ifstream finV("shader.vert");
  std::ifstream finF("shader.frag");
  std::string content;
  if(ShaderType == GL_VERTEX_SHADER)
  {
    // If the file was opened successfully, continue
    if(finV)
    {
      while(finV)
      {
        std::cout << content << std::endl;
        getline(finV, content);
      }
    }
  }
  else if (ShaderType == GL_FRAGMENT_SHADER)
  {
    if(finF)
    {
      while(finF)
      {
        std::cout << content << std::endl;
        getline(finF, content);
      }
    }
  }
  finV.close();
  finF.close();
  return content;
}

// Use this method to add shaders to the program. When finished - call finalize()
bool Shader::AddShader(GLenum ShaderType)
{

  if(ShaderType == GL_VERTEX_SHADER)
  {
    m_s = readFile(GL_VERTEX_SHADER);
  }
  else if(ShaderType == GL_FRAGMENT_SHADER)
  {
    m_s = readFile(GL_FRAGMENT_SHADER);
  }

  GLuint ShaderObj = glCreateShader(ShaderType);

  if (ShaderObj == 0)
  {
    std::cerr << "Error creating shader type " << ShaderType << std::endl;
    return false;
  }

  // Save the shader object - will be deleted in the destructor
  m_shaderObjList.push_back(ShaderObj);

  const GLchar* p[1];
  p[0] = m_s.c_str();
  GLint Lengths[1] = { (GLint)m_s.size() };

  glShaderSource(ShaderObj, 1, p, Lengths);

  glCompileShader(ShaderObj);

  GLint success;
  glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);

  if (!success)
  {
    GLchar InfoLog[1024];
    glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
    std::cerr << "Error compiling: " << InfoLog << std::endl;
    return false;
  }

  glAttachShader(m_shaderProg, ShaderObj);

  return true;
}


// After all the shaders have been added to the program call this function
// to link and validate the program.
bool Shader::Finalize()
{
  GLint Success = 0;
  GLchar ErrorLog[1024] = { 0 };

  glLinkProgram(m_shaderProg);

  glGetProgramiv(m_shaderProg, GL_LINK_STATUS, &Success);
  if (Success == 0)
  {
    glGetProgramInfoLog(m_shaderProg, sizeof(ErrorLog), NULL, ErrorLog);
    std::cerr << "Error linking shader program: " << ErrorLog << std::endl;
    return false;
  }

  glValidateProgram(m_shaderProg);
  glGetProgramiv(m_shaderProg, GL_VALIDATE_STATUS, &Success);
  if (!Success)
  {
    glGetProgramInfoLog(m_shaderProg, sizeof(ErrorLog), NULL, ErrorLog);
    std::cerr << "Invalid shader program: " << ErrorLog << std::endl;
    return false;
  }

  // Delete the intermediate shader objects that have been added to the program
  for (std::vector<GLuint>::iterator it = m_shaderObjList.begin(); it != m_shaderObjList.end(); it++)
  {
    glDeleteShader(*it);
  }

  m_shaderObjList.clear();

  return true;
}


void Shader::Enable()
{
    glUseProgram(m_shaderProg);
}


GLint Shader::GetUniformLocation(const char* pUniformName)
{
    GLuint Location = glGetUniformLocation(m_shaderProg, pUniformName);

    if (Location == INVALID_UNIFORM_LOCATION) {
        fprintf(stderr, "Warning! Unable to get the location of uniform '%s'\n", pUniformName);
    }

    return Location;
}

Here is my vertex and fragment shaders respectively.这里分别是我的顶点和片段着色器。

#version 330

layout (location = 0) in vec3 v_position;
layout (location = 1) in vec3 v_color;

smooth out vec3 color;

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

void main(void)
{
  vec4 v = vec4(v_position, 1.0);
  gl_Position = (projectionMatrix * viewMatrix * modelMatrix) * v;
  color = v_color;
}

#version 330

smooth in vec3 color;

out vec4 frag_color;

void main(void)
{
  frag_color = vec4(color.rgb, 1.0);
}

Here is my shader.h as well.这里也是我的 shader.h。

#ifndef SHADER_H
#define SHADER_H

#include <vector>
#include <string>
#include <fstream>

#include "graphics_headers.h"

class Shader
{
  public:
    Shader();
    ~Shader();
    bool Initialize();
    void Enable();
    bool AddShader(GLenum ShaderType);
    bool Finalize();
    GLint GetUniformLocation(const char* pUniformName);
    std::string readFile(GLenum ShaderType);

  private:
    GLuint m_shaderProg;
    std::vector<GLuint> m_shaderObjList;
    std::string m_s;
};

#endif  /* SHADER_H */

Here is my graphics_headers.h to be thorough.这是我的 graphics_headers.h 要彻底。

#ifndef GRAPHICS_HEADERS_H
#define GRAPHICS_HEADERS_H

#include <iostream>

#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED

#if defined(__APPLE__) || defined(MACOSX)
  #include <OpenGL/gl3.h>
  #include <OpenGL/GLU.h>
#else //linux as default
  #include <GL/glew.h>
  //#include <GL/glu.h>
#endif

// GLM for matricies
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/rotate_vector.hpp>

#define INVALID_UNIFORM_LOCATION 0x7fffffff

struct Vertex
{
  glm::vec3 vertex;
  glm::vec3 color;

  Vertex(glm::vec3 v, glm::vec3 c): vertex(v), color(c) {}
};

#endif /* GRAPHICS_HEADERS_H */

std::getline dosen't append the read content to a std::string . std::getline不会将读取的内容附加到std::string The previous content of the std::string is replaced, by the newly extracted sequence. std::string的先前内容被新提取的序列替换。

If you want to read the entire text from a shader file, then you can use a std::istreambuf_iterator :如果要从着色器文件中读取整个文本,则可以使用std::istreambuf_iterator

#include <fstream>
#include <iterator> // std::istreambuf_iterator

std::string content;

std::ifstream finV("shader.vert");
if ( finV.is_open() )
    content = std::string(
        std::istreambuf_iterator<char>(finV), std::istreambuf_iterator<char>());

If you want really want to use std::getline , here is a small dirty hack, simply make buffer and then add it to content, like @up wrote std::getline resets whole content of std::string object and puts new line into it.如果你真的想使用std::getline ,这里有一个小的脏黑客,只需制作缓冲区然后将其添加到内容中,就像@up 写的std::getline重置std::string对象的全部内容并放置新行进去。

Definitely not the fastest solution:绝对不是最快的解决方案:

std::string Shader::readFile(GLenum ShaderType)
{
    std::ifstream finV("shader.vert");
    std::ifstream finF("shader.frag");
    std::string content = "";
    if (ShaderType == GL_VERTEX_SHADER)
    {
        // If the file was opened successfully, continue
        if (finV)
        {
            while (finV)
            {
                std::string buffer = "";
                getline(finV, buffer);
                content += buffer + "\n";
            }
        }
    }
    else if (ShaderType == GL_FRAGMENT_SHADER)
    {
        if (finF)
        {
            while (finF)
            {
                std::string buffer = "";
                getline(finF, buffer);
                content += buffer + "\n";
            }
        }
    }
    finV.close();
    finF.close();
    std::cout << content << std::endl;

    return content;
}

Works for me.为我工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM