Weird Problem With Integers And Instanced Rendering

Started by
1 comment, last by TheChubu 7 years, 9 months ago

I have a weird issue with passing integers to the shader for instanced rendering. When i passed the integers via uniforms there was no problem, but when i switched to instanced rendering i started to get weird problems. When the interger value is zero it works perfectly, but any other value is incorrect, and i cannot figure out why. The values are off by a large margin, for example, any positive integer (in my case 1 and 2) were bigger than 65535 in the shader. The integer values resemble a color value in the shader (0 = white, 1 = black and 2 = red) and i tried simply passing the color instead of an integer, and that worked perfectly. Everything else works perfectly. The matrices used in the instanced rendering process are all working as intended

I double checked the values in the GLint* modelColors array, and all values were 0, 1 or 2. This leads me to believe that something either is going wrong while setting up the data buffer, or the there is something weird going on in the shader.

If anyone knows whats going wrong here, i'd be happy to hear it!

C++ code


glm::mat4 model;
glm::mat4* modelMatrices = new glm::mat4[maxInstances];
GLint* modelColors = new GLint[maxInstances];
std::vector<std::vector<Square>> squares = //get grid info;
GLuint index = 0;
for (int x = 0; x < squares.size(); ++x)
{
	for (int y = 0; y < squares[0].size(); ++y)
	{
		modelColors[index] = squares[x][y].active ? 1 : 0;
		model = glm::translate(glm::mat4(), squares[x][y].position);
		modelMatrices[index] = model;
		index++;

		modelColors[index] = 2;
		model = glm::translate(glm::mat4(), squares[x][y].centreRight.position));
		modelMatrices[index] = model;
		index++;
	}
}

GLfloat vertices[] = {
	// Positions        // Texture Coords
	-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
	-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
	1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
	1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
};

GLuint buffer;
glGenVertexArrays(1, &this->quadVAO);
glGenBuffers(1, &buffer);

glBindVertexArray(this->quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));


// Setup colors
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);

glBufferData(GL_ARRAY_BUFFER, maxInstances * sizeof(GLint), &modelColors[0], GL_STATIC_DRAW);

glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_INT, GL_FALSE, sizeof(GLint), (GLvoid*)0);

// Setup matrices
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);

glBufferData(GL_ARRAY_BUFFER, maxInstances * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);

glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(sizeof(glm::vec4)));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(2 * sizeof(glm::vec4)));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (GLvoid*)(3 * sizeof(glm::vec4)));

glVertexAttribDivisor(2, 1);
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

Vertex shader


#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in int instanceColor;
layout (location = 3) in mat4 instanceMatrix;


out vec2 TexCoords;
out vec4 Color;

uniform mat4 view;
uniform mat4 projection;

vec4 GetColor(int colorIndex)
{
	if(colorIndex == 0)
		return vec4(1.0, 1.0, 1.0, 1.0);
	else if (colorIndex == 1)
		return vec4(0.0, 0.0, 0.0, 1.0);
	else if (colorIndex == 2)
		return vec4(1.0, 0.0, 0.0, 1.0);
	else if (colorIndex == 3)
		return vec4(0.3, 0.3, 0.3, 1.0);

		
	return vec4(0.0, 1.0, 0.0, 1.0);
}

void main()
{
	gl_Position = projection * view * instanceMatrix * vec4(position, 1.0);
	Color = GetColor(instanceColor);
    TexCoords = texCoords;
}
Advertisement

You need to use glVertexAttribIPointer rather than glVertexAttribPointer for this; see the documentation:

For glVertexAttribPointer, if normalized is set to GL_TRUE, it indicates that values stored in an integer format are to be mapped to the range [-1,1] (for signed values) or [0,1] (for unsigned values) when they are accessed and converted to floating point. Otherwise, values will be converted to floats directly without normalization.

For glVertexAttribIPointer, only the integer types GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT are accepted. Values are always left as integer values.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Yes! That! It bit me in the ass so hard the first time I wanted to upload integer data :D

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

This topic is closed to new replies.

Advertisement