GLSL Shader not rendering anything, VAO is filled, VBO filled with vertices - c++

I have filled VBO with my vertices (2x position, 2x size, 4x uv, 2x texture data(1 float sets correct texture array and 2. sets index of texture in array), still not rendering, what am i missing?
I tried setting geometry shader to render simple quad, nothing showed up, i tried just rendering color in fragment, nothing showed up, I checked OPENGL debug message, nothing there, in vertex shader i checked calculation for my matrix, everything should be fine
Data is being loaded every frame using glBufferData to same buffer, because of resizing, this code is for entities and amount of them on screen can change easily.
Fragment shader:
void main()
{
texColor = vec4(1.0,0.0,0.0,1.0); //Red fillment
FragColor = texColor;
}
Vertex shader:
layout:
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 size;
layout(location = 2) in vec4 uv;
layout(location = 3) in vec2 textureData; //1. data is to pick correct atlas, 2. is index of texture in atlas
interface:
out VS_OUT
{
mat4 screenMatrix;
vec2 position;
vec4 uv;
vec2 textureData;
vec2 size;
} vs_out;
matrix:
mat4 screenMatrix = mat4((2.0/screenRatio.x),0.0,0.0,0.0,0.0,(2.0/screenRatio.y),0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0);
Geometry Shader:
Layout:
layout (points) in;
layout(triangle_strip,max_vertices = 4) out;
out:
out vec2 TexData;
out vec2 TexCoord;
code:
void renderPlayer(mat4 screenMatrix, vec4 position,vec2 textureData,vec2 size,vec4 uv)
{
gl_Position = nullPos+((position+vec4(0.0,0.0,0.0,0.0))*screenMatrix); // 1:bottom-left
TexData = textureData;
TexCoord = vec2(uv.xy);
EmitVertex();
gl_Position = nullPos+((position+vec4(size.x,0.0,0.0,0.0))*screenMatrix); // 2:bottom-right
TexData = textureData;
TexCoord = vec2(uv.zy);
EmitVertex();
gl_Position = nullPos+((position+vec4(0.0,size.y,0.0,0.0))*screenMatrix); // 3:top-left
TexData = textureData;
TexCoord = vec2(uv.xw);
EmitVertex();
gl_Position = nullPos+((position+vec4(size.x,size.y,0.0,0.0))*screenMatrix); // 4:top-right
TexData = textureData;
TexCoord = vec2(uv.zw);
EmitVertex();
EndPrimitive();
}
main:
void main() {
renderPlayer(gs_in[0].screenMatrix,vec4(gs_in[0].position,0.0,0.0),gs_in[0].textureData,gs_in[0].size,gs_in[0].uv);
}
C++ code:
VBO data inicialization:
float* vertices = new float[totalVertices];
for (EntityRenderData renderDataCurrent : renderData)
{
for (int layerI = 0; layerI < renderDataCurrent.getLayerCount(); layerI++)
{
int i = 0;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).xPos;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).yPos;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).xSize;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).ySize;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).U0;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).V0;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).U1;
vertices[layerI * 10 + i++] = renderDataCurrent.getLayer(layerI).V1;
vertices[layerI * 10 + i++] = (float)renderDataCurrent.getLayer(layerI).textureAtlasId;
vertices[layerI * 10 + i++] = (float)renderDataCurrent.getLayer(layerI).textureIndex;
drawCount++;
}
}
Render Part:
glBindVertexArray(playerVAO);
glBindBuffer(GL_ARRAY_BUFFER, playerVBO);
glBufferData(GL_ARRAY_BUFFER, totalVertices * sizeof(float), vertices, GL_STREAM_DRAW);
game->renderer->entityShader->use();
glDrawArrays(GL_POINTS, 0, drawCount);
Inicialization Part:
glGenVertexArrays(1, &playerVAO);
glGenBuffers(1, &playerVBO);
glBindVertexArray(playerVAO);
// position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// size
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(2 * sizeof(float)));
glEnableVertexAttribArray(1);
// uv
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(4 * sizeof(float)));
glEnableVertexAttribArray(2);
// texture data
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(8 * sizeof(float)));
glEnableVertexAttribArray(3);

If a non-zero named array buffer object is bound, then the last parameter of glVertexAttribPointer is treated as a byte offset into the buffer object's data store.
The definition of the generic vertex attribute data and the referenced buffer is stated in the Vertex Array Object.
It is not sufficient to generate a buffer object, the array buffer object has to be the currently bound buffer object, when using glVertexAttribPointer:
glGenVertexArrays(1, &playerVAO);
glGenBuffers(1, &playerVBO);
glBindVertexArray(playerVAO);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, playerVBO); // <--- bind the buffer object
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(2 * sizeof(float)));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(4 * sizeof(float)));
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(8 * sizeof(float)));

Related

How to read vertex texcoords with OpenMesh

I use OpenGL + OpenMesh to render a 3d mesh
My mesh reading and processing code:
void read(MyMesh &model, const string &path) {
model.request_vertex_colors();
model.request_face_normals();
OpenMesh::IO::Options opt;
opt += OpenMesh::IO::Options::VertexColor;
opt += OpenMesh::IO::Options::FaceNormals;
if (!OpenMesh::IO::read_mesh(model, path, opt)) {
cerr << "read error\n";
exit(1);
}
// fill the vertices and normals array
for (auto f : model.faces())
for (auto v : model.fv_range(f)){ // how can I get vertex texcoords based on face?
vertices.push_back(model.point(v));
normals.push_back(model.normal(f));
colors.push_back(model.color(v));
}
model.release_vertex_colors();
model.release_face_normals();
}
But I find that I can't get vertex texcoords based on the face in OpenMesh.
It seems there isn't a function called model.texcoords(face_handle, vertex_handle) to let me get the vertex texcoords on this face.
Or can I get the texcoords index of each face like these in obj file:
f 481/1/1 480/2/1 24/3/1 25/4/1
f 477/5/2 7/6/2 17/7/2 18/8/2
f 1/9/3 326/10/3 11/11/3
f 482/12/4 481/1/4 25/4/4
f 478/13/5 477/5/5 18/8/5 19/14/5
f 2/15/6 1/9/6 11/11/6 12/16/6
f 479/17/7 478/13/7 19/14/7 20/18/7
f 3/19/8 2/15/8 12/16/8 13/20/8
f 8/21/9 479/17/9 20/18/9 21/22/9
I use glDrawArrays(...) to draw mesh.
Declarations
vector<MyMesh::Point> vertices; // `MyMesh::Point` is like float3 struct which has 3 float numbers in it
vector<MyMesh::Point> normals;
vector<MyMesh::Point> colors;
unsigned int model_vbo[3], model_vao;
Data bind
glGenBuffers(3, model_vbo);
glGenVertexArrays(1, &model_vao);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float), vertices.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(float), colors.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[2]);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(float), normals.data(), GL_DYNAMIC_DRAW);
glBindVertexArray(model_vao);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glBindBuffer(GL_ARRAY_BUFFER, model_vbo[2]);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Draw loop
s.use();
s.setMat4("model", Rotate * Scale);
s.setMat4("projection", cam.projection());
s.setMat4("view", cam.view());
glBindVertexArray(model_vao);
glDrawArray(GL_TRIANGLES, 0, vertices.size() / 3);
vertex shader
#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec3 normal;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec3 Color;
out vec3 Normal;
void main(){
Normal = normal;
Color = color;
gl_Position = projection * view * model * vec4(position, 1.0);
}
fragment shader
#version 450 core
out vec4 scene_color;
in vec3 Color; // vertex color
in vec3 Normal;
void main(){
scene_color = vec4(Color,1.0);
}

Opengl 3+ draw lines with differents colors

I'm using SIFT algorithm and I want to draw lines between keypoints in differents image. I made it, but actually, all my lines have the same color so it's unreadable.
What I want to achieve is to set a random color to each line, but 1 and only 1 color to a line.
I have to use shaders to do that, and so I send LINES and POINTS (that is the color) to the same shader, and I don't know what's wrong in my code (I have a crash when trying to execute my code. EDIT : It is not that something is wrong in my code (well, obviously yes...) but the error cause a crash, like if I had a segmentation fault. So I think my errors is due to a wrong place allocation for my color array (because it worked without this array))
my code :
std::vector<GLfloat> points;
std::vector<glm::vec3> colors;
GLuint VAO, VBO[2];
void setupLines() {
glGenVertexArrays(1, &VAO);
glGenBuffers(2, &VBO[0]);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, points.size() * sizeof(GLfloat), &points[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), &colors[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void draw() {
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glDrawArrays(GL_LINES, 0, points.size());
//The error occurs here, it seems...
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glDrawArrays(GL_POINTS, 0, colors.size());
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//for each points, we create the same colors 2by 2 so lines (that are 2 points) have the same colors
void addColor() {
for (int i = 0; i < points.size()/2; ++i) {
float a = rand() / (float)RAND_MAX;
float b = rand() / (float)RAND_MAX;
float c = rand() / (float)RAND_MAX;
colors.push_back(glm::vec3(a, b, c));
colors.push_back(glm::vec3(a, b, c));
}
}
and my vertex Shader :
#version 330 core
layout (location = 0) in vec2 aTexCoord;
layout (location = 1) in vec3 color;
out vec2 TexCoord;
out vec3 Col;
void main()
{
TexCoord = vec2(aTexCoord.xy);
Col = color;
}
and then I use Col in fragment shader to color.
Is it how I have to do this?
You have to set the current position gl_Position in the vertex shader.
The vertex coordinate has to be an attribute:
in vec3 aVertCoord;
and you have to assigne the coordinate to gl_Position:
gl_Position = vec4(aVertCoord.xyz, 1.0);
Note, for 2D coordinates it is should be something like:
in vec2 aVertCoord;
void main()
{
.....
gl_Position = vec4(aVertCoord.xy, 0.0, 1.0);
}
In final you have 2 vertex attributes. The vertex coordinates and the color. You do not need any texture coordinates, because you draw lines (GL_LINES). But I guess what you call aTexCoord is the vertex position, so you have to do it like this:
#version 330 core
layout (location = 0) in vec2 aTexCoord;
layout (location = 1) in vec3 color;
out vec3 TexCoord;
out vec3 Col;
void main()
{
gl_Position = vec4(aTexCoord.xy, 0.0, 1.0);
TexCoord = aTexCoord.xy;
Col = color;
}
The vertex array object VAO stores the states of the generic vertex attributes (glVertexAttribPointer, glEnableVertexAttribArray). The vertex attribute state may refer to a vertex array buffer. You have to bind the vertex array object VAO only, when you draw the object (lines):
void draw() {
glBindVertexArray(VAO);
int numberOfPoints = points.size() / 2; // Number of points, not the number of floats
glDrawArrays(GL_LINES, 0, numberOfPoints );
glBindVertexArray(0);
}
Note, it sufficient to call glDrawArrays one time.
Further, the 1st paramter of glVertexAttribPointer is the attribute index:
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), &colors[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1, // <---------------------------- attribute index
3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
Since you need one color per vertex coordinate, but you want every line to be drawn in a single color, you have to do it like this:
void addColor()
{
int numberOfPoints = points.size() / 2;
for (int i = 0; i < numberOfPoints/2; ++i)
{
glm::vec3 col(
rand() / (float)RAND_MAX,
rand() / (float)RAND_MAX,
rand() / (float)RAND_MAX);
colors.push_back(col);
colors.push_back(col);
}
}

GLSL Variables Not Getting VBO Data

There must be something wrong with how I'm implementing my VAOs and VBOs because my shader isn't getting any of the buffer data I'm allocating to it. It could be something to do with the location of the variables. I tried printing out the location value from glGetUniformLocation (my loc variable), and it printed out 4294967295 for every location value. I would think there's a different location for each of them. I also tried using the location (location = ...) values from the vertex shader and that didn't work either. Any extra insight would be greatly appreciated.
Here is my rendering code:
// load shaders and textures to the current context
glUseProgram(cloudShader);
glActiveTexture(cloudTexture);
glBindTexture(GL_TEXTURE_2D, cloudTexture);
glEnable(GL_POINTS);
glDisable(GL_DEPTH_TEST);
glPointSize(10.0f);
// initial velocity and start time buffer
GLuint vbo[3];
// texture position buffer
GLuint textPosBuf;
glGenBuffers(3, vbo);
//glGenBuffers(1, &textPosBuf);
// gen vao object
GLuint vao[3];
glGenVertexArrays(3, vao);
// define uniforms
glUniform4f(glGetUniformLocation(cloudShader, "color1"), color1.r, color1.g, color1.b, color1.a);
glUniform4f(glGetUniformLocation(cloudShader, "color2"), color2.r, color2.g, color2.b, color2.a);
glUniform3f(glGetUniformLocation(cloudShader, "Accel"), accel.x, accel.y, accel.z);
glUniform1f(glGetUniformLocation(cloudShader, "color1Wght"), color1Wght);
glUniform1f(glGetUniformLocation(cloudShader, "Time"), time);
glUniformMatrix4fv(glGetUniformLocation(cloudShader, "MVP"), 1, GL_FALSE, value_ptr(mat4(GL_PROJECTION_MATRIX) * mat4(GL_MODELVIEW_MATRIX)));
glUniform1i(glGetUniformLocation(cloudShader, "ParticleTex"), cloudTexture);
GLfloat *data = new GLfloat[nParticles * 3];
// I then set data ...
// bind vertex buffer data
// initial velocity data
glBindVertexArray(vao[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, nParticles * 3 * sizeof(GLfloat), reinterpret_cast<void*>(data), GL_DYNAMIC_DRAW);
// VertexInitVel attrib array pointer setup
GLuint loc = glGetUniformLocation(cloudShader, "VertexInitVel");
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
glEnableVertexAttribArray(loc);
// start time data
data = new GLfloat[nParticles];
// I then set the data...
// load start time buffer data
glBufferData(GL_ARRAY_BUFFER, nParticles * sizeof(GLfloat),
reinterpret_cast<void*>(data), GL_DYNAMIC_DRAW);
// InitStartTime attrib array pointer setup
loc = glGetUniformLocation(cloudShader, "StartTime");
glVertexAttribPointer(loc, 1, GL_FLOAT, GL_FALSE, NULL, NULL);
glEnableVertexAttribArray(loc);
// buffer texture position data
data = new GLfloat[nParticles * 2];
// I then set the data...
glBindVertexArray(vao[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferSubData(GL_ARRAY_BUFFER, nParticles * sizeof(GLfloat),
nParticles * 2 * sizeof(GLfloat), reinterpret_cast<void*>(data));
loc = glGetUniformLocation(cloudShader, "texCoordIn");
cout << loc << endl;
glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, NULL,
reinterpret_cast<void*>(nParticles * sizeof(GLfloat)));
glEnableVertexAttribArray(loc);
// buffer particle position data
data = new GLfloat[nParticles * 3];
// data gets set...
glBindVertexArray(vao[2]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ARRAY_BUFFER, nParticles * 3 * sizeof(GLfloat), reinterpret_cast<void*>(data), GL_DYNAMIC_DRAW);
loc = glGetUniformLocation(cloudShader, "VertexStartPos");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
glDrawArrays(GL_POINTS, 0, nParticles);
// cleanup
....
Here is my vertex shader:
#version 450
// information to pass to the fragment shader
out vec2 texCoord; // texture coordinate to pass to fragment shader
out vec4 color1Pass;
out vec4 color2Pass;
out float color1WghtPass;
// Initial velocity and start time
layout (location = 0) in vec3 VertexInitVel;
layout (location = 1) in float StartTime;
layout (location = 2) in vec3 VertexStartPos; // where particle "respawns"
layout (location = 3) in vec2 texCoordIn;
// various values
uniform vec4 color1;
uniform vec4 color2;
uniform float color1Wght; // how strongly color1 is weighted
uniform float Time; // Animation time
uniform mat4 MVP;
uniform vec3 Accel; // Particle acceleration
out float Transp; // Transparency of the particle
const float ParticleLifetime = 10.0f; // Max particle lifetime
void main()
{
// Assume the initial position is as defined by Vertex Start Pos.
// vec3 pos = VertexStartPos;
vec3 pos = vec3(0.0);
Transp = 0.0;
// Particle doesn't exist until the start time
if( Time > StartTime ) {
float t = Time - StartTime;
// particle is born
if( t < ParticleLifetime ) {
pos = VertexInitVel * t + Accel * t * t;
Transp = 1.0 - t / ParticleLifetime;
}
}
color1Pass = color1;
color2Pass = color2;
color1WghtPass = color1Wght;
gl_Position = MVP * vec4(pos, 1.0);
}

Using a matrix as vertex attribute in OpenGL3 Core Profile

I am using OpenGL3.2 Core Profile on OSX.
And I want to do instanced drawing (glDrawArraysInstanced), where I pass a matrix for each instance.
My vertex shader builds just fine:
#version 150
in mediump vec4 position;
in mediump mat4 trf;
in lowp vec4 rgb;
out lowp vec4 colour;
uniform highp mat4 modelcamviewprojmat;
void main()
{
mediump vec4 tpos = trf * position;
gl_Position = modelcamviewprojmat * tpos;
colour = rgb;
}
The binding of 'trf' went fine:
glBindAttribLocation(program, ATTRIB_TRF, "trf" );
But how can I pass in my data?
glVertexAttribPointer can not pass values larger than 4 floats.
So this call fails:
glVertexAttribPointer( ATTRIB_TRF, 16, GL_FLOAT, 0, 16 * sizeof(float), ... );
I suspect that I need to replace it with 4 calls to glVertexAttribPointer, each passing 4 floats.
But what value could I use for 'index' (first parm)? Do I need to use 4 vector attributes instead, and assemble the four vectors in GLSL vertex shader? If so, what kind of GLSL code accomplishes this? Or can I use the return value from BindAttribLocation and use val+0, val+1, val+2 and val+3 for all the rows?
According to this page and my current implementation of hardware instancing in my game, the proper way it's done is that a mat4 attribute takes up 4 attribute locations. The one you bind and the 3 following.
int pos = glGetAttribLocation(shader_instancedarrays.program, "transformmatrix");
int pos1 = pos + 0;
int pos2 = pos + 1;
int pos3 = pos + 2;
int pos4 = pos + 3;
glEnableVertexAttribArray(pos1);
glEnableVertexAttribArray(pos2);
glEnableVertexAttribArray(pos3);
glEnableVertexAttribArray(pos4);
glBindBuffer(GL_ARRAY_BUFFER, VBO_containing_matrices);
glVertexAttribPointer(pos1, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4 * 4, (void*)(0));
glVertexAttribPointer(pos2, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4 * 4, (void*)(sizeof(float) * 4));
glVertexAttribPointer(pos3, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4 * 4, (void*)(sizeof(float) * 8));
glVertexAttribPointer(pos4, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4 * 4, (void*)(sizeof(float) * 12));
glVertexAttribDivisor(pos1, 1);
glVertexAttribDivisor(pos2, 1);
glVertexAttribDivisor(pos3, 1);
glVertexAttribDivisor(pos4, 1);

Glsl skinning obstacle, who can jump that?

I'm currently trying to set up a GPU skinning (with glsl) but it's not working the way I would :) Actually it's not working at all. My mesh disappear when I try this glsl code :
layout(location = 0) in vec3 vertexPos;
layout(location = 1) in vec2 vertexUv;
layout(location = 2) in vec3 vertexNor;
layout(location = 5) in ivec4 joints_influences;
layout(location = 6) in vec4 weights_influences;
uniform mat4 ViewProj, View, Proj, Model;
out vec3 vertexPosEye;
out vec3 vertexNorEye;
const int MAX_INFLUENCES = 4;
const int MAX_BONES = 50;
uniform mat4 animation_matrices[MAX_BONES];
uniform mat4 inv_bind_matrices[MAX_BONES];
void main()
{
vertexPosEye = (View * Model * vec4(vertexPos, 1)).xyz; // Position
vertexNorEye = (View * Model * vec4(vertexNor, 0)).xyz; // Normal matrix
vec4 final_v = vec4(0, 0, 0, 0);
for (int i = 0; i < MAX_INFLUENCES; i++)
{
vec4 v = vec4(vertexPos, 1)
* inv_bind_matrices[joints_influences[i]]
* animation_matrices[joints_influences[i]]
* weights_influences[i];
final_v += v;
}
gl_Position = ViewProj * Model * final_v;
}
when I try this :
gl_Position = ViewProj * Model * vertexPos;
My mesh is back :) but no animations anymore of course...
Here's my application (c++) code when I set VBO attributes :
// Vertex position
glGenBuffers(1, &buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.pos.size() * sizeof(bVector3), &vertices.pos[0], GL_STATIC_DRAW);
// Ibid for uv, normals, tangents and bitangents.
// Skinning : joints index
glGenBuffers(1, &buffer[5]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[5]);
glBufferData(GL_ARRAY_BUFFER, vertices.joints.size() * sizeof(SkinningJoints), &vertices.joints[0], GL_STATIC_DRAW);
// Skinning : weights
glGenBuffers(1, &buffer[6]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[6]);
glBufferData(GL_ARRAY_BUFFER, vertices.weights.size() * sizeof(SkinningWeights), &vertices.weights[0], GL_STATIC_DRAW);
// Indices
glGenBuffers(1, &buffer[7]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[7]);
glBufferData(GL_ARRAY_BUFFER, vertices.indices.size() * sizeof(bUshort), &vertices.indices[0], GL_STATIC_DRAW);
In the main loop :
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(0));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(for uv, normals, tangents and bitangents)...
glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(5));
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(6);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(6));
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->GetBuffer(7));
glDrawElements(GL_TRIANGLES, m->vertices.indices.size(), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
Here is my RenderingVertices struct (after Barr's recomendations):
struct RenderingVertices
{
// std::vector<Vec3>
vVec3 pos, nor, tang, btan;
vVec2 uv;
vUshort indices;
vector<SkinningJoints> joints;
vector<SkinningWeights> weights;
};
And here is my SkinningJoints struct :
struct SkinningJoints
{
int j[MAX_BONES_PER_VERT];
SkinningJoints(Vertex::Weights weights[MAX_BONES_PER_VERT])
{
for (bUint i = 0; i < MAX_BONES_PER_VERT; i++)
j[i] = weights[i].jid;
}
};
My SkinningWeights struct is almost the same, with an array of float instead of int.
Now when I try to debug the joints index, weights values and final vertex as colors, here is what I get :
// Shader
color_debug = joints_influences;
http://www.images-host.fr/view.php?img=00021800pop.jpg
color_debug = weights_influences;
http://www.images-host.fr/view.php?img=00021800pop2.jpg
Another interesting thing, when I try this :
vec4 pop = vec4(vertexPos, 1) * animation_matrices[1] * inv_bind_matrices[1] * 1.0;
gl_Position = ViewProj * Model * pop;
My all mesh is actually rotating, which means that my uniform animation_matrices is good.
Anyone can see what i'm doing wrong here ?
I finally got it working. For those who may be interested, here is what I was doing wrong :
When I send joints indices array to Glsl, instead of doing this:
glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(5));
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, 0, BUFFER_OFFSET(0));
I needed to do this:
glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(5));
glVertexAttribIPointer(5, 4, GL_INT, 0, BUFFER_OFFSET(0));
You have to look closely to find the difference. Instead of calling glVertexAttribPointer(), I needed to call glVertexAttribIPointer() because joints indices are int.
Hope this will help someone someday.
Did you try debugging your skinning attributes? Output the vertex weight as colors so that you can confirm you have meaningful values? If everything is black you'll know where to look.
From a quick glance at your RenderingVertices I can spot a first problem. You are passing a Vector of pointers to GL which I don't think is what you want to do.
Most of the time you will limit skinning influences to 4 joint/weight pairs per vertex. So you can get away with a simple array (ie. SkinningJoints joints[4];).