接收"Error compiling: 0:1(1): error: syntax error, unexpected $end" C++、GLSL、着色器文件



这是我的着色器.cpp。在我的 AddShader 函数中,如果顶点和片段着色器被硬编码为字符串,并且末尾带有'n''',我就可以很好地传递顶点和片段着色器。但是,当我尝试从文件加载它们时,我在标题中收到错误。我读过与我的问题类似的标题,但它们没有帮助。

#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 programn";
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;
}

这分别是我的顶点和片段着色器。

#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);
}

这也是我的着色器.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 */

这是我彻底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不会将读取内容附加到std::stringstd::string的先前内容被新提取的序列替换。

如果要从着色器文件中读取整个文本,则可以使用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>());

如果你真的想使用std::getline,这里有一个小的肮脏的技巧,只需制作缓冲区,然后将其添加到内容中,就像@up编写std::getline重置std::string对象的全部内容并放入新行一样。

绝对不是最快的解决方案:

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

为我工作。

最新更新