So I have created all of the correct sphere vertices using this algorithm:
GLint total = 100;
GLfloat radius = 200;
GLfloat sphereVertices[30000];
for (int i = 0; i < total; i++)
{
float lon = map(i, 0, total, -M_PI, M_PI);
for (int j = 0; j < total; j++)
{
float lat = map(j, 0, total, -M_PI/2, M_PI/2);
sphereVertices[(i * 300) + (j * 3)] = radius * sin(lon) * cos(lat);
sphereVertices[(i * 300) + (j * 3) + 1] = radius * sin(lon) * sin(lat);
sphereVertices[(i * 300) + (j * 3) + 2] = radius * cos(lon);
}
}
But when I draw it using either GL_TRIANGLES and GL_TRIANGLE_STRIP, I'm produced with this result:
As you can see the only triangles which are being rendered are slicing through the center of the sphere. Is my math wrong? Or am I not plotting my data into my array the correct way for my glVertexAttribPointer function to read the data correctly?
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
EDIT 1:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glDrawArrays(GL_TRIANGLES, 0, 10000);
You cant't draw the inices directly by glDrawArrays. You have to bring them in a proper order.
Create a triangle index list and use glDrawElements
See also How to map texture to sphere that rendered by parametric equation using points primitive
Further note, that your loop should run from i = 0 to i <= total, because you want to create vertex coordinates on both poles of the sphere.
GLint layers = 100;
GLint circumferenceTiles = 100;
std::vector<GLfloat> sphereVertices;
va.reserve( (layers+1)*(circumferenceTiles+1)*3 ); // 3 floats: x, y, z
for ( int i = 0; i <= layers; ++ i )
{
GLfloat lon = map(i, 0, layers, -M_PI, M_PI);
GLfloat lon_sin = std::sin( lon );
GLfloat lon_cos = std::cos( lon );
for ( int j = 0; j <= circumferenceTiles; j ++ )
{
GLfloat lat = map(j, 0, circumferenceTiles, -M_PI/2, M_PI/2);
GLfloat lat_sin = std::sin( lat);
GLfloat lat_cos = std::cos( lat);
va.push_back( lon_cos * lat_cos ); // x
va.push_back( lon_cos * lat_sin ); // y
va.push_back( lon_sin ); // z
}
}
You can create triangles by stacking up discs:
// create the face indices
std::vector<GLuint> ia;
ia.reserve( layers*circumferenceTiles*6 );
for ( GLuint il = 0; il < layers; ++ il )
{
for ( GLuint ic = 0; ic < circumferenceTiles; ic ++ )
{
GLuint i0 = il * (circumferenceTiles+1) + ic;
GLuint i1 = i0 + 1;
GLuint i3 = i0 + circumferenceTiles+1;
GLuint i2 = i3 + 1;
int faces[]{ i0, i1, i2, i0, i2, i3 };
ia.insert(ia.end(), faces+(il==0?3:0), faces+(il==layers-1?3:6));
}
}
Specify the vertex array object:
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sphereVertices.size()*sizeof(GLfloat), sphereVertices.data(),
GL_STATIC_DRAW );
GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, ia.size()*sizeof(GLuint), ia.data(), GL_STATIC_DRAW );
GLuint v_attr_inx = 0;
glVertexAttribPointer( v_attr_inx , 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( v_attr_inx );
glBindVertexArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
Draw the sphere:
glBindVertexArray( vao );
glDrawElements( GL_TRIANGLES, (GLsizei)ia.size(), GL_UNSIGNED_INT, 0 );
glBindVertexArray( 0 );
Related
I need to generate a NxN resolution grid in the xy-plane with OpenGL. The final grid needs to be made by triangles (GL_TRIANGLES), so it should seem like the following example:
^
* | ----------
* | |\ |\ |\ |
* | | \| \| \|
* | ----------
* | |\ |\ |\ |
* y | | \| \| \|
* | ----------
* | |\ |\ |\ |
* | | \| \| \|
* | ----------
* |
* |-------------->
* x
Note that I need to store the grid in vertex-index form (given the structures by parameters).
My code at this point:
void generate_grid(
std::uint32_t N,
std::vector<glm::vec3>* vertices,
std::vector<glm::uvec3>* indices)
{
for (int i = 0; i < N; i++) {
glBegin(GL_TRIANGLES);
for (int j = 0; j < N; j++) {
int vertexNum = indices; // Index for vertex j of face i.
double[] vertexCoords = vertices[vertexNum]; // The vertex itself.
glVertex3f(vertexCoords, 0);
}
glEnd();
}
Any advice? Regards.
Since the language is C++ and you are using a std::vector you should change the function signature and pass the parameters by reference instead of by pointer.
void generate_grid(int N, std::vector<glm::vec3> &vertices, std::vector<glm::uvec3> &indices);
First you have to fill the vertex array. Note, for a N*N field you need (N+1)*(N+1) vertices. Second you have to generate the triangle indices, for each field you have to generate 2 triangles:
float f(float x, float y)
{
// use any curve function you want
return sin(x*2.0f*3.141526f) * sin(y*2.0f*3.141526f) * 0.1f;
}
void generate_grid(int N, std::vector<glm::vec3> &vertices, std::vector<glm::uvec3> &indices)
{
for (int j=0; j<=N; ++j)
{
for (int i=0; i<=N; ++i)
{
float x = (float)i/(float)N;
float y = (float)j/(float)N;
float z = f(x, y);
vertices.push_back(glm::vec3(x, y, z));
}
}
for (int j=0; j<N; ++j)
{
for (int i=0; i<N; ++i)
{
int row1 = j * (N+1);
int row2 = (j+1) * (N+1);
// triangle 1
indices.push_back(glm::uvec3(row1+i, row1+i+1, row2+i+1));
// triangle 2
indices.push_back(glm::uvec3(row1+i, row2+i+1, row2+i));
}
}
}
The old school and deprecated way to draw this, would be like this:
void draw_grid(const std::vector<glm::vec3> &vertices, const std::vector<glm::uvec3> &indices)
{
glBegin(GL_TRIANGLES);
for ( auto i : indices )
{
glVertex3fv(glm::value_ptr(vertices[i.x]));
glVertex3fv(glm::value_ptr(vertices[i.y]));
glVertex3fv(glm::value_ptr(vertices[i.z]));
}
glEnd();
}
The common way to draw geometry is to create a Vertex Array Object:
GLuint generate_vao(const std::vector<glm::vec3> &vertices, const std::vector<glm::uvec3> &indices)
{
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, vertices.size()*sizeof(glm::vec3), glm::value_ptr(vertices[0]), GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(glm::uvec3), glm::value_ptr(indices[0]), GL_STATIC_DRAW );
glBindVertexArray( 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
return vao;
}
void draw_vao( GLuint vao, GLsizei n )
{
glBindVertexArray( vao );
glDrawElements( GL_TRIANGLES, (GLsizei)n, GL_UNSIGNED_INT, NULL );
glBindVertexArray( 0 );
}
std::vector<glm::vec3> vertices;
std::vector<glm::uvec3> indices;
GLuint vao = generate_vao( vertices, indices );
.....
draw_vao( vao, (GLsizei)indices.size()*3 );
I'm drawing sprites that are all in a buffer using glDrawElements.
To tell sprites what texture to be in the fragment shader I have uniform sampler2D textures[32]; each vertex has an index, which is passed to the fragment shader from the vertex shader:
color = texture(textures[index], fs_in.uv);
when I try draw my sprites with more than 1 texture active it gets the wrong textures in the top right corner
http://puu.sh/lyr5j/d8c2cf6c8f.png
I have no clue why this is happening have tried texture parameters
I cant seem to find anyone who has had a similar problem.
This is my renderer's init function (I am purposly passing the texid as float since I have heard ints don't work well (also tried))
glGenBuffers(1, &m_VDBO);
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glBindBuffer(GL_ARRAY_BUFFER, m_VDBO);
glBufferData(GL_ARRAY_BUFFER, RENDERER_BUFFER_SIZE, 0, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(SHADER_VERTEX_INDEX);
glEnableVertexAttribArray(SHADER_UV_INDEX);
glEnableVertexAttribArray(SHADER_COLOR_INDEX);
glEnableVertexAttribArray(SHADER_TEXID_INDEX);
glVertexAttribPointer(SHADER_VERTEX_INDEX, 3, GL_FLOAT, GL_FALSE, RENDERER_VERTEX_SIZE, (const void *) offsetof(VertexData, VertexData::vertex));
glVertexAttribPointer(SHADER_UV_INDEX, 2, GL_FLOAT, GL_FALSE, RENDERER_VERTEX_SIZE, (const void *) offsetof(VertexData, VertexData::uv));
glVertexAttribPointer(SHADER_COLOR_INDEX, 4, GL_UNSIGNED_BYTE, GL_TRUE, RENDERER_VERTEX_SIZE, (const void *) offsetof(VertexData, VertexData::color));
glVertexAttribPointer(SHADER_TEXID_INDEX, 1, GL_FLOAT, GL_FALSE, RENDERER_VERTEX_SIZE, (const void *)offsetof(VertexData, VertexData::texID));
glBindBuffer(GL_ARRAY_BUFFER, 0);
const GLushort modelindices[] = { 0, 1, 2, 2, 3, 0 };
GLuint indices[RENDERER_INDICES_SIZE];
for (int i = 0; i < RENDERER_INDICES_SIZE; i += 6)
{
for (int o = 0; o < 6; o++)
{
indices[i + o] = modelindices[o] + (i / 6 * 4);
}
}
glGenBuffers(1, &m_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, RENDERER_INDICES_SIZE * sizeof(GLuint), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
the flush function
glBindVertexArray(m_VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
for (int i = 0; i < m_TextureSlots.size(); i++)
{
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, m_TextureSlots[i]);
}
glDrawElements(GL_TRIANGLES, m_IndexCount, GL_UNSIGNED_INT, 0);
m_TextureSlots.clear();
m_IndexCount = 0;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
It is hard for me to see where your problem is coming from, the only thing I can suggest is taking a look at an Image2d class object constructor that I have. Now, my source depends on outside classes such as a ShaderManager class that relies heavily on template types and a Batch class and a BatchManager class to send over the vertices to the video card. Also this Image2d is an inherited object. However, this may serve as some help to you in tracking down your own problem. There are two different constructors for different versions of the implementation depending on which version of OpenGL and GLSL is being used. If I remember correctly version 2 uses the BatchManager to send the vertices to the video card where version 1 doesn't which can be seen within the render() method.
Image2d v1.0
// ----------------------------------------------------------------------------
// Image2d()
Image2d::Image2d( float fWidth, float fHeight, TextureInfo::FilterQuality filterQuality, bool generateMipMap, const std::string& strTextureFilename, const std::string& strId ) :
VisualMko( glm::uvec2(), strId ),
m_vboTexture( 0 ),
m_vboPosition( 0 ),
m_vboIndices( 0 ),
m_vao( 0 ) {
if ( fWidth <= 0 || fHeight <= 0 ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Invalid image size (" << fWidth << "," << fHeight << ") must be more then 0 in each dimension.";
throw ExceptionHandler( strStream );
}
// Save TextureId
TextureFileReader textureFileReader( strTextureFilename );
m_textureInfo = textureFileReader.getOrCreateTextureInfo( filterQuality, generateMipMap, false );
// Define Texture Co-Ordinates
std::vector<float> vTextureCoordinates;
vTextureCoordinates.push_back( 0.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 0 );
vTextureCoordinates.push_back( 0 );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 1.0f );
vTextureCoordinates.push_back( 0 );
// Define Vertex Positions (x,y,z)
std::vector<float> vVertexPositions;
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( fHeight );
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( fWidth );
vVertexPositions.push_back( fHeight );
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( fWidth );
vVertexPositions.push_back( 0 );
vVertexPositions.push_back( 0 );
// Define 2 Triangle Faces
std::vector<unsigned char> vIndices;
vIndices.push_back( 0 );
vIndices.push_back( 1 );
vIndices.push_back( 2 );
vIndices.push_back( 3 );
// Create Vertex Array Object
glGenVertexArrays( 1, &m_vao );
glBindVertexArray( m_vao ); // Start Array
m_pShaderManager->setAttribute( A_COLOR, COLOR_WHITE );
// Create Position Buffer And Store On Video Card
glGenBuffers( 1, & m_vboPosition );
glBindBuffer( GL_ARRAY_BUFFER, m_vboPosition );
glBufferData( GL_ARRAY_BUFFER, vVertexPositions.size() * sizeof( vVertexPositions[0] ), &vVertexPositions[0], GL_STATIC_DRAW );
m_pShaderManager->enableAttribute( A_POSITION );
// Create Texture Coordinate Buffer
glGenBuffers( 1, &m_vboTexture );
glBindBuffer( GL_ARRAY_BUFFER, m_vboTexture );
glBufferData( GL_ARRAY_BUFFER, vTextureCoordinates.size() * sizeof( vTextureCoordinates[0] ), &vTextureCoordinates[0], GL_STATIC_DRAW );
m_pShaderManager->enableAttribute( A_TEXTURE_COORD0 );
// Create Index Buffer
glGenBuffers( 1, &m_vboIndices );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_vboIndices );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof( vIndices[0] ), &vIndices[0], GL_STATIC_DRAW );
glBindVertexArray( 0 ); // Stop Array
// Disable Attribute Pointers
m_pShaderManager->disableAttribute( A_POSITION );
m_pShaderManager->disableAttribute( A_TEXTURE_COORD0 );
// THIS MUST BE AFTER Vertex Array Buffer Is Unbound!
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Stop Buffer Index
glBindBuffer( GL_ARRAY_BUFFER, 0 ); // Stop Buffer
// We have a Valid Image2d Save Filename
m_strFilename = strTextureFilename;
} // Image2D - v1.0
Image2D - v2.0
// ----------------------------------------------------------------------------
// Image2d()
Image2d::Image2d( const glm::uvec2& origin, const glm::uvec2& size, const std::string& strTextureFilename, const std::string& strId ) :
VisualMko( size, strId ),
m_vboTexture( 0 ),
m_vboPosition( 0 ),
m_vboIndices( 0 ),
m_vao( 0 ) {
m_version = 2;
TextureFileReader textureFileReader( strTextureFilename );
m_textureInfo = textureFileReader.getOrCreateTextureInfo( TextureInfo::FILTER_NONE, false, false );
m_config.uTextureId = m_textureInfo.uTextureId;
if ( 0 == m_textureInfo.size.x || 0 == m_textureInfo.size.y ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << "size of " << strTextureFilename << " is invalid " << m_textureInfo.size;
throw ExceptionHandler( strStream );
}
// Verify Image Fits Inside Texture
if ( m_textureInfo.size.x < size.x + origin.x || m_textureInfo.size.y < size.y + origin.y ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " " << strTextureFilename << " size is " << m_textureInfo.size
<< " which is too small for an image that is " << size
<< " pixels in size, with an origin point set at " << origin ;
throw ExceptionHandler( strStream );
}
glm::vec2 textureCoordScaleFactor( 1.0f / static_cast<float>( m_textureInfo.size.x ),
1.0f / static_cast<float>( m_textureInfo.size.y ) );
glm::vec2 textureCoordBottomLeft = glm::vec2( textureCoordScaleFactor.x * origin.x,
textureCoordScaleFactor.y * ( m_textureInfo.size.y - origin.y - size.y ) );
glm::vec2 textureCoordTopRight = glm::vec2( textureCoordScaleFactor.x * ( origin.x + size.x ),
textureCoordScaleFactor.y * ( m_textureInfo.size.y - origin.y ) );
// Set Colors And Texture Coordinates (Position Will Be Updated In Render Function)
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( textureCoordBottomLeft.x, textureCoordTopRight.y ) ) );
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( textureCoordBottomLeft.x, textureCoordBottomLeft.y ) ) );
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( textureCoordTopRight.x, textureCoordTopRight.y ) ) );
m_vVertices.push_back( GuiVertex( glm::vec2(), COLOR_WHITE, glm::vec2( textureCoordTopRight.x, textureCoordBottomLeft.y ) ) );
} // Image2d - v2.0
and here is my render() method
// ----------------------------------------------------------------------------
// render()
void Image2d::render() {
if ( 1 == m_version ) {
m_pShaderManager->setTexture( 0, U_TEXTURE0_SAMPLER_2D, m_textureInfo.uTextureId );
glBindVertexArray( m_vao );
glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, nullptr );
glBindVertexArray( 0 );
} else {
// Version 2.0
// Update Vertices
if ( m_transformMatrix.updateTranslation || m_transformMatrix.updateScale || m_transformMatrix.updateRotation ) {
m_transformMatrix.updateTranslation = m_transformMatrix.updateScale = m_transformMatrix.updateRotation = false;
// Order Of Operations Matter Here!
glm::mat4 matrix; // Identity
if ( m_transformMatrix.hasTranslation ) {
matrix[3][0] = m_transformMatrix.translation.x;
matrix[3][1] = m_transformMatrix.translation.y;
}
if ( m_transformMatrix.hasRotation ) {
matrix = glm::rotate( matrix, m_transformMatrix.fRotationAngleRadians, glm::vec3( 0.0f, 0.0f, -1.0f ) );
}
if ( m_transformMatrix.hasScale ) {
matrix = matrix * glm::mat4( m_transformMatrix.scale.x, 0.0f, 0.0f, 0.0f,
0.0f, m_transformMatrix.scale.y, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
}
// Center Offset
if ( m_offsetPosition.x != 0 || m_offsetPosition.y != 0 ) {
matrix = glm::translate( matrix, glm::vec3( -m_offsetPosition.x, -m_offsetPosition.y, 0.0f ) );
}
// Apply Transformation To All 4 Vertices
m_vVertices[0].position = glm::vec2( matrix * glm::vec4( 0, 0, 0, 1.0f ) );
m_vVertices[1].position = glm::vec2( matrix * glm::vec4( 0, m_size.y, 0, 1.0f ) );
m_vVertices[2].position = glm::vec2( matrix * glm::vec4( m_size.x, 0, 0, 1.0f ) );
m_vVertices[3].position = glm::vec2( matrix * glm::vec4( m_size.x, m_size.y, 0, 1.0f ) );
}
renderBatch();
}
} // render
Make sure that the sizes you are specifying in your glBufferData(GL_ARRAY_BUFFER, RENDERER_BUFFER_SIZE, 0, GL_DYNAMIC_DRAW);
is accurate. Also make sure that you are stopping your your VertexArray at the appropriate time as well as disabling your Attribute Pointers. Everything that you bound must be unbound, and for some types Order does matter!
I tried to create a cylinder VBO by passing a std::vector to the vertex buffer instead of the static const GLfloat variableName[]= { some data}; . However, nothing gets drawn in my window.
What's wrong with my code?
My VBO:
glGenBuffers(1, &vertexbuffer2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
std::vector<float> bufferData = CreateCylinder();
glBufferData(
GL_ARRAY_BUFFER,
sizeof(bufferData),
&bufferData.front(),
GL_STATIC_DRAW);
CreateCylinder method:
std::vector<float> CreateCylinder(){
std::vector<float> outputArray;
int i, j, k;
for (j = 0; j <= 360; j += precision_deg){
outputArray.push_back(float(cos((pi / 180 * j))));
outputArray.push_back(1.0);
outputArray.push_back(float(sin((pi / 180 * j))));
outputArray.push_back(float(cos((pi / 180 * j))));
outputArray.push_back(-1.0);
outputArray.push_back(float(sin((pi / 180 * j))));
}
for (i = 1; i >= -1; i -= 2){
outputArray.push_back(0.0);
outputArray.push_back(float(i));
outputArray.push_back(0.0);
for (k = 0; k <= 360; k += precision_deg){
outputArray.push_back(i*float(cos((pi / 180 * k))));
outputArray.push_back(float(i));
outputArray.push_back(float(sin((pi / 180 * k))));
}
}
return outputArray;
}
Render method:
void RenderScene6(){
glDisable(GL_DEPTH_TEST);
Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
View = glm::lookAt(
glm::vec3(5.63757, 1.7351, -2.19067),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
Model = glm::mat4(1.0f);
MVP = Projection * View * Model;
glUseProgram(programID_1);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_QUAD_STRIP, 0, 437);
glDrawArrays(GL_TRIANGLE_FAN, 438, 888); //THESE ARE HARDCODED ATM.
glDisableVertexAttribArray(0);
}
The problem is the size you are passing to glBufferData: sizeof(bufferData) is the same as std::vector<float> and has nothing to do with the size of the vectors data.
What you have to do is to pass the actual size of the data stored in the vector as follows:
glBufferData(
GL_ARRAY_BUFFER,
bufferData.size() * sizeof(float),
&bufferData.front(),
GL_STATIC_DRAW);
With all of my objects that are to be rendered, I use glDrawElements. However, my venture into Compute Shaders has left me a setup that uses glDrawArrays. As with many who are breaching the topic, I used this PDF as a basis. The problem is that when it is rendered, nothing appears.
#include "LogoTail.h"
LogoTail::LogoTail(int tag1) {
tag = tag1;
needLoad = false;
shader = LoadShaders("vertex-shader[LogoTail].txt","fragment-shader[LogoTail].txt");
shaderCompute = LoadShaders("compute-shader[LogoTail].txt");
for( int i = 0; i < NUM_PARTICLES; i++ )
{
points[ i ].x = 0.0f;
points[ i ].y = 0.0f;
points[ i ].z = 0.0f;
points[ i ].w = 1.0f;
}
glGenBuffers( 1, &posSSbo);
glBindBuffer( GL_SHADER_STORAGE_BUFFER, posSSbo );
glBufferData( GL_SHADER_STORAGE_BUFFER, sizeof(points), points, GL_STATIC_DRAW );
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
for( int i = 0; i < NUM_PARTICLES; i++ )
{
times[ i ].x = 0.0f;
}
glGenBuffers( 1, &birthSSbo);
glBindBuffer( GL_SHADER_STORAGE_BUFFER, birthSSbo );
glBufferData( GL_SHADER_STORAGE_BUFFER, sizeof(times), times, GL_STATIC_DRAW );
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
for( int i = 0; i < NUM_PARTICLES; i++ )
{
vels[ i ].vx = 0.0f;
vels[ i ].vy = 0.0f;
vels[ i ].vz = 0.0f;
vels[ i ].vw = 0.0f;
}
glGenBuffers( 1, &velSSbo );
glBindBuffer( GL_SHADER_STORAGE_BUFFER, velSSbo );
glBufferData( GL_SHADER_STORAGE_BUFFER, sizeof(vels), vels, GL_STATIC_DRAW );
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
}
void LogoTail::Update(const double dt, float sunTime,glm::vec3 sunN) {
position=glm::translate(glm::mat4(), glm::vec3(4.5f,0,0));
}
void LogoTail::Draw(shading::Camera& camera){
shaderCompute->use();
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 4, posSSbo );
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 5, velSSbo );
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 6, birthSSbo );
glDispatchCompute( NUM_PARTICLES / WORK_GROUP_SIZE, 1, 1 );
glMemoryBarrier( GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT );
shaderCompute->stopUsing();
shader->use();
shader->setUniform("camera", camera.matrix());
shader->setUniform("model",position);
glBindBuffer( GL_ARRAY_BUFFER, posSSbo );
glVertexPointer( 4, GL_FLOAT, 0, (void *)0 );
glEnableClientState( GL_VERTEX_ARRAY );
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
glDisableClientState( GL_VERTEX_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
shader->stopUsing();
}
The header contains the needed structures and other variables so they do not fall out of scope for the specific object.
Here is the compute shader itself.
#version 430 core
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable
layout( std140, binding=4 ) buffer Pos
{
vec4 Positions[ ]; // array of vec4 structures
};
layout( std140, binding=5 ) buffer Vel
{
vec4 Velocities[ ]; // array of vec4 structures
};
layout( std140, binding=6 ) buffer Tim
{
float BirthTimes[ ]; // array of structures
};
layout( local_size_x = 128, local_size_y = 1, local_size_z = 1 ) in;
const vec3 G = vec3( 0., -0.2, 0. );
const float DT = 0.016666;
void main() {
uint gid = gl_GlobalInvocationID.x; // the .y and .z are both 1
vec3 p = Positions[ gid ].xyz;
vec3 v = Velocities[ gid ].xyz;
vec3 pp = p + v*DT + .5*DT*DT*G;
vec3 vp = v + G*DT;
Positions[ gid ].xyz = pp;
Velocities[ gid ].xyz = vp;
}
For testing purposes I lowered the gravity.
I believe that nothing is out of scope, nor is there a needed bind, but yet it alludes me to why the particles are not drawing.
In addition, I also added a geometry shader that constructs a quad around each point but it did not solve anything.
Last 5 lines seems to me problematic:
glBindBuffer( GL_ARRAY_BUFFER, posSSbo );
glVertexPointer( 4, GL_FLOAT, 0, (void *)0 );
glEnableClientState( GL_VERTEX_ARRAY );
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
glDisableClientState( GL_VERTEX_ARRAY );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
My guess is You are trying to use old way of doing things in programmable pipeline.I am not sure how it is stated in OpenGL specs but it seems that in the newer versions (GL4.2) you are forced to bind your vertex buffers to VAO(may be that is vendor specific rules?).Once I needed to implement OIT and tried Cyril Crassin's demo which was using buffers with elements draw-just like you.I am using GL4.2 and NVidia cards.Nothing was showing up.I then bound them to a VAO and the issue was gone.So that is what I suggest you to try.
I have been given the task of importing an obj file and loading it up in C++.
Its loading the file correctly but displainy it incorrectly. Can anybody see anything wrong with my setup of opengl stuff? :)
Here is a picture of what the render looks like atm
#define _USE_MATH_DEFINES
#include<stdio.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include "InitShader.h"
#include <math.h>
#include "MatrixStack.h"
#include "Object.h"
#include <time.h>
#define BUFFER_OFFSET( offset ) ((GLvoid*) (offset))
float x = 1.0;
const int NumVertices = 144;
const int NumIndicies = 104;
GLfloat vertices[NumVertices];
// RGBA olors
GLfloat vertexColours[NumVertices];
// each entry is an index into the vertices matrix
GLint vertexIndicies[NumIndicies];
//GLfloat vertices2[NumVertices];
// RGBA olors
//GLfloat vertexColours2[NumVertices];
// each entry is an index into the vertices matrix
//GLint vertexIndicies2[NumIndicies];
GLuint vao;
GLuint program;
GLuint buffers[2];
GLfloat radius = 1.0;
GLfloat theta = 0.0;
GLfloat phi = 0.0;
const GLfloat dr = 5.0 * M_PI/180.0;
// Projection transformation parameters
GLfloat left2 = -1.0, right2 = 1.0;
GLfloat bottom = -1.0, top = 1.0;
GLfloat zNear = 0.5, zFar = 3.0;
GLuint modelView; // model-view matrix uniform shader variable location
GLuint projection; // projection matrix uniform shader variable location
MatrixStack modelViewStack(5);
MatrixStack projectionStack(5);
// OpenGL initialization
void
init()
{
srand ( time(NULL) );
Object myst("assignment1.obj");
float *tempFloat = myst.verts();
float *tempFloat2 = myst.indis();
for (unsigned int i=0; i<NumVertices; vertices[i]=tempFloat[i],i++);
for (unsigned int i=0; i<NumIndicies; vertexIndicies[i]=tempFloat2[i],i++);
for (unsigned int i=0; i<NumVertices;i++){
float a = (float)(rand()%10);
a = a/10;
cout << a;
vertexColours[i]=a;
}
for (unsigned int i=0; i<NumVertices; cout << vertices[i] << endl ,i++);
for (unsigned int i=0; i<NumIndicies; cout << vertexIndicies[i] << endl ,i++);
glEnable( GL_DEPTH_TEST );
//make background yerpul in colour
glClearColor( 0.235, 0.194, 0.314, 1.0 );
// Load shaders and use the resulting shader program
program = InitShader( "vshader41.glsl", "fshader41.glsl" );
glUseProgram( program );
// Create a vertex array object
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize two buffer objects
glGenBuffers( 2, buffers);
//one buffer for the vertices and colours
glBindBuffer( GL_ARRAY_BUFFER, buffers[0]);
glBufferData( GL_ARRAY_BUFFER, sizeof(vertices) + sizeof(vertexColours),NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(vertices), sizeof(vertexColours), vertexColours);
//one buffer for the indices
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndicies),vertexIndicies, GL_STATIC_DRAW );
// set up vertex arrays
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices)) );
modelView = glGetUniformLocation( program, "model_view" );
projection = glGetUniformLocation( program, "projection" );
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//----------------------------------------------------------------------------
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
modelViewStack.loadIdentity();
modelViewStack.lookAt(radius*sin(theta)*cos(phi),
radius*sin(theta)*sin(phi),
radius*cos(theta),
0.0,0.0,0.0,
0.0,1.0,0.0);
glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewStack.getMatrixf());
projectionStack.loadIdentity();
projectionStack.ortho(left2,right2,bottom,top,zNear,zFar);
glUniformMatrix4fv(projection, 1, GL_FALSE, projectionStack.getMatrixf());
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
//Indexing into vertices we need to use glDrawElements
glDrawElements (GL_TRIANGLES, NumIndicies, GL_UNSIGNED_INT, 0);
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void keyboard( unsigned char key, int x, int y )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case 'x': left2 *= 1.1; right2 *= 1.1; break;
case 'X': left2 *= 0.9; right2 *= 0.9; break;
case 'y': bottom *= 1.1; top *= 1.1; break;
case 'Y': bottom *= 0.9; top *= 0.9; break;
case 'z': zNear *= 0.9; zFar *= 1.1; break;
case 'Z': if (zNear<zFar){zNear *= 1.1; zFar *= 0.9;} break;
case 'r': radius *= 2.0; break;
case 'R': radius *= 0.5; break;
case 'o': theta += dr; break;
case 'O': theta -= dr; break;
case 'p': phi += dr; break;
case 'P': phi -= dr; break;
case ' ': // reset values to their defaults
left2 = -1.0;
right2 = 1.0;
bottom = -1.0;
top = 1.0;
zNear = -1.0;
zFar = 1.0;
radius = 1.0;
theta = 0.0;
phi = 0.0;
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void idle(){
theta += .001;
left2 += .0001;
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
reshape( int width, int height )
{
glViewport( 0, 0, width, height );
}
//----------------------------------------------------------------------------
int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutCreateWindow( "Orbit the Color Cube - Orthographic" );
glewInit();
init();
glutIdleFunc(idle);
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutReshapeFunc( reshape );
glutMainLoop();
return 0;
}
The vertex indexes of the faces in the .obj file starts at 1, not 0 as might be expected. Try to decrease each index with 1 when you load the file. If I read your code correctly, this line:
for (unsigned int i=0; i<NumIndicies; vertexIndicies[i]=tempFloat2[i],i++);
should be
for (unsigned int i=0; i<NumIndicies; vertexIndicies[i]=tempFloat2[i] - 1,i++);