я имел glCreateProgram()
ошибка возврата 1282 раньше, но исправил это после удаления контекста glfwWindowsHint
звонки. Но даже после этого на экране ничего не появляется! Вот мой код шейдера:
Shader.h
#pragma once
#include <iostream>
#include "file_utils.h"#include "GL/glew.h"
class Shader {
private:
GLuint shaderID;
const char *vertPath;
const char *fragPath;
public:
Shader(const char *vertexPath, const char *fragmentPath);
~Shader();
void enable() const;
void disable() const;
private:
GLuint load();
};
Shader.cpp
#include "shader.h"
Shader::Shader(const char *vertexPath, const char *fragmentPath)
{
vertPath = vertexPath;
fragPath = fragmentPath;
shaderID = load();
}
Shader::~Shader()
{
glDeleteProgram(shaderID);
}GLuint Shader::load()
{
GLuint program = glCreateProgram();
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);std::string g_vert = FileUtils::readFile(vertPath);
std::string g_frag = FileUtils::readFile(fragPath);
const char *vertSource = g_vert.c_str();
const char *fragSource = g_frag.c_str();glShaderSource(vertex, 1, &vertSource, NULL);
glCompileShader(vertex);GLchar infoL[1024];
GLint result;
glGetShaderiv(vertex, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
glGetShaderInfoLog(vertex, sizeof(infoL), 0, infoL);
std::cout << "ERROR COMPLING VERTEX SHADER: " << infoL << std::endl;
glDeleteShader(vertex);
return 0;
}
glShaderSource(fragment, 1, &fragSource, NULL);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
glGetShaderInfoLog(fragment, sizeof(infoL), 0, infoL);
std::cout << "ERROR COMPLING FRAGMENT SHADER: " << infoL << std::endl;
glDeleteShader(fragment);
return 0;
}
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vertex);
glDeleteShader(fragment);
return program;
}void Shader::enable() const
{
glUseProgram(shaderID);
}
void Shader::disable() const
{
glUseProgram(0);
}
vertex.glsl
#version 330 corelayout (location = 0) in vec4 position;uniform mat4 pr_matrix;
uniform mat4 vw_matrix = mat4(1.0);
uniform mat4 ml_matrix = mat4(1.0);void main()
{
gl_Position = position;
}
fragment.glsl
#version 330 corelayout (location = 0) out vec4 color;void main()
{
color = vec4(1.0, 0.0, 1.0, 1.0);
}
И, наконец, вот главное:
#include <iostream>
#include "WindowCreation.h"#include "Maths.h"#include "shader.h"const int SCREEN_WIDTH = 800, SCREEN_HEIGHT = 600;int main(){
WindowCreation *mainWindow = new WindowCreation();if (mainWindow->createWindow(&SCREEN_WIDTH, &SCREEN_HEIGHT, "GoldSpark Engine") == 0)
{
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
}
else
{
cout << "Could not create window. EXITING..." << endl;
return 1;
}GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);Shader shaders("resources/shaders/vertex.glsl", "resources/shaders/fragment.glsl");
shaders.enable();while(!mainWindow->getShouldClose())
{
mainWindow->clear();glDrawArrays(GL_TRIANGLES, 0, 6);mainWindow->update();}
shaders.disable();
glBindBuffer(GL_ARRAY_BUFFER, 0);
delete mainWindow;
return 0;
}
WindowCreation.h
#pragma once
#include <iostream>
#include "GL/glew.h"#include "GLFW/glfw3.h"
using namespace std;
class WindowCreation
{
public:
int bufferWidth, bufferHeight;
WindowCreation();
~WindowCreation();
bool getShouldClose() { return glfwWindowShouldClose(window); }
void createCallBacks();GLfloat getXChange() {
GLfloat xCh = xChange;
xChange = 0.0f;
return xCh;
}
GLfloat getYChange() {
GLfloat yCh = yChange;
yChange = 0.0f;
return yCh;
}
bool *getKeyPress() { return keys; }
void update() {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
}
void clear() {
glfwSwapBuffers(window);
}
int createWindow(const int *screenWidth, const int *screenHeight, const char* title); // ovdje pravimo sve sto treba da se prozor pojavi
GLFWwindow *getWindow() { return window; }
private:
GLFWwindow *window;
bool firstTime;
bool keys[1024];
GLfloat lastX, lastY, xChange, yChange;
static void handleKeyboard(GLFWwindow* window, int key, int code, int action, int mode);
static void handleMouse(GLFWwindow* window, double xPos, double yPos);};
WindowCreation.cpp
#include "WindowCreation.h"WindowCreation::WindowCreation()
{
//sve na 0 postavimo prvo
for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}xChange = 0.0f;
yChange = 0.0f;
firstTime = true;
}
void WindowCreation::createCallBacks()
{
glfwSetKeyCallback(getWindow(), handleKeyboard);
glfwSetCursorPosCallback(getWindow(), handleMouse);
}
void WindowCreation::handleKeyboard(GLFWwindow* window, int key, int code, int action, int mode)
{WindowCreation *thisWindow = static_cast<WindowCreation*>(glfwGetWindowUserPointer(window));
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(thisWindow->window, GLFW_TRUE);
}
if (key >= 0 && key <= 1024)
{
if (action == GLFW_PRESS)
{
thisWindow->keys[key] = true;
}
else if (action == GLFW_RELEASE)
{
thisWindow->keys[key] = false;
}}}void WindowCreation::handleMouse(GLFWwindow* window, double xPos, double yPos)
{
WindowCreation *thisWindow = static_cast<WindowCreation*>(glfwGetWindowUserPointer(window));
if (thisWindow->firstTime)
{
thisWindow->lastX = xPos;
thisWindow->lastY = yPos;
thisWindow->firstTime = false;
}thisWindow->xChange = xPos - thisWindow->lastX;
thisWindow->yChange = thisWindow->lastY - yPos;
thisWindow->lastX = xPos;
thisWindow->lastY = yPos;
}
int WindowCreation::createWindow(const int *screenWidth,const int *screenHeight, const char* title)
{
bufferWidth = 0;
bufferHeight = 0;if (!glfwInit()) // inicijalizujemo glfw
{
cout << "Could not initialize glfw." << endl;
glfwTerminate();
return 1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);window = glfwCreateWindow(*screenWidth, *screenHeight, title, NULL, NULL);
glfwGetFramebufferSize(window, &bufferWidth, &bufferHeight);
if (!window)
{
cout << "Window could not be created." << endl;
system("pause");
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK)
{
cout << "Could not initialize GLEW";
system("pause");
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
glewExperimental = true;glViewport(0, 0, bufferWidth, bufferHeight);glfwSetWindowUserPointer(window, this);
createCallBacks();return 0;
}WindowCreation::~WindowCreation()
{
glfwDestroyWindow(window);
glfwTerminate();for (size_t i = 0; i < 1024; i++)
{
keys[i] = 0;
}
window = nullptr;
xChange = 0.0f;
yChange = 0.0f;
lastX = 0.0f;
lastY = 0.0f;
}
Понятия не имею, что я тут не так сделал. Это очень просто, как вы можете видеть, и шейдерный код должен быть запущен. Я проверил строки загрузчиков файлов, которые он возвращает, и это правильно, как в тех .GLSL файлы.
В функции mainWindow->update()
является glfwSwapBuffers(window)
и в функции mainWindow->clear()
в порядке: glClear(GL_COLOR_BUFFER_BIT);
glfwPollEvents();
Также эти информационные журналы ничего не возвращают. Окно действительно появляется, но все синее, в середине нет квадрата.
Обновление: теперь вы предоставили код WindowCreation, проверьте ваш метод WindowCreation-> update, где вы вызываете glClear, удалите вызов glClear, и вы увидите ваш визуализированный прямоугольник.
Как отмечалось в комментариях, вы не предоставили весь код, необходимый для создания окна, и, как ответил Робтблок, вы не создали массив вершин, ниже приведена рабочая смесь вашего основного кода с учебным кодом для создания окна и рендеринга треугольников из http://www.opengl-tutorial.org/beginners-tutorials/tutorial-1-opening-a-window/ который успешно отображает квадрат и использует ваш класс Shader, после изменения, чтобы обойти отсутствующий код File_Utils. Скомпилировано и проверено в Visual Studio 2017 для Windows 10.
#include "shader.h"#include "GL/glew.h"#include "GLFW/glfw3.h"
GLFWwindow* window;
int main(void)
{
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow(1024, 768, "Tutorial 02 - Purple Square", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
Shader shader("vertex.glsl", "fragment.glsl");static const GLfloat g_vertex_buffer_data[] = {
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
do {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT);
// Use our shader
//glUseProgram(programID);
shader.enable();
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the square !
glDrawArrays(GL_TRIANGLES, 0, 6); //
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
shader.disable();
shader.~Shader();
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}
Ну, видимо, все время у меня были неправильные индексы вершин. Ницца!
Это даже не показывало использование старого рисунка opengl, который был glBegin()
так далее… glClearColor
показывал цвет, но треугольник не рисовал только потому, что я поставил минус на вершине, которая должна была быть ВВЕРХ.
Пока вы настраиваете программу для использования (судя по всему), вы не устанавливаете какие-либо унифицированные матричные параметры в программе. Вершинный шейдер не может преобразовать ваши вершины в результате.
Как уже упоминалось, всегда проверяйте ошибки GL вашей программы (или включайте профиль отладки, и используйте более новую версию). API отладки). Как минимум, у вас должно быть что-то вроде этого:
void printError(int err, const char* str, const char* file, const int line)
{
std::cout << "gl_error: " << str << ": " << file << "." << line << " > ";
switch(err)
{
case GL_INVALID_ENUM: std::cout << "GL_INVALID_ENUM" << std::endl;
case GL_INVALID_VALUE: std::cout << "GL_INVALID_VALUE" << std::endl;
case GL_INVALID_OPERATION: std::cout << "GL_INVALID_OPERATION" << std::endl;
case GL_INVALID_FRAMEBUFFER_OPERATION: std::cout << "GL_INVALID_FRAMEBUFFER_OPERATION" << std::endl;
case GL_OUT_OF_MEMORY: std::cout << "GL_OUT_OF_MEMORY" << std::endl;
case GL_STACK_UNDERFLOW: std::cout << "GL_STACK_UNDERFLOW" << std::endl;
case GL_STACK_OVERFLOW: std::cout << "GL_STACK_OVERFLOW" << std::endl;
default: break;
}
}
#define CHECK_GL(X) X; { \
int __err = glGetError(); \
if(__err != GL_NO_ERROR) printError(__err, #X, __FILE__, __LINE__); \
}
Что вы можете использовать в своих вызовах GL следующим образом:
CHECK_GL(glDeleteProgram(1, &prog));