opengl es nacl probleme - c++

I have an opengl es 2 code working outside of NaCl but returns this error in Chrome:
[.PPAPIContext]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 3
There is my code :
static float theta = 0.0;
glClearColor(0.5, 0.5, 0.5, 1);
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
g_matrices.PushMatrix();
g_matrices.Rotatef( theta, 0.0f, 0.0f, 1.0f );
EnableGUIShader(SM_DEFAULT);
GLfloat col[4] = {1.0f, 0.33f, 0.0f, 0.11f};
GLfloat ver[3][3];
ver[0][0] = 0.0f;
ver[0][1] = 1.0f;
ver[0][2] = 0.0f;
ver[1][0] = 0.87f;
ver[1][1] = -0.5f;
ver[1][2] = 0.0f;
ver[2][0] = -0.87f;
ver[2][1] = -0.5f;
ver[2][2] = 0.0f;
GLint posLoc = GUIShaderGetPos();
GLint colLoc = GUIShaderGetCol();
glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(ver), ver);
glVertexAttribPointer(1, 4, GL_FLOAT, 0, sizeof(col), col);
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(posLoc);
glDisableVertexAttribArray(1);
DisableGUIShader();
g_matrices.PopMatrix();
theta += 1.0f;

In the calls to glVertexAttribPointer() and glEnableVertexAttribArray() for the color, you ned to use colLoc for the first argument instead of 1:
GLint posLoc = GUIShaderGetPos();
GLint colLoc = GUIShaderGetCol();
glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(ver), ver);
glVertexAttribPointer(colLoc, 4, GL_FLOAT, 0, sizeof(col), col);
glEnableVertexAttribArray(posLoc);
glEnableVertexAttribArray(colLoc);
Also, if you want to pass in the colors as an array, you need a color per vertex. So for your 3 vertices, the color array would have to be col[3][4]. If you want to use the same color for all vertices, replace the glVertexAttribPointer(colLoc, ...) call with:
glVertexAttrib4f(colLoc, col[0], col[1], col[2], col[3]);

Related

Problem with orthographic projection in OpenGL

So I'm pretty new to OpenGL I was trying to create orthographic projection and the problem is when I do
glm::mat4 ortho;
ortho = glm::ortho(-(float)WINDOW_WIDTH / 2.0f, (float)WINDOW_WIDTH / 2.0f, -(float)WINDOW_HEIGHT / 2.0f, (float)WINDOW_HEIGHT / 2.0f, -1.f, 1.f);
It works just fine but the 0, 0 point is in the middle of the screen
The thing I wanna do is have 0, 0 point in the down left corner of the window but when I do
glm::mat4 ortho;
ortho = glm::ortho(0.0f, (float)WINDOW_WIDTH, 0.0f, (float)WINDOW_HEIGHT, -1.0f, 1.0f);
It ends up like this
I was searching so long so by now I'm just asking for help
These are vertices positions of my rectangle
float positions[8] =
{
-100.0f, -100.0f,
100.0f, -100.0f,
100.0f, 100.0f,
-100.0f, 100.0f,
};
I also use index buffer to draw it
unsigned indices[6] =
{
0, 1, 2,
2, 3, 0
};
These are my buffers
unsigned buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
unsigned ibo = 0;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned), indices, GL_STATIC_DRAW);
And it's drawn using
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
So what I have done wrong is in shader I have multiplied position by orth projection and not orth projection by position so
do not do this:
gl_Position = position * u_MVP;
do that:
gl_Position = u_MVP * position;

Nothing is drawing after switching from glOrtho to MVP matrix inside shader

I've used orthographic perspective before, which drew everything properly. I used the following code during initialization:
glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WIDTH, HEIGHT, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
And this shader:
vec3 actualPos = inPos + cubeVert * (inMass * scale);
gl_Position = vec4(actualPos, 1.0);
Mass = inMass;
UV = cubeVert.xy + vec2(0.5, 0.5);
I've been trying to switch to using the MVP matrix inside my shader instead, but I get no output on my screen, other than the color I clear it with.
I build it with:
glm::mat4 model(1.f);
glm::mat4 projection(1.f);
projection = glm::perspective(glm::radians(30.f), (float)WIDTH / (float)HEIGHT, 0.1f, 100.f);
glm::mat4 view(1.f);
view = glm::lookAt(glm::vec3(-10.f, -10.f, -10.f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 1.f, 0.f));
glm::mat4 MVP = projection * view * model;
And then apply it during initialization, after removing the old code:
glViewport(0, 0, WIDTH, HEIGHT);
glUniformMatrix4fv(glGetAttribLocation(program, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
And this is my current main drawing loop:
glClearColor(0.01f, 0.10f, 0.15f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glUniformMatrix4fv(glGetAttribLocation(program, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE0, texture);
glUniform1i(sampler, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBOcube);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, (void*)0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, AMOUNT * sizeof(Body), NULL, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, AMOUNT * sizeof(Body), bods);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Body), (void*)0);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Body), (void*)sizeof(glm::vec3));
glVertexAttribDivisor(0, 0);
glVertexAttribDivisor(1, 1);
glVertexAttribDivisor(2, 1);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, AMOUNT);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
I've tried to move the camera around, rotate it, in case the objects were being drawn outside of the view, but I'm not sure if anything is even being drawn at this point.
"MVP" Is a uniform variable. To geht the location index of a uniform variable, you've to use glGetUniformLocation rather than glGetAttribLocation.
glLinkProgram(program);
GLint mvp_loc = glGetUniformLocation(program, "MVP"):
glUseProgram(program);
glUniformMatrix4fv(mvp_loc, 1, GL_FALSE, glm::value_ptr(MVP));

How to draw multiple objects in OpenGL using multiple VAO and VBO?

I'm trying to render multiple objects in OpenGL using multiple VAO's and VBO's. To render multiple objects using the same vertices I've done it, but what I want to do is to use different vertices for each object, for example to draw a square and a circle. For a square I only need 6 vertices but for circle I need 360.
I have error with reading or creating the shaders.
Here is the Vertex Shader:
#version 330 core
layout (location = 0) in vec4 position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * position;
}
Fragment Shader:
#version 330 core
layout(location = 0) out vec4 color;
uniform vec4 u_Color;
void main()
{
color = u_Color;
}
The VAO and VBO generating and binding
// Circle
std::vector<VertexFormat> vertices;
for (int i = 0; i < 360; i++)
{
GLfloat angle = i * ((2.0f * 3.14159f) / 360);
vertices.push_back(VertexFormat(glm::vec3(cos(angle) * 100.0f, sin(angle) * 100.0f, 0.0f)));
}
// Pipette object
std::vector<VertexFormat> pipetteVertices;
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 500.0f, 0.0f))); // 0
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 500.0f, 0.0f))); // 1
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 700.0f, 0.0f))); // 2
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 700.0f, 0.0f))); // 3
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 500.0f, injPipette.y + 500.0f, 0.0f)));
pipetteVertices.push_back(VertexFormat(glm::vec3(injPipette.x + 700.0f, injPipette.y + 700.0f, 0.0f)));
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 6, &pipetteVertices[0], GL_STATIC_DRAW);
//Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid *)0);
GLuint vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
GLuint vbo2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 360, &vertices[0], GL_STATIC_DRAW);
//Position attribute
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (GLvoid *) 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
And the draw call in the rendering loop:
//Get the uniform locations of model, view and projection matrices
modelID = glGetUniformLocation(program, "model");
viewID = glGetUniformLocation(program, "view");
projectionID = glGetUniformLocation(program, "projection");
//View transform
glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 2), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
//Projection transform
//glm::mat4 projection = glm::perspective(45.0f, (GLfloat)screenWidth / (GLfloat)screenHeight, 0.1f, 1000.0f);
glm::mat4 projection = glm::ortho(0.0f, (GLfloat)screenWidth, 0.0f, (GLfloat)screenHeight, 0.1f, 10.0f);
{
glUniformMatrix4fv(viewID, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionID, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(100.0f + move_x, 100.0f + move_y, 0.0f));
glm::mat4 rotate = glm::rotate(glm::mat4(1.0), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 1.0f, 2.0f));
glm::mat4 model = translate * rotate * scale;
glUniformMatrix4fv(modelID, 1, GL_FALSE, glm::value_ptr(model));
glUniform4f(color, 0.0f, 0.0f, 1.0f, 1.0f);
//Render
glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
}
{
glUniformMatrix4fv(viewID, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionID, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 translate = glm::translate(glm::mat4(1.0), glm::vec3(300.0f + injPipette.x, 300.0f + injPipette.y, 0.0f));
glm::mat4 rotate = glm::rotate(glm::mat4(1.0), 0.0f, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 scale = glm::scale(glm::mat4(1.0), glm::vec3(1.0f, 1.0f, 2.0f));
glm::mat4 model = translate * rotate * scale;
glUniformMatrix4fv(modelID, 1, GL_FALSE, glm::value_ptr(model));
glUniform4f(color, 1.0f, 0.0f, 0.0f, 0.5f);
//Render
glDrawArrays(GL_TRIANGLES, 0, 6);
}
I repeat, to draw multiple objects using the same vertices I've done it. I need to know how to draw multiple objects using the same vertex and fragment shader but different number of vertices. The project is small, just rendering maximum 10 objects in 2D.
Drawing commands such as glDrawArrays process and draw the arrays of generic vertex attribute data specified in the currently bound Vertex Array Object.
This means that you need to bind the correct vertex array object before executing the Draw call:
// [...]
glBindVertexArray(vao2);
glDrawArrays(GL_TRIANGLE_FAN, 0, 360);
// [...]
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
I found a project with the code:
#pragma once
#include "glm\glm.hpp"
struct VertexFormat
{
glm::vec3 position;
VertexFormat(const glm::vec3 &iPos)
{
position = iPos;
}
VertexFormat()
{
}
};

OpenGL Shader stretches geomatry

I created a simple program that renders a quad
Initialize:
Math::float3 vertices[4];
vertices[0] = Math::float3(-0.5f, 0.5f, -1.0f);
vertices[1] = Math::float3(-0.5f, -0.5f, -1.0f);
vertices[2] = Math::float3(0.5f, -0.5f, -1.0f);
vertices[3] = Math::float3(0.5f, 0.5f, -1.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int indices[] = {
0, 1, 2,
2, 3, 0
};
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
Rendering:
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(Math::float3), 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
Which renders a perfectly square quad.
I continued by adding a vertex shader program:
Vertex shader
layout (location = 0) in vec3 Position;
void main(){
gl_Position = vec4(Position.x, Position.y, Position.z, 1.0);
}
Fragment shader
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
And if I run my program again, the quad seems to be stretched to about twice its size on x axis, and stretched slightly on the Y.
Without shaders
With shaders
Any idea on what could be causing this? If you need more code snippets or additional info, please let me know :)
Update
Some extra code.
Opening the window / reshape
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);
glutCreateWindow(TITLE);
...
if(_h == 0) _h = 1;
float ratio = 1.0f * _w / _h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, _w, _h);
gluPerspective(45.0f, ratio, 1, 1000);
glMatrixMode(GL_MODELVIEW);
Update 2
My problem sadly still persists, some extra info here:
My geomatry:
Math::float3 vertices[4];
vertices[0] = Math::float3(-0.5, -0.5f, -1.0f);
vertices[1] = Math::float3(0.5f, -0.5f, -1.0f);
vertices[2] = Math::float3(0.5f, 0.5f, -1.0f);
vertices[3] = Math::float3(-0.5f, 0.5f, -1.0f);
unsigned int indices[] = { 0, 1, 2, 2, 3, 0 };
My vertex shader
#version 330
layout (location = 0) in vec3 Position;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vec4(Position.x, Position.y, Position.z, 1.0);
}
Setup view
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define FOV 60.0f
#define RATIO 1.0f * SCREEN_WIDTH / SCREEN_HEIGHT
#define ZNEAR 1.0f
#define ZFAR 1000.0f
if(_h == 0) _h = 1;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, _w, _h);
gluPerspective(FOV, RATIO, ZNEAR, ZFAR);
glMatrixMode(GL_MODELVIEW);
Initialize
Math::float3 vertices[4];
vertices[0] = Math::float3(-0.5, -0.5f, -1.0f);
vertices[1] = Math::float3(0.5f, -0.5f, -1.0f);
vertices[2] = Math::float3(0.5f, 0.5f, -1.0f);
vertices[3] = Math::float3(-0.5f, 0.5f, -1.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int indices[] = { 0, 1, 2, 2, 3, 0 };
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
sl = new Loader::ShaderLoader();
sl->Initialize();
sl->AddShader("data/shaders/shader.vs", VERTEX_SHADER);
sl->AddShader("data/shaders/shader.fs", FRAGMENT_SHADER);
sl->CompileShaders();
Render
MVP = glGetUniformLocation(sl->GetShaderProgram(), "MVP");
float m[16];
f -= 0.01f;
m[0] = 1.0f;
m[1] = 0.0f;
m[2] = 0.0f;
m[3] = 0.0f;
m[4] = 0.0f;
m[5] = 1.0f;
m[6] = 0.0f;
m[7] = 0.0f;
m[8] = 0.0f;
m[9] = 0.0f;
m[10] = 1.0f;
m[11] = 0.0f;
m[12] = 0.0f;
m[13] = 0.0f;
m[14] = 0.0f;
m[15] = 1.0f;
glUniformMatrix4fv(MVP, 1, GL_TRUE, m);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
I've also printed the value for MVP per render call, and it's always 0 for some reason.
Again, any additional tips are welcome, thanks!
Most likely you have a non-identity transformation chain (non-identity projection and/or modelview matrix) set up with the fixed function. When using shaders the fixed function matrices are not used, which may explain the difference.
This is caused by different approach to PVM (projection-view-model) matrix in OpenGL. In fixed pipeline, this matrix was defined by functions glMatrixMode.
When shaders are used, these matrices are usually sent to vertex shader as uniform and handled here.
Your vertex shader then will be something like this:
in vec3 Position;
uniform mat4 Projection;
uniform mat4 View;
uniform mat4 Model;
void main(){
gl_Position = Projection * View * Model * vec4(Position.x, Position.y, Position.z, 1.0);
}
This should provide some more info about these three matrices: Tutorial 3 matrices

Having difficulty with OpenGL in C++, when rendering multiple objects

I'm having trouble rendering multiple cubes to screen. I have a cube class which sets up the cubes vertices and loads the appropriate shader. The problem that happens is that when multiple instances of my class are created like this:
Cube * cube = new Cube();
Cube * cube1 = new Cube();
And then I initialise the cube objects like so:
cube->setPos(0, 0, 0);
cube->setType(Cube::Type::Green);
cube->createCube();
cube1->setPos(1, 0, 0);
cube1->setType(Cube::Type::Red);
cube1->createCube();
Then I draw the cubes to screen in my render method like so:
cube->draw();
cube1->draw();
My cube class looks like this:
include "cube.h"
Shader* shader;
GLuint tex;
GLuint shaderProgram, fragmentShader, vertexShader;
GLuint vbo, ebo;
GLfloat x, y, z;
GLfloat r, g, b;
Cube::Cube() {
}
void Cube::setPos(GLfloat X, GLfloat Y, GLfloat Z) {
x = X;
y = Y;
z = Z;
}
void Cube::setType(Type type) {
switch (type) {
case Type::Red:
r = 1.0f;
g = 0.0f;
b = 0.0f;
break;
case Type::Green:
r = 0.0f;
g = 1.0f;
b = 0.0f;
break;
case Type::Blue:
r = 0.0f;
g = 1.0f;
b = 0.0f;
break;
default:
r = 0.0f;
g = 0.0f;
b = 0.0f;
break;
}
}
Cube::~Cube() {
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
}
void Cube::createCube() {
createShader();
GLfloat vertices[] = {
//X, Y, Z, R, G, B
x - 0.5f, y - 0.5f, z - 0.5f, r, g, b, // 0
x + 0.5f, y - 0.5f, z - 0.5f, r, g, b, // 1
x + 0.5f, y + 0.5f, z - 0.5f, r, g, b, // 2
x - 0.5f, y + 0.5f, z - 0.5f, r, g, b, // 3
x - 0.5f, y - 0.5f, z + 0.5f, r, g, b, // 4
x + 0.5f, y - 0.5f, z + 0.5f, r, g, b, // 5
x + 0.5f, y + 0.5f, z + 0.5f, r, g, b, // 6
x - 0.5f, y + 0.5f, z + 0.5f, r, g, b, // 7
};
GLuint elements[] = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
7, 3, 0, 0, 4, 7,
6, 2, 1, 1, 5, 6,
0, 1, 5, 5, 4, 0,
3, 2, 6, 6, 7, 3
};
// Create a Vertex Buffer Object and copy the vertex data to it
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Create an element array
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements,
GL_STATIC_DRAW);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat),
(void*) (3 * sizeof(GLfloat)));
}
void Cube::update() {
// Calculate transformation
glm::mat4 trans;
trans = glm::rotate(trans, (float) clock() / (float) CLOCKS_PER_SEC * 1.0f,
glm::vec3(0.0f, 0.0f, 1.0f));
GLint uniTrans = glGetUniformLocation(shaderProgram, "model");
glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans));
glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans));
glm::mat4 view = glm::lookAt(glm::vec3(1.2f, 1.2f, 1.2f), glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f));
GLint uniView = glGetUniformLocation(shaderProgram, "view");
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));
glm::mat4 proj = glm::perspective(45.0f, 800.0f / 600.0f, 1.0f, 10.0f);
GLint uniProj = glGetUniformLocation(shaderProgram, "proj");
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));
}
void Cube::draw() {
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}
void Cube::createShader() {
// load vertex shader source
const GLchar* vertexSource = shader->fileRead("src/shaders/vertex.vs");
if (vertexSource != NULL) std::cout << "vertexSource" << std::endl;
// load fragment shader source
const GLchar* fragmentSource = shader->fileRead("src/shaders/fragment.fs");
if (fragmentSource != NULL) std::cout << "fragmentSource" << std::endl;
// Create and compile the vertex shader
vertexShader = shader->compileShader(vertexSource, GL_VERTEX_SHADER);
// Create and compile the fragment shader
fragmentShader = shader->compileShader(fragmentSource, GL_FRAGMENT_SHADER);
// Link the vertex and fragment shader into a shader program
shaderProgram = shader->compileProgram(vertexShader, fragmentShader);
}
Long story short. I create and initialise two cubes. Both are drawn to screen in code yet when teh compiled program is run only the second cube is shown on screen.
A copy of my full code is available from My GitHub, if you'd like to clone and build it.
I've spent hours upon hours searching for a way to fix this and can't so I'm reaching out to the community. I have a feeling it's something to do with needing a VAO but I can't find out how or where to implement this I've tried a few different ways already.
Any helps greatly appreciated. Thanks in advance!
none of the state you set in the create function will persist beyond another call to it.
First you should move the values to members of the cube class.
Then in create you should create and use a vao:
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
Before specifying the vertex layout.
Then during the draw call:
void Cube::draw() {
glUseProgram(shaderProgram);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}
Add a call to glUseProgram(shaderProgram); in update as well.
However it's more efficient to use a single static program and then load the model matrix in the uniform;
void Cube::draw() {
//assume program is already bound and non-cube-specific uniforms are already set
glBindVertexArray(vao);
glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(trans));//kept in a field
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}
Without going into depth on your OpenGL usage (which #ratchetfreak already did in a separate answer), you have a very fundamental C++ problem.
You're declaring a bunch of variables at the start of your Cube.cpp file:
Shader* shader;
GLuint tex;
GLuint shaderProgram, fragmentShader, vertexShader;
GLuint vbo, ebo;
GLfloat x, y, z;
GLfloat r, g, b;
With the variables declared like this, you will have only a single copy of these values, which are shared between all instances of the Cube class. For example, all your cubes will have the same position, which is the one of the last cube you created, because they all share the same x, y and z variables that hold the position.
You need to define these variables as class members so that each Cube instance has separate values. This means that they need to go into the header file, typically in the private section of the class. For example:
class Cube {
public:
// Declaration of constructor, methods, etc.
private:
GLfloat x, y, z;
};
You'll probably want to use more descriptive names for the variables.