我正在尝试将纹理应用于opengl程序,但是该程序由于某种原因而崩溃,有人可以告诉我我做错了什么吗?现在尝试修复此问题两天:/当片段着色器中的颜色设置为某种随机颜色,但当颜色为时: vec4 textColor = texture(u_Texture,v_TextCoord); color = textColor;
编辑:
#define GLEW_STATIC
#define alloca __builtin_alloca
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stb_image.h>
using namespace std;
static string ParseShader(const string& filepath);
static unsigned int CompileShader(unsigned int type, const string& source);
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader);
void glCheckError();
float vertex[] =
{
0.5f, 0.5f, 0.0f,
1.0f, 1.0f, // 0
0.5f, -0.5f, 0.0f,
1.0f, 0.0f, // 1
-0.5f, -0.5f, 0.0f,
0.0f, 0.0f, // 2
-0.5f, 0.5f, 0.0f,
0.0f, 1.0f // 3
};
float vertexBack[] =
{
-0.6, -0.6f, -0.5f, // 0
0.6f, -0.6f, -0.5f, // 1
0.6f, 0.6f, -0.5f, // 2
-0.6f, 0.6f, -0.5f // 3
};
unsigned int indexes[] =
{
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
{
cout << "GLFW failed to load!" << endl;
return -1;
}
else
cout << "GLFW loaded" << endl << endl;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(800, 600, "Window", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
cout << "Error loading GLEW" << endl;
else
cout << "GLEW loaded - version: " << glGetString(GL_VERSION) << endl;
unsigned int shader = CreateShader(ParseShader("shaders/vertex.shader"), ParseShader("shaders/fragment.shader"));
glUseProgram(shader);
// Make vertex position array
unsigned int buffers;
glGenBuffers(1, &buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
// Make vertex position indexes out of arrays
unsigned int ib;
glGenBuffers(1, &ib);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexes), indexes, GL_STATIC_DRAW);
// Position layout
unsigned int posAttrib = glGetAttribLocation(shader, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
// Texture layout
unsigned int texAttrib = glGetAttribLocation(shader, "texCoord");
glEnableVertexAttribArray(texAttrib);
glCheckError();
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(3 * sizeof(float)));
// Load image
int h, w, v_bpp;
unsigned char *image = stbi_load("texture.png", &w, &h, &v_bpp, 4);
if(image == nullptr)
cout << "failed to load image!" << endl;
unsigned int texture_id;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(image);
// Set slot
glActiveTexture(GL_TEXTURE0);
int location = glGetUniformLocation(shader, "u_Texture");
glUniform1i(location, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window) && glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS)
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glCheckError();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
static string ParseShader(const string& filepath) {
ifstream stream(filepath);
string line;
stringstream code;
while(getline(stream, line))
code << line << "\n";
return code.str();
}
static unsigned int CompileShader(unsigned int type, const string& source) {
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, NULL);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if(result == GL_FALSE)
{
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "Vertex" : "Fragment") << " shader!" << endl;
cout << message << endl;
glDeleteShader(id);
return 0;
}
return id;
}
static unsigned int CreateShader(const string& vertexShader, const string& fragmentShader) {
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
void glCheckError() {
GLenum err = glGetError();
while(err!=GL_NO_ERROR) {
string error;
switch(err) {
case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break;
case GL_INVALID_ENUM: error="INVALID_ENUM"; break;
case GL_INVALID_VALUE: error="INVALID_VALUE"; break;
case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break;
}
cerr << err << " (" << error.c_str() << ")" <<endl;
err=glGetError();
}
}
答案 0 :(得分:2)
您完全搞砸了顶点属性ponter的设置:
// Position layout unsigned int posAttrib = glGetAttribLocation(shader, "position"); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
首先,您查询名为position
的属性,但是您从未使用该索引,而是使用0
。
// Texture layout unsigned int texAttrib = glGetAttribLocation(shader, "texCoord"); glEnableVertexAttribArray(1); glCheckError(); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void*)(3 * sizeof(float)));
然后,您查询texCoord
,再次忽略它,启用属性数组1
,并覆盖属性0
的属性指针。
这意味着属性1
具有一些未定义的指针值,并且您具有未定义的行为。
最有可能发生的事情是,当您不使用纹理时,您很幸运,因为只有一个活动属性恰巧获得位置0。并且您的GL实现似乎忽略了非活动属性的属性数组,因此不会崩溃。同时启用两个属性时,它们将分别为0
和1
,并且没有办法不取消引用该无效指针。