How to use two shaders to render two objects in OpenGL - c++

I'm trying to use two different shader programs in order to render two different objects.
I have two vertex shaders with the same input parameters, and two fragment shaders, where one of them is set to color the fragments red.
When trying to get the attribute location of color in the loadPlainShader, I get a GL_INVALID_INDEX as a return.
Why can't OpenGL find the color attribute the second time, even though the vertex shaders are practically alike?
I have included my code, and it is also available here:
https://www.dropbox.com/sh/8o98ovh8pzubxiw/XGbO-IGQsW/stackoverflow
What I am trying
From main I'm trying to first load the two shader programs:
int main(int argc, char* argv[]) {
... GLUT and GLEW initilization ...
loadPlainShader();
loadShader();
loadGeometry();
glutMainLoop();
}
loadPlainShader()
void loadPlainShader(){
plainShader = InitShader("plain-shader.vert", "plain-shader.frag", "fragColor");
plainProjUniform = glGetUniformLocation(plainShader, "projection");
plainModelViewUniform = glGetUniformLocation(plainShader, "modelView");
plainColorAttribute = glGetAttribLocation(plainShader, "color");
plainPositionAttribute = glGetAttribLocation(plainShader, "position");
}
loadShader()
void loadShader(){
shaderProgram = InitShader("color-shader.vert", "color-shader.frag", "fragColor");
projectionUniform = glGetUniformLocation(shaderProgram, "projection");
modelViewUniform = glGetUniformLocation(shaderProgram, "modelView");
colorAttribute = glGetAttribLocation(shaderProgram, "color");
positionAttribute = glGetAttribLocation(shaderProgram, "position");
}
initShader()
GLuint InitShader(const char* vShaderFile, const char* fShaderFile, const char* outputAttributeName) {
struct Shader {
const char* filename;
GLenum type;
GLchar* source;
} shaders[2] = {
{ vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL }
};
GLuint program = glCreateProgram();
for ( int i = 0; i < 2; ++i ) {
Shader& s = shaders[i];
s.source = readShaderSource( s.filename );
if ( shaders[i].source == NULL ) {
std::cerr << "Failed to read " << s.filename << std::endl;
exit( EXIT_FAILURE );
}
GLuint shader = glCreateShader( s.type );
glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );
glCompileShader( shader );
GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
std::cerr << s.filename << " failed to compile:" << std::endl;
GLint logSize;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( shader, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
delete [] s.source;
glAttachShader( program, shader );
}
/* Link output */
glBindFragDataLocation(program, 0, outputAttributeName);
/* link and error check */
glLinkProgram(program);
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
std::cerr << "Shader program failed to link" << std::endl;
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
/* use program object */
glUseProgram(program);
return program;
}
loadGeometry()
void loadGeometry() {
vec3 color(1.0f, 1.0f, 0.0f);
vec3 colorR(1.0f, 0.0f, 0.0f);
Vertex rectangleData[rectangleSize] = {
{ vec2(-5.0, -5.0 ), color },
{ vec2(-5.0, 5.0 ), color },
{ vec2( 8.0, 5.0 ), color },
{ vec2( 8.0, -5.0 ), color }
};
Vertex triangleData[triangleSize] = {
{ vec2(2.0, 2.0 ), vec3(1.0f, 0.0f, 0.0f)},
{ vec2(5.0, 2.0 ), vec3(0.0f, 1.0f, 0.0f) },
{ vec2( 3.5, 5.0 ), vec3(0.0f, 0.0f, 1.0f) }
};
rectangleVertexArrayBuffer = loadBufferData(rectangleData, rectangleSize);
triangleVertexArrayBuffer = loadPlainBufferData(triangleData, triangleSize);
}
loadBufferData
GLuint loadBufferData(Vertex* vertices, int vertexCount) {
GLuint vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(positionAttribute);
glEnableVertexAttribArray(colorAttribute);
glVertexAttribPointer(positionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)0);
glVertexAttribPointer(colorAttribute , 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)sizeof(vec2));
return vertexArrayObject;
}
loadPlainBufferData
GLuint loadPlainBufferData(Vertex* vertices, int vertexCount) {
GLuint vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(plainPositionAttribute);
glEnableVertexAttribArray(plainColorAttribute);
glVertexAttribPointer(plainPositionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)0);
glVertexAttribPointer(plainColorAttribute , 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)sizeof(vec2));
return vertexArrayObject;
}
My display function
void display() {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
mat4 projection = Ortho2D(-15.0f, 15.0f, -10.0f, 15.0f);
glUniformMatrix4fv(projectionUniform, 1, GL_TRUE, projection);
mat4 modelViewRec;
mat4 modelViewTri;
modelViewRec = RotateZ(45) * modelViewRec;
// render rectangle
glUniformMatrix4fv(modelViewUniform, 1, GL_TRUE, modelViewRec);
glBindVertexArray(rectangleVertexArrayBuffer);
glDrawArrays(GL_TRIANGLE_FAN, 0, rectangleSize);
modelViewTri = Translate(6,7,0) * modelViewTri;
glUseProgram(plainShader);
// render triangle
glUniformMatrix4fv(plainModelViewUniform, 1, GL_TRUE, modelViewTri);
glBindVertexArray(triangleVertexArrayBuffer);
glDrawArrays(GL_TRIANGLES, 0, triangleSize);
glutSwapBuffers();
Angel::CheckError();
}
color-shader vertex shader and plain-shader vertex shader (identical)
#version 150
uniform mat4 projection;
uniform mat4 modelView;
in vec2 position;
in vec3 color;
out vec4 colorV;
void main (void)
{
colorV = vec4(color, 1.0);
gl_Position = projection * modelView * vec4(position, 0.0, 1.0);
}
Plainshader fragment shader
#version 150
in vec4 colorV;
out vec4 fragColor;
void main(void)
{
fragColor = vec4(1.0,0.0,0.0,1.0);
}
color-shader fragment shader
#version 150
in vec4 colorV;
out vec4 fragColor;
void main(void)
{
fragColor = colorV;
}

Related

OpenGL: glGenVertexArrays() gives EXC_BAD_ACCESS

When I use OpenGL and run my code to make a triangle the function glGenVertexArrays() gives me EXE_BAD_ACCESS
Error
Code:
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <cmath>
// Window specs
const int HEIGHT = 800;
const int WIDTH = 600;
// Shader source code
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.8f, 0.3f, 0.02f, 1.0f);\n"
"}\n\0";
int main(void)
{
if (!glfwInit())
{
std::cout<<"GLFW failed to Initialize!"<<std::endl;
return -1;
}
GLfloat vertices[] =
{
-0.5f, -0.5f * float(sqrt(3)) / 3, 0.0f,
0.5f, -0.5f * float(sqrt(3)) / 3, 0.0f,
0.0f, 0.5f * float(sqrt(3)) * 2 / 3, 0.0f
};
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Open GL", NULL, NULL);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwMakeContextCurrent(window);
if(!window)
{
std::cout<<"Something went Wrong when Creating a Window!\nShutting down ..."<<std::endl;
glfwTerminate();
return -1;
}
//
gladLoadGL();
glViewport(0, 0, WIDTH, HEIGHT);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLuint VAO;
GLuint VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while(!glfwWindowShouldClose(window))
{
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
I used glad to write the code. Does anybody have any idea how to fix this or what I did wrong.
To recreate it use Xcode 13.2.1 then link Glad using Opengl 4.1 and GLFW and make it look something like this
File Layout
Then paste the code into main and run.
A few things:
glfwWindowHint() only affects the next glfwCreateWindow() call so make sure to call them before you create a window. The default hint settings will generally give you a version 2.1 Compatibility context on macOS which won't be able to handle #version 330 core GLSL code.
GLFW_CONTEXT_VERSION_MAJOR was used twice; you need a GLFW_CONTEXT_VERSION_MINOR too.
macOS needs GLFW_OPENGL_FORWARD_COMPAT set to GLFW_TRUE for Core contexts.
Check for shader compilation/link errors.
Your GLAD might have been out of sync for the GL version you were targeting; see the generator link in the comments for the settings I used.
GLFW has a perfectly usable GLADloadproc in glfwGetProcAddress(); might as well switch from gladLoadGL() to gladLoadGLLoader().
Supplying a glfwSetErrorCallback() can get you some early/immediate error reporting from GLFW. It's how I discovered the missing GLFW_CONTEXT_VERSION_MINOR hint. No reason not to use it.
All together:
// g++ -Iinclude main.cpp src/glad.c `pkg-config --cflags --libs glfw3`
// Commandline:
// --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --no-loader --extensions=""
// Online:
// https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&api=gl%3D3.3
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cmath>
void CheckStatus( GLuint obj, bool isShader )
{
GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
std::cerr << (GLchar*)log << "\n";
std::exit( EXIT_FAILURE );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader, true );
glAttachShader( program, shader );
glDeleteShader( shader );
}
const char* const vert = 1 + R"GLSL(
#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
};
)GLSL";
const char* const frag = 1 + R"GLSL(
#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(0.8f, 0.3f, 0.02f, 1.0f);
}
)GLSL";
int main(void)
{
glfwSetErrorCallback( []( int, const char* desc )
{
std::cerr << desc << "\n";
std::exit( EXIT_FAILURE );
} );
if (!glfwInit())
{
std::cout<<"GLFW failed to Initialize!"<<std::endl;
return -1;
}
GLfloat vertices[] =
{
-0.5f, -0.5f * float(sqrt(3)) / 3, 0.0f,
0.5f, -0.5f * float(sqrt(3)) / 3, 0.0f,
0.0f, 0.5f * float(sqrt(3)) * 2 / 3, 0.0f
};
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "Open GL", NULL, NULL);
if(!window)
{
std::cout<<"Something went Wrong when Creating a Window!\nShutting down ..."<<std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress );
glViewport(0, 0, 800, 600);
GLuint prog = glCreateProgram();
AttachShader( prog, GL_VERTEX_SHADER, vert );
AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog, false );
glUseProgram( prog );
GLuint VAO;
GLuint VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while(!glfwWindowShouldClose(window))
{
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(prog);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(prog);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Note that with a 3.3 core profile on MacOS you may also need to call glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
by GM at comment Section and genpfault

Opengl only draw the first object create

i can't render multiples triangles using openGl, only 1 object is display.
I only view the first object, i have create.
For me the problem is with indices or glBufferData() or glVertexAttribPointer().
For the demo is only use vertices and indices.
Vertices are type Float and indices are type unsigned int.
void Objets::createShader() {
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar* adapter[1];
string temp = readShaderCode("VertexShaderCode.glsl");
adapter[0] = temp.c_str();
glShaderSource(vertexShaderID, 1, adapter, 0);
temp = readShaderCode("FragmentShaderCode.glsl");
adapter[0] = temp.c_str();
glShaderSource(fragmentShaderID, 1, adapter, 0);
glCompileShader(vertexShaderID);
glCompileShader(fragmentShaderID);
//checkShaders(vertexShaderID, fragmentShaderID); no error
programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
//checkProgram(programID); no error
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &vertexBufferID);
glGenBuffers(1, &colorBufferID);
glGenBuffers(1, &indexBufferID);
}
I use createShader() after i have create my window with sfml.
I create 2 shapes and load my 2 shapes :
graphiques3d.createShapeAndBufferit(Shapes::loadFromFileObj("objs/Cube.004.obj"));
graphiques3d.createShapeAndBufferit(Shapes::loadFromFileObj("objs/Cube.007.obj"));
Shapes Shapes::loadFromFileObj(string nameFile) {
Shapes shape;
string newString;
string buf;
string line;
ifstream myfile(nameFile);
if (myfile.is_open())
{
while (getline(myfile, line))
{
std::stringstream ss;
if (line.rfind(shape.verticesS, 0) == 0) {
newString = line.substr(2, line.length());
ss.str(newString);
while (ss >> buf) {
shape.vertices.push_back((GLfloat)stof(buf));
}
}
else if (line.rfind(shape.indicesS, 0) == 0) {
newString = line.substr(2, line.length());
ss.str(newString);
while (ss >> buf) {
GLuint valBuffer = (GLuint)atoi(buf.c_str());
shape.indices.push_back((GLuint)(valBuffer - 1));
}
}
}
myfile.close();
}
else cout << "Unable to open file";
return shape;
}
Then it use createShapeAndBufferit(Shapes shape);
void Objets::createShapeAndBufferit(Shapes shape) {
for (int a = 0; a < shape.getVertices().size(); a++)
vertices.push_back(shape.getVertices().at(a));
for (int b = 0; b < shape.getIndices().size(); b++)
indices.push_back(shape.getIndices().at(b));
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
}
When i print my shapes, i have this :
/1/1/-3/1/-1/-3/1/1/-1/1/-1/-1/-1/1/-3/-1/-1/-3/-1/1/-1/-1/-1/-1 sizeVertices: 24
:4:2:0:2:7:3:6:5:7:1:7:5:0:3:1:4:1:5:4:6:2:2:6:7:6:4:5:1:3:7:0:2:3:4:0:1 sizeIndices: 36
/3/1/1/3/-1/1/3/1/3/3/-1/3/1/1/1/1/-1/1/1/1/3/1/-1/3 sizeVertices: 24
:4:2:0:2:7:3:6:5:7:1:7:5:0:3:1:4:1:5:4:6:2:2:6:7:6:4:5:1:3:7:0:2:3:4:0:1 sizeIndices: 36
And then i draw :
void Objets::dessiner(float x, float y, float z) {
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width, height);
glUseProgram(programID);
mat4 projectionMatrix = glm::perspective(90.f, width / height, 0.1f, 100.f);
mat4 modelTransformMatrix = glm::translate(vec3(x, y, z));
mat4 modelFullTransformMatrix = projectionMatrix * modelTransformMatrix;
GLint modelTransformMatrixUniformLocation =
glGetUniformLocation(programID, "modelFullTransformMatrix");
glUniformMatrix4fv(modelTransformMatrixUniformLocation,
1, GL_FALSE, &modelFullTransformMatrix[0][0]);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (GLvoid*)0);
glBindVertexArray(0);
}
I don't know if you need the fragmentShader and the vertexShader, so i put it :
fragmentShader :
#version 330 core
out vec4 FragColor;
in vec3 color;
void main()
{
FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
vertexShader :
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform mat4 modelFullTransformMatrix;
out vec3 color;
void main()
{
vec4 v = vec4(aPos, 1.0);
gl_Position = modelFullTransformMatrix*v;
color = aColor;
}
So if I understand your explanation correctly, your problem is that you load two separate meshes ('shapes'), and for each one the indices start from zero, but you want to draw both of them in a single draw call?
Maybe glMultiDrawElementsBaseVertex is what you're after?
See also https://www.khronos.org/opengl/wiki/Vertex_Rendering for other alternatives in addition to the basic DrawArrays / DrawElements.

OpenGL, a very basic shader not working

I am learning OpenGL through TheCherno Project.
The code below is from there and I faithfully reproduce it for my learning purpose. I have also added both vertex and fragment shaders as well.
My issue here is in my square output I don't see the color at all and I am guessing it is using the default shader.
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
std::cout << "ERROR GLEW" << std::endl;
std::cout << glGetString(GL_VERSION) << std::endl;
float positions[] = {
-0.5f,-0.5f, //0
0.5f, -0.5f, //1
0.5f, 0.5f, //2
-0.5f, 0.5f //3
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * 2 * sizeof(float), positions, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
glEnableVertexAttribArray(0);
unsigned int ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
ShaderSourceProgram shader = ParseShader("res/shaders/Basic.shader");
//std::cout << "VERTEX" << std::endl;
//std::cout << shader.VertexShader << std::endl;
unsigned int shaderProgram = CreateShader(shader.VertexShader, shader.FragmentShader);
glUseProgram(shaderProgram);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
The shaders:
#shader vertex
#version 330 core
layout(location = 0)in vec4 position;
void main()
{
gl_Position = position;
};
#shader fragment
#version 330 core
out vec4 color;
void main()
{
color = vec4(0.0,1.0,0.0,1.0);
};
EDIT: Please click here for the entire project (github)
As #Ripi2 pointed out your glBufferData() calls, while not exactly wrong (they overrequest buffer space), aren't exactly correct either. Since you're using raw arrays you can use a straight sizeof(<arrayname>) for the size parameter:
glBufferData( GL_ARRAY_BUFFER, sizeof( positions ), positions, GL_STATIC_DRAW );
...
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW );
I suspect your (unknown) shader loader might be wonky since my personal one worked fine.
All together:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <iostream>
#include <cstdarg>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
int main( void )
{
GLFWwindow* window;
/* Initialize the library */
if( !glfwInit() )
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow( 640, 480, "Hello World", NULL, NULL );
if( !window )
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent( window );
if( glewInit() != GLEW_OK )
std::cout << "ERROR GLEW" << std::endl;
std::cout << glGetString( GL_VERSION ) << std::endl;
float positions[] = {
-0.5f,-0.5f, //0
0.5f, -0.5f, //1
0.5f, 0.5f, //2
-0.5f, 0.5f //3
};
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
unsigned int buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, 6 * 2 * sizeof( float ), positions, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 2, 0 );
glEnableVertexAttribArray( 0 );
unsigned int ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof( unsigned int ), indices, GL_STATIC_DRAW );
const char* vert = GLSL
(
330 core,
layout(location = 0)in vec4 position;
void main()
{
gl_Position = position;
};
);
const char* frag = GLSL
(
330 core,
out vec4 color;
void main()
{
color = vec4(0.0,1.0,0.0,1.0);
};
);
unsigned int shaderProgram = Program::Load
(
vert, GL_VERTEX_SHADER,
frag, GL_FRAGMENT_SHADER,
NULL
);
glUseProgram( shaderProgram );
/* Loop until the user closes the window */
while( !glfwWindowShouldClose( window ) )
{
/* Render here */
glClear( GL_COLOR_BUFFER_BIT );
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr );
/* Swap front and back buffers */
glfwSwapBuffers( window );
/* Poll for and process events */
glfwPollEvents();
}
glDeleteProgram( shaderProgram );
glfwTerminate();
return 0;
}
glUseProgram() needs to be called after shaders are compiled and linked. Here's a piece of a sample code:
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
cout << "Failed to initialize GLAD" << endl;
return -1;
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, 800, 600);
float TriangleVertices[] = {
-0.3f, -0.3f, 0.0f,
0.0f, 0.3f, 0.0f,
0.3f, -0.3f, 0.0f
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
//BindVertexArray for modifying it
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(TriangleVertices), TriangleVertices, GL_STATIC_DRAW);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
const char* vertexShaderSource = "\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
const char* fragmentShaderSource = "\n"
"out vec4 FragColor; \n"
"void main()\n"
"{\n"
"FragColor = vec4(1.0f, 0.7f, 0.5f, 1.0f); \n"
"} \n";
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//// draw triangle using the data from the VAO
//glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}

Vertex shader not passing value to fragment shader

I've encountered following problem:
I got this vertex shader:
#version 410 core
in vec3 vertex_position;
out vec3 color;
void main()
{
color = vec3(0.0, 0.0, 0.0);
gl_Position = vec4(vertex_position, 1.0);
}
And following fragment shader:
#version 410 core
in vec3 color;
out vec4 frag_color;
void main()
{
frag_color = vec4(color, 1.0);
}
I want to pass the color vector from the vertex shader to the fragent shader, however, nothing is showing up on the screen. When I set the frag_color within the fragment shader like: frag_color = vec4(0.0, 0.0, 0.0, 1.0); it works. Thus, something with passing the value between the 2 stages must be wrong.
This is my shader code:
void Shader::CreateShaders(std::string filePathVert, std::string filePathFrag)
{
// setup shaders
std::string vertex_shader_source = LoadSourceFile(filePathVert);
std::string fragment_shader_source = LoadSourceFile(filePathFrag);
const GLchar* vs_source = vertex_shader_source.c_str();
const GLchar* fs_source = fragment_shader_source.c_str();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
CheckShaderError(vs, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
CheckShaderError(fs, GL_COMPILE_STATUS, false, "Error: Shader compilation failed: ");
this->shader_program = glCreateProgram();
glAttachShader(this->shader_program, fs);
glAttachShader(this->shader_program, vs);
glLinkProgram(this->shader_program);
CheckValidationError(this->shader_program);
glDeleteShader(vs);
glDeleteShader(fs);
}
void Shader::Bind()
{
glUseProgram(this->shader_program);
}
void Shader::Destroy()
{
glDeleteProgram(this->shader_program);
}
static std::string LoadSourceFile(std::string filePath)
{
std::ifstream ifs(filePath);
std::string content( (std::istreambuf_iterator<char>(ifs) ),
(std::istreambuf_iterator<char>() ) );
if(content.empty())
{
std::cerr << "source file was empty or not correctly loaded\n";
}
return content;
}
And my drawing code:
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo_positions);
glVertexAttribPointer(glGetAttribLocation(shader.GetProgramID(), "vertex_position"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, vbo_colors);
glVertexAttribPointer(glGetAttribLocation(shader.GetProgramID(), "vertex_color"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
while(!glfwWindowShouldClose(display.GetWindowID())) {
display.UpdateFPSCounter();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.Bind();
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
update();
glfwSwapBuffers(display.GetWindowID());
display.CheckWindowShouldClose();
}
Does anyone see what I'm doing wrong?
Thanks in advance!
vertex_color doesn't match the variable in your vertex shader.
The problem is here:
glEnableVertexAttribArray(0);
glVertexAttribPointer(glGetAttribLocation(shader.GetProgramID(), "vertex_position"),
3, GL_FLOAT, GL_FALSE, 0, NULL);
Both of these calls take the attribute location as the first argument. While the location for the position may happen to be 0, this is not guaranteed, and you should pass the same argument to both these calls:
GLuint posLoc = glGetAttribLocation(shader.GetProgramID(), "vertex_position");
glEnableVertexAttribArray(posLoc);
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);

openGL not rendering colour

I'm having trouble drawing a couple triangles in colour. The shaders load fine, and I have a slight feeling that it's the way I've laid out my data, but in general, I have no clue why it won't draw it in colour.
main.cpp :
//g++ main.cpp -lGL -lGLEW -lGLU -lglut LoadShaders.cpp -o run
#include<GL/glew.h>
#include<GL/freeglut.h>
#include<GL/gl.h>
#include<iostream>
#include"LoadShaders.h"
#include"vgl.h"
using namespace std;
enum VAO_IDs {Triangles, NumVAOs };
enum Attrib_IDs {vPosition = 0, cPosition = 1};
GLuint VAOs;
GLuint Buffers;
const GLuint NumVertices = 6;
void init(void)
{
glGenVertexArrays(1, &VAOs);
glBindVertexArray(VAOs);
GLfloat vertices[NumVertices] [2] = {
{-0.90, -0.90},
{0.85, -0.90 },
{-0.90, 0.85 },
{0.90, -0.85 },
{0.90, 0.90 },
{-0.85, 0.90 }
};
glGenBuffers(1, &Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
GLfloat colours[NumVertices] [3] = {
{0.583f, 0.568f, 1.000f},
{0.100f, 0.435f, 0.235f},
{0.456f, 0.345f, 0.654f},
{0.345f, 0.222f, 0.564f},
{0.109f, 0.538f, 1.000f},
{0.057f, 0.453f, 0.777f},
};
GLuint colourBuffer;
glGenBuffers(1, &colourBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colourBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(0);
ShaderInfo shaders[]={
{GL_VERTEX_SHADER, "triangles.vert"},
{GL_FRAGMENT_SHADER, "triangles.frag"},
{GL_NONE}
};
GLuint program = LoadShaders(shaders);
glUseProgram(program);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAOs);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(512,512);
glutInitContextVersion( 4, 2 );
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow(argv[0]);
if (glewInit()) {
cerr << "Unable to initialize GLEW"<<endl;
exit(EXIT_FAILURE);
}
init();
glutDisplayFunc(display);
glutMainLoop();
}
triangles.vert:
#version 420 core
layout(location = 0) in vec2 vPosition;
layout(location = 1) in vec3 cPosition;
void main()
{
gl_Position = vPosition;
fragmentColor = cPosition;
}
triangles.frag:
#version 420 core
in vec3 fragmentColor;
out vec3 fColor;
void main()
{
fColor = fragmentColor;
}
Two problems in your vertex shader:
Missing a declaration for fragmentColor.
Invalid implicit conversion: gl_Position is a vec4, not a vec2. You have to expand out vPosition manually using a vec4 constructor: vec4( vPosition, 0.0, 1.0 ).
All together:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vector>
#include <iostream>
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( -1 );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
420 core,
layout(location = 0) in vec2 vPosition;
layout(location = 1) in vec3 cPosition;
out vec3 fragmentColor;
void main()
{
gl_Position = vec4( vPosition, 0.0, 1.0 );
fragmentColor = cPosition;
}
);
const char* frag = GLSL
(
420 core,
in vec3 fragmentColor;
out vec3 fColor;
void main()
{
fColor = fragmentColor;
}
);
GLuint VAO;
const GLuint NumVertices = 6;
void init()
{
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
GLfloat vertices[NumVertices] [2] =
{
{-0.90, -0.90},
{0.85, -0.90 },
{-0.90, 0.85 },
{0.90, -0.85 },
{0.90, 0.90 },
{-0.85, 0.90 },
};
GLuint Buffer;
glGenBuffers(1, &Buffer);
glBindBuffer(GL_ARRAY_BUFFER, Buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
GLfloat colours[NumVertices] [3] =
{
{0.583f, 0.568f, 1.000f},
{0.100f, 0.435f, 0.235f},
{0.456f, 0.345f, 0.654f},
{0.345f, 0.222f, 0.564f},
{0.109f, 0.538f, 1.000f},
{0.057f, 0.453f, 0.777f},
};
GLuint colourBuffer;
glGenBuffers(1, &colourBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colourBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(colours), colours, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(0);
GLuint program = Program::Load( vert, NULL, frag );
glUseProgram(program);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize(512, 512);
glutInitContextVersion(4, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow(argv[0]);
glewExperimental = GL_TRUE;
if( GLEW_OK != glewInit() )
{
return 1;
}
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}