OpenGL 着色器有时编译有时不编译
OpenGL Shaders sometimes compile and sometimes not
我正在学习 OpenGL,当我 运行 程序有时可以运行(三角形红色)有时不能运行(三角形白色但没有三角形)。我正在使用 makefile 使用 msvc(命令行中的cl.exe)编译它。
这是程序的简化版本,如果您也遇到同样的奇怪行为,请告诉我。
预期结果(运行 的 10%)
错误结果(运行 的 90%)
main.cpp
#define SDL_MAIN_HANDLED
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <GL/glew.h>
#include <SDL2/SDL.h>
//Loading the file, I suspect that the shaders sometimes are not loaded properly but I'm not sure.
std::string loadFile(const std::string filepath)
{
std::ifstream file(filepath.c_str());
if(!file.is_open())
{
std::cerr << "Error loading Shader" << std::endl;
std::exit(1);
}
std::string output = std::string((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());
return output;
}
//Just error checking (Probably I should include the shader validation here)
void checkProgramError(GLuint program)
{
GLint success = 0;
char infolog[1024] = {};
glGetProgramiv(program,GL_LINK_STATUS,&success);
if(!success)
{
glGetProgramInfoLog(program,1024,nullptr,infolog);
std::cerr << infolog << std::endl;
}
}
void checkShaderError(GLuint shader)
{
GLint success = 0;
char infolog[1024] = {};
glGetShaderiv(shader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(shader,1024,nullptr,infolog);
std::cerr << infolog << std::endl;
}
}
/*
In my folder:
|basicShader.vs
|basicShader.fs
|main.cpp
|makefile
*/
GLuint createProgram(std::string name)
{
const char* vertex_shader_source = loadFile(name + ".vs").c_str();
const char* fragment_shader_source = loadFile(name + ".fs").c_str();
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader,1,&vertex_shader_source,nullptr);
glCompileShader(vertex_shader);
checkShaderError(vertex_shader);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader,1,&fragment_shader_source,nullptr);
checkShaderError(fragment_shader);
GLuint program = glCreateProgram();
glAttachShader(program,vertex_shader);
glAttachShader(program,fragment_shader);
glLinkProgram(program);
checkProgramError(program);
glValidateProgram(program);
return program;
}
int main(int argc,char* argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,4);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32);
SDL_Window* window = SDL_CreateWindow("Ventana",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,600,600,SDL_WINDOW_OPENGL);
SDL_GL_CreateContext(window);
GLenum error = glewInit();
if(error != GLEW_OK){
printf("Error: Problemas al iniciar glew\n");
printf("Error: %s",glewGetErrorString(error));
}
float first_triangle[] = {
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
};
//Create and config mesh
GLuint VAO,VBO;
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(first_triangle),&first_triangle,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
//Load and enable shader
GLuint program = createProgram("basicShader");
glUseProgram(program);
for(bool running = true;running;)
{ SDL_Event event;
while(SDL_PollEvent(&event))
if(event.type == SDL_QUIT) running = false;
//Clear Screen
glClearColor(0.0,0.7,0.3,1.0);
glClear(GL_COLOR_BUFFER_BIT);
//Draw mesh
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
return 0;
}
basicShader.vs(顶点着色器)
#version 120
attribute vec3 aPos;
void main()
{
gl_Position = vec4(aPos,1.0);
}
basicShader.fs(片段着色器)
#version 120
void main()
{
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
makefile
LIBS=SDL2.lib SDL2main.lib opengl32.lib glu32.lib glew32.lib
CXX=cl
CFLAGS=/std:c++17 /EHsc /Zi
SOURCES=main.cpp
all :main.cpp
$(CXX) $(CFLAGS) $(SOURCES) /Fe:main.exe $(LIBS) /link /subsystem:console
main.exe
如果您安装了 BuildTools,您可以使用以下命令在您的终端中获得 cl.exe:
CMD: "C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
POWERSHELL: cmd.exe /k '"C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Auxiliary\Build\vcvars64.bat" & powershell'
您在此处调用未定义的行为:
const char* vertex_shader_source = loadFile(name + ".vs").c_str();
load_file()
returns std::string
存储在此处的临时文件中,并在表达式结束后立即销毁,留下一个指向现在使用的内存的悬空指针-销毁对象。
我正在学习 OpenGL,当我 运行 程序有时可以运行(三角形红色)有时不能运行(三角形白色但没有三角形)。我正在使用 makefile 使用 msvc(命令行中的cl.exe)编译它。 这是程序的简化版本,如果您也遇到同样的奇怪行为,请告诉我。
预期结果(运行 的 10%)
错误结果(运行 的 90%)
main.cpp
#define SDL_MAIN_HANDLED
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <GL/glew.h>
#include <SDL2/SDL.h>
//Loading the file, I suspect that the shaders sometimes are not loaded properly but I'm not sure.
std::string loadFile(const std::string filepath)
{
std::ifstream file(filepath.c_str());
if(!file.is_open())
{
std::cerr << "Error loading Shader" << std::endl;
std::exit(1);
}
std::string output = std::string((std::istreambuf_iterator<char>(file)),std::istreambuf_iterator<char>());
return output;
}
//Just error checking (Probably I should include the shader validation here)
void checkProgramError(GLuint program)
{
GLint success = 0;
char infolog[1024] = {};
glGetProgramiv(program,GL_LINK_STATUS,&success);
if(!success)
{
glGetProgramInfoLog(program,1024,nullptr,infolog);
std::cerr << infolog << std::endl;
}
}
void checkShaderError(GLuint shader)
{
GLint success = 0;
char infolog[1024] = {};
glGetShaderiv(shader,GL_COMPILE_STATUS,&success);
if(!success)
{
glGetShaderInfoLog(shader,1024,nullptr,infolog);
std::cerr << infolog << std::endl;
}
}
/*
In my folder:
|basicShader.vs
|basicShader.fs
|main.cpp
|makefile
*/
GLuint createProgram(std::string name)
{
const char* vertex_shader_source = loadFile(name + ".vs").c_str();
const char* fragment_shader_source = loadFile(name + ".fs").c_str();
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader,1,&vertex_shader_source,nullptr);
glCompileShader(vertex_shader);
checkShaderError(vertex_shader);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader,1,&fragment_shader_source,nullptr);
checkShaderError(fragment_shader);
GLuint program = glCreateProgram();
glAttachShader(program,vertex_shader);
glAttachShader(program,fragment_shader);
glLinkProgram(program);
checkProgramError(program);
glValidateProgram(program);
return program;
}
int main(int argc,char* argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,4);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE,32);
SDL_Window* window = SDL_CreateWindow("Ventana",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,600,600,SDL_WINDOW_OPENGL);
SDL_GL_CreateContext(window);
GLenum error = glewInit();
if(error != GLEW_OK){
printf("Error: Problemas al iniciar glew\n");
printf("Error: %s",glewGetErrorString(error));
}
float first_triangle[] = {
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
};
//Create and config mesh
GLuint VAO,VBO;
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(first_triangle),&first_triangle,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
//Load and enable shader
GLuint program = createProgram("basicShader");
glUseProgram(program);
for(bool running = true;running;)
{ SDL_Event event;
while(SDL_PollEvent(&event))
if(event.type == SDL_QUIT) running = false;
//Clear Screen
glClearColor(0.0,0.7,0.3,1.0);
glClear(GL_COLOR_BUFFER_BIT);
//Draw mesh
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES,0,3);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
}
return 0;
}
basicShader.vs(顶点着色器)
#version 120
attribute vec3 aPos;
void main()
{
gl_Position = vec4(aPos,1.0);
}
basicShader.fs(片段着色器)
#version 120
void main()
{
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
makefile
LIBS=SDL2.lib SDL2main.lib opengl32.lib glu32.lib glew32.lib
CXX=cl
CFLAGS=/std:c++17 /EHsc /Zi
SOURCES=main.cpp
all :main.cpp
$(CXX) $(CFLAGS) $(SOURCES) /Fe:main.exe $(LIBS) /link /subsystem:console
main.exe
如果您安装了 BuildTools,您可以使用以下命令在您的终端中获得 cl.exe:
CMD: "C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
POWERSHELL: cmd.exe /k '"C:\Program Files (x86)\Microsoft Visual Studio19\BuildTools\VC\Auxiliary\Build\vcvars64.bat" & powershell'
您在此处调用未定义的行为:
const char* vertex_shader_source = loadFile(name + ".vs").c_str();
load_file()
returns std::string
存储在此处的临时文件中,并在表达式结束后立即销毁,留下一个指向现在使用的内存的悬空指针-销毁对象。