Я использую кроссплатформенные библиотеки (glfw, glew, glm), чтобы создать простое приложение OpenGl Sample Program. Он просто берет изображение с моего компьютера, размером 512 x 512 PNG, и должен отобразить его на квадрате, который у меня отображается. Программа без наложения текстур прекрасно работает и квадрат виден. С отображением текстур ничего не видно, не могли бы вы помочь мне найти ошибку?
Редактировать: Возможно, я пропускаю привязку или что-то в моем цикле рисования до кадра?
Основная программа (внешне правильно определены LoadShaders и stbi_Image)
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
// Open a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow (640, 480, "Hello Triangle", NULL, NULL);
if(!window)
{
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" );
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = GL_TRUE; // Needed for core profile
GLenum err = glewInit();
if (err != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return -1;
}const GLubyte* renderer = glGetString (GL_RENDERER); // get renderer string
const GLubyte* version = glGetString (GL_VERSION); // version as a string
printf ("Renderer: %s\n", renderer);
printf ("OpenGL version supported %s\n", version);
// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable (GL_DEPTH_TEST); // enable depth-testing
glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer"
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window,GLFW_STICKY_KEYS,GL_TRUE );
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader",
"SimpleFragmentShader.fragmentshader" );
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <->
// 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model;unsigned char* image_data;
int x, y, n;
char* file_name;
file_name = "/home/syk435/Pictures/texture_sample.png";
int force_channels = 4;
image_data = stbi_load(file_name, &x, &y, &n, force_channels);
if (!image_data)
{
fprintf (stderr, "ERROR: could not load %s\n", file_name);
}
//check if not normal dims
if (x & (x - 1) != 0 || y & (y - 1) != 0)
{
fprintf (stderr, "WARNING: texture %s is not power-of-2 dimensions\n",
file_name);
}
//invert to norm
int width_in_bytes = x * 4;
unsigned char *top = NULL;
unsigned char *bottom = NULL;
unsigned char temp = 0;
int half_height = y / 2;
for (int row = 0; row < half_height; row++) {
top = image_data + row * width_in_bytes;
bottom = image_data + (y - row - 1) * width_in_bytes;
for (int col = 0; col < width_in_bytes; col++)
{
temp = *top;
*top = *bottom;
*bottom = temp;
top++;
bottom++;
}
}static const GLfloat g_vertex_buffer_data[] = {
-0.75f,-0.75f,0.0f,
-0.75f, 0.75f,0.0f,
0.75f,-0.75f,0.0f,
0.75f, 0.75f,0.0f,
-0.75f, 0.75f,0.0f,
0.75f,-0.75f,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);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//texture stuff
unsigned int tex = 0;
glGenTextures (1, &tex);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, tex);
GLuint TextureID = glGetUniformLocation(programID, "basic_texture");
glTexImage2D (
GL_TEXTURE_2D,
0,
GL_RGBA,
x,
y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image_data
);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
float texcoords[] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
1.0, 0.0
};
unsigned int vt_vbo;
glGenBuffers (1, &vt_vbo);
glBindBuffer (GL_ARRAY_BUFFER, vt_vbo);
int dimensions = 2; // 2d data for texture coords
int length = 6; // 6 vertices
glBufferData (
GL_ARRAY_BUFFER,
dimensions * length * sizeof (float),
texcoords,
GL_STATIC_DRAW
);
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
// Set our "myTextureSampler" sampler to user Texture Unit 0
glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);// note: this is your existing VAO
glEnableVertexAttribArray(1);
glBindBuffer (GL_ARRAY_BUFFER, vt_vbo);
// note: I assume that vertex positions are location 0
dimensions = 2; // 2d data for texture coords
glVertexAttribPointer (1, dimensions, GL_FLOAT, GL_FALSE, 0, NULL);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 6); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
glfwSwapBuffers(window);
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey( window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && window!=NULL );
// Close OpenGL window and terminate GLFW
glfwTerminate();
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &vt_vbo);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &vao);
return 0;
VertexShader:
#version 420
// Input vertex data, different for all executions of this shader.
layout (location = 0) in vec3 vertexPosition_modelspace;
layout (location = 1) in vec2 vt; // per-vertex texture co-ords
out vec2 texture_coordinates;
uniform mat4 MVP;
void main(){
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
texture_coordinates = vt;
}
FragmentShader:
#version 420
// Ouput data
//texture stuff
in vec2 texture_coordinates;
uniform sampler2D basic_texture;
out vec3 frag_colour;
void main()
{
frag_colour = texture2D(basic_texture, texture_coordinates).rgb;
}
Для тех, кто не хочет искать комментарии …
Либо удалите эти 2 строки (т.е. не включайте проверку глубины).
glEnable (GL_DEPTH_TEST); // enable depth-testing
glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer"
Или с включенным буфером глубины, очистите буфер глубины в начале цикла do while
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
(Ответ в комментарии под вопросом от Andon Coleman. Пока я читаю Учебники Антона по OpenGL 4 Я думал, что немного потренируюсь и посмотрю, смогу ли я заставить работать код. Выполнение любого из вышеперечисленных отображает текстуру.)
Других решений пока нет …