各位程序员大家好。
我对我的 opengl 项目中的这个概念感到非常困惑。 我在编译中收到以下错误:
[Error]: failed to compile vertex shader.
[Log]: 0:1(1): error: syntax error, unexpected end of file
[Error]: failed to compile fragment shader.
[Log]: 0:1(1): error: syntax error, unexpected end of file
我有一个 main.cpp 一个 util/debug.hpp 和 util/debug.cpp 用于调试目的以及 res/shaders/basic.shader
main.cpp:
#include <GLFW/glfw3.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include "util/debug.hpp"
struct ShaderProgramSource
{
std::string vertex_source;
std::string fragment_source;
};
static ShaderProgramSource parse_shader(const std::string& filepath)
{
std::ifstream stream(filepath);
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line))
{
if (line.find("#shader") != std::string::npos)
{
if (line.find("vertex") != std::string::npos)
type = ShaderType::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = ShaderType::FRAGMENT;
}
else
{
ss[(int)type] << line << '\n';
}
}
return { ss[0].str(), ss[1].str() };
}
static unsigned int compile_shader(unsigned int type, const std::string& source)
{
GLCall(unsigned int id = glCreateShader(type));
const char *src = source.c_str();
GLCall(glShaderSource(id, 1, &src, nullptr));
GLCall(glCompileShader(id));
int result;
GLCall(glGetShaderiv(id, GL_COMPILE_STATUS, &result));
if (result == GL_FALSE)
{
int length;
GLCall(glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length));
char* message = (char*)alloca(length * sizeof(char));
GLCall(glGetShaderInfoLog(id, length, &length, message));
util::error(std::string("failed to compile ") + (type == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader.");
util::log(message);
GLCall(glDeleteShader(id));
return 0;
}
return id;
}
static unsigned int create_shader(const std::string& vertex_shader, const std::string& fragment_shader)
{
GLCall(unsigned int program = glCreateProgram());
unsigned int vs = compile_shader(GL_VERTEX_SHADER, vertex_shader);
unsigned int fs = compile_shader(GL_FRAGMENT_SHADER, fragment_shader);
GLCall(glAttachShader(program, vs));
GLCall(glAttachShader(program, fs));
GLCall(glLinkProgram(program));
GLCall(glValidateProgram(program));
GLCall(glDeleteShader(vs));
GLCall(glDeleteShader(fs));
return program;
}
int main(void)
{
GLFWwindow* window;
if (!glfwInit())
util::error_exit("failed to initialize glfw.", -1);
window = glfwCreateWindow(640, 480, "Simple Window", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
if (glewInit() != GLEW_OK)
util::error_exit("failed to initialize glew.", -1);
std::cout << "[OpenGL Information]" << std::endl;
util::info("Version: " + std::string((const char*)glGetString(GL_VERSION)));
util::info("Renderer: " + std::string((const char*)glGetString(GL_RENDERER)));
util::info("Vendor: " + std::string((const char*)glGetString(GL_VENDOR)));
float positions[] = {
-0.5f, -0.5f, // 0
0.5f, -0.5f, // 1
0.5f, 0.5f, // 2
-0.5f, 0.5f // 3
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int buffer;
GLCall(glGenBuffers(1, &buffer));
GLCall(glBindBuffer(GL_ARRAY_BUFFER, buffer));
GLCall(glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), positions, GL_STATIC_DRAW));
GLCall(glEnableVertexAttribArray(0));
GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));
unsigned int ibo;
GLCall(glGenBuffers(1, &ibo));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW));
ShaderProgramSource source = parse_shader("res/shaders/basic.shader");
unsigned int shader = create_shader(source.vertex_source, source.fragment_source);
GLCall(glUseProgram(shader));
GLCall(int location = glGetUniformLocation(shader, "u_Color"));
ASSERT(location != -1);
GLCall(glUniform4f(location, 0.2f, 0.3f, 0.8f, 1.0f));
float r = 0.0f;
float increment = 0.05f;
while (!glfwWindowShouldClose(window))
{
/* Render */
GLCall(glClear(GL_COLOR_BUFFER_BIT));
GLCall(glUniform4f(location, r, 0.3f, 0.8f, 1.0f));
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));
if (r > 1.0f)
increment = -0.05f;
if (r < 0.0f)
increment = 0.05f;
r += increment;
glfwSwapBuffers(window);
glfwPollEvents();
}
GLCall(glDeleteProgram(shader));
glfwTerminate();
return 0;
}
util/debug.hpp:
#pragma once
#include <iostream>
#ifdef _WIN32
#include <intrin.h>
#define DEBUGBREAK() __debugbreak()
#else
#include <csignal>
#define DEBUGBREAK() raise(SIGTRAP)
#endif
#define ASSERT(x) if (!(x)) { DEBUGBREAK(); }
#define GLCall(x) util::GLClearError();\
x;\
ASSERT(util::GLLogCall(#x, __FILE__, __LINE__))
namespace util {
void log(const std::string& msg);
void warn(const std::string& msg);
void info(const std::string& msg);
void error(const std::string& msg);
int error_exit(const std::string& msg, int err_code) ;
void GLClearError();
bool GLLogCall(const char* function, const char* file, int line);
}
util/debug.cpp:
#include "debug.hpp"
#include <GL/glew.h>
namespace util
{
void log(const std::string& msg) { std::cout << "[Log]: " << msg << std::endl; }
void warn(const std::string& msg) { std::cout << "[Warn]: " << msg << std::endl; }
void info(const std::string& msg) { std::cout << "[Info]: " << msg << std::endl; }
void error(const std::string& msg) { std::cout << "[Error]: " << msg << std::endl; }
int error_exit(const std::string& msg, int err_code)
{
error(msg);
return err_code;
}
void GLClearError()
{
while (glGetError() != GL_NO_ERROR);
}
bool GLLogCall(const char* function, const char* file, int line)
{
while (GLenum error = glGetError())
{
std::cout << "[OpenGL Error]: " << error << std::endl;
std::cout << "[Function]: " << function << std::endl;
std::cout << "[File]: " << file << std::endl;
std::cout << "[Line]: " << line << std::endl;
return false;
}
return true;
}
}
res/shaders/basic.shader:
#shader vertex
#version 460 compatibility
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
#shader fragment
#version 460 compatibility
layout(location = 0) out vec4 color;
uniform vec4 u_Color;
void main()
{
color = u_Color;
}
我不知道我的着色器代码有什么问题,它看起来很好,实际上,当我将程序切换到 CLion - JetBrains IDE 时,我就遇到了这些错误。 我来自 vscode,当我使用 make 时它可以工作,并且着色器代码看起来很好。
为了好奇,这里是 makefile,文件结构在我的 vscode 项目中有点不同,但我可以保证我当前正在编译的代码正在读取正确的路径。
生成文件:
CXX = g++
CXFLAGS = -Iinc/ -lglfw -lGLEW -lGL -ldl
SRC = $(wildcard src/*.cpp) $(wildcard src/*/*.cpp)
OBJ = $(SRC:.cpp=.o)
BIN = bin
EXEC = $(BIN)/main
all: $(EXEC)
$(EXEC): $(OBJ)
@mkdir -p $(BIN)
$(CXX) $^ -o $@ $(CXFLAGS)
%.o: %.cpp
$(CXX) -c $< -o $@ $(CXFLAGS)
run: $(EXEC)
@./$(EXEC)
clean:
@rm -rf $(BIN)
旧项目的完整输出(程序有效):
ralph@wolf:~/Desktop/Dev/C++/Backup$ make
g++ src/main.o src/util/debug.o -o bin/main -Iinc/ -lglfw -lGLEW -lGL -ldl
ralph@wolf:~/Desktop/Dev/C++/Backup$ make run
[OpenGL Information]
[Info]: Version: 4.6 (Compatibility Profile) Mesa 23.2.1-1ubuntu3.1~22.04.2
[Info]: Renderer: Mesa Intel(R) UHD Graphics 630 (CML GT2)
[Info]: Vendor: Intel
ralph@wolf:~/Desktop/Dev/C++/Backup$
JetBrains CMake 的新输出 - Ninja(不起作用):
/home/ralph/Desktop/Dev/C++/OpenGL/cmake-build-debug/OpenGL
[OpenGL Information]
[Info]: Version: 4.6 (Compatibility Profile) Mesa 23.2.1-1ubuntu3.1~22.04.2
[Info]: Renderer: Mesa Intel(R) UHD Graphics 630 (CML GT2)
[Info]: Vendor: Intel
[Error]: failed to compile vertex shader.
[Log]: 0:1(1): error: syntax error, unexpected end of file
[Error]: failed to compile fragment shader.
[Log]: 0:1(1): error: syntax error, unexpected end of file
[OpenGL Error]: 1281
[Function]: glAttachShader(program, vs)
[File]: /home/ralph/Desktop/Dev/C++/OpenGL/main.cpp
[Line]: 82
Process finished with exit code 133 (interrupted by signal 5:SIGTRAP)
1281 opengl 错误表示空数据或错误数据作为函数参数传递给 GlAttachShader 程序。
您是否在 CMakeList.txt 中包含着色器文件? add_executable(MyOpenGLProject main.cpp 着色器.cpp)