OpenGL lines not colored - c++

I'm working in OpenGL, with VBOs, and I have a set of three lines (along the X, Y and Z axes - think Czech hedgehog). The lines are grey by default, but I want them bright red so I can see them better. Unfortunately, though I added color information as vertex data, the lines still appear grey. I'm probably missing something basic, but I can't see it. Here is how I create the VBO:
//Position data
sf::Vector3<float> Top = sf::Vector3<float>(0.0, 1.0, 0.0);
sf::Vector3<float> Front = sf::Vector3<float>(0.0, 0.0, -1.0);
sf::Vector3<float> Right = sf::Vector3<float>(1.0, 0.0, 0.0);
sf::Vector3<float> Back = sf::Vector3<float>(0.0, 0.0, 1.0);
sf::Vector3<float> Left = sf::Vector3<float>(-1.0, 0.0, 0.0);
sf::Vector3<float> Bottom = sf::Vector3<float>(0.0, -1.0, 0.0);
//Color data
//Just to be clear, I also tried with 255.0, although I'm rather certain OpenGL
//does its colors on a 0-1 scale.
sf::Vector3<float> Color = sf::Vector3<float>(1.0, 0.0, 0.0);
//Create vector
std::vector<float> LineArray;
//Top
LineArray.push_back(Top.x);
LineArray.push_back(Top.y);
LineArray.push_back(Top.z);
LineArray.push_back(Color.x);
LineArray.push_back(Color.y);
LineArray.push_back(Color.z);
//Bottom
LineArray.push_back(Bottom.x);
LineArray.push_back(Bottom.y);
LineArray.push_back(Bottom.z);
LineArray.push_back(Color.x);
LineArray.push_back(Color.y);
LineArray.push_back(Color.z);
//Front
LineArray.push_back(Front.x);
LineArray.push_back(Front.y);
LineArray.push_back(Front.z);
LineArray.push_back(Color.x);
LineArray.push_back(Color.y);
LineArray.push_back(Color.z);
//Back
LineArray.push_back(Back.x);
LineArray.push_back(Back.y);
LineArray.push_back(Back.z);
LineArray.push_back(Color.x);
LineArray.push_back(Color.y);
LineArray.push_back(Color.z);
//Right
LineArray.push_back(Right.x);
LineArray.push_back(Right.y);
LineArray.push_back(Right.z);
LineArray.push_back(Color.x);
LineArray.push_back(Color.y);
LineArray.push_back(Color.z);
//Left
LineArray.push_back(Left.x);
LineArray.push_back(Left.y);
LineArray.push_back(Left.z);
LineArray.push_back(Color.x);
LineArray.push_back(Color.y);
LineArray.push_back(Color.z);
//Create buffer
glGenBuffers(1, &m_Buffer);
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
int SizeInBytes = LineArray.size() * 6 * sizeof(float);
glBufferData(GL_ARRAY_BUFFER, SizeInBytes, NULL, GL_STATIC_DRAW);
//Upload buffer data
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * LineArray.size(), &LineArray[0]);
And this is how I display it every tick:
glPushMatrix();
//Translate
glTranslatef(m_Position.x, m_Position.y, m_Position.z);
//Rotate
glMultMatrixf(m_RotationMatrix);
//Bind buffers for vertex and color arrays
glBindBuffer(GL_ARRAY_BUFFER, m_Buffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), 0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 6 * sizeof(float), (void*)12);
//Draw
glDrawArrays(GL_LINES, 0, 36);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//Unbind the buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glPopMatrix();
I've never used GL_COLOR_ARRAY before, but I based the code off of successful use of GL_NORMAL_ARRAY. Can someone point out what's wrong?
EDIT: On the offchance that I'm setting up my basic OpenGL parameters wrong (lighting in particular), here are those:
m_AmbientLight = {0.5f, 0.5f, 0.5f, 1.0f};
m_DiffuseLight = {1.0f, 1.0f, 1.0f, 1.0f};
m_LightPos = {8.0f, -16.0f, 8.0f, 0.0f};
//Smooth Shading
glShadeModel(GL_SMOOTH);
// Set color and depth clear value
glClearDepth(1.f);
//Color here is in RGB, converted to a 0-1 scale.
glClearColor(0.3f, 0.3f, 0.3f, 1.f);
// Enable Z-buffer read and write
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
///
///LIGHTING
///
//Set up lighting.
//This activates the ambient light.
glLightfv(GL_LIGHT0, GL_AMBIENT, m_AmbientLight);
//This activates the diffuse light.
glLightfv(GL_LIGHT1, GL_DIFFUSE, m_DiffuseLight);
//This sets the position of the diffuse light.
glLightfv(GL_LIGHT1, GL_POSITION, m_LightPos);
//This enables the light.
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
//Enables all lighting...?
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
//glEnable(GL_NORMALIZE);
// Setup a perspective projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.f, 1.33f, 0.1f, 512.f);
EDIT 2: Having established that glColor3f() also doesn't have any effect, I wonder if my shaders are the problem:
Vert shader:
void main()
{
vec3 normal, lightDir;
vec4 diffuse;
float NdotL;
normal = normalize(gl_NormalMatrix * gl_Normal);
lightDir = normalize(vec3(gl_LightSource[0].position));
NdotL = max(dot(normal, lightDir), 0.0);
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
gl_FrontColor = NdotL * diffuse;
gl_Position = ftransform();
}
Frag shader:
void main()
{
gl_FragColor = gl_Color;
}

Not 100% positive, but I don't believe you should have GL_COLOR_MATERIAL enabled while you draw the lines. Try disabling that.
edit (copied from comment):
Your shader doesn't make sense to me. You should just be passing in a color, and then passing that color straight to the fragment shader. Why are you using a lighting shader to draw lines? You should create a different shader that doesn't use any of that materials stuff. Enabling/disabling lighting has no effect unless you're using fixed function pipeline. I think you're mixing up fixed function commands with your shaders and getting confused.

Sounds to me like you've got lighting enabled while drawing the lines, hence the color of the vertex data being overridden by the color of the illumination calculation. Add a glDisable(GL_LIGHTING) right before the glDrawArrays.

Related

How to create two shapes using OpenGL and shaders

I am trying to create a cylinder and plane to put underneath cylinder. Before I created a new vertex buffer object for the plane, the cylinder was rendering just fine. But for some reason, neither the cylinder or the plane are rendering when I run the program. I have created an EBO for the cylinder, but I am still getting a black window. I don't know if I need to create an EBO for each shape and a VAO for each shape or if there is something wrong with my draw function. Can someone point out what may be the problem? Here is my code:
#include <GL\glew.h>
#include <GLFW\glfw3.h>
#include <iostream>
// GLM library
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
int width, height;
const double PI = 3.14159;
const float toRadians = PI / 180.0f;
// Draw Primitive(s)
void draw() {
GLenum mode = GL_TRIANGLES;
GLsizei indices = 60;
glDrawElements(mode, indices, GL_UNSIGNED_BYTE, nullptr);
}
// Create and Compile Shaders
static GLuint CompileShader(const string& source, GLuint shaderType) {
// Create Shader Object
GLuint shaderID = glCreateShader(shaderType);
const char* src = source.c_str();
// Attach source code to Shader object
glShaderSource(shaderID, 1, &src, nullptr);
// Compile Shader
glCompileShader(shaderID);
// Return ID of Compiled shader
return shaderID;
}
// Create Program Object
static GLuint CreateShaderProgram(const string& vertexShader, const string& fragmentShader) {
// Compile vertex shader
GLuint vertexShaderComp = CompileShader(vertexShader, GL_VERTEX_SHADER);
// Compile fragment shader
GLuint fragmentShaderComp = CompileShader(fragmentShader, GL_FRAGMENT_SHADER);
// Create program object
GLuint shaderProgram = glCreateProgram();
// Attch vertex and fragment shaders to program object
glAttachShader(shaderProgram, vertexShaderComp);
glAttachShader(shaderProgram, fragmentShaderComp);
// Link shaders to create executable
glLinkProgram(shaderProgram);
// Delete compiled vertex and fragment shaders
glDeleteShader(vertexShaderComp);
glDeleteShader(fragmentShaderComp);
// Return Shader Program
return shaderProgram;
}
int main(void) {
width = 640; height = 480;
GLFWwindow* window;
// Initialize the library
if (!glfwInit())
return -1;
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(width, height, "Main Window", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
if (glewInit() != GLEW_OK)
cout << "Error!" << endl;
GLfloat cylinderVertices[] = {
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos(0 * toRadians), sin(0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos(60 * toRadians), sin(60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos(0 * toRadians), sin(0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos(60 * toRadians), sin(60 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos(120 * toRadians), sin(120 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos(180 * toRadians), sin(180 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos(240 * toRadians), sin(240 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos(300 * toRadians), sin(300 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
};
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
GLfloat planeVertices[] = {
// positon attributes (x,y,z)
0.0f, 0.0f, 0.0f, // vert 14
0.0f, 1.0f, 0.0f, // red
0.0f, 0.866f, 0.0f, // vert 15
0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, 0.0f, // vert 16
0.0f, 1.0f, 0.0f, // blue
1.0f, 0.866f, 0.0f, // vert 17
1.0f, 0.0f, 1.0f // purple
};
// Define element indices
GLubyte planeIndices[] = {
14,16,15,
16,17,15
};
// Enable Depth Buffer
glEnable(GL_DEPTH_TEST);
// Wireframe mode
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
GLuint cylinderVBO, planeVBO, EBO, VAO;
glGenBuffers(1, &cylinderVBO); // Create VBO and returns ID
glGenBuffers(1, &planeVBO);
glGenBuffers(1, &EBO); // Create EBO
glGenVertexArrays(1, &VAO); // Create VAO
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO); // Select VBO and activate buffer
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); // Select EBO
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); // Load vertex attributes
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); // Load indices attributes
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
// Vertex shader source code
string vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec4 vPosition;"
"layout(location = 1) in vec4 aColor;"
"out vec4 oColor;"
"uniform mat4 model;"
"uniform mat4 view;"
"uniform mat4 projection;"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vPosition;"
"oColor = aColor;"
"}\n";
// Fragment shader source code
string fragmentShaderSource =
"#version 330 core\n"
"in vec4 oColor;"
"out vec4 fragColor;"
"void main()\n"
"{\n"
"fragColor = oColor;"
"}\n";
// Creating Shader Program
GLuint shaderProgram = CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
while (!glfwWindowShouldClose(window)) {
// Resize window and graphics simultaneously
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Render here
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use Shader Program exe and select VAO before drawing
glUseProgram(shaderProgram); // Call Shader per-frame when updating attributes
// Declare identity matrix
glm::mat4 modelMatrix(1.0f);
glm::mat4 viewMatrix(1.0f);
glm::mat4 projectionMatrix(1.0f);
// Initialize transforms
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.5f, 0.5f, 0.5f));
// I increased the third argument from -3.0f to -6.0f to make the object smaller
// Moved the cup to the right by increasing the x coordinate
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.5f, 0.0f, -6.0f));
// I changed up somme of the arguments, so the object would tilt right instead of toward me
viewMatrix = glm::rotate(viewMatrix, 45.0f * toRadians, glm::vec3(-0.5f, 1.0f, 1.5f));
projectionMatrix = glm::perspective(45.0f * toRadians, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
// Select uniform shader and variable
GLuint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLuint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLuint projectionLoc = glGetUniformLocation(shaderProgram, "projection");
// Pass transform to Shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glBindVertexArray(VAO); // User-defined VAO must be called before draw
for (GLuint i = 0; i < 4; i++) {
glm::mat4 modelMatrix(1.0f);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(modelMatrix));
// Draw primitive(s)
draw();
}
// Unbind Shader exe and VOA after drawing per frame
glBindVertexArray(0); // In case different VAO will be used after
glUseProgram(0); // In case different shader will be used after
glBindVertexArray(VAO);
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Ok, so there is a bit of a structural problem with your plane & cylinder buffer layouts (ind indexing).
Vertex Buffers
First, let's start with the vertex data and associated buffers (we'll worry about indexing later).
You have 2 choices for how to send the data to the GPU.
Seperate vertex buffers for each shape. i.e. specify a cylinderVBO (with all cylinder vertices) and a planeVBO (with all plane vertices).
Combine both sets of vertices into a single vertex buffer.
If you are specifying the buffers separately, then setup EACH buffer in turn.
// do the cylinder buffer first!
glGenBuffers(1, &cylinderVBO);
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cylinderVertices), cylinderVertices, GL_STATIC_DRAW); // Load vertex attributes
// NOW do the plane buffer!
glGenBuffers(1, &planeVBO);
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW); // Load vertex attributes
If you want to combine the buffers into one big blob, then generate one big array:
GLfloat allVertices[] = {
// ------------- cylinderVertices[]
// Base of the cylinder
// Triangle One // Color
0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // Vertex 0 red
cos(0 * toRadians), sin(0 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 1 green
cos(60 * toRadians), sin(60 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 2 blue
// Part of Triangle Two
cos(120 * toRadians), sin(120 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 3 purple
// Part of Triangle Three
cos(180 * toRadians), sin(180 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 4 greem
// Part of Triangle Four
cos(240 * toRadians), sin(240 * toRadians), 0.0, 0.0, 0.0, 1.0, // Vertex 5 blue
// Part of Triangle Five
cos(300 * toRadians), sin(300 * toRadians), 0.0, 1.0, 0.0, 1.0, // Vertex 6 purple
// Part of Triangle Six
cos(360 * toRadians), sin(360 * toRadians), 0.0, 0.0, 1.0, 0.0, // Vertex 7 green
// Sides of the cylinder
// Part of Triangle Seven
cos(0 * toRadians), sin(0 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 8 red
// Part of Triangle Eight
cos(60 * toRadians), sin(60 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 9 green
// Part of Triangle Nine
cos(120 * toRadians), sin(120 * toRadians), 2.0, 0.0, 0.0, 1.0, // Vertex 10 blue
// Part of Triangle Ten
cos(180 * toRadians), sin(180 * toRadians), 2.0, 1.0, 0.0, 1.0, // Vertex 11 purple
// Part of Triangle Eleven
cos(240 * toRadians), sin(240 * toRadians), 2.0, 1.0, 0.0, 0.0, // Vertex 12 red
// Part of Triangle Twelve
cos(300 * toRadians), sin(300 * toRadians), 2.0, 0.0, 1.0, 0.0, // Vertex 13 green
// ------------- planeVertices[]
// positon attributes (x,y,z)
0.0f, 0.0f, 0.0f, // vert 14
0.0f, 1.0f, 0.0f, // red
0.0f, 0.866f, 0.0f, // vert 15
0.0f, 1.0f, 0.0f, // green
1.0f, 0.0f, 0.0f, // vert 16
0.0f, 1.0f, 0.0f, // blue
1.0f, 0.866f, 0.0f, // vert 17
1.0f, 0.0f, 1.0f // purple
};
// Now generate a vertex buffer with all vertex data in one buffer
GLuint allVerticesVBO;
glGenBuffers(1, & allVerticesVBO);
glBindBuffer(GL_ARRAY_BUFFER, allVerticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(allVertices), allVertices, GL_STATIC_DRAW); // Load vertex attributes
Index Buffers
Now, depending on how you set the vertex buffers up previously, you will have to do one (but not both!) of the following.
If you have separated your vertex buffers (one for cylinder, one for the plane), then you will need separate index buffers as well.
// we need two index buffers, one for the plane, one for the cylinder
GLuint cylinderIBO, planeIBO;
//--------------------
// cylinder
//--------------------
// Define element indices
GLubyte cylinderIndices[] = {
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13
};
glGenBuffers(1, &cylinderIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cylinderIndices), cylinderIndices, GL_STATIC_DRAW); // Load indices attributes
//--------------------
// plane
//--------------------
GLubyte planeIndices[] = {
0,2,1, //< NOTE: These must start at ZERO in this case!
2,3,1
};
glGenBuffers(1, &planeIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); // Load indices attributes
If however you wish to combine both shapes into a single buffer, then instead do this:
// we need one index buffer!
GLuint allIndicesIBO;
// Define element indices
GLubyte allIndices[] = {
//--------------------
// cylinder
//--------------------
// Bottom base
0,1,2,
0,2,3,
0,3,4,
0,4,5,
0,5,6,
0,6,7,
// Sides
1,2,8,
2,9,8,
2,3,9,
3,10,9,
3,4,10,
4,11,10,
5,11,4,
5,12,11,
5,6,12,
6,13,12,
6,1,13,
1,8,13,
//--------------------
// plane
//--------------------
14,16,15, //< NOTE: these now start at 14!
16,17,15
};
glGenBuffers(1, &allIndicesIBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, allIndicesIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(allIndices), allIndices, GL_STATIC_DRAW); // Load indices attributes
Vertex Buffer Objects
If you have set up separate buffers for each shape, then you have two choices in how you set up the VAOs.
1.1 Create two VAO's, one for each shape.
GLuint cylinderVAO, planeVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, & cylinderVAO);
glBindVertexArray(cylinderVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
// generate a bind new VAO for the plane
glGenVertexArrays(1, &planeVAO);
glBindVertexArray(planeVAO);
// specify which buffers the current VAO should use
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
To render the data like this, you'll need 2 draw calls, one for each shape.
glBindVertexArray(cylinderVAO);
glDrawElements(mode, 54, GL_UNSIGNED_BYTE, nullptr);
glBindVertexArray(planeVAO);
glDrawElements(mode, 6, GL_UNSIGNED_BYTE, nullptr);
1.2 Setup 1 VAO, but rebind the vertex & index buffers on the fly.
GLuint sharedVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, & sharedVAO);
glBindVertexArray(sharedVAO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
To render the data like this, you'll need 2 draw calls, one for each shape.
// specify the shared vertex format
glBindVertexArray(sharedVAO);
// specify data sources for cylinder, and render
glBindBuffer(GL_ARRAY_BUFFER, cylinderVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cylinderIBO);
glDrawElements(mode, 54, GL_UNSIGNED_BYTE, nullptr);
// specify data sources for plane, and render
glBindBuffer(GL_ARRAY_BUFFER, planeVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, planeIBO);
glDrawElements(mode, 6, GL_UNSIGNED_BYTE, nullptr);
If however you have specified all of the data in a single vertex buffer, and a single index buffer, then instead you can do:
GLuint sharedVAO;
// generate a bind new VAO for the cylinder
glGenVertexArrays(1, & sharedVAO);
glBindVertexArray(sharedVAO);
// specify data sources for the VAO
glBindBuffer(GL_ARRAY_BUFFER, allVerticesVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, allIndicesIBO);
// Specify attributes location and layout to GPU
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
// Color attribute location and layout
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
To render the data like this, you'll need 1 draw call.
// render both shapes in one draw call
glBindVertexArray(sharedVAO);
glDrawElements(mode, 60, GL_UNSIGNED_BYTE, nullptr);
And that's it.

OpenGL Lighting Not Shading

I'm attempting too add basic lighting to my scene. So far even without GLSL. It appears that my lighting doesn't work. And what I mean by that is everything has no shade at all (everything is lit up).
I know the picture isn't the best, but thats partly because of the texture is shaded in the image.
Here is my init code:
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear to black with full alpha
glEnable(GL_DEPTH_TEST); // Enable depth testing
glDepthFunc(GL_LEQUAL); // Specify depth testing function
glClearDepth(1.0); // Clear the full extent of the depth buffer (default)
glEnable(GL_CULL_FACE); // Enable face culling
glCullFace(GL_BACK); // Cull back faces of polygons
glFrontFace(GL_CCW);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glEnable ( GL_COLOR_MATERIAL );
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 0.2f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = {0, 100.0f, 0, 1.0f };
glLightModelfv(GL_AMBIENT, ambientLight);
glLightModelfv(GL_DIFFUSE, ambientLight);
glLightModelfv(GL_SPECULAR, specularLight);
glLightModelfv(GL_POSITION, position);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);
Draw code:
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
//For loop of the lights...
glLightfv(GL_LIGHT0+m_lights.at(i)->id, GL_POSITION, glm_to_array(m_lights.at(i)->position));
glEnable(GL_LIGHT0+m_lights.at(i)->id);
//Draw geometry here...
And yes, I am retrieving the normals from the mesh file and inserting the glNormal3f of every face. (GL_TRIANGLES) And even the plane the model sits on never gets affected even if I completely change the normal to random values.
Plane Example:
if(m_shader_programme){
glUseProgram(m_shader_programme);
}
if(m_texture_id){
glBindTexture(GL_TEXTURE_2D, m_texture_id);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}
glBegin(GL_TRIANGLES);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, m_sizey/10);
glVertex3f(m_sizex, m_height, m_sizey);
glTexCoord2f(m_sizex/10, m_sizey/10);
glVertex3f(m_sizex, m_height, -m_sizey);
glTexCoord2f(m_sizex/10, 0.0f);
glVertex3f(-m_sizex, m_height, -m_sizey);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(m_sizex/10, 0.0f);
glVertex3f(-m_sizex, m_height, -m_sizey);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-m_sizex, m_height, m_sizey);
glTexCoord2f(0.0f, m_sizey/10);
glVertex3f(m_sizex, m_height, m_sizey);
glEnd();
if(m_shader_programme){
glUseProgram(0);
}
if(m_texture_id){
glBindTexture(GL_TEXTURE_2D, 0);
}
GLSL Fragment Shader:
#version 120
uniform sampler2D tex;
void main()
{
vec4 color = texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color;
}
Vertex Shader:
#version 120
void main() {
vec3 normal, lightDir;
vec4 diffuse, ambient, globalAmbient;
float NdotL;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
normal = normalize(gl_NormalMatrix * gl_Normal);
lightDir = normalize(vec3(gl_LightSource[0].position));
NdotL = max(dot(normal, lightDir), 0.0);
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
/* Compute the ambient and globalAmbient terms */
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
globalAmbient = gl_LightModel.ambient * gl_FrontMaterial.ambient;
gl_FrontColor = NdotL * diffuse + globalAmbient + ambient;
gl_Position = ftransform();
}
System Specs
OS X (Yosemite) 10.10.13 (64bit)
Renderer: NVIDIA GeForce GTX 780M
OpenGL Engine OpenGL version supported 2.1 NVIDIA-10.2.7 310.41.25f01
Just encase anyone is wondering why I'm not using OpenGL 3.x is because GL 3.x doesn't appear to play nice on my machine.
Your fragment shader:
vec4 color = texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color;
Simply discards all the computations you did in the vertex shader and samples the texture color. You need to multiply the texture sample by the interpolated color value:
vec4 color = texture2D(tex, gl_TexCoord[0].st) * gl_Color;
^~~~~~
gl_FragColor = color;

Lighting not appearing in OpenGL

I've been trying to implement lighting for my OpenGL project, but so far I haven't been able to get any lighting effects.
I know that many things could go wrong, so I've tried hardcoding my normals (and using only a few triangles), but still I don't get anything.
In my scene, I have a few objects laying down along the "ground" at 0,0,0, hoping to see light coming down from above on them. They have a very basic texture on them which would easily show if they were lit up or not.
I initialize my scene like this:
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glTranslatef(0,0,0);
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 0.2f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = {0, 100.0f, 0, 1.0f };
glLightModelfv(GL_AMBIENT, ambientLight);
glLightModelfv(GL_DIFFUSE, ambientLight);
glLightModelfv(GL_SPECULAR, specularLight);
glLightModelfv(GL_POSITION, position);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
GLfloat shine [] = {50};
GLfloat diffuse[] = {1.0f, 0.f, 0.f, 1.0f};
GLfloat spec[] = {1.0f, 0.f, 0.f, 1.0f};
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,spec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS,shine);
And when I go to render:
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tiles[x]->image.width(), tiles[x]->image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tiles[x]->image.bits());
glNormal3d(0,1,0); //Will eventually calculate
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 3, 3);
"Tiles" is just a class of mine that holds an image and corresponding vectors for my objects. The "vertices" that are called is just a list of vectors (so each object has 6 vectors = 2 triangles.
My fragment shader:
uniform sampler2D texture;
in vec4 gl_Color;
in vec2 varyingTextureCoordinate;
out vec4 fragColor;
void main(void)
{
fragColor = texture2D(texture, varyingTextureCoordinate);
}
And my vertex shader:
uniform mat4 mvpMatrix;
in vec4 vertex;
in vec2 textureCoordinate;
out vec2 varyingTextureCoordinate;
void main(void)
{
varyingTextureCoordinate = textureCoordinate;
gl_Position = mvpMatrix * vertex;
}
Is my lack of lighting due to a conflict with the texture? No matter how I change that normal, I don't get any lighting.
I think you're trying to combine pre-programmable shader opengl and shader open gl here. I recommend learning how to implement lighting by utilizing as much shader code as possible
BennyBox has a great youtube series on OpenGL covering shaders and engine design
Here is his git repo and the java version.

Sending two textures to GLSL shader

When sending two textures to my GLSL shader only one actually arrives. What is strange is the first texture I bind is used for both textures slots in my shader. This leads me to believe the way I am passing my textures in OpenGL is wrong. However, I am unable to track down the problem.
Here is the code where I configure the textures for use in my shader.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo2);
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Get uniforms
GLuint pass_3O = glGetUniformLocation(blend_shader, "org");
GLuint pass_3B = glGetUniformLocation(blend_shader, "blur");
// Activate shaders
glUseProgram(blend_shader);
// Bind first texture
glActiveTexture(GL_TEXTURE0 );
glBindTexture(GL_TEXTURE_2D, init_texture);
// Bind the second texture
glActiveTexture(GL_TEXTURE1 );
glBindTexture(GL_TEXTURE_2D, third_texture);
// Assign index to 2d images
glUniform1i(pass_3O, 0);
glUniform1f(pass_3B, 1);
The code above is passing in two textures. The first is a 2D image of the first rendering pass of the 3D scene. The third is that same texture with x2 levels of blur added. This final stage is to blend them together for a poor mans bloom.
Here is the code where I am drawing both textures to the quad.
// Draw to quad
glBegin(GL_QUADS);
glMultiTexCoord2f(GL_TEXTURE0, 0.0f, 0.0f);
glMultiTexCoord2f(GL_TEXTURE1, 0.0f, 0.0f);
glVertex3f(-w_width/2.0, -w_height/2.0, 0.5f);
glMultiTexCoord2f(GL_TEXTURE0, 0.0f, 1.0f);
glMultiTexCoord2f(GL_TEXTURE1, 0.0f, 1.0f);
glVertex3f(-w_width/2.0, w_height/2.0, 0.5f);
glMultiTexCoord2f(GL_TEXTURE0, 1.0f, 1.0f);
glMultiTexCoord2f(GL_TEXTURE1, 1.0f, 1.0f);
glVertex3f(w_width/2.0, w_height/2.0, 0.5f);
glMultiTexCoord2f(GL_TEXTURE0, 1.0f, 0.0f);
glMultiTexCoord2f(GL_TEXTURE1, 1.0f, 0.0f);
glVertex3f(w_width/2.0, -w_height/2.0, 0.5f);
glEnd();
glFlush();
glPopAttrib();
// Unbind textures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
// Disable blend shader
glUseProgram(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
And here is the shader I am using to render the final image.
Vert
#version 120
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1] = gl_MultiTexCoord1;
gl_Position = ftransform();
}
Frag
#version 120
uniform sampler2D org;
uniform sampler2D blur;
void main()
{
vec4 orig_clr = texture2D( org, gl_TexCoord[0].st);
vec4 blur_clr = texture2D( blur, gl_TexCoord[1].st );
//gl_FragColor = orig_clr;
gl_FragColor = blur_clr;
}
If I switch between the last two lines in the fragment shader I get the same exact results. The only way to change which texture gets render is to change the order in which I bind them.
For example, the following would finally pass me the blurred image. Once again, only getting one of the two images.
glActiveTexture(GL_TEXTURE0 );
glBindTexture(GL_TEXTURE_2D, third_texture);
glActiveTexture(GL_TEXTURE1 );
glBindTexture(GL_TEXTURE_2D, init_texture);
Any thoughts on what I am overlooking?
Look at this code:
glUniform1i(pass_3O, 0);
glUniform1f(pass_3B, 1);
you have some small typo here, it should be glUniform1*i* instead of Uniform1*f* in the second call. The type must match that of the shader variable, so this call should just result in some error, leaving the uniform initialized at 0, which completely explains your results.

Can I use fixed glEnable(GL_LIGHTING) alongside fragment/vertex shaders?

I have browsed many online articles and adding lighting seems very straight forward but I'm not able to get a result. I'm using OpenGL 3.0 and I use a vertex and fragment shaders for my animating model. Btw, I'm new to OpenGL.
Disregarding the lighting I have everything working fine with the 3D char running around the environment.
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
*snip*
glEnable(GL_LIGHTING);
glEnable (GL_LIGHT0);
float ambientLight0[] = { 0.2f, 0.2f, 0.2f, 1.0f };
float diffuseLight0[] = { 0.8f, 0.8f, 0.8f, 1.0f };
float specularLight0[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float position0[] = { -2.5f, 1.0f, -1.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight0);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight0);
glLightfv(GL_LIGHT0, GL_POSITION, position0);
//glEnable(GL_COLOR_MATERIAL);
//float mcolor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
//glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mcolor);
m_Beast.onRender();
Here's how m_Beast.onRender() looks:
glPushMatrix();
Vector3 pos = getPosition();
glTranslatef(pos.x, pos.y, pos.z);
glBindTexture(GL_TEXTURE_2D, m_beastTextureID);
static float modelviewMatrix[16];
static float projectionMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
m_shaderProgram->bindShader();
m_shaderProgram->sendUniform4x4("modelview_matrix", modelviewMatrix);
m_shaderProgram->sendUniform4x4("projection_matrix", projectionMatrix);
m_shaderProgram->sendUniformTexture("texture0", 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
glVertexAttribPointer((GLint)1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, m_interpolatedFrame.vertices.size());
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glPopMatrix();
I just want a quick way to get some directional lighting on my model. I'm really not interesting in writing a lighting shader at this point.
As soon as you use vertex shaders, you must implement the lighting calculations yourself. In older OpenGL one could still use the fixed function vertex pipeline and program only the fragment stage. But with OpenGL-3 and onwards you're required to do it all.
However you shouldn't feel too bad about this. In the end you'll write less, because the huge plethora of function calls required to configure fixed function, can be replaced by much shorter and concise shader code.