OpenGL shadow mapping, frame buffer with multiple glDrawElements - c++

I have a scene that consists of a lot of objects, and when I'm rendering them I iterate through all items that are in the scene and call glDrawElements on them. This works fine. However, now I'm implementing shadow mapping to the scene, and I am using the same way to draw to the shadow buffer. However, only the first element in the scene is drawn to the texture in a correct way, I'm checking this by attaching the depth texture to a scene element which you will see below.
The code is as follows:
glBindFramebuffer(GL_FRAMEBUFFER, vFrameBuffers[ShadowFB]);
glViewport(0,0,1024,1024);
glClearDepth(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(shadowShader);
depth_loc = glGetUniformLocation(shadowShader, "depthProj");
model_view_loc = glGetUniformLocation(shadowShader, "modelmat");
glUniformMatrix4fv(depth_loc, 1, GL_FALSE, depthproj);
depthproj = mat4(1.0);
depthproj = Ortho(-250.0f, 250.0f, -200.0f, 200.0f, -200.0f, 200.0f);
depthproj = depthproj * RotateX(15);
depthproj = depthproj * RotateY(220);
for (int i = 0; i < _objectArray.size(); i++)
{
modelmat = mat4(1.0);
modelmat = modelmat*Translate(_objectArray[i]->getLocation()->getX(),
_objectArray[i]->getLocation()->getY(),
_objectArray[i]->getLocation()->getZ());
glUniformMatrix4fv(model_view_loc, 1, GL_FALSE, modelmat);
if (_objectArray[i]->getType() == TypeMountain)
{
glBindVertexArray(vArrays[ShadowMountainA]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowMountainE]);
glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
}
else if (_objectArray[i]->getType() == TypePasture)
{
glBindVertexArray(vArrays[ShadowPastureA]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowPastureE]);
glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
}
else if (_objectArray[i]->getType() == TypeWater)
{
glBindVertexArray(vArrays[ShadowWaterA]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowWaterE]);
glDrawElements(GL_TRIANGLES, 40*40*6, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
}
else if (_objectArray[i]->getType() == TypeTree)
{
glBindVertexArray(vArrays[ShadowTreeA]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vElements[ShadowTreeE]);
glDrawElements(GL_TRIANGLES, 180, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
}
}
glUseProgram(0);
When I run it only on the mountain object, this is the resulting image I get, as you can see it is correct.
It works on other scene elements individually as well.
My question is how do I draw without problems into the same buffer using multiple draws?
edit:
Just because it was requested here are the shadow shader components:
Vertex shader:
#version 330 core
uniform mat4 depthProj;
uniform mat4 modelmat;
layout(location = 0) attribute vec4 vPosition;
void main()
{
gl_Position = depthProj * modelmat * vPosition;
}
Fragment shader:
#version 330 core
layout(location = 0) out float fragmentDepth;
void main()
{
}

I don't know why, but when the lines,
glUniformMatrix4fv(depth_loc, 1, GL_FALSE, depthproj);
and
glUniformMatrix4fv(model_view_loc, 1, GL_FALSE, modelmat);
are turned into;
glUniformMatrix4fv(depth_loc, 1, GL_TRUE, depthproj);
and
glUniformMatrix4fv(model_view_loc, 1, GL_TRUE, modelmat);
the scene is drawn as it should.

Related

opengl shader for drawing feature point in slam [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I want to draw points using opengl shader.
Now my code using glvertex3f(pos.x, pos.y, pos.z) but when too many point to draw using it, it slow. So I want to using shader and glDrawarrays. But its not work. please check my code.
original code :
for (const auto lm : landmarks) {
const openvslam::Vec3_t pos_w = lm->get_pos_in_world();
glColor3ub(lm->color_[0], lm->color_[1], lm->color_[2]);
glVertex3f(pos_w.cast<float>().eval().x(),pos_w.cast<float>().eval().y(), pos_w.cast<float>().eval().z());
}
my code :
for (const auto lm : landmarks) {
const openvslam::Vec3_t pos_w = lm->get_pos_in_world();
int buffer_size = local_landmarks.size();
glGenBuffers(2, buffers_);
glBindBuffer(GL_ARRAY_BUFFER, buffers_[0]);
glm::vec3 pos_pt = glm::vec3(pos_w.cast<float>().eval().x(),pos_w.cast<float>().eval().y(), pos_w.cast<float>().eval().z());
glBufferData(GL_ARRAY_BUFFER, 3*buffer_size*sizeof(float), &pos_pt , GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, buffers_[1]);
glm::vec3 color_pt = glm::vec3(lm->color_[0], lm->color_[1], lm->color_[2]);
glBufferData(GL_ARRAY_BUFFER, buffer_size*3*sizeof(float), &color_pt, GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
Eigen::Matrix4f mvp = s_cam_shader_opengl->GetProjectionModelViewMatrix();
//Eigen::Matrix4f mvp = s_cam_shader_opengl->GetProjectionMatrix() * s_cam_shader_opengl->GetModelViewMatrix();
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, mvp.data());
glPointSize(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_POINTS, 0, 3*num);
}
vertex shader
#version 460
uniform mat4 mvpMat;
layout (location = 0) in vec3 test_position;
layout (location = 1) in vec3 test_color;
out vec3 colorr;
void main(void){
colorr = test_color;
gl_Position = vec4(test_position,1.0);
}
fragment shader
#version 460
uniform mat4 mvpMat;
in vec3 colorr;
out vec4 frag_color;
void main(void) {
frag_color = vec4(colorr, 1.0);
}
////////////////////////////////////////////////////////////////////////
+edit
I update code but it said segmentation error.
Whats problem?
struct TLandmarkData
{
glm::vec3 pos;
glm::vec3 color;
};
using TLandmarks = std::vector<TLandmarkData>;
TLandmarks landmarks_;
...
code
...
glUseProgram(points_program_);
while(){
...
for (const auto lm : landmarks) {
TLandmarkData aaa;
glm::vec3 pos_pt = glm::vec3(pos_w.cast<float>().eval().x(),pos_w.cast<float>().eval().y(), pos_w.cast<float>().eval().z());
glm::vec3 color_pt = glm::vec3(lm->color_[0], lm->color_[1], lm->color_[2]);
aaa.pos = pos_pt;
aaa.color = color_pt;
landmarks_.push_back(aaa);
}
...
GLuint vbo_;
GLuint vao_;
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, landmarks_.size()*sizeof(*landmarks_.data()), landmarks_.data(), GL_STATIC_DRAW);
glGenVertexArrays(1, &vao_);
glBindVertexArray(vao_);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), 0);
glEnableVertexAttribArray( 0 );
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), (void*)(sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(GL_POINTS, 0, landmarks_.size());
}
vertex shader
#version 460
layout (location = 0) in vec3 test_position;
layout (location = 1) in vec3 test_color;
out vec3 colorr;
void main(void){
colorr = test_color;
gl_Position = vec4(test_position,1.0);
}
fragment shader
#version 460
in vec3 colorr;
out vec4 frag_color;
void main(void) {
frag_color = vec4(colorr, 1.0);
}
+
What you actually do is to create landmarks.size() buffers rather than 1 buffer. You have to create one single buffer. For the best performance gain you have to create tha buffer once (respectively when it changes only) and to do the world transformation in the shader.
Use the following data structure to represent a point (or a similar aggregate):
struct TLandmarkData
{
glm::vec3 pos;
glm::vec3 color;
};
using TLandmarks = std::vector<TLandmarkData>;
Create a Vertex Array Object and a Vertex Buffer Object (once at initialization):
(See also Vertex Specification)
TLandmarks landmarks;
GLuint vbo_;
GLuint vao_;
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, landmarks.size()*sizeof(*landmarks.data()), landmarks.data(), GL_STATIC_DRAW);
glGenVertexArrays(1, &vao_);
glBindVertexArray(vao_);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), 0);
glEnableVertexAttribArray( 0 );
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TLandmarkData), (void*)(sizeof(glm::vec3)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
As you can see, you don't need any loop. If the data changes, the buffer (vbo_) can be updated (e.g. glBufferSubData).
When you want to draw the points, then it is sufficient to bind the vertex array object. The count argument to glDrawArrays has to be the number of vertices:
glBindVertexArray(vao_);
glDrawArrays(GL_POINTS, 0, landmarks.size());
Use a Uniform of type mat4, to transform the points to world coordinates in the vertex shader:
#version 460
uniform mat4 mvpMat;
layout (location = 0) in vec3 test_position;
layout (location = 1) in vec3 test_color;
layout (location=0) uniform mat4 worldtransform;
out vec3 colorr;
void main(void){
colorr = test_color;
gl_Position = worldtransform * vec4(test_position,1.0);
}
Set the uniform (update it per frame) by glUniformMatrix4fv after the program is installed by glUseProgram:
glm::mat4 toworld(1.0f);
// set toworld
// [...]
glUseProgram(myProgram);
glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(toworld));

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);
}
}

Vertex shader makes GUI disappear

I have some code to render GUI's, and if I dont use a vertex shader then it renders exactly where its meant to :
However, as soon as I use a vertex shader, even simply one that calls
gl_position = vec4(position,1.0);
It hides, or moves, or otherwise makes my GUI disappear
Whats the correct way to have a shader for GUIs in OpenGL?
GUI render :
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
RendererUtils.setWireframeMode(false);
for (Interface i : interfaces)
{
i.updateShaderForThisB();
if (i instanceof InterfaceContainer)
{
((InterfaceContainer) i).draw();
}
else
{
((InterfaceControl) i).draw();
}
}
InterfaceShader.getInstance().unbind();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
InterfaceContainer and InterfaceControl's draw call is largely the same, so I'll only add one of them.
InterfaceControl.draw()
public void draw()
{
this.updateShaderForThisB();
this.getMesh().draw();
if (this.hasText)
{
//this.updateShaderForThisF();
//drawText();
}
}
InterfaceControl.updateShaderForThisB()
public void updateShaderForThisB()
{
InterfaceShader shader = InterfaceShader.getInstance();
shader.bind();
shader.setColour(this.getActingColour());
shader.setLocation(this.getLocation());
shader.setSize(this.getBounds());
shader.setGradient(this.getShouldGradient());
shader.updateUniforms();
}
Mesh.draw()
public void draw()
{
glEnableVertexAttribArray(0); //Vertices
glEnableVertexAttribArray(1); //Tex coords
glEnableVertexAttribArray(2); //Normals
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT,0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
InterfaceShader.vs
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
uniform mat4 viewMatrix;
out vec2 texCoord0;
void main()
{
gl_Position = viewMatrix * vec4(position,1.0);
texCoord0 = texCoord;
}
Can anyone see an obvious problem that i've overlooked? My first thought was that the shader was translating my interface-oriented coordinates (ie 50,50,1) into real world coordinates, but I dont know
Edit : As requested, updated shader code and added matrix projection code
https://pastebin.com/gKdewDVi
pastebin for Transform class, for getting the view matrix and such, and how it's related back to the shader
The fixed function vertex processing pipeline multiplies the vertex positions by the current matrix given by GL_PROJECTION * GL_MODELVIEW. You have to do the same thing in your vertex shader like so:
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);
Please note that you are using outdated OpenGL programming practices by using the fixed-function processing. This has been deprecated for a while now.

can't draw any other objects before or after drawing particles

I am working on a game, and trying to implement the instancized CPU-Particle System programmed on http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/particles-instancing/
i managed to get it working in my code structure, but i am trying to draw other objects in the same window, which i can't, i have tested it, and it only allows me to draw one, either draw the particle system or draw the object i want.
The problem happens specifically at this code part :
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Use our shader
glUseProgram(particleprogramID->programHandle);
unit2 +=1;
glActiveTexture(GL_TEXTURE0 + unit2);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(TextureID, unit2);
glm::mat4 ViewMatrix = camera->getViewMatrix();
// Same as the billboards tutorial
glUniform3f(CameraRight_worldspace_ID, ViewMatrix[0][0], ViewMatrix[1][0], ViewMatrix[2][0]);
glUniform3f(CameraUp_worldspace_ID , ViewMatrix[0][1], ViewMatrix[1][1], ViewMatrix[2][1]);
glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, &mvp[0][0]);
//glUniformMatrix4fv(modviewprojID, 1, GL_FALSE, &mvp[0][0]);
//1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
// 2nd attribute buffer : positions of particles' centers
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
glVertexAttribPointer(
1,
4,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
// 3rd attribute buffer : particles' colors
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
glVertexAttribPointer(
2,
4,
GL_UNSIGNED_BYTE,
GL_TRUE,
0,
(void*)0
);
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 1);
glVertexAttribDivisor(2, 1);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
then i try to draw my star:
unit2 += 1;
starTexture->Bind(unit2);
shaderObject ->useShader();
glUniform1i(glGetUniformLocation(shaderObject->programHandle, "colorTexture"), unit2);
glUniformMatrix4fv(glGetUniformLocation(shaderObject->programHandle, "modelMatrix"), 1, GL_FALSE, glm::value_ptr(star1->getModelMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shaderObject->programHandle, "projectionMatrix"), 1, GL_FALSE, glm::value_ptr(projectionViewMatrix));
star1->draw();
the vertex and fragment shader for the particle system:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 squareVertices;
layout(location = 1) in vec4 xyzs; // Position of the center of the particule and size of the square
layout(location = 2) in vec4 color; // Position of the center of the particule and size of the square
// Output data ; will be interpolated for each fragment.
out vec2 UV;
out vec4 particlecolor;
// Values that stay constant for the whole mesh.
uniform vec3 CameraRight_worldspace;
uniform vec3 CameraUp_worldspace;
uniform mat4 VP; // Model-View-Projection matrix, but without the Model (the position is in BillboardPos; the orientation depends on the camera)
void main()
{
float particleSize = xyzs.w; // because we encoded it this way.
vec3 particleCenter_wordspace = xyzs.xyz;
vec3 vertexPosition_worldspace =
particleCenter_wordspace
+ CameraRight_worldspace * squareVertices.x * particleSize
+ CameraUp_worldspace * squareVertices.y * particleSize;
// Output position of the vertex
gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f);
// UV of the vertex. No special space for this one.
UV = squareVertices.xy + vec2(0.5, 0.5);
particlecolor = color;
}
frragment shader:
#version 330 core
// Interpolated values from the vertex shaders
in vec2 UV;
in vec4 particlecolor;
// Ouput data
out vec4 color;
uniform sampler2D myTexture;
void main(){
// Output color = color of the texture at the specified UV
color = texture2D( myTexture, UV ) * particlecolor;
}
and it only displays the particle system:
worth mentioning is:
the object i want to draw is a star modelled in blender and is displayed correctly when drawn alone or with other objects other than the particle system. and has its own class having buffers for psitions, UVs, indices and normals...
it seems like the star data are being swallowed by the buffer...
i appreciate every help...

Lighting is misbehaving in shader program

Here is my shader program:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexNormal_modelspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform mat3 blNormalMatrix;
uniform vec3 lightPos;
out vec4 forFragColor;
const vec3 diffuseColor = vec3(0.55, 0.09, 0.09);
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * diffuseColor;
// all following gemetric computations are performed in the
// camera coordinate system (aka eye coordinates)
vec3 vertexNormal_cameraspace = (V*M*vec4(vertexNormal_modelspace,0)).xyz;
vec4 vertexPosition_cameraspace4 = V*M* vec4(vertexPosition_modelspace,1);
vec3 vertexPosition_cameraspace = vec3(vertexPosition_cameraspace4).xyz;
vec3 lightDir = normalize(lightPos - vertexPosition_cameraspace);
float lambertian = clamp(dot(lightDir,vertexNormal_cameraspace), 0.0,1.0);
forFragColor = vec4(lambertian*diffuseColor , 1.0);
}
My problem is that this "worked" in the older opengl profile, didn't even have the version number, I think it was around Opengl 2.1 or so, the key change was that I originally had normal = gl_normalMatrix * gl_normal and things worked.
However that was based on my professor's code which I've updated to the 3.3+ core profile and after maybe fixing the deprecated functions I am now left with this:
https://drive.google.com/file/d/0B6oLZ_d7S-U7cVpkUXpVXzdaZEk/edit?usp=sharing is a link to the video of my program's behavior.
The light source should be a point light at (0,0,3) or so that shouldn't move; but its not following a particularly logical behaviorial pattern, I can't make sense of it.
I tried passing the inverse transpose of the model matrix and using them as a replacement normalMatrix but it wrecked my normals. So I don't know.
This was my normalMatrix:
glm::mat3 MyNormalMatrix = glm::mat3(glm::transpose(glm::inverse(ModelMatrix)));
Edit: Here is my Display code:
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
// Use our shader
glUseProgram(programID);
// Get our transformations iff we move the camera around.
glm::mat4 MyModelMatrix = ModelMatrix * thisTran * ThisRot;
MVP = ProjectionMatrix * ViewMatrix * MyModelMatrix;
glm::mat4 ModelView = ViewMatrix * MyModelMatrix;
glm::mat3 MyNormalMatrix = glm::mat3(glm::transpose(glm::inverse(ModelView)));
glm::vec3 newLightPos = lightPos;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &MyModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glUniformMatrix4fv(BlNormalMatrix,1,GL_FALSE, &MyNormalMatrix[0][0]);
glUniformMatrix4fv(BlRotations, 1, GL_FALSE, &ThisRot[0][0]);
glUniform3f(BlCamera, cameraLoc.x, cameraLoc.y, cameraLoc.z);
glUniform3f(lPosition, newLightPos.x,newLightPos.y,newLightPos.z);
// VBO buffer: vertices
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2rd attribute buffer : normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
1, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// draw object using opengl 3.3 shit
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
The problem ultimately turned out to be an issue with the Model Loader provided by my Professor, was somehow incompatible with modern opengl and would only "mostly" work in that it was clearly missing the left/right normals or they had invalid values. Solved with using an implementation of Assimp.
The code, with assimp linked is like this:
void blInitResWAssimp() {
cout << "blInitResWAssimp" << endl;
blCreateModelViewProjectionMatrix();
//loads object
bool res = loadAssImp("Resources/RCSS-subdiv.obj", indices, indexed_vertices, indexed_uvs, indexed_normals);
//bool res = loadAssImp("Resources/cheb.obj", indices, indexed_vertices, indexed_uvs, indexed_normals);
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Load it into a VBO
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW);
// Normal buffer
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);
// Generate a buffer for the indices as well
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);
//ModelMatrix = ModelMatrix * glm::translate(glm::mat4(1.0f), glm::vec3(-0.5, -0.5, 0));
}
Assimp stuff
bool loadAssImp(
const char * path,
std::vector<unsigned short> & indices,
std::vector<glm::vec3> & vertices,
std::vector<glm::vec2> & uvs,
std::vector<glm::vec3> & normals
){
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, 0/*aiProcess_JoinIdenticalVertices | aiProcess_SortByPType*/);
if (!scene) {
fprintf(stderr, importer.GetErrorString());
getchar();
return false;
}
const aiMesh* mesh = scene->mMeshes[0]; // In this simple example code we always use the 1rst mesh (in OBJ files there is often only one anyway)
const aiMaterial* material = scene->mMaterials[0];
// Fill vertices positions
vertices.reserve(mesh->mNumVertices);
for (unsigned int i = 0; i<mesh->mNumVertices; i++){
aiVector3D pos = mesh->mVertices[i];
vertices.push_back(glm::vec3(pos.x, pos.y, pos.z));
}
// Fill vertices texture coordinates
/*
uvs.reserve(mesh->mNumVertices);
for (unsigned int i = 0; i<mesh->mNumVertices; i++){
aiVector3D UVW = mesh->mTextureCoords[0][i]; // Assume only 1 set of UV coords; AssImp supports 8 UV sets.
uvs.push_back(glm::vec2(UVW.x, UVW.y));
}*/
// Fill vertices normals
normals.reserve(mesh->mNumVertices);
for (unsigned int i = 0; i<mesh->mNumVertices; i++){
aiVector3D n = mesh->mNormals[i];
//aiVector3D n = mesh->mVertices[i];
normals.push_back(glm::vec3(n.x, n.y, n.z));
}
// Fill face ind5ices
indices.reserve(3 * mesh->mNumFaces);
for (unsigned int i = 0; i<mesh->mNumFaces; i++){
// Assume the model has only triangles.
indices.push_back(mesh->mFaces[i].mIndices[0]);
indices.push_back(mesh->mFaces[i].mIndices[1]);
indices.push_back(mesh->mFaces[i].mIndices[2]);
}
// The "scene" pointer will be deleted automatically by "importer"
}