当前位置: 动力学知识库 > 问答 > 编程问答 >

OpenGL 3.3 no texture gets rendered (black texture, C++, GLFW/SOIL)

问题描述:

I'm currently learning OpenGL 3.3 using C++ and GLFW (and SOIL for loading image files to create textures). I've implemented a batch rendering system that takes vertex information, maps the VBO data to a buffer variable, writes submitted vertex information to that buffer every frame and renders said frame.

The renderer.cpp looks like this: http://pastebin.com/N6nWdew6 while the VertexData struct is defined in the renderer.hpp as:

struct VertexData {

VertexData()

: vertex(glm::vec3(0.0f, 0.0f, 0.0f)),

color(glm::vec4(0.0f, 0.0f, 0.0f, 0.0f)),

texCoord(glm::vec2(0.0f, 0.0f)),

tid(0) {};

VertexData(glm::vec3 vertex, glm::vec4 color, glm::vec2 texCoord, GLuint tid)

: vertex(vertex),

color(color),

texCoord(texCoord),

tid(tid) {};

~VertexData() {};

glm::vec3 vertex;

glm::vec4 color;

glm::vec2 texCoord;

GLuint tid;

};

Now, submitting and rendering actual vertices, color information, texture coordinates etc. seems to work, but the texture still doesn't get rendered, all I get is a black square. The most important bits of the actual submission in the main loop look like this (warning: looks bad, just for testing purposes; I tried to shorten it the best I could):

[...]

/*Static variables in the window class, just for testing purposes*/

Shader* Window::_exampleShader = nullptr;

Texture* Window::_exampleTexture = nullptr;

Renderer::VertexData Window::vA;

Renderer::VertexData Window::vB;

Renderer::VertexData Window::vC;

Renderer::VertexData Window::vD;

[...]

/*Initialization in the window constructor*/

_exampleShader = new Shader("../src/glsl/basicVertex.glsl", "../src/glsl/basicFragment.glsl");

_exampleTexture = new Texture("../res/test.png");

/*TOP LEFT*/

vA.vertex = glm::vec3(-0.5f, 0.5f, 0.0f);

vA.color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);

vA.texCoord = glm::vec2(0.0f, 1.0f);

vA.tid = _exampleTexture->getTextureID();

/*TOP RIGHT*/

vB.vertex = glm::vec3(0.5f, 0.5f, 0.0f);

vB.color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);

vB.texCoord = glm::vec2(1.0f, 1.0f);

vB.tid = _exampleTexture->getTextureID();

/*BOTTOM LEFT*/

vC.vertex = glm::vec3(-0.5f, -0.5f, 0.0f);

vC.color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);

vC.texCoord = glm::vec2(0.0f, 0.0f);

vC.tid = _exampleTexture->getTextureID();

/*BOTTOM RIGHT*/

vD.vertex = glm::vec3(0.5f, -0.5f, 0.0f);

vD.color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);

vD.texCoord = glm::vec2(1.0f, 0.0f);

vD.tid = _exampleTexture->getTextureID();

[...]

/*Submission in the main loop*/

_exampleShader->bind();

_exampleTexture->bind();

_exampleShader->setUniformMat4("model_matrix", glm::mat4(1.0f));

_exampleShader->setUniformMat4("view_matrix", glm::lookAt(glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 1.0f, 0.0f)));

_exampleShader->setUniformMat4("projection_matrix", glm::perspective(ConversionUtils::convertFOV(90.0f), getAspectRatio(), 0.0001f, 100.0f));

Renderer::begin();

Renderer::submit(vC);

Renderer::submit(vA);

Renderer::submit(vB);

Renderer::submit(vC);

Renderer::submit(vD);

Renderer::submit(vB);

Renderer::end();

glfwSwapBuffers(_window);

[...]

As you can see, I create some example vertex data and submit that every frame. Now, the last bits of code are my vertex and fragment shaders:

Vertex Shader:

#version 330 core

layout(location = 0) in vec3 v_vertex;

layout(location = 1) in vec4 v_color;

layout(location = 2) in vec2 v_texCoord;

layout(location = 3) in uint v_tid;

out vec4 f_color;

out vec2 f_texCoord;

flat out uint f_tid;

uniform mat4 model_matrix;

uniform mat4 view_matrix;

uniform mat4 projection_matrix;

void main() {

f_color = v_color;

f_texCoord = v_texCoord;

f_tid = v_tid;

mat4 mvp = projection_matrix * view_matrix * model_matrix;

gl_Position = mvp * vec4(v_vertex, 1.0);

}

Fragment shader:

#version 330 core

in vec4 f_color;

in vec2 f_texCoord;

flat in uint f_tid;

out vec4 color;

uniform sampler2D texSampler;

void main() {

color = texture(texSampler, f_texCoord);

}

That's what I'm working with. Now, I already did a bunch of googling and even asked on the OpenGL channel @ freenode, but no one could help me with this. I removed deprecated functionality by using the core 3.3 profile, even the forward compatible profile, despite the fact that I should not be doing this. Other things I already checked:

  • I'm only using one thread with a valid GL context, so there's probably no problems regarding "packaging an OGL object in a C++ class"
  • Both the shader and the texture are bound; since the texture sampler and the active texture are 0 by default, that shouldn't cause any problems either
  • I am actually loading test.png properly (texture.cpp if you're interested: http://pastebin.com/hWGTCe5C)
  • I am not using deprecated functionality afaik, even the SOIL functions that use deprecated functionality aren't called; loading the image via SDL2 und SDL2_image, which I did before switching libraries, caused the same problem
  • The shader gets valid texture coordinates (tested by outputting them as colors to the square I'm rendering)
  • Neither the shader nor the compiler give me any warnings/errors, despite the -Wall compiler flag being set, glGetError() doesn't help either

Other information that might be useful: I've tested this on both Intel and Nvidia GPUs using their most recent drivers on Antergos (Arch) Linux (one on Wayland, one on X11). 64-bit architecture. Most recent versions of the libraries (GLFW3, SOIL, GLEW and GLM). Compiled using Clang++. Valgrind doesn't give me any useful output either.

Me and the IRC chatroom are running out of ideas - what could cause this?

网友答案:

As @RetoKoradi said in his comment, you are not actually passing any parameters to your texture, therefore your texture is not complete.

Try to add in texture.cpp something like :

glBindTexture(GL_TEXTURE_2D, texture_id);
glTexImage2D(GL_TEXTURE_2D, 0, your_internal_format, width, height, 0, your_format, your_type, texture_pointer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, your_behavior);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, your_behavior);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);

or

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

or

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);

you can find more informations about texture completness here : OpenGL Common Mistakes. Note that the problem @RetoKoradi is refering about is addressed in this link.

分享给朋友:
您可能感兴趣的文章:
随机阅读: