Не может текстурировать и трансформировать одновременно - PullRequest
0 голосов
/ 10 января 2019

Я сделал цветной квадрат, который вращается вокруг центра. И может также текстурировать квадрат. Но когда я объединяю их, я получаю только вращающийся черный квадрат.

В фрагментном шейдере я могу обмениваться показом цветов, определенных в массиве вершин, и отображением изображения, выбранного для текстуры. Это путем обмена комментариями двух строк в основном. Оба прекрасно работают, когда не вращаются:

#version 450 core
in vec3 ourColor;
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
   //   color = vec4(ourColor, 1.0f);
   color = texture(ourTexture, TexCoord); 
}

В шейдере Vertex я могу выбрать вращение или нет, чередуя комментарии строк gl_Position:

#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;

out vec3 ourColor;
out vec2 TexCoord;

uniform mat4 transform;

void main()
{
    gl_Position = transform*vec4(position, 1.0f);
//  gl_Position = vec4(position, 1.0f);
    ourColor = color;
    TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
}

И код для управления этими:

GLfloat vertices[] = {
    // Positions          // Colors           // Texture Coords
    0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top Right
    0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
    -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Left
    -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Left
};

unsigned int indices[] = {
    0, 1, 3, // First Triangle
    1, 2, 3, // Second Triangle
};

GLuint VBO, VAO, indexBuffer;
glCreateVertexArrays(1, &VAO);
glCreateBuffers(1, &indexBuffer);
glCreateBuffers(1, &VBO);

glNamedBufferStorage(VBO, sizeof (vertices), vertices, GL_DYNAMIC_STORAGE_BIT);
glNamedBufferStorage(indexBuffer, sizeof (indices), indices, GL_DYNAMIC_STORAGE_BIT);

// Create index buffer
glVertexArrayElementBuffer(VAO, indexBuffer);

//position
glEnableVertexArrayAttrib(VAO, 0);
glVertexArrayAttribFormat(VAO, 0, 3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(VAO, 0, 0);

//color
glEnableVertexArrayAttrib(VAO, 1);
glVertexArrayAttribFormat(VAO, 1, 3, GL_FLOAT, GL_FALSE, (3 * sizeof ( GLfloat))); // relative offset is the size in bytes until the first "color" attribute
glVertexArrayAttribBinding(VAO, 1, 0);

//texture
glEnableVertexArrayAttrib(VAO, 2);
glVertexArrayAttribFormat(VAO, 2, 2, GL_FLOAT, GL_FALSE, (6 * sizeof ( GLfloat))); // relative offset is the size in bytes until the first "color" attribute
glVertexArrayAttribBinding(VAO, 2, 0);

glVertexArrayVertexBuffer(VAO, 0, VBO, 0, 8 * sizeof ( GLfloat)); // The stride is the number of bytes between hver vertex

// ===================
// Texture
GLuint texture = 0;
int width = 0, height = 0;
glCreateTextures(GL_TEXTURE_2D, 1, &texture);

unsigned char *image = SOIL_load_image("image2.png", &width, &height, 0, SOIL_LOAD_RGBA);

std::cout << "Bredde: " << width << "   Højde: " << height << "\n";
glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureStorage2D(texture, 1, GL_RGBA2, width, height);
glTextureSubImage2D(texture, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateTextureMipmap(texture);
SOIL_free_image_data(image);
glBindTextureUnit(0, 0);

// Game loop
while (!glfwWindowShouldClose(window)) {
    glfwPollEvents();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    ourShader.Use();

    glm::mat4 transform = glm::mat4(1.0);
    transform = glm::rotate(transform, (GLfloat) glfwGetTime() * 5.0f, glm::vec3(0.0f, 0.0f, 1.0f));

    const auto Textureloc = glGetUniformLocation(ourShader.Program, "ourTexture");
    glBindTextureUnit(Textureloc, texture);

    // Get matrix's uniform location and set matrix
    const GLint transformLoc = glGetUniformLocation(ourShader.Program, "transform");
    glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));

    std::cout << "Transform location: " << transformLoc << "\n";
    std::cout << "Texture location: " << Textureloc << "\n";

    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
    glBindTextureUnit(0, 0);

    // Swap the screen buffers
    glfwSwapBuffers(window);
}

Боюсь, я перепутал кое-что с DSA с не-DSA. Поэтому сообщение в: Использование glBindVertexArray в цикле обновления в коде DSA или нет

Кто-нибудь может увидеть, что я делаю неправильно?

1 Ответ

0 голосов
/ 10 января 2019

Вы путаете расположение универсальной переменной сэмплера текстуры и единицы текстуры.

Местоположение универсальной переменной является активным программным ресурсом, который можно получить по glGetUniformLocation:

const auto Textureloc = glGetUniformLocation(ourShader.Program, "ourTexture");

Но вы можете выбрать текстурный блок текстурный блок и привязать текстуру к этому блоку.
Затем вы должны установить значение индекса единицы текстуры в единицу сэмплера текстуры:

, например

GLuint unit = 3;
glBindTextureUnit(unit, texture); 
glUniform1i(Textureloc, unit);      

Обратите внимание, что текстурный блок является связующим звеном между программой шейдера и объектом текстуры.

См. Спецификация профиля совместимости API OpenGL 4.6; 7.10 Пробоотборники; страница 154 :

Сэмплеры - это специальные формы, используемые в языке шейдеров OpenGL для идентификации объект текстуры, используемый для каждого поиска текстуры. Значение сэмплера указывает на доступ к единице изображения текстуры. При установке значения сэмплера на i выбирается номер единицы изображения текстуры i.

Прежний код сработал, и вы «увидели» текстуру, потому что, если вы не используете унифицированную переменную «transform», то униформа не активна и не получает одинакового местоположения. Таким образом, "ourTexture" является единственной оставшейся униформой и, вероятно, имеет унифицированное местоположение 0 (Textureloc == 0).
Поскольку значение "ourTexture" не задано явно, его значением является значение по умолчанию 0.
В этом особом случае текстурный блок, местоположение Textureloc и значение "ourTexture" равны, все они равны 0. Ваш код работал по совпадению.

Начиная с GLSL версии 4.2, текстурный блок может быть установлен с помощью Layout Qualifier (GLSL) внутри шейдера. Установите Binding point , с текстурным блоком:

GLuint unit = 3;
glBindTextureUnit(unit, texture); 

Вершинный шейдер: binding = 3 означает текстурный блок 3

layout(binding = 3) uniform sampler2D ourTexture;
...