OpenGL - Texture not rendering properly - c++

I'm trying to render a cube with a wood texture (all faces of the cube with the same texture), but the texture is not being rendered as it should (looks like the texture is trasparent at some parts):
But if look inside the cube, it seems to be rendering properly:
:
Here is the .obj file that I'm reading from (with the texture coords and vertices):
mtllib crate.mtl
o Cube_Cube.002
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 1.000000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 6/1/1 1/2/1 5/3/1
f 7/4/2 2/5/2 6/6/2
f 8/7/3 3/8/3 7/9/3
f 5/10/4 4/11/4 8/12/4
f 2/13/5 4/11/5 1/14/5
f 7/4/6 5/15/6 8/12/6
f 6/1/1 2/16/1 1/2/1
f 7/4/2 3/17/2 2/5/2
f 8/7/3 4/18/3 3/8/3
f 5/10/4 1/19/4 4/11/4
f 2/13/5 3/17/5 4/11/5
f 7/4/6 6/20/6 5/15/6
Here is the way I'm loading the texture to OpenGL:
unsigned char* localBuffer = stbi_load(filepath.c_str(), &this->width, &this->height, &this->bitsPerPixel, 4);
glGenTextures(1, &this->id);
glActiveTexture(GL_TEXTURE0 + this->slot);
glBindTexture(GL_TEXTURE_2D, this->id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localBuffer);
glBindTexture(GL_TEXTURE_2D, 0);
Here is the the vertex shader:
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 textureCoords;
out vec2 vTextureCoords;
uniform mat4 Mvp;
void main()
{
vTextureCoords = textureCoords;
gl_Position = Mvp * vec4(aPos, 1.0);
}
Here is the fragment shader:
out vec4 FragColor;
in vec2 vTextureCoords;
uniform sampler2D textureSlot;
void main()
{
FragColor = texture(textureSlot, vTextureCoords);
}
Can someone tell me what I'm doing wrong here?

Thanks to #Sync it I find out that the solution was to enable depth testing.
glEnable(GL_DEPTH_TEST);

I've had a very similar issue, however I'm using DirectX. The reason was that I didn't have the depth-stencil buffer set and I so the pixel depth values were being overridden by whatever order they were drawn in first. Check to make sure you have some equivalent of this enabled in OpenGl.

Related

How do I read Blender's default cube?

I'm learning DirectX 11 and I've got very confused after looking at Blender's default cube, I've exported it in the Wavefront OBJ format, and this is the file I've got:
# Blender v2.92.0 OBJ File: ''
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.125000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/5/2 3/4/2 7/6/2 8/7/2
f 8/8/3 7/9/3 5/10/3 6/11/3
f 6/12/4 2/13/4 4/5/4 8/14/4
f 2/13/5 1/1/5 3/4/5 4/5/5
f 6/11/6 5/10/6 1/1/6 2/13/6
I know the secret for it to render is use the provided indices, but I'm not sure how I should implement the buffer for this data, if the vertex, uv and normals were in the same amount I could organize them in a array of structures, but if they are in a different number I don't know how could I do this and create a buffer.
The Wavefront OBJ format is very old-school, but it's been around a long time so it's well understood and fairly easy to parse. That said, 3D renderer packages like Blender don't have to store their data in the same formats that you typically use for runtime rendering, so expect to do some work to change the Wavefront OBJ method of individual indices for each kind of data into the Vertex format for single-stream rendering.
Another challenge is that Wavefront OBJ stores faces as 'n-gons', and you need to convert it to triangles to render with Direct3D 11. You can also run into relative indices (i.e. negative numbers) for the different arrays. And then there's dealing with the mtl file.
An example of doing all the text file parsing and conversion in C++ can be found on GitHub: WavefrontReader.h which is documented here.
WaveFrontReader<uint16_t> wfReader;
Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> indexBuffer;
HRESULT hr = wfReader.Load(L"cube.obj");
if (FAILED(hr))
// Error
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.ByteWidth = static_cast<UINT>(wfReader.vertices.size() * sizeof(WaveFrontReader::Vertex));
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
D3D11_SUBRESOURCE_DATA initData = { wfReader.vertices.data(), 0, 0 };
hr = device->CreateBuffer(&bufferDesc, &initData, &vertexBuffer);
if (FAILED(hr))
// Error
bufferDesc.ByteWidth = static_cast<UINT>(wfReader.indices.size() * sizeof(uint16_t));
bufferDesc.bindFlags = D3D11_BIND_INDEX_BUFFER;
initData.pSysMem = wfReader.indices.data();
hr = device->CreateBuffer(&bufferDesc, &initData, &indexBuffer);
if (FAILED(hr))
// Error
UINT vertexStride = sizeof(WaveFrontReader::Vertex);
uint vertexOffset = 0;
deviceContext->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &vertexStride, &vertexOffset);
deviceContext->IASetIndexBuffer(indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
A common strategy--at least games--is to do all that parsing offline and write out a nice, GPU-friendly runtime file format that you can just read into memory and render with. For DirectX, there a number of 'sample' formats like VBO, SDKMESH, or Visual Studio's CMO. Using these tools typically makes reading the Vertex & Index buffer at runtime trivial. See DirectXMesh's meshconvert, the DirectX SDK Samples Content Exporter, and the Visual Studio Content pipeline. Code for loading and rendering all these formats can be found in the DirectX Tool Kit.
Of course, for a simple common shape like a cube, you can just create it in memory directly rather than having to go through all the mess of parsing a model in the first place. That's what GeometricPrimitive in the DirectX Tool Kit does.
Note: Even if you went with multi-stream rendering you'd still have to duplicate the data because all streams have to use the same index from the IB for each vertex. Since you are already doing some data rearranging on the CPU, you might as well create a single-stream packed Vertex which is more efficient than have 2 or 3 streams.

VK_FILTER_NEAREST not working during sampling

I have a problem with my sampler in Vulkan: it doesn't matter if I create the sampler with VK_FILTER_NEAREST or VK_FILTER_LINEAR for both magnification or minification filter, my texture will be sampled as if I created it with VK_FILTER_LINEAR;
This is the method where I create my sampler:
void Gui::Texture_2D::createVkSampler(const VkFilter & _magFilter,
const VkFilter & _minFilter,
const VkSamplerMipmapMode & _mipMapFilter,
const unsigned char & _maxAnisotropy) {
VkSamplerCreateInfo samplerInfo = {};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = _magFilter; // VK_FILTER_NEAREST
samplerInfo.minFilter = _minFilter; // VK_FILTER_NEAREST
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerInfo.anisotropyEnable = _maxAnisotropy == 0 ? VK_FALSE : VK_TRUE; // 0
samplerInfo.maxAnisotropy = _maxAnisotropy; // 0
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = _mipMapFilter; // VK_SAMPLER_MIPMAP_MODE_NEAREST
samplerInfo.mipLodBias = 0.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = static_cast<float>(image.getMipLevels());
if (vkCreateSampler(logicalDevice, &samplerInfo, nullptr, &sampler) != VK_SUCCESS)
throw std::runtime_error("Texture sampler creation failed!");
}
...but the texture is rendered as if I passed VK_FILTER_LINEAR and VK_SAMPLER_MIPMAP_MODE_LINEAR, and I really don't know what's wrong.
Does someone have an idea? Thanks.
More Info:
This is the image texture (a simple 8x8 .png with every 4x4 corner of a different color):
This is the result using VK_FILTER_NEAREST and VK_SAMPLER_MIPMAP_MODE_NEAREST:
This is the .obj file of the cube, with Normals and Texture Coordinates:
# Blender v2.79 (sub 0) OBJ File: ''
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 1/1/1 2/2/1 3/3/1 4/4/1
f 5/5/2 8/6/2 7/7/2 6/8/2
f 1/1/3 5/9/3 6/10/3 2/11/3
f 2/12/4 6/13/4 7/7/4 3/14/4
f 3/15/5 7/16/5 8/17/5 4/4/5
f 5/5/6 1/18/6 4/19/6 8/20/6
I would expect a Minecraft-like behaviour, but I get this blurry style that I should obtain with VK_FILTER_LINEAR.
Thanks.
Update
I ran the program on another pc and the texture is sampled correctly, I suppose there's a bug/glitch/problem with my GPU, I'll try to update my drivers.
Update 2
I updated my GPU drivers and I'm now using the latest Vulkan SDK version (1.1.101.0), still nothing; RenderDoc analysis of the sampler reports no problem, I'm using the right filter; Removing/Not using mipmaps doesn't help; Not a single Validation layer error.
I'm starting to think my GPU still doesn't support Vulkan very well (Intel HD Graphics 620) so I guess I'll have to accept it and go on, knowing that at least it'll work on other PCs.
Update 3
I updated my GPU drivers and I'm now using the latest Vulkan SDK version (1.1.114.0), still nothing; RenderDoc analysis of the sampler reports no problem, I'm using the right filter; Removing/Not using mipmaps doesn't help; Not a single Validation layer error.
I'm starting to think my GPU still doesn't support Vulkan very well (Intel HD Graphics 620) so I guess I'll have to accept it and go on, knowing that at least it'll work on other PCs.
I had the exact same issue and decided to mess around with VkSamplerCreateInfo and found out that setting anisotropyEnabled to VK_FALSE fixes the problem, but I don't know why.

Good way to parse Wavefront OBJ with C++ with //?

how to parsing file in this form
my file is looks like this
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
f 2//1 3//1 1//1
f 4//2 7//2 3//2
and my parsing code here:
ifstream fin;
string reader;
while(fin>>reader)
{
if(reader == "v"){
vec3 vertex;
fin>>vertex.x>>vertex.y>>vertex.z;
out_vertices.push_back(vertex);
} else if(reader == "vn"){
vec3 normal;
fin>>normal.x>>normal.y>>normal.z;
out_normals.push_back(normal);
}else if(reader== "f"){
vec2 facet;
vec3 _normal,_vertex;
fin>>_vertex.x>>_vertex.y>>_vertex.z >>_normal.x>>_normal.y>>_normal.z;
facet.normal = _normal;
facet.vetex = _vertex;
out_facets.push_back(facet);
}
}
how ever it can't reading the line start with f? is there any good way to do that ?

Un correct UV texture mapping on a simple cube

The goal of my program is to display a simple cube UV mapped exported from Blender. But the texture mapping in my openGL program is not correct. I want to precise that the display of my UV mapped cube is perfect on Blender. My texture is composed of a simple color for each face(Red, green, blue, purple, yellow and orange). I've choosen to export my mesh in .obj and .mtl files using quads. Here's the content of my .obj file (I've added some comments):
# Blender v2.63 (sub 0) OBJ File: ''
# www.blender.org
mtllib Box.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.500000 1.000000 //1
vt 0.250000 1.000000 //2
vt 0.250000 0.750000 //3
vt 0.500000 0.750000 //4
vt 0.500000 0.250000 //5
vt 0.500000 0.500000 //6
vt 0.250000 0.500000 //7
vt 0.250000 0.250000 //8
vt 0.500000 0.000000 //9
vt 0.250000 0.000000 //10
vt 0.000000 0.750000 //11
vt 0.000000 0.500000 //12
vt 0.750000 0.500000 //13
vt 0.750000 0.750000 //14
usemtl Material_Box.bmp
s off
f 1/1/1 2/2/1 3/3/1 4/4/1 //Orange OK
f 5/5/2 8/6/2 7/7/2 6/8/2 //Green OK
f 1/9/3 5/5/3 6/8/3 2/10/3 //Red OK
f 2/11/4 6/12/4 7/7/4 3/3/4 //White (should be purple) NOT OK
f 3/3/5 7/7/5 8/6/5 4/4/5 //Yellow 5 OK
f 5/13/6 1/14/6 4/4/6 8/6/6 //White (should be blue) NOT OK
My unwraped cube looks like a cross. Here's my UV texture (I want to precise that the '3bis' and '4bis' correspond to the .obj file wrong coordinates. Only the 1, 2, 5 and 6 faces coordinates are correct):
And here's an exemple of my openGL render :
You can see the '4bis' white face like on the uv texture.
So, certain coordinates generated by blender seems to be wrong. Why?
Does the problem comes from that the blue quad doesn't touch the right side of the picture creating a translation of certains coordinates?
Maybe I must precise a special parameter before exportation in Blender...
Does anyone can help me?

Transformation of a point in OpenGL

i need to be able to draw on a model, so i used of course the picking technique, and i used gluunproject in order to do this. now, when i get the point from the gluunproject, it it always multiplied by some permanent number, and i dont know why it happens.
my model is:
***# XSI Wavefront OBJ Export v3.0
# File Created: Mon Oct 29 00:15:19 2007
# XSI Version: 6.02.2007.0613
mtllib cube.mtl
o cube
# Hierarchy (from self to top father)
g cube
#begin 8 vertices
v -8.000000 -8.000000 -8.000000
v 8.000000 -8.000000 -8.000000
v -8.000000 8.000000 -8.000000
v 8.000000 8.000000 -8.000000
v -8.000000 -8.000000 8.000000
v 8.000000 -8.000000 8.000000
v -8.000000 8.000000 8.000000
v 8.000000 8.000000 8.000000
#end 8 vertices
#begin 24 normals
vn 0.000000 -0.000000 -1.000000
vn 0.000000 -0.000000 -1.000000
vn 0.000000 -0.000000 -1.000000
vn 0.000000 -0.000000 -1.000000
vn -0.000000 -1.000000 0.000000
vn -0.000000 -1.000000 0.000000
vn -0.000000 -1.000000 0.000000
vn -0.000000 -1.000000 0.000000
vn -1.000000 0.000000 -0.000000
vn -1.000000 0.000000 -0.000000
vn -1.000000 0.000000 -0.000000
vn -1.000000 0.000000 -0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
#end 24 vertex normals
#begin 24 texture vertices
vt 0.000000 0.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 0.000000 1.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 0.000000 0.000000
vt 1.000000 0.000000 0.000000
vt 1.000000 1.000000 0.000000
vt 0.000000 1.000000 0.000000
#end 24 texture vertices
#begin 6 faces
usemtl material
f 1/1/1 3/2/2 4/3/3 2/4/4
usemtl material
f 1/5/5 2/6/6 6/7/7 5/8/8
usemtl material
f 1/9/9 5/10/10 7/11/11 3/12/12
usemtl material
f 2/13/13 4/14/14 8/15/15 6/16/16
usemtl material
f 3/17/17 7/18/18 8/19/19 4/20/20
usemtl material
f 5/21/21 6/22/22 8/23/23 7/24/24
#end 6 faces***
as you can see, it jusr a regular cube, now for example, when i click of one of its edges, i get the point of (4,4,4) instead of (8,8,8). why does it happen ?