0
votes

I am trying to get textures to work properly in OpenGL.

Here is the current problem:

Problem Image

As you can see, the image comes in on the various faces per triangle rather than around the entire mesh.

I want the textures to work normal: ie: wrap around the entire mesh instead of per triangle.

To further illustrate the problem; I created a wireframe of the model and loaded the various points into a "text dump" so you can see how the mapping should work:

Wireframe Image

Vertices/Normals/UVs for above model

Vertex:  X: -1 Y: -1 Z: -1 Normal:  X: 0 Y: 0 Z: -1 UV Point:  S: 0.998895 T: 0.992545
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 0 Y: 0 Z: -1 UV Point:  S: 0.0232662 T: 0.0169165
Vertex:  X: 1 Y: -1 Z: -1 Normal:  X: 0 Y: 0 Z: -1 UV Point:  S: 0.998895 T: 0.0169165
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 0 Y: 0 Z: -1 UV Point:  S: 0.0232662 T: 0.0169165
Vertex:  X: -1 Y: -1 Z: -1 Normal:  X: 0 Y: 0 Z: -1 UV Point:  S: 0.998895 T: 0.992545
Vertex:  X: -1 Y: 1 Z: -1 Normal:  X: 0 Y: 0 Z: -1 UV Point:  S: 0.023266 T: 0.992545
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: 2.98023e-008 Y: 0 Z: 1 UV Point:  S: 0.333333 T: 0.666667
Vertex:  X: 0.999999 Y: -1 Z: 1 Normal:  X: 2.98023e-008 Y: 0 Z: 1 UV Point:  S: 0 T: 0.333333
Vertex:  X: 1 Y: 0.999999 Z: 1 Normal:  X: 2.98023e-008 Y: 0 Z: 1 UV Point:  S: 0.333333 T: 0.333333
Vertex:  X: 0.999999 Y: -1 Z: 1 Normal:  X: 2.98023e-008 Y: 0 Z: 1 UV Point:  S: 0 T: 0.333333
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: 2.98023e-008 Y: 0 Z: 1 UV Point:  S: 0.333333 T: 0.666667
Vertex:  X: -1 Y: -1 Z: 1 Normal:  X: 2.98023e-008 Y: 0 Z: 1 UV Point:  S: 4.96705e-008 T: 0.666667
Vertex:  X: 1 Y: 0.999999 Z: 1 Normal:  X: 1 Y: -2.98023e-007 Z: 4.47034e-008 UV Point:  S: 0.333333 T: 0.333333
Vertex:  X: 1 Y: -1 Z: -1 Normal:  X: 1 Y: -2.98023e-007 Z: 4.47034e-008 UV Point:  S: 0.666667 T: 1.98682e-008
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 1 Y: -2.98023e-007 Z: 4.47034e-008 UV Point:  S: 0.666667 T: 0.333333
Vertex:  X: 1 Y: -1 Z: -1 Normal:  X: 1 Y: -2.98023e-007 Z: 4.47034e-008 UV Point:  S: 0.666667 T: 1.98682e-008
Vertex:  X: 1 Y: 0.999999 Z: 1 Normal:  X: 1 Y: -2.98023e-007 Z: 4.47034e-008 UV Point:  S: 0.333333 T: 0.333333
Vertex:  X: 0.999999 Y: -1 Z: 1 Normal:  X: 1 Y: -2.98023e-007 Z: 4.47034e-008 UV Point:  S: 0.333333 T: 0
Vertex:  X: 0.999999 Y: -1 Z: 1 Normal:  X: -2.83122e-007 Y: -1 Z: -1.78814e-007 UV Point:  S: 0 T: 1.29143e-007
Vertex:  X: -1 Y: -1 Z: -1 Normal:  X: -2.83122e-007 Y: -1 Z: -1.78814e-007 UV Point:  S: 0.333333 T: 0.333333
Vertex:  X: 1 Y: -1 Z: -1 Normal:  X: -2.83122e-007 Y: -1 Z: -1.78814e-007 UV Point:  S: 2.98023e-008 T: 0.333333
Vertex:  X: -1 Y: -1 Z: -1 Normal:  X: -2.83122e-007 Y: -1 Z: -1.78814e-007 UV Point:  S: 0.333333 T: 0.333333
Vertex:  X: 0.999999 Y: -1 Z: 1 Normal:  X: -2.83122e-007 Y: -1 Z: -1.78814e-007 UV Point:  S: 0 T: 1.29143e-007
Vertex:  X: -1 Y: -1 Z: 1 Normal:  X: -2.83122e-007 Y: -1 Z: -1.78814e-007 UV Point:  S: 0.333333 T: 0
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: -1 Y: 2.38419e-007 Z: -1.3411e-007 UV Point:  S: 0.666667 T: 8.9407e-008
Vertex:  X: -1 Y: -1 Z: -1 Normal:  X: -1 Y: 2.38419e-007 Z: -1.3411e-007 UV Point:  S: 1 T: 0.333333
Vertex:  X: -1 Y: -1 Z: 1 Normal:  X: -1 Y: 2.38419e-007 Z: -1.3411e-007 UV Point:  S: 0.666667 T: 0.333333
Vertex:  X: -1 Y: -1 Z: -1 Normal:  X: -1 Y: 2.38419e-007 Z: -1.3411e-007 UV Point:  S: 1 T: 0.333333
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: -1 Y: 2.38419e-007 Z: -1.3411e-007 UV Point:  S: 0.666667 T: 8.9407e-008
Vertex:  X: -1 Y: 1 Z: -1 Normal:  X: -1 Y: 2.38419e-007 Z: -1.3411e-007 UV Point:  S: 1 T: 0
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.333333 T: 0.666667
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.666667 T: 0.333333
Vertex:  X: -1 Y: 1 Z: -1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.666667 T: 0.666667
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.666667 T: 0.333333
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.333333 T: 0.666667
Vertex:  X: 1 Y: 0.999999 Z: 1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.333333 T: 0.333333

Texture for above Image

Original Texture http://www.guatacrazynight.com/wp-content/uploads/2014/05/Seamless-Dark-Wood-Texturevertical-Wooden-Floor-Texture-Wild-.jpg

Code Listing

Loading the image:

Here is how I load the image in (partial code listing):

glGenTextures(1, &TextureObject_ID);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, TextureObject_ID);
GLsizei iFormat = BytesPerPixel == 24 ? GL_BGR : BytesPerPixel == 8 ? GL_LUMINANCE : 0;
GLsizei iInternalFormat = BytesPerPixel == 24 ? GL_RGB : GL_DEPTH_COMPONENT;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
             WidthOfTexture, HeightOfTexture, 0, iFormat,
             GL_UNSIGNED_BYTE, bytesDataPointer);
glGenerateMipmap(GL_TEXTURE_2D);
FreeImage_Unload(loadedImage);
glGenSamplers(1, &TextureSamplerObject_ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP);
HasMipsBeenGenerated = true;
glBindTexture(GL_TEXTURE_2D, NULL);
glActiveTexture(GL_TEXTURE0);

Binding the attributes and loading into the GPU

And here is how I bind various attributes and send data to the GPU:

glGenVertexArrays(1, &Pointer_VAO);
glBindVertexArray(Pointer_VAO);

glGenBuffers(1, &Vertex_VBO);

glBindBuffer(GL_ARRAY_BUFFER, Vertex_VBO);

glBufferData(GL_ARRAY_BUFFER, TotalBufferSize, NULL, GL_STATIC_DRAW);

glBufferSubData(GL_ARRAY_BUFFER, NULL, VerticesBufferSize, Vertices);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

if (HasNormals) {
    glBufferSubData(GL_ARRAY_BUFFER, NormalOffset, NormalBufferSize, Normals);
    /*
    Set up our Attribute pointer so that our Shader knows where to get our normals.
    */
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);
}

if (HasUVs) {
    glBufferSubData(GL_ARRAY_BUFFER, UVOffset, UVBufferSize, UVs);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(2);
}

glGenBuffers(1, &MVP_VBO);
glBindBuffer(GL_ARRAY_BUFFER, MVP_VBO);
glBufferData(GL_ARRAY_BUFFER, ModelMatrixInstances.size() * sizeof(glm::mat4), NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 0));
glEnableVertexAttribArray(3);
glVertexAttribDivisor(3, 1);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 4));
glEnableVertexAttribArray(4);
glVertexAttribDivisor(4, 1);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 8));
glEnableVertexAttribArray(5);
glVertexAttribDivisor(5, 1);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(GLfloat) * 12));
glEnableVertexAttribArray(6);
glVertexAttribDivisor(6, 1);

glGenBuffers(1, &NormalMatrix_VBO);
glBindBuffer(GL_ARRAY_BUFFER, NormalMatrix_VBO);
glBufferData(GL_ARRAY_BUFFER, ModelMatrixInstances.size() * sizeof(glm::mat3), NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), (void*)(sizeof(GLfloat) * 0));
glEnableVertexAttribArray(7);
glVertexAttribDivisor(7, 1);
glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), (void*)(sizeof(GLfloat) * 3));
glEnableVertexAttribArray(8);
glVertexAttribDivisor(8, 1);
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), (void*)(sizeof(GLfloat) * 6));
glEnableVertexAttribArray(9);
glVertexAttribDivisor(9, 1);

glGenBuffers(1, &Index_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Index_VBO);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, TotalPolygonCount * 3 * sizeof(unsigned int), Indices, GL_STATIC_DRAW);

glBindVertexArray(0); 

Shaders

Vertex shader:

#version 430

layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 vNormal;
layout(location = 2) in vec2 vUV;
layout(location = 3) in mat4 ModelViewProjectionMatrix;
layout(location = 7) in mat3 NormalMatrix;

out vec3 SurfaceNormal;
out vec2 TextureCoordinates;

void main () {
    SurfaceNormal = normalize(NormalMatrix * vNormal);
    TextureCoordinates = vUV;
    gl_Position = ModelViewProjectionMatrix * vec4(vPosition, 1.0);
}

Fragment Shader:

#version 430

uniform MaterialBlock
{
    vec4    MaterialColor;
    vec4    AmbientMeshColor;
    vec4    EmmissiveMeshColor;
    vec4    DiffuseMeshColor;
    vec4    SpecularMeshColor;
    float   MeshShininess;
    float   ObjectHasMaterialFile;
} Material;

uniform float   EnableWireframe;
uniform vec4    WireframeColor;

uniform float   IfEnableMaterial;

uniform float   EnableLighting;
uniform float   EnableSun;

uniform vec3    SunDirection;
uniform vec3    LightHalfVector;
uniform vec4    SunColor;
uniform vec4    SunSpotCutoff;
uniform float   SunlightStrength;

in vec3 SurfaceNormal;
in vec2 TextureCoordinates;

uniform sampler2D MainTextureSampler;


out vec4 finalColor;

void SunlightWithMaterials() {

    vec4 MaterialTextureColor = texture2D(MainTextureSampler, TextureCoordinates);

    float DiffuseValue = max(0.0, dot(SurfaceNormal, SunDirection));
    float SpecularValue = max(0.0, dot(SurfaceNormal, LightHalfVector));
    if (DiffuseValue == 0.0) {
        SpecularValue = 0.0;
    } else {
        SpecularValue = pow(SpecularValue, Material.MeshShininess);
    }
    vec3 ScatteredLight = Material.AmbientMeshColor.rgb + (SunColor.rgb * DiffuseValue);
    vec3 ReflectedLight = SunColor.rgb * SpecularValue * SunlightStrength;
    vec3 CalculatedColor = min(MaterialTextureColor.rgb * ScatteredLight + ReflectedLight, vec3(1.0));
    finalColor = vec4(CalculatedColor, Material.MaterialColor.a);
}

void SunlightWithoutMaterials() {

    float DiffuseValue = max(0.0, dot(SurfaceNormal, SunDirection));
    float SpecularValue = max(0.0, dot(SurfaceNormal, LightHalfVector));
    if (DiffuseValue == 0.0) {
        SpecularValue = 0.0;
    } else {
        SpecularValue = pow(SpecularValue, Material.MeshShininess);
    }
    vec3 ScatteredLight = Material.AmbientMeshColor.rgb + (SunColor.rgb * DiffuseValue);
    vec3 ReflectedLight = SunColor.rgb * SpecularValue * SunlightStrength;
    vec3 CalculatedColor = min(Material.MaterialColor.rgb * ScatteredLight + ReflectedLight, vec3(1.0));
    finalColor = vec4(CalculatedColor, Material.MaterialColor.a);

    }

void main()
{
    if (EnableWireframe == 1) {
        finalColor = WireframeColor;
    } else {
        if (IfEnableMaterial == 1.0 && ObjectHasMaterialFile == 1.0) {
            if (EnableLighting == 1.0) {
                if (EnableSun == 1.0) {
                    SunlightWithMaterials();
                } 
                else {
                    vec4 MaterialTextureColor = texture2D(MainTextureSampler, TextureCoordinates);
                    finalColor = min(MaterialTextureColor * Material.AmbientMeshColor, vec4(1.0));
                }
            } 
            else {
                vec4 MaterialTextureColor = texture2D(MainTextureSampler, TextureCoordinates);
                finalColor = MaterialTextureColor;
            }
        }
        else {
            if (EnableLighting == 1.0) {
                if (EnableSun == 1.0) {
                    SunlightWithoutMaterials();
                } 
                else {
                    finalColor = min(Material.MaterialColor * Material.AmbientMeshColor, vec4(1.0));
                }
            } else {
                finalColor = Material.MaterialColor;
            }
        }
    }
}

Drawing the image in OpenGL:

glBindVertexArray(Pointer_VAO);

for (int i = 0; i < ModelMatrixInstances.size(); i++) {
    glm::mat4 ModelViewMatrix = CurrentOpenGLController->GetViewMatrix() * ModelMatrixInstances[i];
    glm::mat3 NormalMatrix = glm::transpose(glm::inverse(glm::mat3(ModelViewMatrix)));
    glm::mat4 ModelViewProjectionMatrix = CurrentOpenGLController->GetProjectionViewMatrix() * ModelMatrixInstances[i];
    glBindBuffer(GL_ARRAY_BUFFER, MVP_VBO);
    glBufferSubData(GL_ARRAY_BUFFER, (i * (sizeof(glm::mat4))), sizeof(glm::mat4), glm::value_ptr(ModelViewProjectionMatrix));
    glBindBuffer(GL_ARRAY_BUFFER, NormalMatrix_VBO);
    glBufferSubData(GL_ARRAY_BUFFER, (i * (sizeof(glm::mat3))), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));
}

if (Materials[0].HasMaterialFile == true) {
    GLfloat ObjectHasMaterial = 1.0f;
    glUniform1fv(CurrentOpenGLController->GetObjectHasMaterialFileID(), 1, &ObjectHasMaterial);
    glUniform1i(CurrentOpenGLController->GetMainTextureID(), 1);
    Materials[0].bindTexture(1);
}
else {
    glBindTexture(GL_TEXTURE_2D, NULL);
}

glBufferData(GL_UNIFORM_BUFFER, sizeof(Materials[0].ColorProperties), Materials[0].ColorProperties, GL_DYNAMIC_DRAW);

glDrawElementsInstanced(GL_TRIANGLES, TotalVertexCount, 
    GL_UNSIGNED_INT,  NULL, NumberOfChildItems + 1);

if (Materials[0].HasMaterialFile == true) {
    glActiveTexture(NULL);
    glBindTexture(GL_TEXTURE_2D, NULL);
}
1

1 Answers

1
votes

Let's take this

Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.333333 T: 0.666667
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.666667 T: 0.333333
Vertex:  X: -1 Y: 1 Z: -1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.666667 T: 0.666667
Vertex:  X: 1 Y: 1 Z: -1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.666667 T: 0.333333
Vertex:  X: -1 Y: 1 Z: 1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.333333 T: 0.666667
Vertex:  X: 1 Y: 0.999999 Z: 1 Normal:  X: 2.38419e-007 Y: 1 Z: 1.63913e-007 UV Point:  S: 0.333333 T: 0.333333

and condense that a little

    X  Z       s [1/3] t
 A -1  1 (SW)  1       2 
 B  1 -1 (NE)  2       1 
 C -1 -1 (NW)  2       2
 B  1 -1 (NE)  2       1 
 A -1  1 (SW)  1       2
 D  1  1 (SE)  1       1

Now take the points duplicated in that tessellation - A and B aka SouthWest and NorthEast.

Let say s grows from West to East, and (thus) t grows from North to South.

Thus NorthWest aka C should be at st = (1,1) and SouthEast aka D should be at st = (2,2).

But they are not. They're swapped