问题
in this code i want to draw a simple triangle on a blue background using openGL however when i compile and run the code only a window with the blue background appears (without the white triangle that is supposed to be drawn), iam using Xcode
my code
#include <iostream>
#include <string>
#include <GLUT/glut.h>
#include <OpenGL/gl3.h>
#include <fstream>
using namespace std;
// VAO & VBO objects
GLuint VBO;
GLuint VAO;
void display();
// vertex Data (position)
float vertex[] = {-1.0, 0.0 , 1.0,
0.0, 1.0 , 0.0,
0.0, 0.0 , 0.0 };
GLuint Program;
GLuint Vshader;
GLuint Fshader;
// main program
int main (int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(1000, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("My First GLUT/OpenGL Window");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
// main display function
void display()
{
// reading the vertex shader
fstream VertexS;
VertexS.open("/Users/hawbashali/Desktop/Project X/BwlbWl/BwlbWl/vertexShader");
if(VertexS.good() == false)
cout << "Error openning the file \n";
if(VertexS.bad() == true)
cout << "Read/writing error on i/o operation \n";
if (VertexS.fail() == true)
cout <<"Logical error on i/o operation \n";
VertexS.seekg(0,ios::end);
int size = (int)VertexS.tellg();
VertexS.clear();
VertexS.seekg(0,ios::beg);
char* vBuffer = new (nothrow) char[size];
VertexS.read(vBuffer,size);
VertexS.close();
// reading fragment shader
fstream FragS;
FragS.open("/Users/hawbashali/Desktop/Project X/BwlbWl/BwlbWl/fragmentShader");
if(FragS.good() == false)
cout << "Error openning the file \n";
if(FragS.bad() == true)
cout << "Read/writing error on i/o operation \n";
if (FragS.fail() == true)
cout <<"Logical error on i/o operation \n";
FragS.seekg(0,ios::end);
int size2 = (int)FragS.tellg();
FragS.clear();
FragS.seekg(0,ios::beg);
char* fBuffer = new (nothrow) char[size2];
FragS.read(fBuffer,size2);
FragS.close();
// creating shaders
Vshader = glCreateShader(GL_VERTEX_SHADER);
Fshader = glCreateShader(GL_FRAGMENT_SHADER);
GLint x = size;
GLint y = size2;
glShaderSource(Vshader, 1,(const char**)&vBuffer, &x);
glShaderSource(Fshader, 1, (const char**)&fBuffer, &y);
glCompileShader(Vshader);
glCompileShader(Fshader);
Program = glCreateProgram();
glAttachShader(Program, Vshader);
glAttachShader(Program, Fshader);
glLinkProgram(Program);
glUseProgram(Program);
glClearColor(0, 0, 1,1);
glClear(GL_COLOR_BUFFER_BIT);
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER,9 *sizeof(vertex),vertex, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3,GL_FLOAT, GL_TRUE, 0, 0);
// Drawing the triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
glDeleteShader(Vshader);
glDeleteShader(Fshader);
delete [] vBuffer;
delete [] fBuffer;
};
Vertex shader:
#version 320 core
layout(location = 0) in vec4 vPosition;
void
main()
{
gl_Position = vPosition;
}
Fragment Shader
#version 320 core
out vec4 fColor;
void
main()
{
fColor = vec4(0.0, 0.0, 1.0, 1.0);
}
回答1:
glClearColor(0, 0, 1,1);
...
fColor = vec4(0.0, 0.0, 1.0, 1.0);
You're trying to draw a blue triangle on top of a blue background. You'll have to dial up your contrast pretty high to see that :)
Make one of them a different color, like red.
You're also:
- Missing a VAO
- Not requesting a Core context
- Using #version 320 core instead of #version 150 core
Try this:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vector>
#include <iostream>
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
150 core,
layout(location = 0) in vec4 vPosition;
void
main()
{
gl_Position = vPosition;
}
);
const char* frag = GLSL
(
150 core,
out vec4 fColor;
void
main()
{
fColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
// VAO & VBO objects
GLuint VAO;
GLuint VBO;
GLuint prog;
void init()
{
// vertex Data (position)
float vertex[] = { -1.0, -1.0 , 0.0,
1.0, -1.0 , 0.0,
0.0, 1.0 , 0.0 };
glGenVertexArrays( 1, &VAO );
glBindVertexArray( VAO );
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(vertex), vertex, GL_STATIC_DRAW);
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
glEnableVertexAttribArray(0);
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );
}
void display()
{
glClearColor(0, 0, 1,1);
glClear(GL_COLOR_BUFFER_BIT);
// Drawing the triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize(1000, 400);
glutInitWindowPosition(100, 100);
glutInitContextVersion(3, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("My First GLUT/OpenGL Window");
glewExperimental = GL_TRUE;
if( GLEW_OK != glewInit() )
return -1;
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
EDIT: Ported to GL 2.1:
#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
#include <iostream>
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
120,
attribute vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
);
const char* frag = GLSL
(
120,
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
// VBO objects
GLuint VBO;
GLuint prog;
void init()
{
// vertex Data (position)
float vertex[] = { -1.0, -1.0 , 0.0,
1.0, -1.0 , 0.0,
0.0, 1.0 , 0.0 };
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(vertex), vertex, GL_STATIC_DRAW);
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
int posLoc = glGetAttribLocation( prog, "vPosition" );
glEnableVertexAttribArray( posLoc );
glVertexAttribPointer( posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0 );
}
void display()
{
glClearColor(0, 0, 1,1);
glClear(GL_COLOR_BUFFER_BIT);
// Drawing the triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize(1000, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("My First GLUT/OpenGL Window");
if( GLEW_OK != glewInit() )
return -1;
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
回答2:
You have provided invalid buffer size in the following line:
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(vertex), vertex, GL_STATIC_DRAW);
Because sizeof(vertex)
should return the total size of the array (e.g 36) not the underlying type, thus no need to multiply by 9. If you still want to use multiplication try following:
9 * sizeof(float)
I have to write this down... You should separate your initialization and draw cycle like in genpfault's answer.
来源:https://stackoverflow.com/questions/17602130/cant-draw-triangle-using-opengl