OpenGL glm calculations don't seem to work in my program. Nothing moves even when i use the glm translate function to translate the z axis with a variable every frame. Am i missing something?
main.cpp
#define GLEW_STATIC
#define NO_SDL_GLEXT
#include "glew.h"
#include <sdl.h>
#undef main
#include "SDL_opengl.h"
#include "timer.h"
#include <time.h>
#include <shader.h>
using namespace std;
#include <glm/gtc/matrix_projection.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
unsigned int vaoID[1]; // Our Vertex Array Object
unsigned int vboID[1]; // Our Vertex Buffer Object
glm::mat4 projectionMatrix; // Store the projection matrix
glm::mat4 viewMatrix; // Store the view matrix
glm::mat4 modelMatrix; // Store the model matrix
Shader *shader; // Our GLSL shader
float ztransform(0);
bool exited(false);
SDL_Event event;
const int FRAMES_PER_SECOND = 60;
void createSquare(void) {
float* vertices = new float[18]; // Vertices for our square
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Bottom left corner
vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Top left corner
vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner
vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner
vertices[12] = -0.5; vertices[13] = -0.5; vertices[14] = 0.0; // Bottom left corner
vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // Top Right corner
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it
glGenBuffers(1, vboID); // Generate our Vertex Buffer Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, 18 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Disable our Vertex Array Object
glBindVertexArray(0); // Disable our Vertex Buffer Object
delete [] vertices; // Delete our vertices from memory
}
void startGL()
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);
glewInit();
glClearColor(0.4f, 0.0f, 1.0f, 0.0f);
projectionMatrix = glm::perspective(60.0f, (float)800 / (float)600, 0.1f, 100.f); // Create our perspective projection matrix
shader = new Shader("shader.vert", "shader.frag"); // Create our shader by loading our vertex and fragment shader
createSquare();
}
void drawstuff()
{
glViewport(0, 0, 800, 600); // Set the viewport size to fill the window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Clear required buffers
viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, ztransform)); // Create our view matrix which will translate us back 5 units
modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); // Create our model matrix which will halve the size of our model
shader->bind(); // Bind our shader
int projectionMatrixLocation = glGetUniformLocation(shader->id(), "projectionMatrix"); // Get the location of our projection matrix in the shader
int viewMatrixLocation = glGetUniformLocation(shader->id(), "viewMatrix"); // Get the location of our view matrix in the shader
int modelMatrixLocation = glGetUniformLocation(shader->id(), "modelMatrix"); // Get the location of our model matrix in the shader
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]); // Send our projection matrix to the shader
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); // Send our view matrix to the shader
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]); // Send our model matrix to the shader
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object
glDrawArrays(GL_TRIANGLES, 0, 6); // Draw our square
glBindVertexArray(0); // Unbind our Vertex Array Object
shader->unbind(); // Unbind our shader
}
int main (int argc, char* args[])
{
Timer fps;
startGL();
while(exited == false)
{
while( SDL_PollEvent(&event) )
{
if( event.type == SDL_QUIT )
exited = true;
}
drawstuff();
ztransform+=.1
SDL_GL_SwapBuffers();
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
SDL_Quit();
return 0;
}
shader.frag
#version 150 core
in vec3 pass_Color;
out vec4 out_Color;
void main(void)
{
out_Color = vec4(pass_Color, 1.0);
}
shader.vert
#version 150 core
in vec3 in_Position;
in vec3 in_Color;
out vec3 pass_Color;
void main(void)
{
gl_Position = vec4(in_Position, 1.0);
pass_Color = in_Color;
}
You have to apply your transformation in your vertex shader.
you should define in your vertex shader
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
And then apply these transformations to your input position (note: i may have gotten the order wrong)
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_position, 1.0);
Generally though, you would multiply the 3 matrices together in your c++ program and pass in a modelViewProjection matrix.
Related
I am using Assimp to load models to render in OpenGL but am running into an issue where chunks/pieces of a mesh don't render.
Example:
What model is supposed to look like:
What I end up rendering:
As you can see, some of the model is rendering properly, but not all.
I have verified multiple times that the meshes being loaded from assimp are loading the correct vertices and indices into my "Mesh" class. Here is my code for loading a model:
This function will recursively call itself for all child nodes and load each mesh inside the node. Each mesh will then be transformed into my own "Mesh" class by creating a vector of vertices and faces.
void Model::LoadAssimpNode(aiNode* node, const aiScene* scene)
{
// Process assimp meshes
for (unsigned int i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
this->meshes.push_back(this->LoadAssimpMesh(mesh, scene));
}
// Recursivley processes child nodes
for (unsigned int i = 0; i < node->mNumChildren; i++)
{
this->LoadAssimpNode(node->mChildren[i], scene);
}
}
Mesh Model::LoadAssimpMesh(aiMesh* mesh, const aiScene* scene)
{
std::vector<sVertex> vertices;
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
sVertex vertex;
vertex.x = mesh->mVertices[i].x;
vertex.y = mesh->mVertices[i].y;
vertex.z = mesh->mVertices[i].z;
vertex.nx = mesh->mNormals[i].x;
vertex.ny = mesh->mNormals[i].y;
vertex.nz = mesh->mNormals[i].z;
if (mesh->mTextureCoords[0])
{
vertex.u0 = mesh->mTextureCoords[0][i].x;
vertex.v0 = mesh->mTextureCoords[0][i].y;
}
vertices.push_back(vertex);
}
std::vector<sTriangle> faces;
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
sTriangle face;
aiFace assimpFace = mesh->mFaces[i];
if (assimpFace.mNumIndices != 3)
{
std::cout << "Face is not a triangle!" << std::endl;
}
for (unsigned int j = 0; j < assimpFace.mNumIndices; j++)
{
face.vertIndex[j] = assimpFace.mIndices[j];
}
faces.push_back(face);
}
std::vector<Texture> textures;
if (mesh->mMaterialIndex >= 0)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
// Sampler names should adhere to the following convention:
// Diffuse: texure_diffuseN
// Specular: texture_specularN
// Normal: texture_normalN
// Where N = texture numbers
for (Texture texture : this->LoadAssimpMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse"))
{
this->loadedTextures.insert(std::make_pair(texture.path.C_Str(), texture));
textures.push_back(texture);
}
for (Texture texture : this->LoadAssimpMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular"))
{
this->loadedTextures.insert(std::make_pair(texture.path.C_Str(), texture));
textures.push_back(texture);
}
}
return Mesh(vertices, faces, textures);
}
The sVertex and sTriangle structs are defined as:
struct sVertex
{
float x, y, z;
float nx, ny, nz;
float u0, v0;
};
struct sTriangle
{
unsigned int vertIndex[3];
};
Now that the model is effectively loaded from assimp, we now call the SetupMesh() function which sets up the meshes' respective VAO, VBO and EBO:
void Mesh::SetupMesh()
{
// Generate IDs for our VAO, VBO and EBO
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glGenBuffers(1, &this->EBO);
glBindVertexArray(this->VAO);
// Now ANY state that is related to vertex or index buffer
// and vertex attribute layout, is stored in the 'state'
// of the VAO...
// Tell open GL where to look for for vertex data
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(sVertex), &this->vertices[0], GL_STATIC_DRAW);
// Tell open GL where our index buffer begins (AKA: where to look for faces)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->faces.size() * sizeof(sTriangle), &this->faces[0], GL_STATIC_DRAW);
// Set the vertex attributes for this shader
// Layout information can be found in the vertex shader, currently:
// 0 = position
// 1 = normals
// 2 = texture coordinates
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(sVertex), (void*) offsetof(sVertex, x));
glEnableVertexAttribArray(1); // normal
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(sVertex), (void*) offsetof(sVertex, nx));
glEnableVertexAttribArray(2); // textureCoordinates
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(sVertex), (void*)offsetof(sVertex, u0));
// Now that all the parts are set up, unbind buffers
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
Once this is all setup, I will now call the Draw method for each mesh to render in my render loop:
void Mesh::Draw(const CompiledShader& shader)
{
glm::mat4 matModel = glm::mat4(1.0f);
glm::mat4 matTranslate = glm::translate(glm::mat4(1.0f), this->positionXYZ); // Translation matrix
glm::mat4 rotateX = glm::rotate(glm::mat4(1.0f), this->orientationXYZ.x, glm::vec3(1.0f, 0.0f, 0.0f)); // X axis rotation
glm::mat4 rotateY = glm::rotate(glm::mat4(1.0f), this->orientationXYZ.y, glm::vec3(0.0f, 1.0f, 0.0f)); // Y axis rotation
glm::mat4 rotateZ = glm::rotate(glm::mat4(1.0f), this->orientationXYZ.z, glm::vec3(0.0f, 0.0f, 1.0f)); // Z axis rotation
glm::mat4 matScale = glm::scale(glm::mat4(1.0f), glm::vec3(this->scale, this->scale, this->scale)); // Scale the mesh
glm::mat4 matInvTransposeModel = glm::inverse(glm::transpose(matModel));
// Apply all the transformations to our matrix
matModel = matModel * matTranslate;
matModel = matModel * rotateZ;
matModel = matModel * rotateY;
matModel = matModel * rotateX;
matModel = matModel * matScale;
glUseProgram(shader.ID);
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "matModel"), 1, GL_FALSE, glm::value_ptr(matModel)); // Tell shader the model matrix (AKA: Position orientation and scale)
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "matModelInverseTranspose"), 1, GL_FALSE, glm::value_ptr(matInvTransposeModel));
// Draw the mesh
glBindVertexArray(this->VAO);
glDrawElements(GL_TRIANGLES, this->faces.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
My shaders are very simple where the color of a pixel is equal to the vertex's normal:
Vertex Shader:
#version 420
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 textureCoordinates;
uniform mat4 matModel;
uniform mat4 matView;
uniform mat4 matProjection;
uniform mat4 matModelInverseTranspose; // For normal calculation
out vec4 fVertWorldLocation;
out vec4 fNormal;
out vec2 TextureCoordinates;
void main()
{
mat4 MVP = matProjection * matView * matModel;
gl_Position = MVP * vec4(position, 1.0f);
TextureCoordinates = textureCoordinates;
// The location of the vertex in "world" space (not screen space)
fVertWorldLocation = matModel * vec4(position, 1.0f);
// Calculate the normal based on any rotation we've applied.
// This inverse transpose removes scaling and tranlation (movement)
// from the matrix.
fNormal = matModelInverseTranspose * vec4(normal, 1.0f);
};
Fragment Shader:
#version 420
in vec2 TextureCoordinates;
in vec4 fNormal;
out vec4 Color;
uniform sampler2D texture_diffuse;
void main()
{
//Color = vec4(texture(texture_diffuse, TextureCoordinates));
//Color = vec4(TextureCoordinates, 1.0f, 1.0f);
Color = fNormal;
}
Sorry for the insane length of this post, but I feel that all of it was necessary to get my point across.
If anyone could point out what I am doing wrong here it would be greatly appreciated! I feel like I need an extra pair of eyes here because I have read my code over countless times and can't seem to come up with anything.
Made a stupid mistake, I was under the impression that the "count" argument in the glDrawElements() function wanted the number of faces NOT the number of indices.
The problem was fixed by changing my glDrawElements call from:
glDrawElements(GL_TRIANGLES, this->faces.size(), GL_UNSIGNED_INT, 0);
To this:
glDrawElements(GL_TRIANGLES, this->faces.size() * 3, GL_UNSIGNED_INT, 0);
Details:
This shader draws an orbit path of a planet around a star. My intention is to dim the color of the path when it gets farther away from the opengl camera using the uniform floats "near" and "far" to help calculate the color brightness. When I try to use the uniform float variables, the shader doesn't work at all. I have no idea what could be wrong. (I'm new at openGL and C++).
Vertex shader (Works if not using uniform float variables)
#version 450
layout(location=0) in vec3 vertex_position;
uniform mat4 proj, view; //view and projection matrix
uniform mat4 matrix; // model matrix
uniform float near; //closest orbit distance
uniform float far; //farthest orbit distance
uniform vec3 dist_orbit_center;
out vec3 colour;
void main()
{
vec3 dist_vector = dist_orbit_center + vertex_position;
float dist = length(dist_vector);
//Trying out some debugging. Ignoring dist for now
//float ratio = near / far; // Not working!
float ratio = 0.25 / 0.5; // Working!
colour = vec3(0.0, 1.0, 0.1) * ratio;
gl_Position = proj * view * matrix * vec4(vertex_position, 1.0);
}
Fragment shader (Works if not using uniform float variables)
#version 450
in vec3 colour;
out vec4 frag_colour;
void main()
{
frag_colour=vec4 (colour, 1.0);
}
C++ code for drawing planet orbit path (Working except for glUniform1f ?)
if ((orb.flag))
{
double near;
double far;
// get nearest and farthest point of orbit
distance_to_orbit(near, far, cam.pos, sun.pos, plan[orb.body].orbit_radius, plan[orb.body].orbit_axis, Debug);
GLfloat near_display = (float) (near / DISPLAY_FACTOR);
GLfloat far_display = (float) (far / DISPLAY_FACTOR);
glUseProgram(sh_orbit.program);
glBindVertexArray(sh_orbit.vao);
glUniformMatrix4fv (sh_orbit.view_mat_location, 1, GL_FALSE, cam.view_mat.m);
mat4 m = identity_mat4();
mat4 m2;
m2 = translate(m, sun.display_pos);
glUniformMatrix4fv (sh_orbit.matrix_mat_location, 1, GL_FALSE, m2.m);
// For debugging. Not working.
near_display = 0.25;
glUniform1f(sh_orbit.near_location, near_display);
// For debugging. Not working.
far_display = 0.5;
glUniform1f(sh_orbit.far_location, far_display);
glUniform3fv(sh_orbit.dist_orbit_center_location, 1, sun.display_pos.v);
glDrawArrays(GL_LINE_STRIP, 0, 361);
glBindVertexArray(0);
}
C++ code for creating orbit path of planet for vertex shader (Working)
void Setup_planet_orbit(int index)
{
orb.flag = 1;
orb.body = index;
vec3d axis = plan[orb.body].orbit_axis;
vec3d globe = plan[orb.body].origonal_pos;
for (int lp=0; lp<361; lp++)
{
globe = Rotate_point((double) lp * TO_RADIANS, axis,
plan[orb.body].origonal_pos);
sh_orbit.points[lp*3] = (float) (globe.v[0] / DISPLAY_FACTOR);
sh_orbit.points[lp*3+1] = (float) (globe.v[1] / DISPLAY_FACTOR);
sh_orbit.points[lp*3+2] = (float) (globe.v[2] / DISPLAY_FACTOR);
}
glUseProgram(sh_orbit.program);
glBindVertexArray(sh_orbit.vao);
glBindBuffer(GL_ARRAY_BUFFER, sh_orbit.points_vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, 361*3*sizeof(GLfloat),
sh_orbit.points);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
C++ code for initializing shader (Working)
bool Get_orbit_shader()
{
float*& point = sh_orbit.points;
point = (float*)malloc (3 * 361 * sizeof (float));
string vertshader=readFile("orbit.vert.txt");
const char* vertex_shader = vertshader.c_str();
string fragshader=readFile("orbit.frag.txt");
const char* fragment_shader = fragshader.c_str();
// Compile vertex shader program
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_shader, NULL);
glCompileShader(vs);
int params=-1;
glGetShaderiv (vs, GL_COMPILE_STATUS, ¶ms);
if (GL_TRUE != params)
{
fprintf(stderr, "ERROR: GL shader index %i did not compile\n", vs);
print_shader_info_log(vs);
return false;
}
// Compile fragment shader program
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_shader, NULL);
glCompileShader(fs);
glGetShaderiv (fs, GL_COMPILE_STATUS, ¶ms);
if (GL_TRUE != params)
{
fprintf(stderr, "ERROR: GL shader index %i did not compile\n", fs);
print_shader_info_log(fs);
return false;
}
// Link vertex and shader program
sh_orbit.program = glCreateProgram();
glAttachShader(sh_orbit.program, fs);
glAttachShader(sh_orbit.program, vs);
glLinkProgram(sh_orbit.program);
//Check if linked correctly.
glGetProgramiv(sh_orbit.program, GL_LINK_STATUS, ¶ms);
if (GL_TRUE !=params)
{
fprintf (stderr, "ERROR: could not link shader programme GL index
%u\n",
sh_orbit.program);
print_programme_info_log(sh_orbit.program);
return false;
}
print_all(sh_orbit.program);
mat4 matrix = identity_mat4();
glUseProgram(sh_orbit.program);
glGenVertexArrays(1, &sh_orbit.vao);
glBindVertexArray(sh_orbit.vao);
sh_orbit.view_mat_location = glGetUniformLocation(sh_orbit.program,
"view");
glUniformMatrix4fv (sh_orbit.view_mat_location, 1, GL_FALSE,
cam.view_mat.m);
sh_orbit.proj_mat_location = glGetUniformLocation (sh_orbit.program,
"proj");
glUniformMatrix4fv (sh_orbit.proj_mat_location, 1, GL_FALSE,
cam.proj_mat.m);
sh_orbit.proj_mat_location = glGetUniformLocation (sh_orbit.program,
"matrix");
glUniformMatrix4fv (sh_orbit.matrix_mat_location, 1, GL_FALSE, matrix.m);
sh_orbit.near_location = glGetUniformLocation(sh_orbit.program, "near");
glUniform1f (sh_orbit.near_location, 0);
sh_orbit.far_location = glGetUniformLocation (sh_orbit.program, "far");
glUniform1f (sh_orbit.far_location, 0);
vec3 load;
sh_orbit.dist_orbit_center_location = glGetUniformLocation
(sh_orbit.program, "dist_orbit_center");
glUniform3f (sh_orbit.dist_orbit_center_location, load.v[0], load.v[1],
load.v[2]);
glGenBuffers(1, &sh_orbit.points_vbo);
glBindBuffer(GL_ARRAY_BUFFER, sh_orbit.points_vbo);
glBufferData(GL_ARRAY_BUFFER, 361*3*sizeof(GLfloat), sh_orbit.points,
GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
return true;
}
C++ code for finding nearest and farthest point of orbit in 3D space (Working)
/// Find closest and farthest distance to a 3d disk
/// projection of P-C onto plane is Q-C = P-C - Dot(N,P-C)*N
void distance_to_orbit(double &near, double &far, vec3d point, vec3d center,
double radius, vec3d normal, FILE* Debug)
{
vec3d PmC;
vec3d QmC;
vec3d diff;
double lengthQmC;
double sqr_dist;
double dist;
double temp;
vec3d Closest;
vec3d Farthest;
vec3d vec_temp;
PmC = point - center;
double Dot = dot_d(normal, PmC);
vec_temp = normal * Dot; //Distance to plane that circle is on.
QmC = PmC - vec_temp;
lengthQmC = length(QmC);
vec_temp = QmC * (radius / lengthQmC);
Closest = center + vec_temp;
diff = point - Closest;
sqr_dist = dot_d(diff, diff);
near = sqrt(sqr_dist); //distance to nearest point of 3d disc
vec_temp = center - Closest;
vec_temp *= 2.0f;
diff = Closest + vec_temp;
far = get_distance_d(point, diff); //distance to farthest point of 3d
disc
}
Aren't you setting far (and near) to 0 in glUniform1f (sh_orbit.far_location, 0); expression and getting division by zero?
I`m trying to render some particles and save the scene to a bmp file,
here is my code
// vertex shader
const char *vertexShader = STRINGIFY(
uniform float pointRadius; // point size in world space
uniform float pointScale; // scale to calculate size in pixels
void main()
{
// calculate window-space point size
vec3 posEye = vec3(gl_ModelViewMatrix * vec4(gl_Vertex.xyz, 1.0));
float dist = length(posEye);
gl_PointSize = pointRadius * (pointScale / dist);
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0);
gl_FrontColor = gl_Color;
}
);
// pixel shader for rendering points as shaded spheres
const char *spherePixelShader = STRINGIFY(
void main()
{
const vec3 lightDir = vec3(0.577, 0.577, 0.577);
// calculate normal from texture coordinates
vec3 N ;
N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
float mag = dot(N.xy, N.xy);
if (mag > 1.0) discard; // kill pixels outside circle
N.z = sqrt(1.0 - mag);
// calculate lighting
float diffuse = max(0.0, dot(lightDir, N));
gl_FragColor = gl_Color *diffuse;
}
Here is the rendering code
Position of the particles are stored in the VBO target_point_buffer as well as corresponding color data
void display()
{
//pointsprite
glEnable(GL_POINT_SPRITE);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_NV);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
//attach shader
glUseProgram(program);
glUniform1f(glGetUniformLocation(program, "pointScale"), winHeight / tanf(fov*0.5f*(float)M_PI / 180.0f));
glUniform1f(glGetUniformLocation(program, "pointRadius"),radius[0]*scale);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//use vbo
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(3, GL_DOUBLE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
//color buffer
glBindBuffer(GL_ARRAY_BUFFER, color_vbo);
glColorPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
Drawsomething();
}
//Save the scene as an bmp file
void save_as_bmp(char *filename)
{
GLbyte pBits[Imagesize];
GLint iViewPort[4];
GLuint lastBuffer;
glGetIntegerv(GL_VIEWPORT,iViewPort);
glGetIntegerv(GL_READ_BUFFER,&lastBUffer);
glReadPixels(iViewPort[0], iViewPort[1], iViewPort[2], iViewPort[3], GL_BGR, GL_UNSIGNED_BYTE, pBits);
writeBMP(filename,pBits);
}
I`ve got the expected scene like this:
However,when I tried to save the scene as a BMP file,the result was not like I expected:
I suppose that it might be something wrong with the gl_TexCoord in the shader, but I can`t figure it out. Can anyone help?
Set GL_PACK_ALIGNMENT to 1 before your glReadPixels() call if you're going to use a three-component format like GL_BGR with GL_UNSIGNED_BYTE.
I'm attempting to render a triangle using VBOs in OpenGL via C++.
First, I identify my variables:
CBuint _vao;
CBuint _vbo;
CBuint _ebo;
struct Vertex
{
CBfloat position[3];
};
Then, I set the positions for each vertex to form a geometrical triangle:
Vertex v[3];
v[0].position[0] = 0.5f;
v[0].position[1] = 0.5f;
v[0].position[2] = 0.0f;
v[1].position[0] = 0.5f;
v[1].position[1] = -0.5f;
v[1].position[2] = 0.0f;
v[2].position[0] = -0.5f;
v[2].position[1] = -0.5f;
v[2].position[2] = 0.0f;
Simple enough, right?
Then, I declare my indices for the EBO/IBO:
unsigned short i[] =
{
0, 1, 2
};
Now that I have all the attribute data needed for buffering, I bind the VAO as well as the VBOs:
// Generate vertex elements
glGenVertexArrays(1, &_vao);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ebo);
// VAO
glBindVertexArray(_vao);
// VBO
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 9, &v, GL_STATIC_DRAW);
// EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * 3, &i, GL_STATIC_DRAW);
// Location 0 - Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glBindVertexArray(0);
Next, I render them:
glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
I then use the vertex shader:
#version 330 core
// Vertex attributes
layout(location = 0) in vec3 position;
// Node parses
out vec3 Fragpos;
// Uniforms
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
// Vertex loop
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
Fragpos = vec3(model * vec4(position, 1.0f));
}
To simply calculate the model position as well as the camera view. The fragment shader is again, quite simplistic:
#version 330 core
// Node parses
out vec4 color;
in vec3 Fragpos;
// Camera data
uniform vec3 view_loc;
// Global uniforms
uniform struct GLOBAL
{
float ambient_coefficient;
vec3 ambient_colour;
} _global;
// Main loop
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
The uniforms work perfectly fine as I've been using this shader code for previous projects. So what could the problem be? The triangle simply does not render. I can't think of anything that's causing this, any ideas?
Edit: Just to narrow things down, I also use these variables to handle the model matrix that are being parsed to and from the vertex shader:
CBuint _u_model;
mat4 _model;
vec3 _position;
vec4 _rotation;
vec3 _scale;
Then inside the constructor, I initialize the variables like so:
_model = mat4::identity();
_position = vec3(0.0f, 0.0f, 0.0f);
_rotation = vec4(0.0f, 1.0f, 0.0f, 0.0f);
_scale = vec3(1.0f, 1.0f, 1.0f);
_u_model = glGetUniformLocation(shader->_program, "model");
And finally, I update the model matrix using this formula:
_model = translate(_position) *
rotate(_rotation.data[0], _rotation.data[1], _rotation.data[2], _rotation.data[3]) *
scale(_scale);
Edit 2: This is the camera class I use for the MVP:
class Camera : public object
{
private:
CBbool _director;
CBfloat _fov;
CBfloat _near;
CBfloat _far;
CBfloat _speed;
Math::vec3 _front;
Math::vec3 _up;
Math::mat4 _projection;
Math::mat4 _view;
CBuint _u_projection;
CBuint _u_view;
public:
Camera(Shader* shader, Math::vec3 pos, float fov, float n, float f, bool dir) : _speed(5.0f)
{
_model = Math::mat4::identity();
_projection = Math::mat4::identity();
_view = Math::mat4::identity();
_position = pos;
_fov = fov;
_near = n;
_far = f;
_director = dir;
_front = vec3(0.0f, 0.0f, -1.0f);
_up = vec3(0.0f, 1.0f, 0.0f);
_u_projection = glGetUniformLocation(shader->_program, "projection");
_u_view = glGetUniformLocation(shader->_program, "view");
_u_model = glGetUniformLocation(shader->_program, "view_loc");
}
~Camera() {}
inline CBbool isDirector() { return _director; }
inline void forward(double delta) { _position.data[2] -= _speed * (float)delta; }
inline void back(double delta) { _position.data[2] += _speed * (float)delta; }
inline void left(double delta) { _position.data[0] -= _speed * (float)delta; }
inline void right(double delta) { _position.data[0] += _speed * (float)delta; }
inline void up(double delta) { _position.data[1] += _speed * (float)delta; }
inline void down(double delta) { _position.data[1] -= _speed * (float)delta; }
virtual void update(double delta)
{
_view = Math::lookat(_position, _position + _front, _up);
_projection = Math::perspective(_fov, 900.0f / 600.0f, _near, _far);
}
virtual void render()
{
glUniformMatrix4fv(_u_view, 1, GL_FALSE, _view);
glUniformMatrix4fv(_u_projection, 1, GL_FALSE, _projection);
glUniform3f(_u_model, _position.data[0], _position.data[1], _position.data[2]);
}
};
As Amadeus mentioned, I simply had to use gl_Position = vec4(position, 1.0f); for it to render. No idea why, but now's the time to find out! Thanks for your time.
I want to draw simple square. First I use glDrawArrays but now I want to change it to glDrawElements. I read bunch of tutorials but for some reason it doesn't render anything.
Renderer class:
class Renderer_t {
private:
...
glm::mat4 projectionMatrix; // Store the projection matrix
glm::mat4 viewMatrix; // Store the view matrix
glm::mat4 modelMatrix; // Store the model matrix
unsigned int vaoID[1]; // Our Vertex Array Object
unsigned int vboID[3]; // Our Vertex Buffer Object
...
};
Initialize of scene:
Renderer_t::Renderer_t(SDL_Window* window): scene(nullptr), width(800), height(600) {
LOG(info) << "Renderer_t constructor";
gl = SDL_GL_CreateContext(window);
glbinding::Binding::initialize();
//Initialize scene
glClearColor(0.4f, 0.6f, 0.9f, 0.0f);
shader = new Shader("../assets/shader.vert", "../assets/shader.frag");
float ratio = width/height;
projectionMatrix = glm::perspective(60.0f, ratio, 0.1f, 100.f); // Create our perspective projection matrix
int vertnum = 4 * 3; //6x
//Create square
float* vertices = new float[vertnum]; // Vertices for our square
float* colors = new float[vertnum]; // Colors for our vertices
unsigned int* indices = new unsigned int[6];
indices[0] = 0; indices[0] = 1; indices[0] = 2;
indices[0] = 2; indices[0] = 3; indices[0] = 0;
vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Bottom left corner
colors[0] = 1.0; colors[1] = 1.0; colors[2] = 1.0; // Bottom left corner
vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Top left corner
colors[3] = 1.0; colors[4] = 0.0; colors[5] = 0.0; // Top left corner
vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Top Right corner
colors[6] = 0.0; colors[7] = 1.0; colors[8] = 0.0; // Top Right corner
vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Bottom right corner
colors[9] = 0.0; colors[10] = 0.0; colors[11] = 1.0; // Bottom right corner
/*
vertices[12] = -0.5; vertices[13] = -0.5; vertices[14] = 0.0; // Bottom left corner
colors[12] = 1.0; colors[13] = 1.0; colors[14] = 1.0; // Bottom left corner
vertices[15] = 0.5; vertices[16] = 0.5; vertices[17] = 0.0; // Top Right corner
colors[15] = 0.0; colors[16] = 1.0; colors[17] = 0.0; // Top Right corner
*/
glGenVertexArrays(1, &vaoID[0]); // Create our Vertex Array Object
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object so we can use it
glGenBuffers(3, &vboID[0]); // Generate our Vertex Buffer Objects
glBindBuffer(GL_ARRAY_BUFFER, vboID[0]); // Bind our Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, vertnum * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(0); // Enable our Vertex Array Object
glBindBuffer(GL_ARRAY_BUFFER, vboID[1]); // Bind our second Vertex Buffer Object
glBufferData(GL_ARRAY_BUFFER, vertnum * sizeof(GLfloat), colors, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); // Set up our vertex attributes pointer
glEnableVertexAttribArray(1); // Enable the second vertex attribute array
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indices, GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)2, 3, GL_INT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
glBindVertexArray(0); // Disable our Vertex Buffer Object
delete[] vertices; // Delete our vertices from memory
delete[] colors; // Delete our vertices from memory
delete[] indices;
LOG(info) << "Renderer_t constructor done";
}
Rendering:
void Renderer_t::render() {
LOG(info) << "Renderer_t.render()";
glViewport(0, 0, width, height); // Set the viewport size to fill the window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Clear required buffers
viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.f)); // Create our view matrix
modelMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f)); // Create our model matrix
shader->bind(); // Bind our shader
int projectionMatrixLocation = glGetUniformLocation(shader->id(), "projectionMatrix"); // Get the location of our projection matrix in the shader
int viewMatrixLocation = glGetUniformLocation(shader->id(), "viewMatrix"); // Get the location of our view matrix in the shader
int modelMatrixLocation = glGetUniformLocation(shader->id(), "modelMatrix"); // Get the location of our model matrix in the shader
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]); // Send our projection matrix to the shader
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]); // Send our view matrix to the shader
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &modelMatrix[0][0]); // Send our model matrix to the shader
glBindVertexArray(vaoID[0]); // Bind our Vertex Array Object
// glDrawArrays(GL_TRIANGLES, 0, 6); // Draw our square
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[2]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0); // Unbind our Vertex Array Object
shader->unbind(); // Unbind our shader
LOG(info) << "Renderer_t.render() done";
}
I also use shaders:
shader.vert
version 130
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
in vec3 in_Position;
in vec3 in_Color;
out vec3 pass_Color;
void main(void)
{
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0);
pass_Color = in_Color;
}
shader.fraq
#version 130
in vec3 pass_Color;
out vec4 out_Color;
void main(void)
{
out_Color = vec4(pass_Color, 1.0);
}
Just so you know, a triangle list with elements: 0,1,2 0,2,3 is the same thing as glDrawArrays(GL_TRIANGLE_FAN, 0, 4). You could just use a triangle fan here and not have to use indices at all.
Your actual problem is that you keep writing each element in your element array to [0].
Right now your code reads:
indices[0] = 0; indices[0] = 1; indices[0] = 2;
indices[0] = 2; indices[0] = 3; indices[0] = 0;
However, to function correctly it needs to read:
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 2; indices[4] = 3; indices[5] = 0; // This is equivalent to 0, 2, 3
Everything in BDL's answer are also important things you should note.
You try to bind the ELEMENT_ARRAY_BUFFER to a varying of your shader
glVertexAttribPointer((GLuint)2, 3, GL_INT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(2);
Index buffers do not have to be bound to a shader, since they are not directly used as input to them. Beside this, your shader has only two in-variables (most probably numbered 0 and 1), so using 2 will never work.
Another hint:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID[2]);
in your render() is not necessary, since the binding is already stored in the vao during the initialization. But this should not effect the output.