Texture Mapping Issue

Hello,

Using OpenGL tutorials found on opengl-tutorial, I constructed an .obj file loader as well as a texture file loader using SOIL. I have an issue with drawing a textured object. (Shown here) Assuming I created the loaders correctly, my issue is within my rendering method (actually drawing the triangles on the screen). As you can see my texture seems to bend and warp in a very strange way. I’ve asked a couple of different sources and they can’t seem to explain why it happens. My (admittedly messy) code is like this:

Shaders:

    #version 120
    //VShader
    attribute vec3 verPos;
    attribute vec2 UV;

    varying vec2 f_UV;
    varying vec3 normal;
    uniform mat4 comb;

    void main()
    {     
        normal = gl_Normal;
        vec4 v = vec4(verPos, 1.0);
	    gl_Position = comb * v;   
        f_UV = UV;
    }

    #version 120
    //FShader
    uniform sampler2D TextSamp2D;
    varying vec3 normal;

    varying vec2 f_UV;


    void main()
    {
        gl_FragColor = texture2D(TextSamp2D, f_UV);
    }

And just in case the view/projection matrices matter, I will include this little tidbit of code as well.

camera::camera(){
        projectionMatrix = glm::perspective(45.0f, float(640) / float(480), 0.1f, 1000.0f);
        viewMatrix = glm::mat4(1.0);
    }
    void camera::setPos(glm::vec3 nPos){
        myPos = nPos;
    }
    void camera::setProjectionMatrix(float fov, float scHeight, float scWidth, float disC, float disF){
        projectionMatrix = glm::perspective(fov, scHeight/scWidth, disC, disF);
    }

The view matrix is updated by throwing this into the viewMatrix property of a camera instantiated as mainCamera:

mainCamera.viewMatrix = glm::lookAt(myPos, myPos + forwardVec, glm::vec3(0,1,0));

And this is my renderer, this is run every frame (no I don’t frame limit, but my computer is super junky, hence the GLSL 120) :

void obj3D::Draw(){
        if(!loaded) return;
        glDepthMask(GL_TRUE);
        glUseProgram(myProgID);
        
        glm::mat4 modelTrans = glm::translate(myPosition);
        glm::quat myQuat;
        myQuat = glm::quat(myAngle);
        glm::mat4 modelRot = glm::toMat4(myQuat);
        glm::mat4 modelScale = glm::scale(myScale);
        glm::mat4 model = modelTrans * modelRot * modelScale;

        glm::mat4 comb = mainCamera.projectionMatrix * mainCamera.viewMatrix * model;
        GLuint matrixID = glGetUniformLocation(myProgID, "comb");
        glUniformMatrix4fv(matrixID, 1, GL_FALSE, &comb[0][0]);
        
        glActiveTexture(GL_TEXTURE0 + 0);
        //myTexture is the texture ID after it is 
        //loaded into OpenGL, it's a member of  the object class
        glBindTexture(GL_TEXTURE_2D, myTexture);
        glUniform1i(shaderTextureID, 0);
        
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
        glVertexAttribPointer(
            0, 
            3, 
            GL_FLOAT,
            GL_FALSE,
            0, 
            (GLvoid*)0
        );
            
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
        glVertexAttribPointer(
            1, 
            2, 
            GL_FLOAT,
            GL_FALSE,
            0, 
            (GLvoid*)0
        );
            
        glEnableVertexAttribArray(2);
        glBindBuffer(GL_ARRAY_BUFFER, nBuffer);
        glVertexAttribPointer(
            2,                                // attribute
            3,                                // size
            GL_FLOAT,                         // type
            GL_FALSE,                         // normalized?
            0,                                // stride
            (GLvoid*)0                          // array buffer offset
        );
        
        glDrawArrays(GL_TRIANGLES, 0, numTriangles);
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(2);
    }

My question is, why does the texture bend and warp when I rotate the view matrix on the y axis? That is, at what horrifically easy juncture did I go so wrong?

Thanks,

Devmane144

[QUOTE=devmane144;1270156]…my texture seems to bend and warp in a very strange way. …
My question is, why does the texture bend and warp when I rotate the view matrix on the y axis? That is, at what horrifically easy juncture did I go so wrong?[/QUOTE]

Have you tried removing modelScale from your modeling transform?

Thanks for the quick response,

Yes I tried it just now. And although my player model got smaller, the sky-cube I have was already it’s regular size. The texture warping still occurred.

Devmane144

[QUOTE=devmane144;1270186]Thanks for the quick response,

Yes I tried it just now. And although my player model got smaller, the sky-cube I have was already it’s regular size. The texture warping still occurred.

Devmane144[/QUOTE]

Do you have any other ideas?

You might try just rendering the texture coordinate UVs into your color channels (e.g. into red and green). That might help diagnose whether it is the texture that’s the problem or the texture coordinate mapping to the vertices.

Brilliant idea. So I channelled the UVs into the gl_FragColor and found out that as I turn the UV coordinates seem to bend as well. So why is it that the vertex coordinates do not bend but the UVs seem to?

The effect is a lot like I’d expect if you use quads with a non-affine mapping (e.g. map a rectangular polygon to a non-rectangular region of the texture).

If you’re using quads, try changing them to triangles. The texture mapping will still have kinks, but they won’t change with the camera angle.

[QUOTE=GClements;1271201]The effect is a lot like I’d expect if you use quads with a non-affine mapping (e.g. map a rectangular polygon to a non-rectangular region of the texture).

If you’re using quads, try changing them to triangles. The texture mapping will still have kinks, but they won’t change with the camera angle.[/QUOTE]

I took some time to look up this issue, and it seems to fit with my problem, but how would I go about fixing this?

Use triangles rather than quads. If you need something other than an affine or projective mapping (e.g. bilinear mapping), you need to implement it yourself in the fragment shader.

One of the reasons that quads were removed from modern OpenGL is that the mapping was never specified or standardised.

[QUOTE=GClements;1271446]Use triangles rather than quads. If you need something other than an affine or projective mapping (e.g. bilinear mapping), you need to implement it yourself in the fragment shader.

One of the reasons that quads were removed from modern OpenGL is that the mapping was never specified or standardised.[/QUOTE]

I actually am not using quads. I use triangles because I figured I wouldn’t ever be able to use quads in some model with sharp corners. How would I turn on/simulate perspective correction manually?

Devmane144

In which case, the issue wasn’t what I suggested. For a triangle the mapping is automatically affine; it cannot be otherwise.

So if I changed all of my geometry to quads, would it stop warping the textures?

No, GClements was saying that if the geometry were quads, it could be causing the problem. If it’s all tris the mapping shouldn’t be non-affine.

So I used some other UVs from here to see if it was something to do with my obj loader. The UV’s aren’t loaded incorrectly. Also adding

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

didn’t work either. I keep on seeing the affine problem. But if you’re correct the triangles I’m rendering shouldn’t have that problem, correct? So my second find was that projection matrices can mess this up, but I was under the impression that GLM was pretty stable. I looked into 4d texture mapping, but I’m not quite sure where to even begin to try to use that.

Devmane144

It shouldn’t matter if they were. So long as the data is constant, and the geometry consists of triangles, there really isn’t anything which should cause the texture to warp like that.

[QUOTE=devmane144;1271501]Also adding

glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

didn’t work either.[/QUOTE].
In theory, that setting could be relevant. In practice, every OpenGL implementation does perspective-correct interpolation (unless you’re using a shader which specifically uses the “noperspective” qualifier).

Just be be sure, try changing the [var]transpose[/var] parameter in the glUniformMatrix4fv() call to GL_TRUE (a typical perspective projection is close to being symmetric about the main diagonal, so it’s possible that a transposed matrix could result in something that was merely “odd” rather than completely unrecognisable).

It’s not useful unless you’re performing texture projection (e.g. trying to re-create the effect of a projector or a flashlight).

I don’t even think I can possibly do this using glsl 120 can I? Unless of course I did some voodoo black magic. I’ve read that using the varying keyword might bug it out but I don’t really think that plays a big role in this.

I’d have to say that this did indeed turn out “odd” :biggrin-new:

I’m just not sure where to go from here to be honest, I’ve done a lot of searching. I’m not thinking it’s the filtering of the textures at all; that only affects the clarity of the image as far as I can see. Do you think it could be a driver issue that’s fixable without buying new hardware?

You could try disabling filtering (i.e. setting both the min/mag filters to GL_NEAREST), just to check.

I would assume that it’s an issue in your code. You don’t appear to be doing anything unusual, yet the driver presumably works with other OpenGL programs.

Try to simplify your program to the bare minimum amount of code which still exhibits the problem (in particular, get rid of all of the OOP stuff), then post the complete code. When the issue isn’t apparent, often it’s because it’s not actually in the portion of the code which was posted.

[QUOTE=GClements;1271506]You could try disabling filtering (i.e. setting both the min/mag filters to GL_NEAREST), just to check.

I would assume that it’s an issue in your code. You don’t appear to be doing anything unusual, yet the driver presumably works with other OpenGL programs.

Try to simplify your program to the bare minimum amount of code which still exhibits the problem (in particular, get rid of all of the OOP stuff), then post the complete code. When the issue isn’t apparent, often it’s because it’s not actually in the portion of the code which was posted.[/QUOTE]

Okay, so I took an hour or two today to isolate the code with my OpenGL involved. I also decided that it was best to just hard code the attribute coordinates rather than include all of the OBJ loader code. Here’s the code:

Vertex Shader

#version 120
attribute vec3 verPos;
attribute vec2 UV;

varying vec2 f_UV;

uniform mat4 MVP;

void main()
{     
    vec4 v = vec4(verPos, 1.0);
	v = MVP * v;
    gl_Position = v;
    f_UV = UV;
}

Fragment Shader

#version 120

uniform sampler2D TextSamp2D;
varying vec2 f_UV;

void main()
{
    gl_FragColor = texture2D(TextSamp2D, f_UV);
}

And here is the major bulky code that is the main file. In the zip I’ve included it’s example.cpp:

#include <fstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cmath>
#define GLM_FORCE_RADIANS
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include <SDL2/SDL_opengl.h>
#include "SDL2/SDL_image.h"
#include "SOIL/SOIL.h"

bool initGL();
void close();
void Move();
GLuint loadImage(const char*);
GLuint LoadShaders(const char*, const char*);

//The window we'll be rendering to
SDL_Window* window = NULL;

SDL_GLContext glContext;

//Screen dimension constants
bool gameRunning = true;                       
bool arrows[] = {0, 0, 0, 0};

GLuint programID;

glm::vec3 direction;
glm::vec3 myPos;
glm::vec3 myAngle;
glm::vec3 forwardVec;

glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 1000.0f);
glm::mat4 viewMatrix = glm::mat4(1.0f);

int main(int argc, char* args[]){
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
		std::cout << "Init Error: " << SDL_GetError() << std::endl;
        gameRunning = false;
	}
    
    window = SDL_CreateWindow("Eximius", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    
	if(window == NULL){
	    printf("Window could not be created! SDL_Error: %s
", SDL_GetError());
        gameRunning = false;
	}
	if(!initGL()){
		std::cout << "OpenGL Init Failed" << std::endl;
        gameRunning = false;
	}

    SDL_Event e;
    
    programID = LoadShaders("vshade.txt", "fshade.txt");
    
    myPos.y = 0.0f;
    
    static const GLfloat g_vertex_buffer_data[] = { 
		-1.0f,-1.0f,-1.0f,
		-1.0f,-1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f,-1.0f,
		 1.0f,-1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f,
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		 1.0f,-1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f,-1.0f,
		 1.0f,-1.0f, 1.0f,
		-1.0f,-1.0f, 1.0f,
		-1.0f,-1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		-1.0f,-1.0f, 1.0f,
		 1.0f,-1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f,-1.0f,
		 1.0f,-1.0f,-1.0f,
		 1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f,-1.0f,
		-1.0f, 1.0f,-1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f,-1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f, 1.0f, 1.0f,
		-1.0f, 1.0f, 1.0f,
		 1.0f,-1.0f, 1.0f
	};

    static const GLfloat g_uv_buffer_data[] = { 
		0.000059f, 1.0f-0.000004f, 
		0.000103f, 1.0f-0.336048f, 
		0.335973f, 1.0f-0.335903f, 
		1.000023f, 1.0f-0.000013f, 
		0.667979f, 1.0f-0.335851f, 
		0.999958f, 1.0f-0.336064f, 
		0.667979f, 1.0f-0.335851f, 
		0.336024f, 1.0f-0.671877f, 
		0.667969f, 1.0f-0.671889f, 
		1.000023f, 1.0f-0.000013f, 
		0.668104f, 1.0f-0.000013f, 
		0.667979f, 1.0f-0.335851f, 
		0.000059f, 1.0f-0.000004f, 
		0.335973f, 1.0f-0.335903f, 
		0.336098f, 1.0f-0.000071f, 
		0.667979f, 1.0f-0.335851f, 
		0.335973f, 1.0f-0.335903f, 
		0.336024f, 1.0f-0.671877f, 
		1.000004f, 1.0f-0.671847f, 
		0.999958f, 1.0f-0.336064f, 
		0.667979f, 1.0f-0.335851f, 
		0.668104f, 1.0f-0.000013f, 
		0.335973f, 1.0f-0.335903f, 
		0.667979f, 1.0f-0.335851f, 
		0.335973f, 1.0f-0.335903f, 
		0.668104f, 1.0f-0.000013f, 
		0.336098f, 1.0f-0.000071f, 
		0.000103f, 1.0f-0.336048f, 
		0.000004f, 1.0f-0.671870f, 
		0.336024f, 1.0f-0.671877f, 
		0.000103f, 1.0f-0.336048f, 
		0.336024f, 1.0f-0.671877f, 
		0.335973f, 1.0f-0.335903f, 
		0.667969f, 1.0f-0.671889f, 
		1.000004f, 1.0f-0.671847f, 
		0.667979f, 1.0f-0.335851f
	};
    GLuint vBuffer;
	glGenBuffers(1, &vBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

	GLuint uvBuffer;
	glGenBuffers(1, &uvBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(g_uv_buffer_data), g_uv_buffer_data, GL_STATIC_DRAW);

    GLuint tex;
    tex = loadImage("uvtemplate.tga");

    GLuint verPosAttrib = glGetAttribLocation(programID, "verPos");
	GLuint UVAttrib = glGetAttribLocation(programID, "UV");
    GLuint sampID = glGetAttribLocation(programID, "TextSamp2D");
    GLuint mvpID = glGetUniformLocation(programID, "MVP");
    float i = 0.0f;
    
    myPos.z = 20.0f;
    while(gameRunning){
        Move();
        
        forwardVec = glm::vec3(-sin(glm::radians(myAngle.y)), 0.0f, -cos(glm::radians(myAngle.y)));
        glUseProgram(programID);
        
        viewMatrix = glm::lookAt(myPos, myPos + forwardVec, glm::vec3(0,1,0));
        
        glDepthMask(GL_TRUE);
        
        glUniform1i(sampID, 0);
        
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);     
        
        //Just the scale of the model matrix
        glm::mat4 modelScale = glm::scale(glm::vec3(5.0f, 5.0f, 5.0f));
        i += 0.01f;
        glm::quat myQuat;
        myQuat = glm::quat(myAngle);
        glm::mat4 modelRot = glm::eulerAngleYXZ(i, 0.0f, 0.0f);
        
        glm::mat4 model = modelScale * modelRot;
        glm::mat4 MVP = projectionMatrix * viewMatrix * model;
        glUniformMatrix4fv(mvpID, 1, GL_FALSE, &MVP[0][0]);
        
        glEnableVertexAttribArray(verPosAttrib);
        glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
        glVertexAttribPointer(
            verPosAttrib, 
            3, 
            GL_FLOAT,
            GL_FALSE,
            0, 
            (GLvoid*)0
        );
        
        glEnableVertexAttribArray(UVAttrib);
        glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
        glVertexAttribPointer(
            UVAttrib,
            2, 
            GL_FLOAT,
            GL_FALSE,
            0, 
            (GLvoid*)0
        );
	
        glActiveTexture(GL_TEXTURE0 + 0);
        glBindTexture(GL_TEXTURE_2D, tex);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

        glDrawArrays(GL_TRIANGLES, 0, 36);
        
        SDL_GL_SwapWindow(window);
        
        glDisableVertexAttribArray(verPosAttrib);
        glDisableVertexAttribArray(UVAttrib);

        while(SDL_PollEvent(&e) != 0){
            if(e.type == SDL_QUIT){
                gameRunning = false;
            }
            else if(e.type == SDL_KEYDOWN){
                switch(e.key.keysym.sym){
                    case SDLK_DOWN:
                        arrows[3] = true;
                    break;
                    case SDLK_LEFT:
                        arrows[2] = true;
                    break;
                    case SDLK_RIGHT:
                        arrows[0] = true;
                    break;
                    case SDLK_UP:
                        arrows[1] = true;
                    break;
                }
            }
            else if(e.type == SDL_KEYUP){
                switch(e.key.keysym.sym){
                    case SDLK_DOWN:
                        arrows[3] = false;
                    break;
                    case SDLK_LEFT:
                        arrows[2] = false;
                    break;
                    case SDLK_RIGHT:
                        arrows[0] = false;
                    break;
                    case SDLK_UP:
                        arrows[1] = false;
                    break;
                }
            }
        }
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
	close();
	return 0;
}
bool initGL(){
	glContext = SDL_GL_CreateContext(window);
    
    if(glContext == NULL){
        std::cout << "OpenGL context Failed: " << SDL_GetError() << std::endl;
		return false;
    }
    
    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if(GLEW_OK != err){
        std::cout << "GLEW FAILED" << glewGetErrorString(err) << std::endl;
        return false;
    }
    if(glewIsSupported("GL_VERSION_4_0")){
        printf("Ready for OpenGL 4.0
");
    }
    
    GLuint vaID;
    glGenVertexArrays(1, &vaID);
    glBindVertexArray(vaID);
   
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
    
    SDL_GL_SetSwapInterval(1);
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
   	
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glDepthFunc(GL_LEQUAL);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	
	return true;
}
void close(){
    //Destroy window
	SDL_DestroyWindow(window);
    SDL_GL_DeleteContext(glContext);
	//IMG_Quit();
	SDL_Quit();
}
GLuint loadImage(const char * image){
    GLuint texID;
    glActiveTexture(GL_TEXTURE_2D);

    texID = SOIL_load_OGL_texture(image, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB);
    glBindTexture(GL_TEXTURE_2D, texID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    if(texID == 0){
        std::cout << "FAILED TO LOAD TEXTURE" << std::endl;
    }
    else return texID;
}

GLuint LoadShaders(const char * vertexFPath, const char * fragmentFPath){
    GLuint vSID = glCreateShader(GL_VERTEX_SHADER);
    GLuint fSID = glCreateShader(GL_FRAGMENT_SHADER);

    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertexFPath, std::ios::in);
    if(VertexShaderStream.is_open()){
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "
" + Line;
        VertexShaderStream.close();
    }
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragmentFPath, std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            FragmentShaderCode += "
" + Line;
        FragmentShaderStream.close();
    }
    GLint Result = GL_FALSE;
    int InfoLogLength;
    
    std::cout << "Compiling Shader: " << vertexFPath << std::endl;
    char const * VSource = VertexShaderCode.c_str();
    glShaderSource(vSID, 1, &VSource, NULL);
    glCompileShader(vSID);
    
    glGetShaderiv(vSID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(vSID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(vSID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s
", &VertexShaderErrorMessage[0]);
    
    
    std::cout << "Compiling Shader: " << fragmentFPath << std::endl;
    char const * FSource = FragmentShaderCode.c_str();
    glShaderSource(fSID, 1, &FSource, NULL);
    glCompileShader(fSID);
    
    glGetShaderiv(fSID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(fSID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(fSID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s
", &FragmentShaderErrorMessage[0]);
    
    std::cout << "Linking Program" << std::endl;
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, vSID);
    glAttachShader(ProgramID, fSID);
    glLinkProgram(ProgramID);
    
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage(std::max(InfoLogLength, int(1)));
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s
", &ProgramErrorMessage[0]);
    
    glDeleteShader(vSID);
    glDeleteShader(fSID);
    return ProgramID;
}

void Move(){
    if(arrows[0]){
        myAngle -= glm::radians(45.f);
    }
    if(arrows[1]){
        myPos = myPos + forwardVec * 0.2f;
    }
    if(arrows[2]){
       myAngle.y += glm::radians(45.f);
    }
    if(arrows[3]){
        myPos = myPos - forwardVec * 0.2f;
    }
}

And now that we’ve reached the end of that nightmare of a copy and paste…

All of the code files and a makefile are included with this zip. It should run on Linux as long as all of the libraries it needs are there. It should include SOIL, OpenGL, SDL, GLM, SDL_image, GLEW, and GLU.

That works fine for me (Linux/x86-64, Mesa 10.3.7). You’re getting texture warping?

I am. However, have you used the arrow keys to move around at all? If you get a bit closer, the issue is more apparent. If you just tap the forward arrow a bit it’ll get you close enough. (Depending on hardware you might overshoot it by like 3000 miles…) It’s really subtle with that particular texture. With other ones I’ve had “lava” effects as my friend told me.