Как да използвам магазин за изображения с 3D текстури?

Опитвам се да съхраня данни в 3D текстура, но изглежда не работи. Настроих текстурата така:

glGenTextures(1, &voxelTexture);
glBindTexture(GL_TEXTURE_3D, voxelTexture);
unsigned char clearData[VoxelSize* VoxelSize* VoxelSize];
memset(clearData, 5, sizeof(clearData));
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, VoxelSize, VoxelSize, VoxelSize, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, clearData);

По-късно пиша на текстурата:

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, VoxelSize, VoxelSize);
glUseProgram(voxelProg);
glBindTexture(GL_TEXTURE_3D, voxelTexture);
glBindImageTexture(0, voxelTexture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R8UI);
for(const auto & i : models){
    glUniformMatrix4fv(glGetUniformLocation(voxelProg, "M"), 1, GL_FALSE, glm::value_ptr(i->getModelMatrix()));
    glBindVertexArray(i->getMesh()->vao);
    glDrawElements(GL_TRIANGLES, i->getMesh()->nbVertices, GL_UNSIGNED_INT, 0);
}

Знам, че операцията по рисуване работи добре, защото съм я използвал с карта на сенките в друга част на програмата.

Накрая се опитвам да прочета данните от текстурата:

glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
static char data[VoxelSize * VoxelSize *VoxelSize] = {0};
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, data);
for(auto & i : data){
    if(i!=5)
        std::cout << (int)i << " ";
}
endl(std::cout);

Както можете да видите, ако данните бяха променени, тогава те ще се отпечатат на cout. Зададох данните да бъдат 5, за да можете да видите, че glGetTexImage действително чете данните за текстурата (защото в противен случай всичко ще бъде нула).

Програмата, която използвам, има това като върхов буфер:

#version 430

layout(location = 0) in vec3 position;

uniform mat4 M;

void main(){
    gl_Position = M* vec4(position, 1.0);
}

И това като буфер за фрагменти:

#version 430

layout(binding = 0, r8ui)writeonly restrict uniform uimage3D dataTexture;
void main(){
    imageStore(dataTexture, ivec3(6,6,6), uvec4(30));
}

Използвах произволно място за писане, а не такова, което е засегнато от самия фрагмент, така че поне да мога да бъда сигурен, че ако някой фрагмент премине през него, той ще повлияе на текстурата. Изглежда обаче нищо не работи. Опитах се да променя мястото, където imageStore пише, опитах да мащабирам gl_Position в буфера на върховете по различни начини. Всяка помощ ще бъде оценена.

Редактиране:

След като следвате решението за възможни дубликати за промяна на наслоената настройка от false на true, то все още не работи.


person user975989    schedule 01.07.2015    source източник
comment
възможен дубликат на Compute shader не променя 3d текстура   -  person jozxyqk    schedule 01.07.2015
comment
Опитах го. Също така не използвам компютърен шейдър, а по-скоро фрагментен шейдър.   -  person user975989    schedule 01.07.2015
comment
Тогава не е измамник. Не мога да забележа нищо наистина очевидно. Сигурни ли сте, че фрагментите всъщност рисуват? Опитайте да преместите imageStore към върховия шейдър само като тест.   -  person jozxyqk    schedule 01.07.2015
comment
Прав си, работи във вертексния шейдър. Нямам представа защо не преминава във фрагментния шейдър.   -  person user975989    schedule 01.07.2015


Отговори (1)


glUseProgram(voxelProg) и glGetUniformLocation(mainProg, "M") препращат към различни шейдър програми. Следователно матрицата M не е зададена, върховете образуват изродени триъгълници и нито един фрагмент не се растеризира, така че imageStore никога не се извиква.

Също така glBindImageTexture обработва 3D текстури като "слоести" 2D текстури, така че аргументът за наслояване трябва да бъде GL_TRUE. вижте това.

[РЕДАКТИРАНЕ] В този случай M не проектира геометрията правилно и поради други причини (вижте коментарите). За да промените M, така че да мащабира и преобразува мрежата в куб -1 към 1, за да съответства на 3D изображението, вижте: Как да нормализирате мрежа в -1 към 1, след което да се върне от нормализирана мрежа към оригинална?

person jozxyqk    schedule 01.07.2015
comment
Смених и двете, но все още не пиша върху текстурата. - person user975989; 01.07.2015
comment
@user975989 getModelMatrix включва ли необходимите матрици за проекция и изглед? Сигурен ли си, че геометрията ти е правилна? Може би избиването на задното лице пречи? По някаква причина не се растеризира геометрия. - person jozxyqk; 01.07.2015
comment
Хм, прав си. Идеята зад това е да се вокселизира модел. Мислех, че правилният начин да направите това е да не използвате проекция или матрица на изглед, а по-скоро само матрицата на модела. Когато умножих по тях, работи добре. Проблемът обаче е, че проекционната матрица е перспективна, а матрицата на изгледа зависи от това къде се намирам. Искам да вокселизирам модела, независимо от тези две характеристики. Не трябва ли да е достатъчна само матрицата на модела? Освен това и GL_DEPTH_TEST и GL_CULL_FACE са деактивирани. - person user975989; 01.07.2015
comment
Може да искате да използвате ортографска проекция, която ограничава модела. Ако трябва да запазите правилното съотношение на страните, тогава използвайте оста с най-дългата граница и центрирайте модела върху другите две. С други думи, намерете минималните и максималните позиции на върховете x,y,z, след което използвайте този tp, мащабирайте модела в нормализирания куб с координати на устройството -1 към 1 за вашия шейдър. Запазвайки текущия си код, актуализирайте M, за да изпълните мащаба и да преведете към произхода. - person jozxyqk; 01.07.2015
comment
@user975989 добави свързана връзка. - person jozxyqk; 01.07.2015
comment
Нормализирах координатите на моите модели да бъдат между 0 и 1, но запазих съотношението на страните. Сега той напълно вокселизира модела, но проблемът е, че различните гледни точки не се събират. Например нещо, проектирано от оста x, не се подравнява правилно с нещо, проектирано от оста y или z. Опитах да центрирам модела върху двете недоминиращи оси, но това не решава проблема. Имате ли представа как да разрешите този проблем? - person user975989; 02.07.2015
comment
Нека продължим тази дискусия в чата. - person user975989; 02.07.2015