遇到两个问题:
(1)如果geometry shader 文件不加上#version 450 core,compile shader source会报错;
(2)使用GLFW创建窗口时,不添加glewExperimental = GL_TRUE,使用glGenVertexArrays(1, &vao),直接崩溃
(3)创建GL_GEOMETRY_SHADER,找不到该变量,更新glew包到1.3版本即可
(4)使用glew 1.3版本和glut创建应用程序无法启动,使用glfw库来替代,原来的glut过于老了。
源代码如下:
basic.vert (vertex shader)
#version 450 core
in vec2 pos;
void main()
{
gl_Position = vec4(pos, 0.0, 1.0);
}
basic.geom(geometry shader)
#version 450 core
in vec2 pos;
void main()
{
gl_Position = vec4(pos, 0.0, 1.0);
}
basic.frag(fragment shader)
#version 450 core
out vec4 outColor;
void main()
{
outColor = vec4(1.0, 0.0, 0.0, 1.0);
}
class FileManager
{
public:
FileManager();
~FileManager();
public:
unsigned char* readDataFromFile(char* fn);
char* textFileRead(const char* fn);
int textFileWrite(char* fn, char* s);
};
#include "stdafx.h" #include "FileManager.h" #include <iostream> FileManager::FileManager() { } FileManager::~FileManager() { } unsigned char* FileManager::readDataFromFile(char* fn) { FILE *fp; unsigned char *content = NULL; int count = 0; if (fn != NULL) { fopen_s(&fp, fn, "rb"); if (fp != NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); if (count > 0) { content = (unsigned char *)malloc(sizeof(unsigned char) * (count + 1)); count = fread(content, sizeof(unsigned char), count, fp); content[count] = '\0'; } fclose(fp); } } return content; } char* FileManager::textFileRead(const char* fn) { FILE *fp; char *content = NULL; int count = 0; if (fn != NULL) { fopen_s(&fp, fn, "rt"); if (fp != NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); if (count > 0) { content = (char *)malloc(sizeof(char) * (count + 1)); count = fread(content, sizeof(char), count, fp); content[count] = '\0'; } fclose(fp); } } return content; } int FileManager::textFileWrite(char* fn, char* s) { FILE *fp; int status = 0; if (fn != NULL) { fopen_s(&fp, fn, "w"); if (fp != NULL) { if (fwrite(s, sizeof(char), strlen(s), fp) == strlen(s)) status = 1; fclose(fp); } } return(status); }
shader管理类ShaderManager.h/.cpp
程序入口main.cpp#include <iostream> #include "FileManager.h" #include <gl/glew.h> #include <gl/GL.h> using namespace std; class ShaderManager { public: ShaderManager(); ~ShaderManager(); public: void BuildShader(const char* VShaderFile, const char* GShaderFile, const char* FShaderFile); GLuint GetProgram(); void ShowShaderInfo(); public: GLuint m_vShader; GLuint m_fShader; GLuint m_gShader; GLuint m_Program; public: FileManager m_FileManager; }; #include "stdafx.h" #include "ShaderManager.h" ShaderManager::ShaderManager() { } ShaderManager::~ShaderManager() { } void ShaderManager::ShowShaderInfo() { const GLubyte *renderer = glGetString(GL_RENDERER); const GLubyte *vendor = glGetString(GL_VENDOR); const GLubyte *version = glGetString(GL_VERSION); const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION); GLint major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); cout << "GL Vendor :" << vendor << endl; cout << "GL Renderer : " << renderer << endl; cout << "GL Version (string) : " << version << endl; cout << "GL Version (integer) : " << major << "." << minor << endl; cout << "GLSL Version : " << glslVersion << endl; } void ShaderManager::BuildShader(const char* VShaderFile, const char* GShaderFile, const char* FShaderFile) { ShowShaderInfo(); m_vShader = glCreateShader(GL_VERTEX_SHADER); if (m_vShader == 0) { cerr << "Error: Create vertex shader failed!" << endl; return; } const GLchar* vShaderSource = m_FileManager.textFileRead(VShaderFile); const GLchar* vCodeArray[1] = {vShaderSource}; glShaderSource(m_vShader, 1, vCodeArray, NULL); glCompileShader(m_vShader); GLint compileResult; glGetShaderiv(m_vShader, GL_COMPILE_STATUS, &compileResult); if (compileResult == GL_FALSE) { cerr << "Error: Compile vertex shader failed!" << endl; return; } m_gShader = glCreateShader(GL_GEOMETRY_SHADER); if (0 == m_gShader) { cerr << "ERROR: Create geometry failed!" << endl; return; } const GLchar* gShaderCode = m_FileManager.textFileRead(GShaderFile); const GLchar* gCodeArray[1] = { gShaderCode }; glShaderSource(m_gShader, 1, gCodeArray, NULL); glCompileShader(m_gShader); glGetShaderiv(m_gShader, GL_COMPILE_STATUS, &compileResult); if (compileResult == GL_FALSE) { cerr << "ERROR: compile geometry failed!" << endl; GLint logLen; glGetShaderiv(m_gShader, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char *log = (char *)malloc(logLen); GLsizei written; glGetShaderInfoLog(m_gShader, logLen, &written, log); cerr << "vertex shader compile log : " << endl; cerr << log << endl; free(log); } return; } m_fShader = glCreateShader(GL_FRAGMENT_SHADER); if (0 == m_fShader) { cerr << "ERROR: Create fragment shader failed!" << endl; return; } const GLchar* fShaderCode = m_FileManager.textFileRead(FShaderFile); const GLchar* fCodeArray[1] = { fShaderCode }; glShaderSource(m_fShader, 1, fCodeArray, NULL); glCompileShader(m_fShader); glGetShaderiv(m_fShader, GL_COMPILE_STATUS, &compileResult); if (compileResult == GL_FALSE) { cerr << "Error: Compile fragment shader failed!" << endl; return; } m_Program = glCreateProgram(); if (0 == m_Program) { cerr << "ERROR: Create Program failed!" << endl; return; } glAttachShader(m_Program, m_vShader); glAttachShader(m_Program, m_gShader); glAttachShader(m_Program, m_fShader); glLinkProgram(m_Program); GLint linkStatus; glGetProgramiv(m_Program, GL_LINK_STATUS, &linkStatus); if (GL_FALSE == linkStatus) { cerr << "ERROR: Link the program failed!" << endl; return; } glUseProgram(m_Program); } GLuint ShaderManager::GetProgram() { return m_Program; }
// testOpenGL.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #define GLEW_STATIC #include "glew.h" #include "glfw3.h" #include "ShaderManager.h" const GLuint WIDTH = 800; const GLuint HEIGHT = 600; ShaderManager shaderManager; void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { std::cout << key << std::endl; if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { glfwSetWindowShouldClose(window, GL_TRUE); } } void initData() { // GLuint vbo; glGenBuffers(1, &vbo); float points[] = { -0.45f, 0.45f, 0.45f, 0.45f, 0.45f, -0.45f, -0.45f, -0.45f, }; glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW); GLuint vao = 0; glGenVertexArrays(1, &vao); glBindVertexArray(vao); GLint posAttrib = glGetAttribLocation(shaderManager.GetProgram(), "pos"); glEnableVertexAttribArray(posAttrib); glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); } int _tmain(int argc, _TCHAR* argv[]) { std::cout << "Starting GFLEW context, OpenGL 3.3" << std::endl; glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Test GLFW Lib", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window!" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetKeyCallback(window, key_callback); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } glViewport(0, 0, WIDTH, HEIGHT); // 创建shader对象 shaderManager.BuildShader("basic.vert", "basic.geom", "basic.frag"); initData(); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_POINTS, 0, 4); glfwSwapBuffers(window); } glfwTerminate(); return 0; }