Vertex shader not passing value to fragment shader - c++

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

Related

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.

How to apply colour to a triangle with opengl

I am trying to create a simple program with openGL. The goal is to create a triangle with colours for every vertex. The problem is that I can not figure out how to apply the colours to the triangle's vertices.
My vertex shader:
#version 330
layout(location = 0) in vec4 vertex_position;
layout(location = 1) in vec4 vertex_color;
smooth out vec4 theColor;
void main()
{
gl_Position = vec4(vertex_position.x, vertex_position.y, vertex_position.z, 1.0);
theColor = vertex_color;
}
My fragment shader:
#version 330
smooth in vec4 theColor;
out vec4 outColor;
void main()
{
outColor = theColor;
}
main code:
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
0.5f, 0.6f, 0.1f,
0.2f, 0.6, 0.3f,
0.1f, 0.23f, 0.78f
};
GLuint my_vao, my_vbo;
glGenVertexArrays(1, &my_vao);
glBindVertexArray(my_vao);
glGenBuffers(1, &my_vbo);
glBindBuffer(GL_ARRAY_BUFFER, my_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
// glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
// glVertexAttribPointer(3,4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(vao);
glViewport(0, 0, viewport_width, viewport_height);
glDrawArrays(GL_TRIANGLES, 0, 3);
swapBuffers();
The array vertices consists of the vertex points (first 3 vectors) and the color values (second 3 vectors). You can see my result in the following picture:
I have been trying to apply the colours with the following code:
glEnableVertexAttribArray(1);
glVertexAttribPointer(3,4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);
Unfortunately it does not work and I have no idea how to fix that. Can anyone help me out here?
For compiling and loading my shaders I use:
std::string loadVertexShader(const char* vertexPath)
{
std::string vertexCode;
std::ifstream vShaderFile;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
vShaderFile.open(vertexPath);
std::stringstream vShaderStream;
vShaderStream << vShaderFile.rdbuf();
vShaderFile.close();
vertexCode = vShaderStream.str();
}
catch (std::ifstream::failure e)
{
std::cout << "ERROR::VERTEXSHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
return vertexCode;
}
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
std::string vertexVal = loadVertexShader("shader/vertexshader.shader");
const char* vShaderCode = vertexVal.c_str();
std::string fragmentVal = loadFragmentShader("shader/fragmentshader.shader");
const char* fShaderCode = fragmentVal.c_str();
glShaderSource(vertexShader, 1, &vShaderCode, NULL);
glCompileShader(vertexShader);
glShaderSource(fragmentShader, 1, &fShaderCode, NULL);
glCompileShader(fragmentShader);
GLint vertexStatus;
char vertexInfoLog[512];
char fragmentInfoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexStatus);
GLint fragmentStatus;
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentStatus);
if (!vertexStatus)
{
glGetShaderInfoLog(vertexShader, 512, NULL, fragmentInfoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << fragmentInfoLog << std::endl;
}
if (!fragmentStatus)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, vertexInfoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << vertexInfoLog << std::endl;
}
First of all, as was revealed in the discussion in comments, you don't link your program. A typical shader program setup looks like this:
GLuint program = glCreateProgram();
glAttachShader(program, shader1);
glAttachShader(program, shader2);
...
glAttachShader(program, shaderN);
glLinkProgram(program); // <<<<<<<<< a-ha!
After that, a good idea is to check if program linkage was OK. A good example of the full shaders & program setup can be found on OpenGL wiki.
After successful program linkage, you can even detach the shaders from the program (glDetachShader) and delete them (glDeleteShader) - the program is already linked, shaders are of no use now (unless you intend to attach them to another program, of course).
Secondly, your arguments to glVertexAttribPointer are slightly messed up (which is totally OK - it takes time and effort to get used to them).
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, const GLvoid * pointer);
index is the attribute index - same as location as specified in shader, so for your color attribute it should be 1.
size is the attribute's dimension, i.e. number of components; supposing that you are using 3-float RGB, size should be 3
type is the actual type of the components; in you case these are floating-points too, so GL_FLOAT
stride is the distance between attributes of adjacent vertices, which is 3 floats in your case, i.e. 12 bytes; since there's nothing in between adjacent attributes in your vertices array, we can actually leave this zero (both for coordinates & colors)
pointer is the pointer to actual attributes data (or, in your case, offset in VBO); you are passing the same pointer to both glVertexAttribPointer calls, while your color values are 9 floats after the beginning of coordinate values
So, it should be
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (float const *)(nullptr) + 9);

Triangles not being drawn on screen openGL even when no error is occurred

I have written a simple openGL program to draw a triangle on the screen. I have done debugging with glGetError() and now there is no error in the code but when I try to run it only a black screen comes up.
here is my code. I am using GLFW for window creation.
#include<glew.h>
#include<glfw3.h>
#include<stdio.h>
int main(int argc, char ** argv)
{
glfwInit();
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);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
float vertices[] = {
0.0f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f
};
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
const GLchar * vs =
"#version 150\n"
"in vec2 position;\n"
"void main() {\n"
"vec4 gl_Position = vec4( position , 0.0 , 1.0 );\n"
"}";
const GLchar * fs =
"#version 150\n"
"out vec4 out_color; \n"
"void main() { \n"
"out_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
"}";
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vsh, 1, &vs, NULL);
glCompileShader(vsh);
GLint status;
glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
if (status == GL_TRUE) printf("Vertex Shader Compiled success\n");
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fsh, 1, &fs, NULL);
glCompileShader(fsh);
glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
if (status == GL_TRUE) printf("Fragment Shader Compiled success\n");
GLuint sp = glCreateProgram();
glAttachShader(sp, vsh);
glAttachShader(sp, fsh);
glBindFragDataLocation(sp, 0, "out_color");
glBindAttribLocation(sp,1,"position");
glLinkProgram(sp);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glUseProgram(sp);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Update
I have narrowed down the issue to just one line of code
GLint pos = glGetAttribLocation(sp, "position") //sp is shader program
The problem is it is returning -1. I have read in tutorials that if you don't use a variable it will be optimized out by the compiler.I have used the position in the code then why it is getting thrown away. Below is my vertex shader.
const GLchar * vs =
"#version 150\n"
"in vec2 position;\n"
"void main() {\n"
"vec4 gl_Position = vec4( position , 0.0 , 1.0 );\n"
"}";
just add these lines after
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
I mean use location 0 instead of 1
hope this helps

Why my triangle is white?

I am fallowing this tutorial http://learnopengl.com/#!Getting-started/Hello-Triangle and problem with this tutorials is that there is no full code example, and it's little hard to fallow. My code run successful, but my triangle is blank / white. And I think some functions is called twice, and program still can run successful if I delete some of that commands.
// SHADERS
GLuint VBO;
GLuint VAO = 0;
GLuint program;
GLuint vertexShader;
GLuint fragmentShader;
const char* vertexShaderSource =
"#version 330"
"layout (location = 0) in vec3 position;"
"void main(){"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);"
"}";
const char* fragmentShaderSource =
"#version 330"
"out vec4 color;"
"void main(){"
"color = vec4(1.0, 0.5, 1.0, 1.0);"
"}";
void compileShaders() {
vertexShader = glCreateShader(GL_VERTEX_SHADER); // pravi vertex shader
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Odredjuje izvor vertex shadera
glCompileShader(vertexShader); // kompajlira shader
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertexShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
}
void linkShaders() {
program = glCreateProgram(); // pravi program ID
// Linkuje shaderse i program
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glUseProgram(program); // koristi program
// Brise shaderse jer vise nisu potrebni i tako oslobadja memoriju
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // MISLIM DA JE OVO VISAK
}
void initVBO() {
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}
void initVAO() {
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
}
void Init() {
glClearColor(0.20, 0.63, 0.67, 1.0);
glViewport(0, 0, WIDTH, HEIGHT);
compileShaders();
linkShaders();
}
void Render() {
glClear(GL_COLOR_BUFFER_BIT);
initVAO();
initVBO();
glUseProgram(program);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0); // oslobadja momoriju
glutSwapBuffers();
}
Your shaders shouldn't compile. As a result, you don't have a valid program. Depending on the profile of the GL context - and the actual GL implementation - you will get different results. With nvidia drivers, you will typically see a white triangle in that scenario.
The reason why your shaders are invalid is because you forgot to add a newline \n after the #version 330 directive.
You are using C/C++'s syntax for concatenating strings by combining "string1" "string2". The fact that you have a newline outside of the quotes is totally irrelevant, the string you are specifying is
#version 330layout (location = 0) in vec3 position;[...]
all in one line, and that is not a valid preprocessor statement...
You always should check the compile status of your shaders, and the link status of your program. And you should always query the compiler and linker info logs. Have a look at the OpenGL wiki artice about shader compilation for details of how to do that.

How to use two shaders to render two objects in OpenGL

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