Im fairly new to OpenGL and I'm trying to use instancing to draw many 3D rectangles. I have currently positioned each 3d rectangle in a different position and they show properly.
Problem: I now want each 3d rectangle to have a different rotation, defined by me and pass it to the vertex shader. However when I do that, The rectangles do not appear on the screen anymore.
I'm not providing the complete code because it is fairly long. I'm only providing the important part and hoping that i'm making a silly mistake somewhere and you can point it out.
Here is the vertex shader:
#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 offset;
layout (location = 2) in vec2 texCoord;
layout (location = 3) in mat4 instanceMatrix;
uniform mat4 view;
uniform mat4 projection;
out vec2 TexCoord;
void main()
{
TexCoord = texCoord;
gl_Position = projection * view * instanceMatrix * vec4(position + offset, 1.0f) ;
}
Here is the fragment shader:
#version 410 core
out vec4 color;
void main()
{
color = vec4(1.0f,1.0f,1.0f, 1.0f);
}
Here is the C++ code from where im sending the data:
// definition of models variable : std::vector<glm::mat4> models(0);
// Sending the Model matrix for each Rectangle
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), &models[0], GL_STATIC_DRAW);
GLsizei vec4Size = sizeof(glm::vec4);
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(vec4Size));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(2 * vec4Size));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 4 * vec4Size, (GLvoid*)(3 * vec4Size));
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);
// unfocus
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Related
I'm making a simple game in OpenGL where there is one player and multiple bubbles, all being spheres. Unfortunately, instancing doesn't work as expected and causes some strange effects. I'm new to instancing and can't see what may be causing a problem.
Draw method in player class:
void Player::draw(glm::mat4 ViewMat, GLfloat aspect, glm::vec3 light, GLfloat zoom)
{
bindProgram();
bindBuffers();
glm::mat4 Projection = glm::perspective(zoom, aspect, 0.1f, 100.0f);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * ViewMat * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "MVP"), 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "M"), 1, GL_FALSE, &Model[0][0]);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "V"), 1, GL_FALSE, &ViewMat[0][0]);
glUniform3f(glGetUniformLocation(shaderProgram, "origin"), origin.x, origin.y, origin.z);
glUniform3f(glGetUniformLocation(shaderProgram, "lightPosWorld"), light.x, light.y, light.z);
glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size() / 3);
}
Static draw method in bubble class:
void Bubble::drawAll(glm::mat4 ViewMat, GLfloat aspect, glm::vec3 light, GLfloat zoom,
std::vector<Bubble *> allInstances)
{
std::vector<float> origins;
uint count = 0;
for (auto b : allInstances)
{
origins.push_back(b->origin.x);
origins.push_back(b->origin.y);
origins.push_back(b->origin.z);
count++;
}
allInstances[0]->bindProgram();
allInstances[0]->bindBuffers();
glBufferData(GL_ARRAY_BUFFER, origins.size() * sizeof(origins), origins.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, originsBuffer);
glVertexAttribPointer(1, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *)0 // array buffer offset
);
glm::mat4 Projection = glm::perspective(zoom, aspect, 0.1f, 100.0f);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * ViewMat * Model;
GLuint programID = allInstances[0]->shaderProgram;
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 1);
glUniformMatrix4fv(glGetUniformLocation(programID, "MVP"), 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(glGetUniformLocation(programID, "M"), 1, GL_FALSE, &Model[0][0]);
glUniformMatrix4fv(glGetUniformLocation(programID, "V"), 1, GL_FALSE, &ViewMat[0][0]);
glUniform3f(glGetUniformLocation(programID, "lightPosWorld"), light.x, light.y, light.z);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, allInstances[0]->vertices.size() / 3, count);
}
Player vertex shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 origin;
uniform vec3 lightPosWorld;
uniform vec3 cameraPos;
out vec3 vertexPosWorld;
out vec3 vertexNormal;
out vec3 eyeDirectionCamera;
out vec3 lightDirectionCamera;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace + origin,1);
vertexPosWorld = (M * vec4(vertexPosition_modelspace + origin,1)).xyz;
vertexNormal = normalize(vertexPosWorld - origin);
}
Bubble vertex shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 origin;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 lightPosWorld;
uniform vec3 cameraPos;
out vec3 vertexPosWorld;
out vec3 vertexNormal;
out vec3 eyeDirectionCamera;
out vec3 lightDirectionCamera;
void main()
{
gl_Position = MVP * vec4(vertexPosition_modelspace + origin,1);
vertexPosWorld = (M * vec4(vertexPosition_modelspace + origin,1)).xyz;
vertexNormal = normalize(vertexPosWorld - origin);
}
This is what I get:
Effect
But I wanted to get two bubbles that look exactly like the player (which draws correctly).
There are 2 issues in the code:
sizeof(origins) is a byte size of std::vector but not its underlying type. It should be sizeof(float).
glBindBuffer should be called before modifying the buffer’s data and properties.
It should help:
glBindBuffer(GL_ARRAY_BUFFER, originsBuffer);
glBufferData(GL_ARRAY_BUFFER, origins.size() * sizeof(float), origins.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void *)0 // array buffer offset
);
My model looks stretched because of corrupted data in vertex shader attribute location
Here's the vertex shader code:
#version 330 core
layout (location = 0) in vec3 vertPos;
layout (location = 1) in vec3 vertNormal;
layout (location = 2) in vec2 texCoord;
layout (location = 3) in vec4 boneWeigths;
layout (location = 4) in ivec4 boneIDs;
out vec3 vNormal;
out vec3 fragPos;
out vec2 fragTexCoord;
const int MAX_BONES = 100;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 boneTransforms[MAX_BONES];
void main()
{
mat4 boneTx = boneTransforms[boneIDs[0]] * boneWeigths[0]
+ boneTransforms[boneIDs[1]] * boneWeigths[1]
+ boneTransforms[boneIDs[2]] * boneWeigths[2]
+ boneTransforms[boneIDs[3]] * boneWeigths[3];
vec4 pos = boneTx * vec4(vertPos, 1.0f);
gl_Position = MVP * pos;
vec4 normal = boneTx * vec4(vertNormal, 0.0f);
vNormal = normalize(vec3(M * normal));
fragPos = vec3(M * pos);
fragTexCoord = vec2(texCoord.x, texCoord.y);
}
The problem seems to be corrupted data in boneIDs (boneIDs data is fine on CPU, but getting corrupted data in shader). I tried hard-coding boneIDs data in shader, and that works fine.
Here's the code for VAO:
// create buffers/arrays
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
// load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, VBO);
unsigned int sz = sizeof(BoneVertex);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(BoneVertex), &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
// set the vertex attribute pointers
// vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)0);
// vertex normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)(3 * sizeof(float)));
// vertex texture coords
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)(6 * sizeof(float)));
// bone weights
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(BoneVertex), (void*)(8 * sizeof(float)));
// bone ids
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_INT, GL_FALSE, sizeof(BoneVertex), (void*)(12 * sizeof(float)));
glBindVertexArray(0);
BoneVertex structure:
struct BoneVertex
{
glm::vec3 position;
glm::vec3 normal;
glm::vec2 textureCoords;
glm::vec4 boneWeights;
glm::ivec4 boneIDs;
}
This is weird, because the first 3 attributes data seems fine. The problem is with boneIDs and boneWeights
Is this somehow related to padding, and how data is arranged in a structure? Or am I missing something else?
Thanks
boneIDs is a vertex shader input with an integral data type:
layout (location = 4) in ivec4 boneIDs;
If you want to specify the generic vertex attribute data for an integral attribute, then you have to use glVertexAttribIPointer (focus on I) rather than glVertexAttribPointer (see glVertexAttribPointer).
Note, the type argument doesn't specify the type of the target attribute, it specifies the element type of the source data array. glVertexAttribPointer converts the source data array to floating point values, but glVertexAttribIPointer specifies the array for integral target attributes.
glVertexAttribPointer(4, 4, GL_INT, GL_FALSE, sizeof(BoneVertex), (void*)(12 * sizeof(float)));
glVertexAttribIPointer(4, 4, GL_INT, sizeof(BoneVertex), (void*)(12 * sizeof(float)));
I am making a little voxel engine using a chunk system (like in Minecraft). I decided to make 1 VBO per chunk, so the VBO contain multiple cubes that will use different textures.
I actually have the UV of a cube and i would like to use it on all cubes in a VBO so the texture will wrap all cubes the same way if the cubes were in separated VBOs.
Here is what I'm actually getting:
How to tell OpenGL to do the same thing as the first cube on all cubes?
EDIT:
here are my shaders:
vertex shader
#version 400
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
out vec2 UV;
uniform mat4 MVP;
void main() {
gl_Position = MVP * vec4(vertexPosition_modelspace, 1);
UV = vertexUV;
}
fragment shader
#version 400
in vec2 UV;
out vec3 color;
uniform sampler2D textureSampler;
void main(){
color = texture(textureSampler, UV).rgb;
}
my glfw loop:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &chunkHandler.player.mvp[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, grass);
glUniform1i(textureID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, chunkHandler.loaded_chunks[0]->vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, tboID);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_TRIANGLES, 0, chunkHandler.loaded_chunks[0]->nbVertices);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
glfwPollEvents();
tboID: tbo is for texture buffer object
how i create the TBO:
glGenBuffers(1, &tboID);
glBindBuffer(GL_ARRAY_BUFFER, tboID);
glBufferData(GL_ARRAY_BUFFER, 36 * 2 * sizeof(float), uvcube, GL_STATIC_DRAW);
While not a complete answer, I can help in debugging.
It seems to me that the texture coordinate are wrong (you don't provide the code for filling them).
In your fragment shader, I would output the U and V coordinate as colors:
#version 400
in vec2 UV;
out vec3 color;
uniform sampler2D textureSampler;
void main(){
color = vec3(UV.u, UV.v, 0);
}
If the coordinates are correct, you should have a gradient on each cube face (each cube vertex will be colored based on its UV, so a (0,0) vertex is black and (0,1) is green and so on).
If it's not the case, try to fix the texture value until you can see them correctly.
This looks suspicious to me: glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
I've uploaded vertices, colors, normals, and texture coordinates into a single VBO, which is associated with a VAO. I also have an EBO associated with the same VAO that stores indices. I am also using SDL and OpenGL 3.3 (Core Profile context, which is set using SDL).
At first, my model seems to render fine. Then after maybe 8 or so seconds, it looks like the data gets corrupted.
Here is a video: https://youtu.be/eEiH3EFTPFk
Every frame I am pulling the data out of OpenGL (using glGetNamedBufferSubData) and comparing to what it should be, and everything seems to check out.
Does anyone have any idea what might be happening here? I appreciate any insight you guys might be able to provide.
Here is my code for loading the model data:
struct Vbo
{
GLuint id;
};
struct Ebo
{
GLuint id;
GLenum mode;
GLsizei count;
GLenum type;
};
struct Vao
{
GLuint id;
Vbo vbo[4];
Ebo ebo;
};
// ...
MeshId GraphicsEngine::createStaticMesh(
std::vector<glm::vec3> vertices,
std::vector<glm::detail::uint32> indices,
std::vector<glm::vec4> colors,
std::vector<glm::vec3> normals,
std::vector<glm::vec2> textureCoordinates
)
{
Vao vao;
glGenVertexArrays(1, &vao.id);
glGenBuffers(1, &vao.vbo[0].id);
glGenBuffers(1, &vao.ebo.id);
auto size = vertices.size() * sizeof(glm::vec3);
size += colors.size() * sizeof(glm::vec4);
size += normals.size() * sizeof(glm::vec3);
size += textureCoordinates.size() * sizeof(glm::vec2);
glBindVertexArray(vao.id);
glBindBuffer(GL_ARRAY_BUFFER, vao.vbo[0].id);
glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
auto offset = 0;
glBufferSubData(GL_ARRAY_BUFFER, offset, vertices.size() * sizeof(glm::vec3), &vertices[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
offset += vertices.size() * sizeof(glm::vec3);
glBufferSubData(GL_ARRAY_BUFFER, offset, colors.size() * sizeof(glm::vec4), &colors[0]);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(offset));
glEnableVertexAttribArray(1);
offset += colors.size() * sizeof(glm::vec4);
glBufferSubData(GL_ARRAY_BUFFER, offset, normals.size() * sizeof(glm::vec3), &normals[0]);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(offset));
glEnableVertexAttribArray(2);
offset += normals.size() * sizeof(glm::vec3);
glBufferSubData(GL_ARRAY_BUFFER, offset, textureCoordinates.size() * sizeof(glm::vec2), &textureCoordinates[0]);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(offset));
glEnableVertexAttribArray(3);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao.ebo.id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(glm::detail::uint32), &indices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
vao.ebo.count = indices.size();
vao.ebo.mode = GL_TRIANGLES;
vao.ebo.type = GL_UNSIGNED_INT;
vertexArrayObjects_.push_back(vao);
auto index = vertexArrayObjects_.size() - 1;
return MeshId(index);
}
Here is my code that does the rendering:
// Setup camera
const glm::quat temp = glm::conjugate(camera_.orientation);
view_ = glm::mat4_cast(temp);
view_ = glm::translate(view_, glm::vec3(-camera_.position.x, -camera_.position.y, -camera_.position.z));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderProgram_);
const int modelMatrixLocation = glGetUniformLocation(shaderProgram_, "modelMatrix");
const int pvmMatrixLocation = glGetUniformLocation(shaderProgram_, "pvmMatrix");
const int normalMatrixLocation = glGetUniformLocation(shaderProgram_, "normalMatrix");
glm::detail::uint32 i = 0;
for ( const auto& r : renderables_ )
{
const auto& graphicsData = graphicsData_[i];
glm::mat4 newModel = glm::translate(model_, graphicsData.position);
newModel = newModel * glm::mat4_cast( graphicsData.orientation );
newModel = glm::scale(newModel, graphicsData.scale);
// Send uniform variable values to the shader
const glm::mat4 pvmMatrix(projection_ * view_ * newModel);
glUniformMatrix4fv(pvmMatrixLocation, 1, GL_FALSE, &pvmMatrix[0][0]);
glm::mat3 normalMatrix = glm::inverse(glm::transpose(glm::mat3(view_ * newModel)));
glUniformMatrix3fv(normalMatrixLocation, 1, GL_FALSE, &normalMatrix[0][0]);
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &newModel[0][0]);
glBindTexture(GL_TEXTURE_2D, r.texture.id);
glBindVertexArray(r.vao.id);
glDrawElements(r.vao.ebo.mode, r.vao.ebo.count, r.vao.ebo.type, 0);
glBindVertexArray(0);
i++;
}
Fragment shader:
#version 330 core
in vec4 ourColor;
in vec2 texCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
color = texture(ourTexture, texCoord);
}
Vertex shader:
#version 330 core
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat4 pvmMatrix;
uniform mat3 normalMatrix;
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec2 textureCoordinate;
out vec4 ourColor;
out vec2 texCoord;
void main()
{
//gl_Position = vec4(position, 1.0);
gl_Position = pvmMatrix * vec4(position, 1.0);
ourColor = color;
texCoord = textureCoordinate;
}
As per #MichaelNastenkos comment about, I added glEnable(GL_DEPTH_TEST); before my rendering code and it seems to fix it.
I'm trying to texture the ground with grass. Would someone mind looking through my steps to get a 2D texture to show up in 3D space? I haven't had any luck with online tutorials.
Here is my steps:
1) Call the sprite class initialization to set the vertex coordinates and uv data
void Sprite::init(vec3 bottomleft, vec3 topLeft, vec3 topRight, vec3 bottomRight, std::string texturePath)
{
_texture = ImageLoader::loadPNG(texturePath);
_points = { bottomleft.x, bottomleft.y, bottomleft.z, topLeft.x, topLeft.y, topLeft.z, topRight.x, topRight.y, topRight.z, topRight.x, topRight.y, topRight.z, bottomRight.x, bottomRight.y, bottomRight.z, bottomleft.x, bottomleft.y, bottomleft.z };
_uv = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
}
I use the uniform sampler and activate the texture
//draw ground texture
glUniform1i(samplerLocation, 0);
glActiveTexture(GL_TEXTURE0);
_grassTexture.draw();
The draw function is implemented as follows, which puts the data in the buffer and draws the triangle:
void Sprite::draw()
{
if (_vboID == 0)
{
glGenBuffers(1, &_vboID);
}
glBindTexture(GL_TEXTURE_2D, _texture.id);
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glBufferData(GL_ARRAY_BUFFER, _points.size() * sizeof(float) + _uv.size() * sizeof(float), nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, _points.size() * sizeof(float), &_points.front());
glBufferSubData(GL_ARRAY_BUFFER, _points.size() * sizeof(float), _uv.size() * sizeof(float), &_uv.front());
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//position attribute pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, &_points.front());
//uv attribute pointer
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, &_uv.front());
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
The vertex shader:
#version 400
in vec4 vertexPosition;
in vec2 vertexUV;
out vec4 fragmentColor;
out vec2 fragmentUV;
uniform mat4 MVP;
uniform vec4 COLOR;
void main()
{
gl_Position = MVP * vertexPosition;
fragmentColor = COLOR;
fragmentUV = vec2(vertexUV.x, 1.0 - vertexUV.y);
}
and fragment shader:
#version 400
in vec4 fragmentColor;
in vec2 fragmentUV;
out vec4 fragColor;
uniform sampler2D SAMPLER;
void main()
{
vec4 textureColor = texture(SAMPLER, fragmentUV);
fragColor = textureColor * fragmentColor;
}
At this point, nothing displays in the screen. I do know that the textureColor in the fragment shader is green, so it appears the uniform is being set correctly. My best guess is that I'm either missing a texture initialization step or am not filling the buffer correctly.
I think there's a problem with the pointer parameter in your calls to glVertexAttribPointer. You're passing the address of your _points and _uv arrays, but you should be passing the offset relative to the base of your vbo.
Try:
//position attribute pointer
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
//uv attribute pointer
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)(_points.size() * sizeof(float)));