#c #opengl #glsl #glfw
#c #opengl #glsl #glfw
Вопрос:
Я не могу получить значение sampler3D в моем шейдере фрагмента GLSL.
Я пишу шейдер в GLSL и хочу использовать sampler3D (3d текстуру) в качестве объемных данных и выполнять объемный рендеринг. Однако, похоже, я не могу привязать 3d-текстуру к sampler3D моего шейдера. texture3D() всегда возвращает (0,0,0,0) на стороне шейдера. Но на стороне моего приложения я могу использовать glGetTexImage для получения данных.
На стороне приложения (DS является объектом класса шейдеров):
dS.use();
dS.setInt("volumeData", 0);
uint texture;
glGenTextures(1, amp;texture);
glBindTexture(GL_TEXTURE_3D, texture);
float data[64];
for (int i = 0; i < 64; i) data[i] = 1.0f;
glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, 4, 4, 4, 0, GL_RED, GL_FLOAT, data);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_3D, 0);
float read[64];
glBindTexture(GL_TEXTURE_3D, texture);
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED, GL_FLOAT, read);
std::cout << read[0] << "," << read[63] << std::endl; // 1,1
glBindTexture(GL_TEXTURE_3D, 0);
// When drawing.
dS.use();
dS.setMat4("model", glm::mat4(1.0f));
dS.setMat4("view", view);
dS.setMat4("projection", projection);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texture);
cube.draw();
Вершинный шейдер
#version 330 core
// for snow rendering
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
}
Фрагмент шейдера
#version 330
out vec4 FragColor;
uniform sampler3D volumeData;
void main()
{
ivec3 size = textureSize(volumeData, 0);
float c = texture3D(volumeData, vec3(0)).x;
if (size.x == 1)
FragColor = vec4(1.0, 0.0, c, 1.0);
else if (size.x > 2)
FragColor = vec4(0.0, 1.0, 0.0, 1.0);
else if (size.x == 0)
FragColor = vec4(0.0, 0.0, 1.0, 1.0);
else
FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
Я получил только красный куб, что означает size.x == 1, а texture3D возвращает 0, что, как ожидается, будет size.x == 4, а texture3D возвращает 1.0
Я использовал аналогичный метод для 2d текстуры, и он работает. Итак, я думаю, что мой класс шейдеров правильный. И я также пытался добавить glEnable (GL_TEXTURE_3D), прежде чем выполнять какие-либо операции с 3D-текстурой.
И я не уверен, помогает ли это: я использовал glfw-3.2.1 WIN64 и рад.
Комментарии:
1. » Если sampler3D работает, то по крайней мере textureSize не должен возвращать (0,0,0). » Если только это не
textureSize
сломано, а не сам сэмплер. Почему бы вам не удалить все ненужные биты и не проверить, можете ли вы извлекать данные из текстуры?2. @NicolBolas, я добавил textureSize, потому что я пытался просто извлечь данные из текстуры с помощью texture3D, но это не удалось. Поэтому я объединил textureSize и texture3D вместе, чтобы посмотреть, связано ли это с тем, что я использовал неправильные координаты UVW или потому, что sampler3D неверен.
3. Нет правильной или неправильной координаты текстуры, когда все значения в вашей текстуре одинаковы. Кроме того,
texture3D
это старая функция; вы должны просто использоватьtexture
. И что означает «сбой»? Какой цвет вы получили?4. @NicolBolas, «сбой» означает, что texture() или texture3D() возвращает только (0,0,0,0). Затем я использовал textureSize() и обнаружил, что размер всегда равен (1,1,1). Поэтому я думаю, это потому, что я не могу привязать 3d-текстуру к этому единообразному sampler3D.
5. @NicolBolas, я решил это, я просто использовал GL_TEXTURE_2D для установки фильтров MIN и MAG, что привело к неполноте mipmap. Это действительно глупая опечатка. Извините, что потратил ваше время.
Ответ №1:
Я решил это. Это действительно глупая опечатка.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
следует использовать GL_TEXTURE_3D вместо GL_TEXTURE_2D.
И поскольку состояние GL_TEXTURE_MIN_FILTER по умолчанию равно GL_NEAREST_MIPMAP_LINEAR. Это приводит к неполноте mipmap.