gpt4 book ai didi

c++ - GLSL C++ glVertexAttribPointer & glDrawElements 返回 GL_INVALID_OPERATION

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:40:29 24 4
gpt4 key购买 nike

我在第 164 和 183 行收到错误 GL_INVALID_OPERATION,但我不知道如何修复它。

第 164 行:

GLCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));

第 183 行:

GLCall(glDrawElements(GL_TRIANGLES, 6 ,GL_UNSIGNED_INT, nullptr));

我正在使用带有 OpenGL 版本字符串的 Ubuntu 18.04:3.1 Mesa 18.3.0-devel - padoka PPA。顺便说一句,我想画一个立方体。

主要内容:

#include <GL/glew.h>   
#include <GLFW/glfw3.h>

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <sys/stat.h>

#define ASSERT(x) if (!(x)) std::cin.get();
#define GLCall(x) GLClearError();\
x;\
ASSERT(GLLogCall(#x, __FILE__, __LINE__))

static void GLClearError()
{
while(glGetError() != GL_NO_ERROR);
}

static bool GLLogCall(const char* function, const char* file, int line)
{
while(GLenum error = glGetError())
{
std::cout << "[OPENGL ERROR](" << error << ")" << function <<
" " << file << " line: " << line << std::endl;
return false;
}
return true;
}

struct ShaderProgramSource
{
std::string VertexSource;
std::string FragmentSource;
};

static ShaderProgramSource ParseShader(const std::string& filepath)
{
std::fstream stream (filepath);

enum 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 CompileShader(unsigned type, const std::string& source)
{
std::cout << "Compile Shader \n";

unsigned id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);

// TODO: ERROR handling

int result;

glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if(!result)
{
int lenght;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &lenght);
char* message = (char*)&source[0];
glGetShaderInfoLog(id, lenght, &lenght, message);
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " " << std::endl;
std::cout << message << std::endl;
return 0;
}

return id;
}

static unsigned CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned program = glCreateProgram();
unsigned vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);

glDeleteShader(vs);
glDeleteShader(fs);

return program;
}

int main(void)
{
GLFWwindow* window;

/* Initialize the library*/
if(!glfwInit())
return -1;


GLCall(glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4));
GLCall(glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3));
GLCall(glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE));
GLCall(glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE));

/* Create a windowed mode window and its OpenGl context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);

if(!window)
{
glfwTerminate();
return -1;
}


/* Make the window's context current */
GLCall(glfwMakeContextCurrent(window));

if(glewInit() != GLEW_OK) std::cout << "Error!" << std::endl;

std::cout << glGetString(GL_VERSION) << std::endl;


float positions[] = {
-0.5f, -0.5f, //0
0.5f, -0.5f, //1
0.5f, 0.5f, //2
-0.5f, 0.5f //3
};

unsigned indices[]
{
0, 1, 2,
2, 3, 0
};

unsigned 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 ibo; //index buffer Object
GLCall(glGenBuffers(1, &ibo));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned), indices, GL_STATIC_DRAW));

//TODO: Relative path
ShaderProgramSource source = ParseShader("Path"); //This path leads to Shaders

unsigned shader = CreateShader(source.VertexSource, source.FragmentSource);
GLCall(glUseProgram(shader));

/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
GLCall(glClear(GL_COLOR_BUFFER_BIT));

GLCall(glDrawElements(GL_TRIANGLES, 6 ,GL_UNSIGNED_INT, nullptr));

/* Swap front and back buffers */
GLCall(glfwSwapBuffers(window));

/* Poll for and process events */
GLCall(glfwPollEvents());
}

glfwTerminate();
return 0;
}

着色器:

#shader vertex
#version 330 core

layout(location = 0) in vec4 position;

void main()
{
gl_Position = position;
};

#shader fragment
#version 330 core

layout(location = 0) out vec4 color;

void main()
{
color = vec4(0.0, 1.0, 0.0, 1.0);
};

最佳答案

在拥有当前有效的 OpenGL context 之前,您不能调用任何 OpenGL 指令.
此外,glfwWindowHintglfwMakeContextCurrent 不是 OpenGL 指令。

所以 glError 通过宏 GLCall 检查,比如

GLCall(glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4));
....

GLCall(glfwMakeContextCurrent(window));

无效且没有任何意义。

第一次有效使用宏 GLCall 是在 glfwMakeContextCurrent(window) 之后。


由于您使用的是具有前向兼容性的核心配置文件上下文:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

你必须创建一个名为 Vertex Array Object 的绑定(bind).
请注意,在核心配置文件上下文中,默认顶点数组对象 (0) 无效。

在创建缓冲区对象和定义通用顶点属性数据数组之前,创建并绑定(bind)一个命名的顶点数组对象就足够了。该对象取代了兼容性配置文件中的默认顶点数组对象:

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

unsigned 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 ibo; //index buffer Object
GLCall(glGenBuffers(1, &ibo));
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo));
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned), indices, GL_STATIC_DRAW));

在初始化 GLEW 之前设置 glewExperimental = GL_TRUE

glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) std::cout << "Error!" << std::endl;

参见 GLEW documantation其中说:

GLEW obtains information on the supported extensions from the graphics driver. Experimental or pre-release drivers, however, might not report every available extension through the standard mechanism, in which case GLEW will report it unsupported. To circumvent this situation, the glewExperimental global switch can be turned on by setting it to GL_TRUE before calling glewInit(), which ensures that all extensions with valid entry points will be exposed.

关于c++ - GLSL C++ glVertexAttribPointer & glDrawElements 返回 GL_INVALID_OPERATION,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52027367/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com