C/C++ OpenGL Occlusion Culling - c++

I'm trying out raw OpenGL, so I decided to code very, very simple game based on 3d blocks, something a'la retarded Minecraft game, just to improve my skills.
Last problems I've met with were cullings. I've finally figured out how to make Frustum Culling and Backface Culling, and they both work well, but unfortunatelly I have no idea how to code Occlusion Culling to not display boxes that are covered by other boxes that are closer to player.
Just for test in main draw loop I'm looping through all boxes, later I'll change it to a more efficient way, now this is how the code looks like:
for( std::map< std::string, Cube* >::iterator it = Cube::cubesMap.begin( ); it != Cube::cubesMap.end( ); it++ )
{
cube = ( *it ).second;
if( !cube )
continue;
(...)
if( Camera::cubeInFrustum( cube->position.x, cube->position.y, cube->position.z, 0.5f ) && cube->isInRoundDistance( 80 ) )
cube->draw( );
}
And Cube::Draw:
void Cube::draw( )
{
glPushMatrix( );
glTranslatef( position.x, position.y, position.z );
if( showSide1 == false && showSide2 == false && showSide3 == false && showSide4 == false && showSide5 == false && showSide6 == false )
{
glPopMatrix( );
return;
}
GLfloat cube[] =
{
-0.5f, -0.5f, 0.5f,// Front face
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,// Back face
-0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,// Left face
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,// Right face
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,// Top face
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,// Bottom face
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f
};
float textures[] =
{
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
//ss << position.x + 2 << ", " << position.y << ", " << position.z << std::endl;
glVertexPointer(3, GL_FLOAT, 0, cube);
glTexCoordPointer(2, GL_FLOAT, 0, textures);
if( showSide1 || showSide2 || showSide3 || showSide4 )
glBindTexture(GL_TEXTURE_2D, imageSides->texture);
if( showSide1 )
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if( showSide2 )
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
if( showSide3 )
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
if( showSide4 )
glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
if( showSide5 )
{
glBindTexture(GL_TEXTURE_2D, imageUp->texture);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
}
if( showSide6 )
{
glBindTexture(GL_TEXTURE_2D, imageDown->texture);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
}
glPopMatrix( );
}
I'm pretty sure it's inefficient, as I said earlier, this code will be optimized soon. Now I'm trying to make it working. The bool variables showSide are made for detection, if there is box with other box next to it, the sides between them won't be drawn.
I've been looking and googling how to make the occlusion culling, but I failed, there are only laconic informations or theory.
My question is, could anyone help me how to not draw covered blocks? I heard there is GLEW which I've compiled and injected, it has two following lines:
glBeginQuery(GL_SAMPLES_PASSED_ARB, query);
glEndQuery(GL_SAMPLES_PASSED);
Apparently Query is helpful to solve my problem, but I unsuccessfully tried to use it with Google on many ways, firstly no cubes were drawn, secondly game was drawn as earlier, covered cubes also.

Generally, you shouldn't expect a graphical API to do the work for you - its job is rendering, and your job is making sure it has as little to render as possible.
I recommend reading this blog: http://www.sea-of-memes.com/summary/blog_parts.html
It is about someone developing a minecraft-ish engine from scratch, and goes over everything from occlusion to lighting to transparency. In fact, the very first part should answer your question pretty well.

Related

How to subdivide Plane in OpenGL?

I want to generate VBO and EBO for subdivided plane, I draw with GL_TRIANGLES, I want to know effective way to do this.
Eventually it will be a huge cube consists from 6 subdivided plane, so, i can't imagine alghorithm to generate VBO and EBO for subdivide.
What i have as input data:
cube
std::vector<float> vertices =
{
// +Y SIDE //Colors
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
// -Y SIDE
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
// +X SIDE
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
// -X SIDE
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
// +Z SIDE
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
// -Z SIDE
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f
};
std::vector<unsigned int> indices =
{
// +Y
1, 2, 0, 3, 2, 1,
// -Y
4, 6, 5, 5, 6, 7,
// +X
8, 9, 10, 9, 11, 10,
// -X
14, 13, 12, 14, 15, 13,
// +Z
17, 18, 16, 19, 18, 17,
// -Z
20, 22, 21, 21, 22, 23
};
So, i want to write a function witch accept subdivision and change my indeces and vertices vectors, just loop over existed planes in cube and subdivide it

Cube getting squashed and rendering as trapezium

I'm trying to render a cube and rotate it along it's Y axis using OpenGL ES 2.0, however the cube does not render as a cube but rather as some sort of very flat trapezium. A few images showing the odd behaviour:
Very flat:
beginning to rotate:
mid-rotation:
and after rotation:
I'm not exactly sure what is causing the strange behaviour. I am utilising the Pigs in a Blanket library for rendering on PS Vita.
These are my cube vertices. The first 3 values in each row are the vertex data, the last 2 values are for texture mapping
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
This is my initialization function. surface_width = 960, surface_height = 544 and aspect = 1.764706
void TestScene::init(EGLint s_width, EGLint s_height)
{
surface_height = s_height;
surface_width = s_width;
model = glm::mat4(1.0f);
projection = glm::mat4(1.0f);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
texture.load_texture("app0:assets/wall.jpg");
if (!shader.load_shaders("app0:shaders/vert.cg", "app0:shaders/frag.cg"))
sceKernelExitProcess(0);
}
This is my rendering function
void TestScene::render(EGLDisplay display, EGLSurface surface, double deltaTime)
{
glViewport(0, 0, surface_width, surface_height);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.ID);
glUseProgram(shader.ID);
GLint mvpLoc = glGetUniformLocation(shader.ID, "mvp");
GLint position = glGetAttribLocation(shader.ID, "vPosition");
GLint texLoc = glGetAttribLocation(shader.ID, "vTexCoord");
GLfloat aspect = (GLfloat)surface_width/(GLfloat)surface_height;
projection = glm::perspective(glm::radians(camera.Zoom), aspect, 0.1f, 100.0f);
view = camera.GetViewMatrix();
model = glm::rotate(model, glm::radians(1.0f), glm::vec3(0.0f, -1.0f, 0.0f));
glm::mat4 mvp = projection * view * model;
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp));
// Bind vertex positions
glEnableVertexAttribArray(position);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
// Bind texture positions
glEnableVertexAttribArray(texLoc);
glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glDrawArrays(GL_TRIANGLES, 0, 36);
glDisableVertexAttribArray(position);
glDisableVertexAttribArray(texLoc);
eglSwapBuffers(display, surface);
}
My cameras zoom value is 45.0f and this is the GetViewMatrix method:
glm::mat4 Camera::GetViewMatrix()
{
return glm::lookAt(Position, Position + Front, Up);
}
and finally the shaders:
vert.cg
void main
(
uniform float4x4 mvp,
float4 vPosition,
float2 vTexCoord: TEXCOORD0,
out float4 oPosition: POSITION,
out float2 fTexCoord: TEXCOORD
)
{
oPosition = mul(mvp, vPosition);
fTexCoord = vTexCoord;
};
frag.cg
float4 main
(
in float2 fTexCoord: TEXCOORD0,
uniform sampler2D texture1: TEXUNIT0
)
{
float4 col;
col = tex2D(texture1, fTexCoord);
return col;
}
I have a feeling it has something to do with my projection matrix but I'm not entirely sure. Any help is greatly appreciated, thank you
UPDATE:
If I update the near value in glm::perspective from 0.1f to 1.0f it produces a better looking but still false result, so I'm pretty sure the issue is in my projection matrix. What am I doing wrong here?
projection = glm::perspective(glm::radians(camera.Zoom), aspect, 0.1f, 100.0f);
becomes
projection = glm::perspective(glm::radians(camera.Zoom), aspect, 1.0f, 100.0f);
for the following results:
Wider but still incorrect
Another angle
Again
I've found the issue. I was multiplying the model view projection matrix incorrectly in the vert shader.
oPosition = mul(mvp, vPosition);
should be
oPosition = mul(vPosition, mvp);
this works with a near value of 0.1f
EDIT
Also the missing faces were due to incorrect winding order with my vertices. Here is a corrected set of vertices, they are in clockwise order glFrontFace(GL_CW);
GLfloat vertices[] = {
// Back face
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // Bottom-left
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // bottom-right
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // top-left
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // bottom-left
// Front face
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // top-right
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // bottom-right
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // top-right
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // top-left
// Left face
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-right
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-left
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-left
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-left
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-right
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-right
// Right face
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-left
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-right
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // bottom-right
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // top-left
// Bottom face
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // top-right
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // bottom-left
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, // top-left
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // bottom-left
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, // top-right
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // bottom-right
// Top face
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // top-left
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // top-right
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // bottom-right
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // bottom-right
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, // bottom-left
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f // top-left
};

Skybox texture does not show with OpenGL?

So I am having this assignment which requires to create a skybox; the texture is provided as a single file. Bear in mind, I am very slow when it comes to understanding OpenGL, and this particular SkyBox has been driving me insane. I read up on every little thing on the internet that I thought could relate to my issue, but I either can't comprehend what is going on, which is not what I am after since I want to know what I am doing and not copy/paste some code, or the result ends up being something different.
The code relating to the skybox so far:
GLfloat cubeVertexData[108] =
{
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
//4
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
//5
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
//6
0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f
};
GLfloat textureCoordsSkyBox[72] = {
//face 1
0.75,0.33, // 0,1,
0.75,0.67, // 1,1,
0.5,0.33, // 0,0,
0.5,0.33, // 0,0,
0.75,0.67, // 1,0,
0.5,0.67, // 1,1,
//face 2
0.5,1.0, // 1,1,
0.25,1, // 0,1,
0.5,0.67, // 1,0,
0.5,0.67, // 1,0,
0.25,1.0, // 0,1,
0.25,0.67, // 1,1,
//face 3
0,0.67,// 1,1,
0,0.33,// 0,1,
0.25,0.67,// 1,0,
0.25,0.67,// 1,0,
0,0.33,// 0,1,
0.25,0.33,// 0,0,
//face 4
0.25,0.0,// 0,1,
0.5,0.0,// 1,1,
0.25,0.33,// 0,0,
0.25,0.33,// 0,0,
0.5,0.0,// 1,1,
0.5,0.33,// 0,0,
//face 5
0.5,0.67,// 1,0,
0.25,0.67,// 0,0,
0.5,0.33,// 1,1,
0.5,0.33,// 1,1,
0.25,0.67,// 0,0,
0.25,0.33,// 0,1,
//face 6
0.75,0.33,// 1,1,
1.0,0.33,// 0,1,
0.75,0.67,// 1,0,
0.75,0.67,// 1,0,
1.0,0.33,// 0,1,
1.0,0.67// 0,0
};
GLfloat gCubeVertexdataNormals[108] =
{
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f
};
void DrawSkyBox() {
glFrontFace(GL_CW);
glBindTexture(GL_TEXTURE_2D, textures[SKYIMAGE]);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, gCubeVertexdataNormals);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cubeVertexData);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoordsSkyBox);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Loading texture [part of code missing as I have different textures for other elements loaded here]:
.....
#define SKYIMAGE 5 //sky image
const char *textureFiles[TEXTURE_COUNT] = { "stormydays.tga".... };
I am not sure if it is of importance, but I will also mention that the other textured elements of the scene do not have coordinates from 0-1, but from 100 to 1000. I tried previously to set up the textureCoordsSkyBox to 1000 in terms of coordinates, but still no result.
I imagine I do something completely wrong when it comes to the binding of the texture, but I am having a hard time comprehending how I can improve that part. Any advice would be deeply appreciated. Thank you in advance.
-Edit-
So this is the texture I am using:
What I am seeing is just black, besides the other elements of the scene like the back wall, some grass and some flowers [this is what I was referring to when I said textured elements of the scene]. I am attaching the code here of what part of my drawing the scene function looks like:
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
gluLookAt(cameraX, cameraY, cameraZ,//eye
50.00, 90.00, 50.00,//centre
0.00, 1000.00, 0.00);//up
glPushMatrix();
DrawSkyBox();
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, -100.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
drawTexturedSurface(IMAGE1); //grass
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, -350.0);
drawTexturedSurface(IMAGE4); //front stone wall
glPopMatrix();
glPushMatrix();
.......
glPopMatrix();
drawGUI();
glPushMatrix();
glutSwapBuffers();
}
Also, it is the fixed version of OpenGL. I tried messing about with GL_LIGHTING, GL_CULL_FACE, GL_DEPTH_TEST and glDisableClientState but it is the same result. Also, I don't get any errors.
In your case the skybox is a very tiny object in the center of the world.
You have to draw the skybox in at the position of the camera. When you darw the sykbox, then you have to disable the depth test, this cause that the depth buffer is not written and all other parts of the scene cover the skybox.
Further two-dimensional texturing has to be enabled by glEnable(GL_TEXTURE_2D), before the skybox geometry is drawn:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
gluLookAt(
cameraX, cameraY, cameraZ,//eye
50.00, 90.00, 50.00,//centre
0.00, 1000.00, 0.00);//up
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(cameraX, cameraY, cameraZ); // model transformation to the camera position
glEnable(GL_TEXTURE_2D);
DrawSkyBox();
glPopMatrix();
glEnable(GL_DEPTH_TEST);

How can I instantiate an array inside the base class from a derived class?

I have a base class that contains an unassigned pointer _vertices, and I want to populate it from the derived class constructor:
class GameRenderable {
bool _indexed;
int _vertSize;
int _idxSize;
unsigned int VAO, VBO, EBO;
unsigned int _texture0;
protected:
float *_vertices;
unsigned int *_indices;
public:
GameRenderable(GameRenderableMode grm);
~GameRenderable();
void Render();
protected:
void SetupBuffer(int, int);
};
void GameRenderable::SetupBuffer(int vs, int is) {
_indexed = false;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vs, _vertices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
_idxSize = is;
_vertSize = vs;
}
void GameRenderable::Render() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _texture0);
glBindVertexArray(VAO);
glm::mat4 model = glm::mat4(1.0f);
GetShader()->setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, _vertSize);
}
The derived classes:
class Cube : public GameRenderable {
public:
Cube();
~Cube();
};
Cube::Cube():GameRenderable(GameRenderableMode::_3D) {
/* Cube ASCII
E--------F A -0.5f, 0.5f, -0.5f
/| /| B 0.5f, 0.5f, -0.5f
A--------B | C -0.5f, -0.5f, -0.5f
| | | | D 0.5f, -0.5f, -0.5f
| G------|-H E -0.5f, 0.5f, 0.5f
|/ |/ F 0.5f, 0.5f, 0.5f
C--------D G -0.5f, -0.5f, 0.5f
H 0.5f, -0.5f, 0.5f
*/
float vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
_vertices = new float[sizeof(vertices)];
memcpy_s(_vertices, sizeof(vertices), vertices, sizeof(float));
SetupBuffer(36, 0);
SetupTexture("container.jpg");
}
Cube::~Cube() {
}
When I call SetupBuffer() the array passed to openGL is always only 1 element, and nothing is drawn. If I put the code of SetupBuffer() directly inside the constructor, it works.
GL Buffer Issues
The sizeof( type ) operator returns the size in bytes, so for example the code:
std::cout << sizeof(float) << std::endl;
will print the output: 4
so on the following line:
_vertices = new float[sizeof(vertices)];
you are allocating 4 times the amount of data that you need to store the array vertices. It should be something like:
_vertices = new float[sizeof(vertices) / sizeof(float)];
//this is more ugly but could also be:
_vertices = (float*)(new char[sizeof(vertices)]);
//that works since an ascii 'char' is 1 byte
the function memcpy_s from MSDN:
Parameters
dest
New buffer.
destSize
Size of the destination buffer, in bytes for memcpy_s and wide characters (wchar_t) for wmemcpy_s.
src
Buffer to copy from.
count
Number of characters to copy.
so the call should be something like:
memcpy_s(_vertices, sizeof(vertices), vertices, sizeof(vertices));
//although, I would just use the regular 'memcpy':
memcpy(_vertices, vertices, sizeof(vertices));
Your SetupBuffer function takes the parameter vs which is input directly into glBufferData, however glBufferData also takes the size in bytes:
size
Specifies the size in bytes of the buffer object's new data store.
so entering the value 36 will not suffice. You want to find a way to pass the value of sizeof(vertices), although since you know the stride of each vertex (5 floats), you could change the call to:
glBufferData(GL_ARRAY_BUFFER, vs * 5 * sizeof(float), _vertices, GL_STATIC_DRAW);
As many of the comments mentioned, you could also use the std::vector class to simplify some of the code, however I think it is much more important to address the misunderstandings in the code you have already written.
OOP Issues
I am fairly sure the above will fix your problem. However, just to make sure the constructor:
Cube::Cube() : GameRenderable(GameRenderableMode::_3D) {
doesn't overwrite the GameRenderable constructor, the GameRenderable constructor will be called first (with the parameter _3D) so ensure that the code within the GameRenderable constructor doesn't break anything (as I can't see it).

VAO gets deleted without calling glDeleteVertexArrays()

I have just started to learn OpenGL and I am currently trying to apply the OpenGL knowledge I have acquired in a small game architecture, but I am having a hard time making this work with Classes. I am trying to display a triangle on the screen using a separate class like this:
CubeModel.h
#pragma once
#include <vector>
#include <glad\glad.h>
class CubeModel
{
public:
//x y and z are dimensions of the cube
CubeModel();
CubeModel( float x, float y, float z);
~CubeModel();
void Bind();
void Unbind();
private:
unsigned int m_VAO, m_VBO;
std::vector<float> m_vertices = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
std::vector<float> m_vertices2 = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
};
CubeModel.cpp
#include "CubeModel.h"
CubeModel::CubeModel()
{
CubeModel(1.0f, 1.0f, 1.0f);
}
CubeModel::CubeModel(float x, float y, float z)
{
unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices[0]) * m_vertices.size(),
m_vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
m_VAO = VAO;
m_VBO = VBO;
}
CubeModel::~CubeModel()
{
glDeleteVertexArrays(1, &m_VAO);
glDeleteBuffers(1, &m_VBO);
}
void CubeModel::Bind()
{
glBindVertexArray(m_VAO);
}
void CubeModel::Unbind()
{
glBindVertexArray(0);
}
Game_State.h (where CubeModel is used):
#pragma once
#include "Window.h"
#include "Shader.h"
#include "CubeModel.h"
#define TIMESTEP 1.0f/100.0f
class Game_State
{
public:
Game_State();
~Game_State();
int Run();
bool IsDone();
private:
void HandleInput();
void Update(double deltatime);
void Render();
Window m_window;
double m_elapsedTime = 0;
Shader m_cubeShader;
CubeModel m_testCube;
};
Game_State.cpp:
#include "Game_State.h"
Game_State::Game_State()
: m_window("Title to be determined...", glm::vec2(1920, 1080))
, m_cubeShader("cubeshader.vs","cubeshader.fs")
{
}
Game_State::~Game_State()
{
}
int Game_State::Run()
{
while (m_elapsedTime > TIMESTEP)
{
m_elapsedTime -= TIMESTEP;
HandleInput();
Update(m_elapsedTime);
}
Render();
m_elapsedTime += glfwGetTime();
glfwSetTime(0.0f);
return 0;
}
void Game_State::Update(double deltatime)
{
m_window.Update();
}
void Game_State::Render()
{
m_window.BeginDraw(0.7f, 0.5f, 0.3f, 1.0f);
m_cubeShader.use();
m_testCube.Bind();
glDrawArrays(GL_TRIANGLES, 0, 6);
m_testCube.Unbind();
m_window.EndDraw();
}
void Game_State::HandleInput()
{
if (glfwGetKey(m_window.GetWindow(), GLFW_KEY_F11) == GLFW_PRESS)
{
m_window.ToggleFullscreen();
}
if (glfwGetKey(m_window.GetWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
m_window.CloseWindow();
}
}
bool Game_State::IsDone() { return m_window.IsDone(); }
When i tried to debug the code, everything was working and the VAO and VBO both got an ID but by the time i call the bind function before drawing it to the screen in a separate render function it binds the array with ID 0. Both the m_VAO and m_VBO gets reset to 0 by the time bind() is called, what is the reason for this?!?! I've tried using this exact code directly in the render function and it works so the render is fine it seems. (I'm using GLFW and GLAD)
Thanks in advance! :)
This:
CubeModel::CubeModel()
{
CubeModel(1.0f, 1.0f, 1.0f);
}
is wrong. That creates a CubeModel temporary within the constructor. That's not the same thing as delegating the constructor. If that's what you wanted, you have to use the proper C++11 syntax:
CubeModel::CubeModel() : CubeModel(1.0f, 1.0f, 1.0f)
{}
Note that this may not be your only problem, since you neglected to post all of your code.
For example, CubeModel is technically copyable, but it shouldn't be. You make no special allowances for copying (which by its nature, would have to create a new VAO and buffer, and copy the data from the other VAO/buffer). So you need to delete the copy operations, and write appropriate move operations:
CubeModel(const CubeModel &) = delete;
CubeModel(CubeModel &&other) : m_VAO(other.m_VAO), m_VBO(other.m_VBO)
{
other.m_VAO = 0;
other.m_VBO = 0;
}
And do something similar for the move assignment operation. Or just leave it as being unassignable.
In C++, you can't call a constructor from inside another constructor as you do here:
CubeModel::CubeModel()
{
CubeModel(1.0f, 1.0f, 1.0f);
}
What is actually happening here is that you create a temporary, unnamed CubeModel which get's deleted when the default constructor is left. That's when your VAO gets deleted.
If you don't want to duplicate the code in both function, you need to write a new method and call that one from both constructors.