$subj. glGetProgramiv() после glLinkProgram() возращает GL_FALSE, при этом лог, полученный glGetProgramInfoLog(), пустой (и логи даже после успешной компиляции шейдеров тоже - нет даже warning-ов).
thetailgunner@aileron:~$ glxinfo | grep -i version
server glx version string: 1.4
client glx version string: 1.4
GLX version: 1.4
OpenGL core profile version string: 3.3 (Core Profile) Mesa 10.3.2
OpenGL core profile shading language version string: 3.30
OpenGL version string: 3.0 Mesa 10.3.2
OpenGL shading language version string: 1.30
OpenGL ES profile version string: OpenGL ES 3.0 Mesa 10.3.2
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.0
#include <GL/gl3w.h>
#include <GL/glu.h>
#include <glm/glm.hpp>
#include <GLFW/glfw3.h>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <iostream>
#include <stdexcept>
#include <vector>
static const GLfloat globVertexBufferData[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
void getShaderCompileLog(GLuint sId, std::string& outLogStr) {
GLint logLen;
glGetShaderiv(sId, GL_INFO_LOG_LENGTH, &logLen);
outLogStr.resize((unsigned long)logLen);
glGetShaderInfoLog(sId, logLen, &logLen, &outLogStr[0]);
}
void getProgramCompileLog(GLuint pId, std::string& outLog) {
GLint logLen;
glGetProgramiv(pId, GL_INFO_LOG_LENGTH, &logLen);
outLog.resize((unsigned long)logLen);
glGetProgramInfoLog(pId, logLen, &logLen, &outLog[0]);
}
bool shaderCompiled(GLuint id) {
GLint status;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (GL_FALSE == status)
return false;
return true;
}
bool programCompiled(GLuint pId) {
GLint status;
glGetProgramiv(pId, GL_COMPILE_STATUS, &status);
if (GL_FALSE == status)
return false;
return true;
}
GLuint prepareShaders() {
const GLchar* const vertexShaderStr = "#version 330 \n"
"layout(location = 0) in vec3 vertexPos;\n"
"void main() {\n"
"gl_Position.xyz = vertexPos;\n"
"gl_Position.w = 1.0;\n"
"}";
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderId, 1, &vertexShaderStr, nullptr);
glCompileShader(vertexShaderId);
if (!shaderCompiled(vertexShaderId)) {
std::string log;
getShaderCompileLog(vertexShaderId, log);
std::cerr << log;
throw std::runtime_error("unable to compile shader");
}
const GLchar* const fragmentShaderStr = "#version 330 \n"
"precisison mediump float;\n"
"out vec3 color;\n"
"void main() { color = vec3(0, 0, 1); }";
GLuint frShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frShaderId, 1, &fragmentShaderStr, nullptr);
glCompileShader(frShaderId);
if (!shaderCompiled(frShaderId)) {
std::string log;
getShaderCompileLog(frShaderId, log);
std::cerr << log;
throw std::runtime_error("unable to compile shader");
}
GLuint pId = glCreateProgram();
glAttachShader(pId, vertexShaderId);
glAttachShader(pId, frShaderId);
glLinkProgram(pId);
if (!programCompiled(pId)) {
std::string log;
getProgramCompileLog(pId, log);
std::cerr << &log[0];
throw std::runtime_error("unable to compile program");
}
glDeleteShader(vertexShaderId);
glDeleteShader(frShaderId);
return pId;
}
void resizeCallback(GLFWwindow*, int w, int h) {
glViewport(0, 0, w, h);
}
int main() {
if(!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
glfwDefaultWindowHints();
GLFWwindow* window = glfwCreateWindow(300, 300, "Test",
nullptr, nullptr);
if(window == nullptr) {
std::cerr << "Failed to open GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (gl3wInit()) {
return -1;
}
glfwSwapInterval(1);
glfwSetWindowSizeCallback(window, resizeCallback);
glfwShowWindow(window);
glEnable(GL_DOUBLEBUFFER);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(0, 0, 0, 1);
GLuint pId;
try {
pId = prepareShaders();
} catch (...) {
glfwDestroyWindow(window);
glfwTerminate();
return -1;
}
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(globVertexBufferData), globVertexBufferData, GL_STATIC_DRAW);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (glfwWindowShouldClose(window) != GL_FALSE) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pId);
glBindVertexArray(0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0 ,3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}