Advertisement

Textures, Pixel Alignment And Texture Mistakes. What Am I Doing Wrong?

Started by January 18, 2019 06:34 PM
16 comments, last by babaliaris 5 years, 8 months ago

So, I'm trying to solve this problem for months. I have already opened relative threads for this but now that I learned a lot of stuff  I still seek your help for this one. What I learned so far when dealing with texture Uploading and Pixel Reads:

1) Make sure how many channels the source image file has in order to configure the glTexImage2D() to read the data correctly.

2) Make sure that the width * num_OfChannels of the image is multiple of 4, so you won't have problems with the alignment. (OpenGL Common Mistakes, Texture Upload And Pixel Reads)

3) Forcing any kind of texture (R, RG, RGB) to have exactly 4 channels ALWAYS works (But you waste a lot of memory)!!!

 

 

Below, I'm going to show you step by step what I tried and what glitches are occurring, NOTICE that even if I'm creating more than one textures I ONLY render the first one a.jpg:

First check out my texture code. As you can see I'm configuring glTexImage2D() to read pixel data based on how many channels they have (I'm only using textures with 3 and 4 channels) and I already made sure that the width * channels for each image is multiple of 4.


#include "texture.h"
#include "stb_image/stb_image.h"
#include "glcall.h"
#include "engine_error.h"
#include <math.h>



Texture::Texture(std::string path, bool trans, int unit)
{

	//Reverse the pixels.
	stbi_set_flip_vertically_on_load(1);

	//Try to load the image.
	unsigned char *data = stbi_load(path.c_str(), &m_width, &m_height, &m_channels, 0);

	//Debug.
	float check = (m_width * m_channels) / 4.0f;
	printf("file: %20s \tchannels: %d, Divisible by 4: %s, width: %d,  height: %d,  widthXheight: %d\n", 
		path.c_str(), m_channels, check == ceilf(check) ? "yes" : "no", m_width, m_height, m_width * m_height);
	
	/*
	//The length of the pixes row is multiple of 4.
	if ( check == ceilf(check) )
	{
		GLCall(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
	}

	//It's NOT!!!!
	else
	{
		GLCall(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
	}
	*/
	


	//Image loaded successfully.
	if (data)
	{

		//Generate the texture and bind it.
		GLCall(glGenTextures(1, &m_id));
		GLCall(glBindTexture(GL_TEXTURE_2D, m_id));

		
		//Not Transparent texture.
		if (m_channels == 3)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data));
		}

		//Transparent texture.
		else if (m_channels == 4)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
		}

		else
		{
			throw EngineError("Unsupported Channels!!!");
		}

		//Texture Filters.
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));

		//Generate mipmaps.
		GLCall(glGenerateMipmap(GL_TEXTURE_2D));
	}


	//Loading Failed.
	else
		throw EngineError("The was an error loading image: " + path);



	//Unbind the texture.
	GLCall(glBindTexture(GL_TEXTURE_2D, 0));

	//Free the image data.
	stbi_image_free(data);
}


Texture::~Texture()
{
	GLCall(glDeleteTextures(1, &m_id));
}

void Texture::Bind(int unit)
{
	GLCall(glActiveTexture(GL_TEXTURE0 + unit));
	GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
}

 

Now Check out the Main.cpp File


#include "Renderer.h"
#include "camera.h"

Camera *camera;

//Handle Key Input.
void HandleInput(GLFWwindow *window)
{

	//Exit the application with ESCAPE KEY.
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, 1);


	//Move Forward.
	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
		camera->Move(true);

	//Move Backward.
	if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
		camera->Move(false, true);

	//Move left.
	if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
		camera->Move(false, false, true);

	//Move right.
	if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
		camera->Move(false, false, false, true);
}



//Mouse Input.
void MouseInput(GLFWwindow *window, double x, double y)
{
	camera->UpdateRotation(x, y);
}



//Mouse Zoom input.
void MouseZoom(GLFWwindow *window, double x, double y)
{
	camera->UpdateZoom(x, y);
}



int main(void)
{
	GLFWwindow* window;

	/* Initialize the library */
	if (!glfwInit())
		return -1;


	//Use openGL version 3.3 Core Profile.
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	/* Create a windowed mode window and its OpenGL context */
	window = glfwCreateWindow(800, 600, "Hello World", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	/* Make the window's context current */
	glfwMakeContextCurrent(window);


	//Initialize GLEW.
	if (glewInit() != GLEW_OK)
	{
		glfwTerminate();
		return -1;
	}

	//Set Callback functions.
	glfwSetCursorPosCallback(window, MouseInput);
	glfwSetScrollCallback(window, MouseZoom);

	//Disable the cursor.
	glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

	//Enable Depth Test.
	GLCall(glEnable(GL_DEPTH_TEST));


	//Get the max texture size.
	GLint size;
	GLCall(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
	std::cout << "Texture Max Size: "<< size << std::endl;


	camera             = new Camera(glm::vec3(0.0f, 0.0f, 3.0f));
	Renderer *renderer = new Renderer();
	Shader *shader     = new Shader("Shaders/basic_vertex.glsl", "Shaders/basic_fragment.glsl");


	Texture *texture1 = new Texture("Resources/a.jpg", false);
	Texture *texture2 = new Texture("Resources/container.jpg", false);
	Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	Texture *texture4 = new Texture("Resources/brick3.jpg", false);

	//Forget this texture.
	//Texture *texture5 = new Texture("Resources/brick4.jpg", false);

	Texture *texture6 = new Texture("Resources/container2.png", true);


	/* Loop until the user closes the window */
	while (!glfwWindowShouldClose(window))
	{

		//Handle input.
		HandleInput(window);

		//Clear the screen.
		renderer->ClearScreen(0.0f, 0.0f, 0.0f);

		//Render the cube.
		renderer->Render(texture1, shader, camera);

		//Update.
		renderer->Update(window);
	}


	//-------------Clean Up-------------//
	delete camera;
	delete renderer;
	delete shader;

	//forget about textures for now.
	//-------------Clean Up-------------//


	glfwTerminate();
	return 0;
}

 

I will put the code of the rest classes and the glsl shaders at the end if you want to check them out, but i assure you that they work just fine.

Now if i run the code below I'm getting this:

Capture.png

 

Now lets see what happens if I'm loading the textures one by one starting from the first one which is the only one i render.

 

Attempt 1:


	Texture *texture1 = new Texture("Resources/a.jpg", false);
	//Texture *texture2 = new Texture("Resources/container.jpg", false);
	//Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	//Texture *texture4 = new Texture("Resources/brick3.jpg", false);

	//Forget this texture.
	//Texture *texture5 = new Texture("Resources/brick4.jpg", false);

	//Texture *texture6 = new Texture("Resources/container2.png", true);

Capture.png

 

Attempt 2:


	Texture *texture1 = new Texture("Resources/a.jpg", false);
	Texture *texture2 = new Texture("Resources/container.jpg", false);
	//Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	//Texture *texture4 = new Texture("Resources/brick3.jpg", false);

	//Forget this texture.
	//Texture *texture5 = new Texture("Resources/brick4.jpg", false);

	//Texture *texture6 = new Texture("Resources/container2.png", true);

Capture.png

 

Attempt 3:


	Texture *texture1 = new Texture("Resources/a.jpg", false);
	Texture *texture2 = new Texture("Resources/container.jpg", false);
	Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	//Texture *texture4 = new Texture("Resources/brick3.jpg", false);

	//Forget this texture.
	//Texture *texture5 = new Texture("Resources/brick4.jpg", false);

	//Texture *texture6 = new Texture("Resources/container2.png", true);

Capture.png

 

Attempt 4 (Orange Glitch Appears)


	Texture *texture1 = new Texture("Resources/a.jpg", false);
	Texture *texture2 = new Texture("Resources/container.jpg", false);
	Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	Texture *texture4 = new Texture("Resources/brick3.jpg", false);

	//Forget this texture.
	//Texture *texture5 = new Texture("Resources/brick4.jpg", false);

	//Texture *texture6 = new Texture("Resources/container2.png", true);

Capture.png

 

Attempt 5 (Grey Glitch Appears)


	Texture *texture1 = new Texture("Resources/a.jpg", false);
	Texture *texture2 = new Texture("Resources/container.jpg", false);
	Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	Texture *texture4 = new Texture("Resources/brick3.jpg", false);

	//Forget this texture.
	//Texture *texture5 = new Texture("Resources/brick4.jpg", false);

	Texture *texture6 = new Texture("Resources/container2.png", true);

Capture.png

 

If you see it, they only texture which I'm rendering is the first one, so how can the loading of the rest textures affect the rendering, since I'm not using them? (I'm binding the first texture before every draw call, you can check it out in the renderer class). This is so weird I literally can't think anything that causes the problem.

 

Now check this out. I'm going to run Attempt 5 again but with these changes in the Texture class (I'm going to Force 4 channels no matter what the source file's channels?


#include "texture.h"
#include "stb_image/stb_image.h"
#include "glcall.h"
#include "engine_error.h"
#include <math.h>



Texture::Texture(std::string path, bool trans, int unit)
{

	//Reverse the pixels.
	stbi_set_flip_vertically_on_load(1);

	//Try to load the image.
	unsigned char *data = stbi_load(path.c_str(), &m_width, &m_height, &m_channels, 4); //FORCE 4 CHANNELS.

	//Debug.
	float check = (m_width * m_channels) / 4.0f;
	printf("file: %20s \tchannels: %d, Divisible by 4: %s, width: %d,  height: %d,  widthXheight: %d\n", 
		path.c_str(), m_channels, check == ceilf(check) ? "yes" : "no", m_width, m_height, m_width * m_height);
	
	/*
	//The length of the pixes row is multiple of 4.
	if ( check == ceilf(check) )
	{
		GLCall(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
	}

	//It's NOT!!!!
	else
	{
		GLCall(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
	}
	*/
	


	//Image loaded successfully.
	if (data)
	{

		//Generate the texture and bind it.
		GLCall(glGenTextures(1, &m_id));
		GLCall(glBindTexture(GL_TEXTURE_2D, m_id));

		/*
		//Not Transparent texture.
		if (m_channels == 3)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data));
		}

		//Transparent texture.
		else if (m_channels == 4)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
		}

		else
		{
			throw EngineError("Unsupported Channels!!!");
		}
		*/

		GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));

		//Texture Filters.
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));

		//Generate mipmaps.
		GLCall(glGenerateMipmap(GL_TEXTURE_2D));
	}


	//Loading Failed.
	else
		throw EngineError("The was an error loading image: " + path);



	//Unbind the texture.
	GLCall(glBindTexture(GL_TEXTURE_2D, 0));

	//Free the image data.
	stbi_image_free(data);
}


Texture::~Texture()
{
	GLCall(glDeleteTextures(1, &m_id));
}

void Texture::Bind(int unit)
{
	GLCall(glActiveTexture(GL_TEXTURE0 + unit));
	GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
}

Capture.png

Rendering is what I expected!

But I still can't understand why this fixes it. In the first version of my texture class, which I don't force 4 channels but instead I'm using the default channels, I'm configuring glTexImage2D the right way based on the source files channels and also I'm SURE that the width * channels of each image file is multiple of 4.But again in the second version of my texture class, which solve's the problem my mind is thinking again that this might be an alignment problem but it's not, I made sure of that.

So what else can cause such a problem? Does anybody knows the answer?

 

Below you will find the rest of the code:

Vertex Shader:


#version 330 core

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;


out vec2 TexCoord;

void main()
{
	gl_Position = proj * view * model * vec4(aPos, 1.0);

	TexCoord = aTexCoord;
}

 

Fragment Shader:


#version 330 core

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;


out vec2 TexCoord;

void main()
{
	gl_Position = proj * view * model * vec4(aPos, 1.0);

	TexCoord = aTexCoord;
}

 

Renderer Class:


#include "Renderer.h"


Renderer::Renderer()
{

	//Vertex Data.
	float vertices[] = {

		// positions          // normals           // texture coords
		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,
		 0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
		-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,
		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,

		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,
		 0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 0.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,
		-0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 1.0f,
		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,

		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
		-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 1.0f,
		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 0.0f,
		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,

		 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
		 0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 1.0f,
		 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		 0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 0.0f,
		 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,

		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,
		 0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 1.0f,
		 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,
		 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,
		-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 0.0f,
		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,

		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 1.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,
		-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,
		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f
	};


	//Generate a VAO and a VBO.
	GLCall(glGenVertexArrays(1, &m_VAO));
	GLCall(glGenBuffers(1, &m_VBO));

	//Bind VAO and VBO.
	GLCall(glBindVertexArray(m_VAO));
	GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_VBO));

	//Transfer The Data.
	GLCall(glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW));

	//Positions.
	GLCall(glEnableVertexAttribArray(0));
	GLCall(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (void *)0));

	//Normals.
	GLCall(glEnableVertexAttribArray(1));
	GLCall(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (void *) 12));

	//Texture Coordinates.
	GLCall(glEnableVertexAttribArray(2));
	GLCall(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 8, (void *) 24));

	//Unbind The Buffers.
	GLCall(glBindVertexArray(0));
	GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));
}





Renderer::~Renderer()
{
}





void Renderer::ClearScreen(float r, float g, float b)
{
	GLCall(glClearColor(r, g, b, 1.0f));
	GLCall(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}





void Renderer::Update(GLFWwindow * window)
{
	glfwSwapBuffers(window);
	glfwPollEvents();
}





void Renderer::Render(Texture *texture, Shader *program, Camera *camera)
{

	//Bind VAO.
	GLCall(glBindVertexArray(m_VAO));

	//Bind The Program.
	program->Bind();

	//Set the unit to be used on the shader.
	program->SetUniform1i("diffuse", 0);

	//Bind the texture at unit zero.
	texture->Bind(0);

	glm::mat4 model = glm::mat4(1.0f);
	glm::mat4 view  = glm::mat4(1.0f);
	glm::mat4 proj  = glm::mat4(1.0f);

	//Get The View Matrix.
	view = camera->GetView();

	//Create The Perspective Projection.
	proj = glm::perspective(glm::radians(camera->m_fov), 800.0f / 600, 0.1f, 100.0f);

	//Set the transformation uniforms.
	program->SetUniformMat4f("model", model);
	program->SetUniformMat4f("view", view);
	program->SetUniformMat4f("proj", proj);

	//Draw Call.
	GLCall(glDrawArrays(GL_TRIANGLES, 0, 36));
}

 

 

 

Shader Class:


#include "shader.h"
#include "glcall.h"
#include "engine_error.h"
#include <fstream>
#include <string>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>


struct ShaderSource 
{
	std::string vertex_src;
	std::string fragment_src;
};


static void ReadSources(std::string filename, bool is_vertex, struct ShaderSource *src)
{

	//Create a file object.
	std::ifstream file;

	//Open the file.
	file.open(filename, std::ios::in);

	//If the file opened successfully read it.
	if (file.is_open())
	{

		//Size of the file.
		file.seekg(0, std::ios::end);
		std::streampos size = file.tellg();
		file.seekg(0, std::ios::beg);

		//Allocate memory to store the data.
		char *data = (char *)malloc(sizeof(char) * (size + (std::streampos)1) );

		//Read the data from the file.
		file.read(data, size);

		//Close the string.
		data[file.gcount()] = '\0';

		//Close the file.
		file.close();

		//This was the vertex file.
		if (is_vertex)
			src->vertex_src = (const char *)data;

		//This was the fragment file.
		else
			src->fragment_src = (const char *)data;

		//Release the memory for the data since I coppied them into the ShaderSource structure.
		free(data);
	}


	//Problem opening the file.
	else
		throw EngineError("There was a problem opening the file: " + filename);
}





static unsigned int CompileShader(std::string source, GLenum type)
{

	//__________Local Variables__________//
	int length, success;
	//__________Local Variables__________//


	//Create the shader object.
	GLCall(unsigned int shader = glCreateShader(type));

	//std::string to const c string.
	const char *src = source.c_str();

	//Copy the source code into the shader object.
	GLCall(glShaderSource(shader, 1, &src, NULL));

	//Compile the shader.
	GLCall(glCompileShader(shader));

	//Get the shader info length.
	GLCall(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length));

	//Get the shader compilations status.
	GLCall(glGetShaderiv(shader, GL_COMPILE_STATUS, &success));


	//Compilation Failed.
	if (!success)
	{

		//Error string.
		std::string error;

		//Allocate memory for the info log.
		char *info = (char *)malloc(sizeof(char) * (length+1) );

		//Get the info.
		GLCall(glGetShaderInfoLog(shader, length, NULL, info));

		//Terminate the string.
		info[length] = '\0';

		//Initialize the error message as vertex compilation error.
		if (type == GL_VERTEX_SHADER)
			error = "Vertex Shader compilations error: ";

		//Initialize the error message as fragment compilation error.
		else
			error = "Fragment Shader compilation error: ";

		//Add the info log to the message.
		error += info;

		//Free info.
		free(info);

		//Throw a message error.
		throw EngineError(error);
	}

	return shader;
}





static unsigned int CreateProgram(ShaderSource &src)
{

	//__________Local Variables__________//
	int length, success;
	//__________Local Variables__________//

	unsigned int program = glCreateProgram();

	unsigned int vertex_shader   = CompileShader(src.vertex_src, GL_VERTEX_SHADER);
	unsigned int fragment_shader = CompileShader(src.fragment_src, GL_FRAGMENT_SHADER);

	GLCall(glAttachShader(program, vertex_shader));
	GLCall(glAttachShader(program, fragment_shader));

	GLCall(glLinkProgram(program));
	GLCall(glValidateProgram(program));



	//Get the shader info length.
	GLCall(glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length));

	//Get the shader compilations status.
	GLCall(glGetProgramiv(program, GL_LINK_STATUS, &success));

	//Linking Failed.
	if (!success)
	{

		//Error string.
		std::string error = "Linking Error: ";

		//Allocate memory for the info log.
		char *info = (char *)malloc(sizeof(char) * (length + 1));

		//Get the info.
		GLCall(glGetProgramInfoLog(program, length, NULL, info));

		//Terminate the string.
		info[length] = '\0';

		//Add the info log to the message.
		error += info;

		//Free info.
		free(info);

		//Throw a message error.
		throw EngineError(error);
	}

	return program;
}






Shader::Shader(std::string vertex_filename, std::string fragment_filename)
{

	//Create a ShaderSource object.
	ShaderSource source;

	//Read the sources.
	ReadSources(vertex_filename, true, &source);
	ReadSources(fragment_filename, false, &source);

	//Create the program.
	m_id = CreateProgram(source);

	//And start using it.
	this->Bind();
	
}






Shader::~Shader()
{
}





void Shader::Bind()
{
	GLCall(glUseProgram(m_id));
}






void Shader::SetUniform1i(std::string name, int value)
{

	//Bind the shader.
	this->Bind();

	//Get uniform location.
	GLCall(int location = glGetUniformLocation(m_id, name.c_str()));

	//Set the value.
	GLCall(glUniform1i(location, value));
}

void Shader::SetUniformMat4f(std::string name, glm::mat4 mat)
{
	//Bind the shader.
	this->Bind();

	//Get uniform location.
	GLCall(int location = glGetUniformLocation(m_id, name.c_str()));

	//Set the mat4.
	GLCall(glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(mat)));
}

void Shader::SetUniformVec3(std::string name, glm::vec3 vec3)
{
	//Bind the shader.
	this->Bind();

	//Get uniform location.
	GLCall(int location = glGetUniformLocation(m_id, name.c_str()));

	//Set the Uniform.
	GLCall(glUniform3f(location, vec3.x, vec3.y, vec3.z));
}

void Shader::SetUniform1f(std::string name, float value)
{
	//Bind the shader.
	this->Bind();

	//Get uniform location.
	GLCall(int location = glGetUniformLocation(m_id, name.c_str()));

	GLCall(glUniform1f(location, value));
}

 

Camera Class:


#include "camera.h"
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>



Camera::Camera(glm::vec3 cam_pos) : m_cameraPos(cam_pos), m_pitch(0), m_yaw(-90), m_FirstTime(true),
m_sensitivity(0.1), m_fov(45.0)
{
	//Calculate last x and y.
	m_lastx = 800 / 2.0f;
	m_lasty = 600 / 2.0f;
}


Camera::~Camera()
{
}






void Camera::Move(bool forward, bool backward, bool left, bool right)
{

	//Move Forward.
	if (forward)
		m_cameraPos += m_cameraFront * m_speed;

	//Move Backwards.
	else if (backward)
		m_cameraPos -= m_cameraFront * m_speed;

	//Move Left.
	if (left)
		m_cameraPos += glm::normalize(glm::cross(m_cameraUp, m_cameraFront)) * m_speed;

	//Move Right.
	else if (right)
		m_cameraPos -= glm::normalize(glm::cross(m_cameraUp, m_cameraFront)) * m_speed;

}






glm::mat4 Camera::GetView()
{
	return glm::lookAt(m_cameraPos, m_cameraPos + m_cameraFront, m_cameraUp);
}






void Camera::UpdateRotation(double xpos, double ypos)
{

	//First time, don't do anything.
	if (m_FirstTime)
	{
		m_lastx = xpos;
		m_lasty = ypos;

		m_FirstTime = false;
	}


	//Get the offset for pitch and yaw.
	float xoffset = (xpos - m_lastx) * m_sensitivity;
	float yoffset = (m_lasty - ypos) * m_sensitivity;

	//Update lastX and lastY.
	m_lastx = xpos;
	m_lasty = ypos;

	//Add them to pitch and yaw.
	m_pitch += yoffset;
	m_yaw   += xoffset;

	//Limits for pitch.
	if (m_pitch > 89.0f)
		m_pitch = 89.0f;
	if (m_pitch < -89.0f)
		m_pitch = -89.0f;


	//Calculate the new vector.
	glm::vec3 front = glm::vec3(1.0f);
	front.x = cos(glm::radians(m_pitch)) * cos(glm::radians(m_yaw));
	front.y = sin(glm::radians(m_pitch));
	front.z = cos(glm::radians(m_pitch)) * sin(glm::radians(m_yaw));

	//Create the direction camera front vector.
	m_cameraFront = front;
}

void Camera::UpdateZoom(double x, double y)
{
	m_fov -= y;

	if (m_fov <= 25)
		m_fov = 25;

	else if (m_fov > 45)
		m_fov = 45;

	std::cout << m_fov << std::endl;
}

 


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

I don't have time to look over that huge code dump, but in your main.cpp, the HandleInput... That camera->move() function made me scream then sob.  Please, for the love of all that is programming use an enum!  enum class movement_direction: unit8_t { forward, back, left, right }; type deal.  I'll try and come back later today to look the rest of your code over and see if I can spot anything.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

Advertisement
3 minutes ago, CrazyCdn said:

I don't have time to look over that huge code dump, but in your main.cpp, the HandleInput... That camera->move() function made me scream then sob.  Please, for the love of all that is programming use an enum!  enum class movement_direction: unit8_t { forward, back, left, right }; type deal.  I'll try and come back later today to look the rest of your code over and see if I can spot anything.

LoL. Usually when I use enums I'm doing it old style (a bunch of #define statements, not the c++ enum type) bet you would scream more seeing that ?


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

1 minute ago, babaliaris said:

LoL. Usually when I use enums I'm doing it old style (a bunch of #define statements, not the c++ enum type) bet you would scream more seeing that ?

No, even that would be better then camera->move(false, false, false, true); Because even with intellisense it communicates nothing when skimming the code.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

How many code, it seems to me somewhere there is a problem in the creation of an object - values are incorrectly transmitted.

8 minutes ago, Sharik said:

How many code, it seems to me somewhere there is a problem in the creation of an object - values are incorrectly transmitted.

Well, thank you, I openly say that I do not understand, why put a minus?

Hello everyone!

24 minutes ago, Sharik said:

How many code, it seems to me somewhere there is a problem in the creation of an object - values are incorrectly transmitted.

Well, thank you, I openly say that I do not understand, why put a minus?

If you mean about the vertex specification, you can check it at the constructor of the Renderer class . I don't think I have any vertex data wrong in there.

Also I would like to mention that  A LOT of people who run Nvidia run my code and everything was rendering fine. But on my computer (AMD GPU) does this.

Someone in an older post told me that "Some OpneGL Implementations are more forgiven that others and 99% when a glitch like this appears it's your fault, not the driver's."

As much as I want to believe him, I cant' find what else I might be doing wrong.


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

Advertisement

Babaliaris, the fragment shader u posted looks like the vertex shader u posted :-)

5 minutes ago, ddlox said:

Babaliaris, the fragment shader u posted looks like the vertex shader u posted ?

Yes you are right (copy-paste mistake). For some reason I cant edit the original post so I'm going to post the code here:

Fragment Shader


#version 330 core

out vec4 Color;
in vec2 TexCoord;

uniform sampler2D diffuse;

void main()
{
	Color = texture(diffuse, TexCoord);
}

 


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

Guys just give me some hints. If the glTexImage2D() is configured correctly , if the width of the source images is multiple of 4 and  my sharers and vertex data are fine, what else could go wrong?? Nobody has the experience to tell me? What should i check first?


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

On 1/18/2019 at 10:34 AM, babaliaris said:

But I still can't understand why this fixes it. In the first version of my texture class, which I don't force 4 channels but instead I'm using the default channels, I'm configuring glTexImage2D the right way based on the source files channels and also I'm SURE that the width * channels of each image file is multiple of 4.But again in the second version of my texture class, which solve's the problem my mind is thinking again that this might be an alignment problem but it's not, I made sure of that.

I looked over my texture code for my OpenGL class and I never check for width * channels is a multiple of 4.  All my textures are power of 2 though in both x and y directions.  Some of the textures are 1, 2, 3 or 4 channel textures and I just set glTexImage2D based on the number of channels in the loaded texture.  I didn't have time yesterday to look over your code and I'm heading out to run some errands shortly, but I'll leave this tab up for when I get home later.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

This topic is closed to new replies.

Advertisement