Unable to plot multiple elements using FBO - c++

I'm trying to edit this tutorial so to render multiple circles within the FBO. I simplified the tutorial so to save memory that I'm sending through the FBO: I'm only sending the x and y coordinates, alongside with a float that will determine the colour of the node. This information is read from this text file. Even though I'm trying to plot ~660 nodes, my code does not display all of them. My application should scale up and possibly plot any possible size of nodes read in input.
I provide a graphical illustration of what I would expect to obtain via a plot made in R:
library(ggplot2)
t <-read.table("pastebin_file.txt", header = T)
ggplot(t, aes(x, y)) + geom_point(aes(colour = factor(col)))
In OpenGL, I'm getting an inferior number of vertices (I know, the colors are inverted, but that is not my concern):
I guess that the problem might be with the VBO, or I forgot to set all the parameters properly. At this stage, I don't know what the problem is. How could I fix this problem so to replicate R's output on OpenGL? I provide a MWE with all the shaders in the last part of the question:
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "utils/shaders.h"
size_t n = 0;
void render(void)
{
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// I want to render exactly all the vertices that were loaded on the VBO.
glDrawArrays(GL_POINTS, 0, n);
glutSwapBuffers(); // Update the rendering
}
program programma;
void set_shader()
{
// Loading the shaders using a custom class. Nevertheless, the code is exactly the same as the one in https://open.gl/content/code/c7_final.txt, that is loading and compiling the three shaders, and then linking them together in one single program
programma.add_shader(shader_t::vertex, "shaders/vertexShader3.txt");
programma.add_shader(shader_t::fragment, "shaders/fragmentShader3.txt");
programma.add_shader(shader_t::geometry, "shaders/geometryShader3.txt");
programma.compile();
}
GLuint vbo;
GLuint vao;
#include <regex>
#include <iostream>
size_t fbo(const std::string& filename) {
// Create VBO with point coordinates
glGenBuffers(1, &vbo);
std::fstream name{filename};
std::string line;
std::getline(name, line); // Skipping the first line, that just contains the header
std::vector<GLfloat> points; // Storage for all the coordinates
n = 0;
std::regex rgx ("\\s+");
while (std::getline(name, line)) {
std::sregex_token_iterator iter(line.begin(), line.end(), rgx, -1);
std::sregex_token_iterator end;
points.emplace_back(std::stof(*iter++)/20); // x, rescaled, so it can fit into screen
points.emplace_back(std::stof(*iter++)/20); // y, rescaled, so it can fit into screen
int i = std::stoi(*iter++);
points.emplace_back(i); // determining the color
n++;
}
std::cout << n << std::endl; // number of vertices
std::cout << sizeof(float) * 3 * n << std::endl; // expected size in B = 7992
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, points.size(), points.data(), GL_STATIC_DRAW);
// Create VAO
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Specify the layout of the node data: just two floats for the (x,y) pairs
GLint posAttrib = glGetAttribLocation(programma.id, "pos");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
// Determining the color of the circle with one single float parameter
GLint sidesAttrib = glGetAttribLocation(programma.id, "sides");
glEnableVertexAttribArray(sidesAttrib);
glVertexAttribPointer(sidesAttrib, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*) (2 * sizeof(GLfloat)));
return points.size()/3;
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(200, 200);
glutCreateWindow("Stuff");
glutIdleFunc(render);
glewInit();
if (!glewIsSupported("GL_VERSION_2_0")) {
fprintf(stderr, "GL 2.0 unsupported\n");
return 1;
}
set_shader();
fbo("pastebin_file.txt");
glutMainLoop();
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
return 0;
}
#endif
shaders/vertexShader3.txt
#version 150 core
in vec2 pos; // input vertex position
in float sides; // determines the output color
out vec3 vColor;
void main() {
gl_Position = vec4(pos, 0.0, 1.0);
if (sides == 1.0) { // determining the color
vColor = vec3(1.0,0.0,0.0);
} else {
vColor = vec3(0.0,1.0,0.0);
}
}
shaders/geometryShader3.txt
#version 150 core
layout(points) in;
layout(line_strip, max_vertices = 640) out;
in vec3 vColor[];
out vec3 fColor;
const float PI = 3.1415926;
const float lati = 10;
void main() {
fColor = vColor[0];
// Safe, GLfloats can represent small integers exactly
for (int i = 0; i <= lati; i++) {
// Angle between each side in radians
float ang = PI * 2.0 / lati * i;
// Offset from center of point
vec4 offset = vec4(cos(ang) * 0.3/20, -sin(ang) * 0.4/20, 0.0, 0.0);
gl_Position = gl_in[0].gl_Position + offset;
EmitVertex();
}
EndPrimitive();
}
shaders/fragmentShader3.txt
#version 150 core
in vec3 fColor;
out vec4 outColor;
void main() {
outColor = vec4(fColor, 1.0); // Simply returning the color
}

The 2nd argument of glBufferData has to be the size of the buffer in bytes:
glBufferData(GL_ARRAY_BUFFER, points.size(), points.data(), GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER,
points.size() * sizeof(points[0]), points.data(), GL_STATIC_DRAW);

Related

Trying to draw sphere in OpenGL, Only part of the sphere is showing, seems clipped?

I created a minimal setup with a fragment shader setting the color to write, so not even a parameter.
The vertex shader passes in a matrix and transforms the points. We can see the sphere, but only part of it.
I hesitate to post the whole code, trying as hard as possible for a minimum working solution but it's about 300 lines including the shader loading code. I will post just the core pieces, and if people want more I will post it all.
Here is the code for the demo including a stripped down Sphere class and glmain.
Not shown is main() which does try..catch and calls glmain
#include <GL/glew.h>
#include "common/common.hh"
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <numbers>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <string>
using namespace std;
using namespace glm;
using namespace std::numbers;
class Sphere {
private:
uint32_t progid; // handle to the shader code
uint32_t vao; // array object container for vbo and indices
uint32_t vbo; // handle to the point data on the graphics card
uint32_t lbo; // handle to buffer of indices for lines for wireframe sphere
uint32_t latRes, lonRes;
uint32_t resolution;
public:
/**
* #brief Construct a sphere
*
* #param r radius of the sphere
* #param latRes resolution of the grid in latitude
* #param lonRes resolution of the grid in latitude
*/
Sphere(double r, uint32_t latRes, uint32_t lonRes);
~Sphere() { cleanup(); }
void render(mat4& trans);
void cleanup();
};
Sphere::Sphere(double r, uint32_t latRes, uint32_t lonRes) : latRes(latRes), lonRes(lonRes),
resolution((2*latRes-2)*lonRes + 2) {
progid = loadShaders( "05_3d.vert", "02simple.frag" );
double dlon = 2.0*numbers::pi / lonRes, dlat = numbers::pi / latRes;
double z;
double lat = -numbers::pi/2 + dlat; // latitude in radians
double rcircle;
float vert[resolution*3]; // x,y,z
uint32_t c = 0;
for (uint32_t j = 0; j < 2*latRes-2; j++, lat += dlat) {
//what is the radius of hte circle at that height?
rcircle = r* cos(lat); // size of the circle at this latitude
z = r * sin(lat); // height of each circle
double t = 0;
for (uint32_t i = 0; i < lonRes; i++, t += dlon) {
vert[c++] = rcircle * cos(t), vert[c++] = rcircle * sin(t);
vert[c++] = z;
}
cout << endl;
}
// south pole
vert[c++] = 0;
vert[c++] = 0;
vert[c++] = -r;
// north pole
vert[c++] = 0;
vert[c++] = 0;
vert[c++] = r;
cout << "resolution: " << resolution << endl;
cout << "predicted num vert components: " << resolution*3 << endl;
cout << "actual num vert components: " << c << endl;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, resolution, vert, GL_STATIC_DRAW);
glBindVertexArray(0);
}
void Sphere::render(mat4& trans) {
glUseProgram(progid); // Use the shader
uint32_t matrixID = glGetUniformLocation(progid, "trans");
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &trans[0][0]);
glBindVertexArray(vao);
glVertexAttribPointer(
0, // first parameter to shader, numbered 0
3, // 3 floating point numbers (x,y,z)
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // this is the entire set of data, move on
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(0); // pass x,y to shader
glEnable(GL_PROGRAM_POINT_SIZE);
//points don't work, why not? And how to set the size of the points?
glPointSize(5);
glDrawArrays(GL_POINT, 0, resolution);
// line strips work, but incomplete (see screen shot)
glDrawArrays(GL_LINE_STRIP, 0, resolution);
glDisableVertexAttribArray(0);
}
void Sphere::cleanup() {
glDeleteBuffers(1, &vbo); // remove vbo memory from graphics card
glDeleteVertexArrays(1, &vao); // remove vao from graphics card
glDeleteProgram(progid);
}
using namespace std;
void glmain() {
win = createWindow(800, 800, "Sphere demo");
glClearColor(0.0f, 0.0f, 0.4f, 0.0f); // Dark blue background
Sphere sphere(1.0, 30, 15);
mat4 trans= lookAt(vec3(0,0,0), vec3(10,5,10), vec3(0,1,0));
do {
glClear( GL_COLOR_BUFFER_BIT ); // Clear the screen
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
//glDepthFunc(GL_LESS);
sphere.render(trans);
glfwSwapBuffers(win); // double buffer
glfwPollEvents();
} while( glfwGetKey(win, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(win) == 0 );
}
Points did not display at all so the call is commented out. We drew a line strip instead. That works somewhat. Why is it truncated? Why doesn't it at least finish the layer of the sphere?
The shaders are shown below:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 v;
uniform mat4 trans;
void main(){
gl_PointSize = 5;
gl_Position = trans * vec4(v,1.0);
gl_Position.w = 1.0;
}
fragment shader:
#version 330 core
out vec4 color;
void main()
{
color = vec4(1,1,1,1);
}
The size argument of glBufferData specifies the size in bytes of the buffer object's new data store:
glBufferData(GL_ARRAY_BUFFER, resolution, vert, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, resolution * 3 * sizeof(float), vert, GL_STATIC_DRAW);

How to accurately time performance of intensive vertex shader? [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 10 months ago.
Improve this question
I have a compute-heavy OpenGL vertex shader which I'm trying to profile the performance of.
Following the conventional wisdom
¹ ² ³, I'm computing the frames per second in my glfw app by waiting over 1 second and dividing the number of frames by the time elapsed. My FPS counter claims ≈30 FPS but it's clearly more like 1 FPS. Notice the grass blowing in the breeze behind the screen.
My minimal example below and in this gist, animates a densely tessellated grid and performs dummy computation in the vertex shader until the issue appears.
Is there a way to measure FPS or the performance of this shader in a way that it accurately reflects its real behavior?
// Controls how much (dummy) computation happens in the vertex shader.
const int m = 20000;
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl3.h>
#define __gl_h_
#include <Eigen/Core>
#include <Eigen/Geometry>
#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#include <chrono>
#include <string>
#include <chrono>
#include <thread>
#include <iostream>
std::string vertex_shader = R"(
#version 330 core
uniform mat4 proj;
uniform mat4 model;
uniform float t;
uniform int m;
in vec3 position;
out vec4 position_eye;
void main()
{
vec4 deformed =
vec4(
position.x,
position.y,
sin(t*3.14159)*
cos(position.x*3.14159)*
cos(position.y*3.14159)
,
1.);
for(int j = 0;j<m;j++)
{
deformed.z = deformed.z + 0.000001*float(j)/float(m);
}
position_eye = proj * model * deformed;
gl_Position = position_eye;
}
)";
std::string fragment_shader = R"(
#version 330 core
in vec4 position_eye;
out vec3 color;
void main()
{
vec3 xTangent = dFdx(position_eye.xyz);
vec3 yTangent = dFdy(position_eye.xyz);
color = normalize( cross( yTangent, xTangent ) )*0.5 + 0.5;
}
)";
// width, height, shader id, vertex array object
int w=800,h=600;
double highdpi=1;
GLuint prog_id=0;
GLuint VAO;
// Mesh data: RowMajor is important to directly use in OpenGL
Eigen::Matrix< float,Eigen::Dynamic,3,Eigen::RowMajor> V;
Eigen::Matrix<GLuint,Eigen::Dynamic,3,Eigen::RowMajor> F;
int main(int argc, char * argv[])
{
using namespace std;
const auto get_seconds = []()
{
return
std::chrono::duration<double>(
std::chrono::system_clock::now().time_since_epoch()).count();
};
if(!glfwInit())
{
cerr<<"Could not initialize glfw"<<endl;
return EXIT_FAILURE;
}
const auto & error = [] (int error, const char* description)
{
cerr<<description<<endl;
};
glfwSetErrorCallback(error);
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(w, h, "WebGL", NULL, NULL);
if(!window)
{
glfwTerminate();
cerr<<"Could not create glfw window"<<endl;
return EXIT_FAILURE;
}
glfwMakeContextCurrent(window);
int major, minor, rev;
major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
rev = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
printf("OpenGL version recieved: %d.%d.%d\n", major, minor, rev);
printf("Supported OpenGL is %s\n", (const char*)glGetString(GL_VERSION));
printf("Supported GLSL is %s\n", (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_NORMAL);
const auto & reshape = [] (GLFWwindow* window, int w, int h)
{
::w=w,::h=h;
};
glfwSetWindowSizeCallback(window,reshape);
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
int width_window, height_window;
glfwGetWindowSize(window, &width_window, &height_window);
highdpi = width/width_window;
reshape(window,width_window,height_window);
}
// Compile each shader
const auto & compile_shader = [](const GLint type,const char * str) -> GLuint
{
GLuint id = glCreateShader(type);
glShaderSource(id,1,&str,NULL);
glCompileShader(id);
return id;
};
GLuint vid = compile_shader(GL_VERTEX_SHADER,vertex_shader.c_str());
GLuint fid = compile_shader(GL_FRAGMENT_SHADER,fragment_shader.c_str());
// attach shaders and link
prog_id = glCreateProgram();
glAttachShader(prog_id,vid);
glAttachShader(prog_id,fid);
glLinkProgram(prog_id);
GLint status;
glGetProgramiv(prog_id, GL_LINK_STATUS, &status);
glDeleteShader(vid);
glDeleteShader(fid);
// construct a regular grid mesh
const int nx = 300;
const int ny = 305;
V.resize(nx*ny,3);
for(int i = 0;i<nx;i++)
{
for(int j = 0;j<ny;j++)
{
const float x = float(i)/(nx-1);
const float y = float(j)/(ny-1);
V.row(j*nx+i) << x,y, 0;
}
}
F.resize((nx-1)*(ny-1)*2,3);
for(int y = 0;y<ny-1;y++)
{
for(int x = 0;x<nx-1;x++)
{
// index of southwest corner
const int sw = (x +nx*(y+0));
const int se = (x+1+nx*(y+0));
const int ne = (x+1+nx*(y+1));
const int nw = (x +nx*(y+1));
// Index of first triangle in this square
const int gf = 2*(x+(nx-1)*y);
F(gf+0,0) = sw;
F(gf+0,1) = se;
F(gf+0,2) = nw;
F(gf+1,0) = se;
F(gf+1,1) = ne;
F(gf+1,2) = nw;
}
}
V.rowwise() -= V.colwise().mean();
V /= (V.colwise().maxCoeff()-V.colwise().minCoeff()).maxCoeff();
V /= 1.2;
// Generate and attach buffers to vertex array
glGenVertexArrays(1, &VAO);
GLuint VBO, EBO;
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*V.size(), V.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*F.size(), F.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
double t0 = get_seconds();
const auto draw = [&]()
{
double tic = get_seconds();
// clear screen and set viewport
glClearColor(0.1,0.1,0.1,0.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,w*highdpi,h*highdpi);
// Projection and modelview matrices
Eigen::Matrix4f proj;
float near = 0.01;
float far = 100;
float top = tan(35./360.*M_PI)*near;
float right = top * (double)::w/(double)::h;
float left = -right;
float bottom = -top;
proj.setConstant(4,4,0.);
proj(0,0) = (2.0 * near) / (right - left);
proj(1,1) = (2.0 * near) / (top - bottom);
proj(0,2) = (right + left) / (right - left);
proj(1,2) = (top + bottom) / (top - bottom);
proj(2,2) = -(far + near) / (far - near);
proj(3,2) = -1.0;
proj(2,3) = -(2.0 * far * near) / (far - near);
Eigen::Affine3f model = Eigen::Affine3f::Identity();
model.translate(Eigen::Vector3f(0,0,-1.5));
// select program and attach uniforms
glUseProgram(prog_id);
GLint proj_loc = glGetUniformLocation(prog_id,"proj");
glUniformMatrix4fv(proj_loc,1,GL_FALSE,proj.data());
GLint model_loc = glGetUniformLocation(prog_id,"model");
glUniformMatrix4fv(model_loc,1,GL_FALSE,model.matrix().data());
GLint t_loc = glGetUniformLocation(prog_id,"t");
glUniform1f(t_loc,tic-t0);
GLint m_loc = glGetUniformLocation(prog_id,"m");
glUniform1i(m_loc,m);
// Draw mesh as wireframe
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, F.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
};
// Main display routine
while (!glfwWindowShouldClose(window))
{
double tic = get_seconds();
static size_t count = 0;
static double t_prev = get_seconds();
if(tic-t_prev > 1)
{
const double fps = double(count)/(tic-t_prev);
std::stringstream ss;
ss << fps <<" FPS";
glfwSetWindowTitle(window, ss.str().c_str());
count = 0;
t_prev = tic;
}
count++;
draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return EXIT_SUCCESS;
}
GPU execution is highly parallelised and asynchronous, so timing it in the way you would CPU code is not going to work. Your GPU vendor will have profiling tools you can download which can provide a better insight than this kind of simple time measuring.

How to setup shaders in openGL

I'm working on developing code in OpenGL, and I was completing one of the tutorials for a lesson. However, the code that I completed did not color the triangle. Based off of the tutorial, my triangle should come out as green, but it keeps turning out white. I think there is an error in the code for my shaders, but I can't seem to find the error.
I tried altering the code a few times, and I even moved on to the next tutorial, which shades each vertex. However, my triangle is still coming out as white.
#include <iostream> //Includes C++ i/o stream
#include <GL/glew.h> //Includes glew header
#include <GL/freeglut.h> //Includes freeglut header
using namespace std; //Uses the standard namespace
#define WINDOW_TITLE "Modern OpenGL" //Macro for window title
//Vertex and Fragment Shader Source Macro
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif
//Variables for window width and height
int WindowWidth = 800, WindowHeight = 600;
/* User-defined Function prototypes to:
* initialize the program, set the window size,
* redraw graphics on the window when resized,
* and render graphics on the screen
* */
void UInitialize(int, char*[]);
void UInitWindow(int, char*[]);
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateVBO(void); //This step is missing from Tutorial 3-3
void UCreateShaders(void);
/*Vertex Shader Program Source Code*/
const GLchar * VertexShader = GLSL(440,
in layout(location=0) vec4 vertex_Position; //Receive vertex coordinates from attribute 0. i.e. 2
void main(){
gl_Position = vertex_Position; //Sends vertex positions to gl_position vec 4
}
);
/*Fragment Shader Program Source Code*/
const GLchar * FragmentShader = GLSL(440,
void main(){
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); //Sets the pixels / fragments of the triangle to green
}
);
//main function. Entry point to the OpenGL Program
int main(int argc, char* argv[])
{
UInitialize(argc, argv); //Initialize the OpenGL program
glutMainLoop(); // Starts the Open GL loop in the background
exit(EXIT_SUCCESS); //Terminates the program successfully
}
//Implements the UInitialize function
void UInitialize(int argc, char* argv[])
{
//glew status variable
GLenum GlewInitResult;
UInitWindow(argc, argv); //Creates the window
//Checks glew status
GlewInitResult = glewInit();
if(GLEW_OK != GlewInitResult)
{
fprintf(stderr, "Error: %s\n", glewGetErrorString(GlewInitResult));
exit(EXIT_FAILURE);
}
//Displays GPU OpenGL version
fprintf(stdout, "INFO: OpenGL Version: %s\n", glGetString(GL_VERSION));
UCreateVBO(); //Calls the function to create the Vertex Buffer Object
UCreateShaders(); //Calls the function to create the Shader Program
//Sets the background color of the window to black. Optional
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
//Implements the UInitWindow function
void UInitWindow(int argc, char* argv[])
{
//Initializes freeglut
glutInit(&argc, argv);
//Sets the window size
glutInitWindowSize(WindowWidth, WindowHeight);
//Memory buffer setup for display
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
//Creates a window with the macro placeholder title
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow); //Called when the window is resized
glutDisplayFunc(URenderGraphics); //Renders graphics on the screen
}
//Implements the UResizeWindow function
void UResizeWindow(int Width, int Height)
{
glViewport(0,0, Width, Height);
}
//Implements the URenderGraphics function
void URenderGraphics(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clears the screen
/*Creates the triangle*/
GLuint totalVertices = 3; //Specifies the number of vertices for the triangle i.e. 3
glDrawArrays(GL_TRIANGLES, 0, totalVertices); //Draws the triangle
glutSwapBuffers(); //Flips the back buffer with the front buffer every frame. Similar to GL Flush
}
//Implements the CreateVBO function
void UCreateVBO(void)
{
//Specifies coordinates for triangle vertices on x and y
GLfloat verts[] =
{
0.0f, 1.0f, //top-center of the screen
-1.0f, -1.0f, //bottom-left of the screen
1.0f, -1.0f //bottom-right of the screen
};
//Stores the size of the verts array / number of the coordinates needed for the triangle i.e. 6
float numVertices = sizeof(verts);
GLuint myBufferID; //Variable for vertex buffer object id
glGenBuffers(1, &myBufferID); //Creates 1 buffer
glBindBuffer(GL_ARRAY_BUFFER, myBufferID); //Activates the buffer
glBufferData(GL_ARRAY_BUFFER, numVertices, verts, GL_STATIC_DRAW); //Sends vertex or coordinate data to GPU
/*Creates the Vertex Attribute Pointer*/
GLuint floatsPerVertex = 2; //Number of coordinates per vertex
glEnableVertexAttribArray(0); //Specifies the initial position of the coordinates in the buffer
/*Instructs the GPU on how to handle the vertex bugger object data.
* Parameters: attribPointerPosition | coordinates per vertex | data type | deactivate normalization | 0 strides | 0 offset
*/
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, 0, 0);
}
//Implements the UCreateShaders function
void UCreateShaders(void)
{
//Create a shader program object
GLuint ProgramId = glCreateProgram();
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); //Create a Vertex Shader Object
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); //Create a Fragment Shader Object
glShaderSource(vertexShaderId, 1, &VertexShader, NULL); //Retrieves the vertex shader source code
glShaderSource(fragmentShaderId, 1, &FragmentShader, NULL); //Retrieves the fragment shader source code
glCompileShader(vertexShaderId); //Compile the vertex shader
glCompileShader(fragmentShaderId); //Compile the fragment shader
//Attaches the vertex and fragment shaders to the shader program
glAttachShader(ProgramId, vertexShaderId);
glAttachShader(ProgramId, fragmentShaderId);
glLinkProgram(ProgramId); //Links the shader program
glUseProgram(ProgramId); //Uses the shader program
}
When completed correctly, the code should result in a solid green triangle.
The variable gl_FragColor is unavailable in GLSL 4.4 core profile since it was deprecated. Because you don't specify a compatibility profile, the default core is assumed. Either use
#version 440 compatibility
for your shaders, or, even better, use the GLSL 4.4 onwards approach:
#version 440 core
layout(location = 0) out vec4 OUT;
void main(){
OUT = vec4(0.0, 1.0, 0.0, 1.0);
}

OpenGL 4.1: Triangle Flashes and Disappears Immediately after Being Drawn

I want to render a green triangle.
OpenGL Version: 4.1
Shading Language Version: 4.10
Problem
The code below, when executed, shows a green triangle that flashes for an instant and disappears.
I saw this post: A red rectangle drawn on 2D texture disappears right after being drawn, who has a similar issue of disappearing triangles, but his was because he called Swap Buffer multiple times, but I only have one instance of glutSwapBuffers() in the displayFunc().
C++ Code:
#include <iostream>
#include "OpenGLMatrix.h"
#include "BasicPipelineProgram.h"
using namespace std;
int windowWidth = 1280;
int windowHeight = 720;
char windowTitle[512] = "Simple Green Triangle";
// global variables
OpenGLMatrix *matrix;
GLuint buffer;
BasicPipelineProgram *pipelineProgram;
GLint program;
GLuint vao;
// objects to render
int numVertices = 3;
float positions[9] =
{ -1, -1, -1,
1, -1, -1,
-1, 1, -1 }; // 3 vertices of triangle to render
float colors[12] =
{ 0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1 }; // all vertices green with alpha = 1
void bindProgram() {
// upload model view matrix to shader
float m[16];
matrix->SetMatrixMode(OpenGLMatrix::ModelView);
matrix->GetMatrix(m);
pipelineProgram->SetModelViewMatrix(m);
// upload projection matrix to shader
float p[16];
matrix->SetMatrixMode(OpenGLMatrix::Projection);
matrix->GetMatrix(p);
pipelineProgram->SetProjectionMatrix(p);
}
void displayFunc() {
// computing modelview matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
matrix->LoadIdentity();
// camera at (0,0,1), looking in -z direction, up vector y
matrix->LookAt(0, 0, 1, 0, 0, -1, 0, 1, 0);
bindProgram();
// use the VAO
pipelineProgram->Bind();
glBindVertexArray(vao);
GLint first = 0;
GLsizei count = numVertices;
glDrawArrays(GL_TRIANGLES, first, count);
glBindVertexArray(0);
glutSwapBuffers();
}
void idleFunc() {
// make the screen update
glutPostRedisplay();
}
void reshapeFunc(int w, int h) {
GLfloat aspect = (GLfloat) w / (GLfloat) h;
glViewport(0, 0, w, h);
// setup perspective matrix
matrix->SetMatrixMode(OpenGLMatrix::Projection);
matrix->LoadIdentity();
matrix->Perspective(60.0, aspect, 0.01, 1000.0);
matrix->SetMatrixMode(OpenGLMatrix::ModelView);
}
void initPipelineProgram() {
// initialize shader pipeline program
pipelineProgram = new BasicPipelineProgram();
pipelineProgram->Init();
pipelineProgram->Bind();
program = pipelineProgram->GetProgramHandle();
// VAO (vertex array objects) to contain the VBOs
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// get location index of the "position" shader variable
GLuint loc = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(loc);
const void *offset = (const void*) 0;
GLsizei stride = 0;
GLboolean normalized = GL_FALSE;
glVertexAttribPointer(loc, 3, GL_FLOAT, normalized, stride, offset);
// get location index of the "color" shader variable
loc = glGetAttribLocation(program, "color");
glEnableVertexAttribArray(loc);
offset = (const void*) sizeOfPositions;
stride = 0;
normalized = GL_FALSE;
glVertexAttribPointer(loc, 4, GL_FLOAT, normalized, stride, offset);
glBindVertexArray(0);
}
void initVBO() {
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeOfPositions + sizeOfColors, NULL, GL_STATIC_DRAW);
// upload position data
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeOfPositions, positions);
// upload color data
glBufferSubData(GL_ARRAY_BUFFER, sizeOfPositions, sizeOfColors, colors);
}
void initScene(int argc, char *argv[])
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
matrix = new OpenGLMatrix();
initVBO();
initPipelineProgram();
}
int main(int argc, char *argv[])
{
cout << "Initializing GLUT..." << endl;
glutInit(&argc,argv);
cout << "Initializing OpenGL..." << endl;
#ifdef __APPLE__
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
#else
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);
#endif
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow(windowTitle);
// glut callback functions
glutDisplayFunc(displayFunc);
glutIdleFunc(idleFunc);
glutReshapeFunc(reshapeFunc);
initScene(argc, argv);
glutMainLoop();
}
In the code, OpenGLMatrix *matrix and BasicPipelineProgram *pipelineProgram are classes defined elsewhere, and whose code, unless requested, I don't think we need to worry about. "position" and "color" in initPipelineProgram() refer to variables in the GLSL shader specification:
#version 150
in vec3 position;
in vec4 color;
out vec4 col;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main()
{
// compute the transformed and projected vertex position (into gl_Position)
// compute the vertex color (into col)
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0f);
col = color;
}
I don't understand why the triangle flashes and then immediately disappears??
I'm a beginner in OpenGL and any help is greatly appreciated. Thank you!

OpenGL 3.1 lighting messed up, using phong shading

After many painful hours of attempting to figure out why my lighting is messed up I am still at a loss.
The OpenGL normals are correct (backface culling does not cause any of my triangles to disappear)
I calculate my normals in order to interpolate for lighting, all the triangles on the same faces also have the same normals.
If any one has any thoughts that would be appreciated.
I am definitely new to OpenGL, so that is a bit obvious in my code.
here are my shaders:
vertex shader
#version 330 core
layout(location = 0) in vec3 Position;
layout(location = 1) in vec3 vertexColor;
in vec3 vNormal;
out vec3 fragmentColor; // Output data ; will be interpolated for each fragment.
uniform mat4 MVP;
uniform mat4 transformMatrix;
uniform vec4 LightPosition;
// output values that will be interpretated per-fragment
out vec3 fN;
out vec3 fE;
out vec3 fL;
void main()
{
fN = vNormal;
fE = Position.xyz;
fL = LightPosition.xyz;
if( LightPosition.w != 0.0 ) {
fL = LightPosition.xyz - Position.xyz;
}
// Output position of the vertex, in clip space : MVP * position
vec4 v = vec4(Position,1); // Transform in homoneneous 4D vector
gl_Position = MVP * v;
//gl_Position = MVP * v;
// The color of each vertex will be interpolated
// to produce the color of each fragment
//fragmentColor = vertexColor; // take out at some point
}
and the fragmentShader, using phong shading
#version 330
//out vec3 color;
// per-fragment interpolated values from the vertex shader
in vec3 fN;
in vec3 fL;
in vec3 fE;
out vec4 fColor;
uniform vec4 AmbientProduct, DiffuseProduct, SpecularProduct;
uniform mat4 ModelView;
uniform vec4 LightPosition;
uniform float Shininess;
in vec3 fragmentColor; // Interpolated values from the vertex shaders
void main()
{
// Normalize the input lighting vectors
vec3 N = normalize(fN);
vec3 E = normalize(fE);
vec3 L = normalize(fL);
vec3 H = normalize( L + E );
vec4 ambient = AmbientProduct;
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd*DiffuseProduct;
float Ks = pow(max(dot(N, H), 0.0), Shininess);
vec4 specular = Ks*SpecularProduct;
// discard the specular highlight if the light's behind the vertex
if( dot(L, N) < 0.0 ) {
specular = vec4(0.0, 0.0, 0.0, 1.0);
}
fColor = ambient + diffuse + specular;
fColor.a = 1.0;
//color = vec3(1,0,0);
// Output color = color specified in the vertex shader,
// interpolated between all 3 surrounding vertices
//color = fragmentColor;
}
void setMatrices()
{
GLfloat FoV = 45; // the zoom of the camera
glm::vec3 cameraPosition(4,3,3), // the position of your camera, in world space // change to see what happends
cameraTarget(0,0,0), // where you want to look at, in world space
upVector(0,-1,0);
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 Projection = glm::perspective(FoV, 3.0f / 3.0f, 0.001f, 100.0f); // ratio needs to change here when the screen size/ratio changes
// Camera matrix
glm::mat4 View = glm::lookAt(
cameraPosition, // Camera is at (4,3,3), in World Space
cameraTarget, // and looks at the origin
upVector // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f); // Changes for each model !
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model * transformMatrix; //matrix multiplication is the other way around
// Get a handle for our "MVP" uniform.
// Only at initialisation time.
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
// For each model you render, since the MVP will be different (at least the M part)
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
RotationID = glGetUniformLocation(programID,"transformMatrix");
//lighting
cubeNormal = glGetAttribLocation( programID, "vNormal" );
}
void setBuffers()
{
// Get a vertex array object
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glUseProgram(programID);
// cube buffer objects
glGenBuffers(1, &CubeVertexbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, CubeVertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(CubeBufferData), CubeBufferData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
// cube normal objects
glGenBuffers(1, &CubeNormalbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, CubeNormalbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(CubeNormalBufferData), CubeNormalBufferData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
//octahedron buffer objects
glGenBuffers(1, &OctaVertexbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, OctaVertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(octahedronBufData), octahedronBufData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
//tetrahedron buffer objects
glGenBuffers(1, &TetraVertexbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, TetraVertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(tetrahedronBufData), tetrahedronBufData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
//dodecahedron buffer objects
glGenBuffers(1, &DodecaVertexbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, DodecaVertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(dodecahedronBufData), dodecahedronBufData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
//icosahedron buffer objects
glGenBuffers(1, &icosaVertexbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, icosaVertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(icosahedronBufData), icosahedronBufData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
//sphere buffer objects
glGenBuffers(1, &sphereVertexbuffer); // Generate 1 buffer, put the resulting identifier in vertexbuffer
glBindBuffer(GL_ARRAY_BUFFER, sphereVertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(sphereBufData), sphereBufData, GL_STATIC_DRAW); // Give our vertices to OpenGL.
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
// lighting stuff
// Initialize shader lighting parameters
point4 light_position= { 0.0, 20.0, -10.0, 0.0 };
color4 light_ambient ={ 0.2, 0.2, 0.2, 1.0 };
color4 light_diffuse ={ 1.0, 1.0, 1.0, 1.0 };
color4 light_specular ={ 1.0, 1.0, 1.0, 1.0 };
color4 material_ambient ={ 1.0, 0.0, 1.0, 1.0 };
color4 material_diffuse ={ 1.0, 0.8, 0.0, 1.0 };
color4 material_specular ={ 1.0, 0.8, 0.0, 1.0 };
float material_shininess = 20.0;
color4 ambient_product;
color4 diffuse_product;
color4 specular_product;
int i;
for (i = 0; i < 3; i++) {
ambient_product[i] = light_ambient[i] * material_ambient[i];
diffuse_product[i] = light_diffuse[i] * material_diffuse[i];
specular_product[i] = light_specular[i] * material_specular[i];
}
//printColor("diffuse", diffuse_product);
//printColor("specular", specular_product);
glUniform4fv( glGetUniformLocation(programID, "AmbientProduct"),
1, ambient_product );
glUniform4fv( glGetUniformLocation(programID, "DiffuseProduct"),
1, diffuse_product );
glUniform4fv( glGetUniformLocation(programID, "SpecularProduct"),
1, specular_product );
glUniform4fv( glGetUniformLocation(programID, "LightPosition"),
1, light_position );
glUniform1f( glGetUniformLocation(programID, "Shininess"),
material_shininess );
}
and some more....
void display()
{
setMatrices(); // initilize Matrices
// Use our shader
//glUseProgram(programID);
glClearColor(0.0f, 0.0f, 0.3f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 2nd attribute buffer : colors
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1, // attribute. No particular reason for 1, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(0); // 1rst attribute buffer : vertices
// enum platosShapes{tet, cube, octah, dodec, icos};
switch(shapeInUse)
{
case tet:
{
glBindBuffer(GL_ARRAY_BUFFER, TetraVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. 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
);
glDrawArrays(GL_TRIANGLES, 0, 4*3); // Starting from vertex 0; 3 vertices total -> 1 triangle // need to know amount of vertices here // and change to triangle strips accordingly
}
break;
case cube:
{
//GLuint cubeNormal = glGetAttribLocation( programID, "vNormal" );
glEnableVertexAttribArray( cubeNormal );
glVertexAttribPointer( cubeNormal, 3, GL_FLOAT, GL_FALSE, 0,
(const GLvoid *) (sizeof(CubeNormalBufferData)) );
//glDisableVertexAttribArray( cubeNormal );
glBindBuffer(GL_ARRAY_BUFFER, CubeVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. 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
);
glDrawArrays(GL_TRIANGLES, 0, 12*3); // Starting from vertex 0; 3 vertices total -> 1 triangle // need to know amount of vertices here // and change to triangle strips accordingly
}
break;
case octah:
{
glBindBuffer(GL_ARRAY_BUFFER, OctaVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. 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
);
glDrawArrays(GL_TRIANGLES, 0, 8*3); // Starting from vertex 0; 3 vertices total -> 1 triangle // need to know amount of vertices here // and change to triangle strips accordingly
}
break;
case dodec:
{
glBindBuffer(GL_ARRAY_BUFFER, DodecaVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. 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
);
glDrawArrays(GL_TRIANGLE_FAN, 0, 5 * 6); // Starting from vertex 0; 3 vertices total -> 1 triangle // need to know amount of vertices here // and change to triangle strips accordingly
glDrawArrays(GL_TRIANGLE_FAN, (5 * 6) + 1, 30);
//glutSolidDodecahedron();
//glDrawArrays(GL_TRIANGLE_STRIP,0,5*12);
}
break;
case icos:
{
glBindBuffer(GL_ARRAY_BUFFER, icosaVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. 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
);
glDrawArrays(GL_TRIANGLES, 0, 3*20); // Starting from vertex 0; 3 vertices total -> 1 triangle // need to know amount of vertices here // and change to triangle strips accordingly
}
break;
case sphere:
{
glBindBuffer(GL_ARRAY_BUFFER, sphereVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. 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
);
//glDrawElements(GL_TRIANGLES, cnt2, GL_UNSIGNED_INT, 0)
glDrawArrays(GL_TRIANGLE_FAN, 0, 100);
}
}
glDisableVertexAttribArray(0);
glFlush();
}
and some more........
void calculateNormals(GLfloat bufData[], GLfloat normBufData[], int size) // probalby works
{
int count = 0;
GLfloat temp[9];
for(int i = 0; i < size; i++)
{
temp[count] = bufData[i];
count++;
if((i+1) % 9 == 0)
{
count = 0;
//for(int i = 0; i < 9; i++)
//{
// cout << temp[i] << "!,";
// if((i + 1) % 3 == 0)
// cout << "\n";
//}
calculateCross(temp, normBufData);
}
}
printNormals(normBufData, size);
}
void calculateCross(GLfloat bufData[], GLfloat normBufData[]) // probably works
{
static int counter = 0; // need to reset in bettween new buffers
glm::vec3 C1;
glm::vec3 C2;
glm::vec3 normal;
//cout << bufData[0] << "," << bufData[1] << "," << bufData[2] << " buf 1 \n";
//cout << bufData[3] << "," << bufData[4] << "," << bufData[5] << " buf 2 \n";
//cout << bufData[6] << "," << bufData[7] << "," << bufData[8] << " buf 3 \n\n";
//C1.x = bufData[3] - bufData[0];
//C1.y = bufData[4] - bufData[1];
//C1.z = bufData[5] - bufData[2];
//C2.x = bufData[6] - bufData[0];
//C2.y = bufData[7] - bufData[1];
//C2.z = bufData[8] - bufData[2];
C1.x = bufData[0] - bufData[3];
C1.y = bufData[1] - bufData[4];
C1.z = bufData[2] - bufData[5];
C2.x = bufData[0] - bufData[6];
C2.y = bufData[1] - bufData[7];
C2.z = bufData[2] - bufData[8];
//C2.x = bufData[6] - bufData[0];
//C2.y = bufData[7] - bufData[1];
//C2.z = bufData[8] - bufData[2];
//cout << C1.x << " 1x \n";
//cout << C1.y << " 1y \n";
//cout << C1.z << " 1z \n";
//cout << C2.x << " 2x \n";
//cout << C2.y << " 2y \n";
//cout << C2.z << " 2z \n";
normal = glm::cross(C1, C2);
//cout << "\nNORMAL : " << normal.x << "," << normal.y << "," << normal.z << " counter = " << counter << "\n";
for(int j = 0; j < 3; j++)
{
for(int i = 0; i < 3; i++)
{
normBufData[counter] = normal.x;
normBufData[counter + 1] = normal.y;
normBufData[counter + 2] = normal.z;
}
counter+=3;
}
}
and main.....
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(700, 700); // Window Size
glutCreateWindow("Michael - Lab 3");
glutDisplayFunc(display);
glutTimerFunc(10, timeFucn, 10);
glutIdleFunc(Idle);
glutKeyboardFunc(keyboard);
glewExperimental = GL_TRUE;
glewInit();
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST); // Enable depth test
glDepthFunc(GL_LESS); // Accept fragment if it closer to the camera than the former one
GenerateSphere(); // this function generates points for the sphere
programID = LoadShader( "VertexShader.glsl", "FragmentShader.glsl" ); // Create and compile our GLSL program from the shaders
setBuffers(); // initilize buffers
calculateNormals(CubeBufferData,CubeNormalBufferData,108); // calculate norms
//printNormals(CubeNormalBufferData);
glutMainLoop();
}
You forgot to bind the buffer object with normals before calling glVertexAttribPointer( cubeNormal, 3,....);. Therefore, the actual data for normals is taken from the color buffer, which causes weirdest Phong evaluation result.
BTW, nice coding style :)
Phong and Gouraud shadings are not applicable to objects with all planar surfaces, e.g. a cube.