I'm trying to figure out how to use multiple buffers associated to a single vertex array object on the basis of one buffer per "object model" (e.g. verticies, normal, textures). To make it very simple in the sample code that follows I have couple objects composed of just one triangles (3 vertices) and associated colors. Buffer element indexed by ArrayBuffer1 receive the vertex coords (homogeneous coords) and an RGBA color vectors. Same for Buffer element indexed by ArrayBuffer2.
The vertex shader is a passthrough as following
#version 400 core
layout( location = 0 ) in vec4 vPosition;
layout( location = 1 ) in vec4 vColor;
out vec4 color;
void
main()
{
color= vColor;
gl_Position = vPosition;
}
The fragment shader is a passthroug has well
#version 450 core
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}
I d like to pass on data with one buffer per object grouping vertex attributes in the same buffer.
I can't figure how to raw these 2 objects.
Here is the client code (init part)
enum VertexDim { xDim, yDim, zDim, wDim, NumDim};
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer1, ArrayBuffer2, NumBuffers };
enum Attrib_IDs { vPosition = 0, vColor=1 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
const GLuint curDim= NumDim;
// first triangle
GLfloat static_vertices1[NumVertices/2][NumDim] = {
{ -0.90f, -0.90f, 0.5f, 1}, { 0.85f, -0.90f, 0.3f, 1 }, { -0.90f, 0.85f, 0.0f, 1 } // Triangle 1
};
// second triangle
GLfloat static_vertices2[NumVertices/2][NumDim] = {
{ 0.90f, -0.85f, -0.1f, 1 }, { 0.90f, 0.90f, -0.5f, 1 }, { -0.85f, 0.90f, -0.8f, 1 } // Triangle 2
};
// a base color from which to compute different vertex colors
GLfloat infColor_value[4]= {0.9f, 0.7f, 0.5f, 1.0f};
//----------------------------------------------------------------------------
//
// init
//
void
init( void )
{
const unsigned int n=NumVertices/2;
GLfloat infColor_values1[n][curDim];
GLfloat infColor_values2[n][curDim];
// compute different vertex colors from base color infColor_value
// .. loop over infColor_values1 and infColor_values2
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles2.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles2.frag" },
{ GL_NONE, NULL }
};
// LoadShaders is a wrapper to load, compile code and link shaders
GLuint program = LoadShaders( shaders );
if( program == 0) { std::cerr<<"shader program failed to build" << std::endl; }
glUseProgram( program );
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
glCreateBuffers( NumBuffers, Buffers );
// vertex 1
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer1] );
glNamedBufferData( Buffers[ArrayBuffer1], sizeof(static_vertices1)+sizeof(infColor_values1) , NULL, GL_STATIC_DRAW);
glNamedBufferSubData( Buffers[ArrayBuffer1], 0, sizeof(static_vertices1), static_vertices1);
glNamedBufferSubData( Buffers[ArrayBuffer1], sizeof(static_vertices1), sizeof(infColor_values1), infColor_values1);
GLuint64 offset = 0;
glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
offset = sizeof(static_vertices1);
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
glEnableVertexAttribArray( vColor );
// vertex 2
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer2] );
glNamedBufferData( Buffers[ArrayBuffer2], sizeof(static_vertices2)+sizeof(infColor_values2) , NULL, GL_STATIC_DRAW);
glNamedBufferSubData( Buffers[ArrayBuffer2], 0, sizeof(static_vertices2), static_vertices1);
glNamedBufferSubData( Buffers[ArrayBuffer2], sizeof(static_vertices2), sizeof(infColor_values2), infColor_values2);
offset = 0;
glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
offset = sizeof(static_vertices2);
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
glEnableVertexAttribArray( vColor );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindVertexArray(0);
}
and here follows the code to render
void
display( void )
{
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glBindVertexArray(0);
}
to sum it up : how to store an object vertices attributes in a single buffer and still display multiple objects ?
I could fetch verything in the same sub buffers (one for vertex coord, one for vetex colors) but I can't come up wit ha solution where I would sparate the obejcts to render.
I ve read close answers ( Architecture to draw many different objects in OpenGL What are Vertex Array Objects? ) related to this question yet it does not answer my question.
Defining a VAO for each object made it following #Rabbid76 advice
change for the init code
enum Buffer_IDs { Mesh, NumBuffers };
//....
// triangle 1
glBindBuffer( GL_ARRAY_BUFFER, Buffers1[Mesh] );
glNamedBufferData( Buffers1[Mesh], sizeof(static_vertices1)+sizeof(infColor_values1) , NULL, GL_STATIC_DRAW);
glNamedBufferSubData( Buffers1[Mesh], 0, sizeof(static_vertices1), static_vertices1);
glNamedBufferSubData( Buffers1[Mesh], sizeof(static_vertices1), sizeof(infColor_values1), infColor_values1);
GLuint64 offset = 0;
glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
offset = sizeof(static_vertices1);
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
glEnableVertexAttribArray( vColor );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindVertexArray(0);
// triangle 2
glBindVertexArray( VAOs[Triangle2] );
glCreateBuffers( NumBuffers, Buffers2 );
glBindBuffer( GL_ARRAY_BUFFER, Buffers2[Mesh] );
glNamedBufferData( Buffers2[Mesh], sizeof(static_vertices2)+sizeof(infColor_values2) , NULL, GL_STATIC_DRAW);
glNamedBufferSubData( Buffers2[Mesh], 0, sizeof(static_vertices2), static_vertices2);
glNamedBufferSubData( Buffers2[Mesh], sizeof(static_vertices2), sizeof(infColor_values2), infColor_values2);
offset = 0;
glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
offset = sizeof(static_vertices2);
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
glEnableVertexAttribArray( vColor );
change for the render code
void
display( void )
{
static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangle1] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices/2 );
glBindVertexArray( VAOs[Triangle2] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices/2 );
glBindVertexArray(0);
}
I'm trying to render in opengl using shaders, the background colour generates and no error messages appear but the object I'm trying to render doesn't show. I've been trying all day to solve this but have come to nothing. I'm reading vertices and indices in from a .txt file but that doesn't seem to be the problem as all the numbers are exactly what they should be. Here is my init:
void init() {
readFile("pendulum.txt", pVert, pIndices, pCols);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable( GL_DEPTH_TEST );
glClearColor(0.5,0.5,0.5,1.0);
program = InitShader( "aVertexShader64.glsl", "aFragShader63.glsl" );
glUseProgram( program );
modelView = glGetUniformLocation( program, "model_view" );
projection = glGetUniformLocation( program, "projection" );
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize two buffer objects
glGenBuffers( 2, buffers);
//one buffer for the vertexPositions and colours
glBindBuffer( GL_ARRAY_BUFFER, buffers[0]);
glBufferData( GL_ARRAY_BUFFER, numVertexPositionBytes + numVertexColourBytes,NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions );
glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, vertexColours);
//one buffer for the indices
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData( GL_ELEMENT_ARRAY_BUFFER, numVertexIndexBytes,vertexIndices, 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(numVertexPositionBytes) );
}
Main:
int main( int argc, char **argv ){
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize(winWidth, winHeight);
glutCreateWindow( "pendulum" );
glewInit();
init();
//initialiseBoxCoordinates();
//glutTimerFunc(1,timer,0);
glutReshapeFunc(reshape);
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutIdleFunc( idle );
glutMainLoop();
return 0;
}
And Display:
void display( void ) {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
pStack.pushMatrix();
pStack.loadIdentity();
pStack.rotated(theta,0.0,1.0,0.0);
pStack.translated(0.0,0.0,-1.0);
for(int i = 0; i<NumPVerts; i++){
pStack.transformd(&pVert[i*4],&pVertActual[i*4]);
}
glBindVertexArray(lineVao);
glDrawArrays(GL_LINES,0, lineVertSize/3);
glBindVertexArray(pVao);
glBindBuffer(GL_ARRAY_BUFFER, pBuffers[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, numPVertexBytes, pVertActual);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pBuffers[1]);
glDrawElements(GL_TRIANGLES, NumPIndices, GL_UNSIGNED_BYTE, 0);
pStack.popMatrix();
//switch buffers
glutSwapBuffers();
}
After the matrix transformations the vertices are all where they should be and I have used the same matrix class before with no problems so I don't think it's that. I think it has something to do with the shaders but I'm still new to opengl and am really not sure. Here are the vertex shader:
in vec4 vPosition;
in vec4 vColor;
out vec4 color;
uniform mat4 model_view;
uniform mat4 projection;
void main() {
gl_Position = projection*model_view*vPosition/vPosition.w;
color = vColor;
}
And the fragment shader:
in vec4 color;
out vec4 fColor;
void main() {
fColor = color;
}
As far as i can see, your shaders are kinda fine. But you don't use #version tag there, which could lead to some problems, like shader compilation errors.
I don't understand why you have the division vPosition/vPosition.w in your vertex shader. This is still done automatically by opengl pipeline, you don't need to do this.
There are some rucial bits in your sources left out. For example, i don't know what InitShader(...) does, and i don't see any calls to glUniform(..) (i suppose, they are hidden in pStack object?). And i don't see initialization code of some important variables like numVertexPositionBytes, or what BUFFER_OFFSET(numVertexPositionBytes) is supposed even to mean.
I'm just trying to draw a bunch of lines that make up a "cube". I can't for the life of me figure out why this is producing a black screen. The debugger does not break at any point.
I'm sure it's a problem with my pointers, as I'm only decent at them in regular c++ and in OpenGL it gets even worse.
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
int main() {
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
GLuint indices[] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
//glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo);
//glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
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, 0, 0 );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED)) {
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, sizeof(indices), GL_UNSIGNED_INT, indices );
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
EDIT: Full code trying the first answer's recommendation. Still blank.
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#pragma comment( lib, "glfw.lib")
#pragma comment( lib, "opengl32.lib")
#pragma comment( lib, "glew32s.lib")
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void initializeGLFW();
int main() {
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i ) {
vertices[i] /= 2.0f;
}
GLubyte indices[] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
//glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo);
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
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, 0, vertices );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED)) {
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, 24, GL_UNSIGNED_BYTE, indices);
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
void initializeGLFW() {
glfwInit();
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( 800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW );
glfwSetWindowTitle( "OpenGL" );
}
The "default" projection is essentially glOrtho(-1, 1, -1, 1, -1, 1) with the camera at (0,0,0) looking down the -Z axis.
Move the camera back:
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
And make your object smaller:
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i )
{
vertices[i] /= 2.0f;
}
Complete:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <cstdlib>
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void initializeGLFW()
{
glfwInit();
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( 800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW );
glfwSetWindowTitle( "OpenGL" );
}
int main()
{
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] =
{
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i )
{
vertices[i] /= 2.0f;
}
GLuint indices[] =
{
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
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, 0, 0 );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED))
{
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, sizeof(indices), GL_UNSIGNED_INT, indices );
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
I have created a basic shader program to brush up on my openGL GLSL.
on the cpu side i have properly created my shader program .vp and .fp linked properly and error checked
my result when i render is always a black Triangle
Right before i link my program but after i attach both shaders i do this
glBindAttribLocation( program, 0, "vVertexPos" );
glBindAttribLocation( program, 1, "vColor" );
both my position variables and my color variable in the shaders
all of this is just a quick run through so im not worried about ugly code besides the openGL calls and shader setup
struct PosColVertex
{
float pos[3];
float color[4];
};
PosColVertex verts[3];
float vPos1[3] = { 0.5f, 0.0f, -1.0f };
float vPos2[3] = { 0.0f, 1.0f, -1.0f };
float vPos3[3] = { -0.5f, 0.0f, -1.0f };
memcpy( verts[0].pos, vPos1, sizeof(float)*3 );
memcpy( verts[1].pos, vPos2, sizeof(float)*3 );
memcpy( verts[2].pos, vPos3, sizeof(float)*3 );
float vColor1[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
float vColor2[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
float vColor3[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
memcpy( verts[0].color, vColor1, sizeof(float)*4 );
memcpy( verts[1].color, vColor2, sizeof(float)*4 );
memcpy( verts[2].color, vColor3, sizeof(float)*4 );
glGenBuffers( 1, &vboHandle );
glBindBuffer( GL_ARRAY_BUFFER, vboHandle );
glBufferData( GL_ARRAY_BUFFER, sizeof(PosColVertex)*3, verts, GL_DYNAMIC_READ );
for my rendering this is what i do
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//use our shader program
glUseProgram( program );
//set which vertices we will be using
glBindBuffer( GL_ARRAY_BUFFER, vboHandle );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
//specify our vertex attribute
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof( PosColVertex ), (void*)(0) );
//specify our texture attribute
glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, sizeof( PosColVertex ), (void*)(12) );
glPushMatrix();
//draw our rectangle
glDrawArrays( GL_TRIANGLES, 0, 3 );
glPopMatrix();
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 1 );
did i do something wrong with the glVertexAttribPointer calls? i've checked my shader it works and it does change the values since i hard coded values in there before to test it. but im assuming im not telling openGL on the CPU side how to read my verts properly. any help?
tri.vp
#version 330
in vec3 vVertexPos;
void main(void)
{
gl_Position = vec4( vVertexPos.x, vVertexPos.y, vVertexPos.z, 1 );
}
tri.fp
#version 330
out vec4 vFragColor;
in vec4 vColor;
void main(void)
{
vFragColor = vColor;
}
You can't access attributes inside of fragment shaders, only inside of vertex shaders. This makes sense because you are specifying a color for each vertex, and not for each fragment. So, I'd recommend changing your code to read in the color in the vertex shader and smoothly output it to your fragment shader:
Vertex shader:
in vec3 vVertexPos;
in vec4 vColor;
smooth out vec4 fColor;
void main(void)
{
gl_Position = vec4( vVertexPos.x, vVertexPos.y, vVertexPos.z, 1 );
fColor = vColor;
}
Fragment shader:
smooth in vec4 fColor;
out vec4 vFragColor;
void main(void)
{
vFragColor = fColor;
}
I'm working on a 2D engine in C++ at the moment.
I've run into a problem which I seem to believe I've come up against once before, but have since forgotten how I fixed it.
The engine is cross platform ( Win, OSX, Linux ) and to accomplish this I am using GLFW as a base.
When doing the normal texturing thing I end up with this :
As you can see the texturing isn't right ( as the image is supposed to be a simple Image of me ).
Using geDebugger I can confirm that the image being buffered to the GPU is correct, but some how it is ending up as you see in the Image.
I'll include some cuts of relevant code below, but should you want more info feel free to ask.
-Buffer Generation Code
glGenVertexArrays( 1, &_vao );
// Generate Buffers and so on.
glBindVertexArray( _vao );
glGenBuffers( 1, &_vboVertices );
glBindBuffer( GL_ARRAY_BUFFER, _vboVertices );
glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * _numVertices, _vertices, GL_STATIC_DRAW );
glGenBuffers( 1, &_vboTexCoords );
glBindBuffer( GL_ARRAY_BUFFER, _vboTexCoords );
glBufferData( GL_ARRAY_BUFFER, sizeof(GLfloat) * 2 * _numVertices, _texCoords, GL_STATIC_DRAW );
glGenBuffers( 1, &_vboIndices );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, _vboIndices );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * _numIndices, _indices, GL_STATIC_DRAW );
-Render Code
glm::mat4 modelViewProjMatrix = projMatrix * viewMatrix * modelMatrix;
ShaderResource * shader = ShaderManager::GetInstance()->GetShader( _shaderName.c_str() );
TextureResource * texture = TextureManager::GetInstance()->GetTexture( _textureName.c_str() );
shader->BindShader();
// Bind VAO
glBindVertexArray( _vao );
// Bind all VBO's
glBindBuffer( GL_ARRAY_BUFFER, _vboVertices );
GLint posLocation = shader->GetAttribLocation("in_position");
glVertexAttribPointer( posLocation, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
GLint texCoordLocation = shader->GetAttribLocation("in_texCoord");
glVertexAttribPointer( texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, _vboIndices );
// Enable VBO Pointers
glEnableVertexAttribArray( posLocation );
glEnableVertexAttribArray( texCoordLocation );
// Find and assign Uniforms
GLint MVPMatrixLocation = shader->GetUniformLocation("in_MVPMatrix");
GLint colourLocation = shader->GetUniformLocation("in_colour");
GLint textureLocation = shader->GetUniformLocation("texMap");
glUniformMatrix4fv( MVPMatrixLocation, 1, GL_FALSE, glm::value_ptr( modelViewProjMatrix ) );
glUniform4fv( colourLocation, 1, glm::value_ptr( _colour ) );
// Texture Uniform
if( texture != 0 )
{
glActiveTexture( GL_TEXTURE0 );
glUniform1i( textureLocation, 0 );
glBindTexture( GL_TEXTURE_2D, texture->GetTextureId() );
}
glDrawElements( GL_TRIANGLES, _numIndices, GL_UNSIGNED_INT, (void*) 0 );
glDisableVertexAttribArray( posLocation );
glDisableVertexAttribArray( texCoordLocation );
shader->UnbindShader();
glBindVertexArray( 0 );
-Vert Shader
#version 150
in vec3 in_position;
in vec2 in_texCoord;
out vec4 out_colour;
smooth out vec2 out_texCoord;
uniform vec4 in_colour;
uniform mat4 in_MVPMatrix;
void main()
{
out_colour = in_colour;
out_texCoord = in_texCoord;
gl_Position = in_MVPMatrix * vec4( in_position, 1.0 );
}
-Frag Shader
#version 150
in vec4 out_colour;
smooth in vec2 out_texCoord;
out vec4 fragColor;
uniform sampler2D texMap;
void main()
{
vec4 diffuseTexel = texture2D( texMap, out_texCoord );
fragColor = out_colour * diffuseTexel;
}
glVertexAttribPointer( posLocation, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
glVertexAttribPointer( texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
This means that both the positions and texture coordinates come from the same locations in the buffer. That they overlap.
You seem to want them to come from different buffer objects. That means you have to bind a new buffer to GL_ARRAY_BUFFER between your first and second glVertexAttribPointer calls.
// Bind all VBO's
glBindBuffer( GL_ARRAY_BUFFER, _vboVertices );
GLint posLocation = shader->GetAttribLocation("in_position");
glVertexAttribPointer( posLocation, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
GLint texCoordLocation = shader->GetAttribLocation("in_texCoord");
glVertexAttribPointer( texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
VertexAttribPointer for texcoords should be set after binding _vboTexCoord, not _vboVertices.