Reputation: 366
I am working on an opengl based raytracer application in c++. I would like to send data from the cpu side to the fragment shader. The data is a bounding volume hierarchies (BVH) tree. Unfortunately on the shader side I got junk data, when I am trying to write out the coordinates as color with gl_fragcolor. I don't know why. Any help is appreciated.
I have this structure on CPU side:
struct FlatBvhNode {
glm::vec4 min;
glm::vec4 max;
int order;
bool isLeaf;
bool createdEmpty;
vector<glm::vec4> indices;
FlatBvhNode() { }
FlatBvhNode(glm::vec3 min, glm::vec3 max, int ind, bool isLeaf, bool createdEmpty, vector<glm::vec3> indices) {
this->min=glm::vec4(min.x, min.y, min.z, 1.0f);
this->max=glm::vec4(max.x, max.y, max.z, 1.0f);
this->order=ind;
this->isLeaf=isLeaf;
this->createdEmpty=createdEmpty;
indices.reserve(2);
for (int i = 0; i < indices.size(); i++) {
this->indices.push_back(glm::vec4(indices.at(i).x, indices.at(i).y, indices.at(i).z, 1));
}
}
};
I would like to receive the above structure in the fragment shader as:
struct FlatBvhNode{ //base aligment aligned offset
vec3 min; // 16 byte 0
vec3 max; // 16 byte 16
int order; // 4 byte 20
bool isLeaf; // 4 byte 24
bool createdEmpty; // 4 byte 28
vec3 indices[2]; // 32 byte 32
};
I am not sure that the aligned offsets are right. I have read that vec3s are treated as 16 bytes , booleans and integers as 4 bytes. Secondly the aligned offset has to be equal or multiple of the base aligment.
I am sending the above structure with these code:
vector<BvhNode::FlatBvhNode>* nodeArrays=bvhNode.putNodeIntoArray();
unsigned int nodesArraytoSendtoShader;
glGenBuffers(1, &nodesArraytoSendtoShader);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, nodesArraytoSendtoShader);
glBufferData(GL_SHADER_STORAGE_BUFFER, nodeArrays->size() * sizeof(BvhNode::FlatBvhNode), nodeArrays, GL_STATIC_DRAW);
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 2, nodesArraytoSendtoShader, 0, nodeArrays->size() * sizeof(BvhNode::FlatBvhNode));
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
Upvotes: 1
Views: 304
Reputation: 210909
When you specify the Shader Storage Buffer Object, then you have to use the std430
qualifier.
See OpenGL 4.6 API Core Profile Specification; 7.6.2.2 Standard Uniform Block Layout.
If you want to use the following data structure in the shader:
struct FlatBvhNode
{
// base aligment aligned offset
vec4 min; // 16 byte 0
vec4 max; // 16 byte 16
int order; // 4 byte 32
int isLeaf; // 4 byte 36
int createdEmpty; // 4 byte 40
vec4 indices[2]; // 32 byte 48
};
layout(std430) buffer TNodes
{
FlatBvhNode nodes[];
}
then you have to consider, that indices
is an array of type vec4
. Hence indices
is aligned to 16 bytes.
This corresponds to the following data structure in c ++
struct FlatBvhNode {
glm::vec4 min;
glm::vec4 max;
int order;
int isLeaf;
int createdEmpty;
int dummy; // alignment
std::array<glm::vec4, 2> indices;
}
Note, while std::vector
encapsulates dynamic size arrays, std::array
encapsulates fixed size arrays. std::array<glm::vec4, 2>
corresponds to glm::vec4[2]
, but std::vector<glm::vec4>
is more like glm::vec4*
and some additional size information.
Upvotes: 1