Since I filled the array with 1s I expected the square to be white. But when I ran the code the square was black. My idea was to use buffer sub data to upload the array to the buffer. I also tried to use persistent mapping so that I could write directly to the buffers memory. I have written a function that reads a texture from a file using stb image. Why is it that when using stb image to initialize the array the image shows up but it doesnt work with this array
Here is where I think the code is going wrong:
voxelEngine::BiomeMap::BiomeMap(int textureUnit) {
pixels = new unsigned char[apothem*apothem*4];
for(size_t i = 0; i < sizeof(pixels); i ) {
pixels[i] = 1;
}
_textureUnit = textureUnit;
glGenBuffers(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glGenBuffers(1, &tbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float vertex_data[] = {
0, 0, 0, 0, 0,
0, 1, 0, 0, 1,
1, 1, 0, 1, 1,
1, 0, 0, 1, 0
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
unsigned int indices[] = {
0, 1, 2,
0, 2, 3
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glActiveTexture(GL_TEXTURE0 _textureUnit);
glBindBuffer(GL_TEXTURE_2D, tbo);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, apothem, apothem, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, apothem, apothem, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// set the texture wrapping/filtering options (on the currently bound texture object)
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_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA, apothem, apothem);
glGenerateMipmap(GL_TEXTURE_2D);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);
}
Fragment shader:
#version 330 core
out vec4 FragColor;
in vec2 oTexCoord;
uniform sampler2D my_sampler;
void main()
{
FragColor = texture(my_sampler, oTexCoord);
//FragColor = vec4(1, 1, 1, 1);
}
Vertex shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 texCoord;
out vec2 oTexCoord;
uniform mat4 modelMat;
uniform mat4 projMat;
void main()
{
gl_Position = projMat * modelMat * vec4(aPos.x, aPos.y, aPos.z, 1.0);
oTexCoord = texCoord;
}
What image format does teximage2d expect why doesn't a linear array of rgba color values work? Does it have to do with texsubimage/teximage2d or are the textures not configured correctly?
CodePudding user response:
pixels = new unsigned char[apothem*apothem*4];
This allocates apothem*apothem*4
unsigned char
s.
for(size_t i = 0; i < sizeof(pixels); i ) {
sizeof(pixels)
does not do what you think it does. Since pixels
is, presumably, an unsigned char *
, sizeof(pixels)
will always be 8, on a 64-bit platform because all pointers take up 8 bytes.
I filled the array with 1s
No, you did not. You only filled the first 8 values in the array. And, if apothem
happens to be 1 you just scrambled a bunch of memory, and created undefined behavior.
The fix is obvious.
size_t pixels_s=apothem*apothem*4;
pixels = new unsigned char[pixels_s];
for(size_t i = 0; i < pixels_s; i ) {
and so on.
Even better: forget about new, use a std::vector<unsigned char>
use the appropriate constructor that allocates the vector and initializes it, and you don't have to worry about forgetting to delete
anything, and leak memory. This is what std::vector
is for.