O
Ich hole mal den Thread wieder hoch. Nicht weil ich ne Frage hab, sondern weil ich ne Antwort geben möchte. Leider hat sich ja das OpenGl Grundproblem nicht geändert - es ist einfach unglaublich schwierig, aktuelle Tutorials oder Einstiege zu finden. Die neuen Nehe-Tutorials sind auch deprecated, das Redbook kann man leider fast komplett wegwerfen, weil Shader nur mal am Rand erwähnt werden - aber nun in OpenGL zentral sind. Das zieht sich halt komplett durch alle Tutorials durch.
Deswegen hab ich mal festgehalten, welche Tutorials scheinbar im aktuellen OpenGL gültig sind. Eigentlich sind es nur zwei, und die scheinen sogar mit opengl 3.2 core zu laufen:
1. Das OpenGL Wiki
http://www.opengl.org/wiki/Tutorial2:_VAOs,_VBOs,_Vertex_and_Fragment_Shaders_%28C_/_SDL%29
2. Ein Tutorial das hier in einem anderen, älteren Thread verlinkt wurde:
http://sites.google.com/site/opengltutorialsbyaks/introduction-to-opengl-3-2---tutorial-01
und meine Version, die ich auf Basis von SFML zusammen gebastelt hab. Das ist echt Frickelarbeit. 160 Zeilen Code, nur für ein Dreieck? Ich bin bestrebt zu glauben, dass das doch viel einfacher gehen sollte.
En bissl kommentiert, aber das ist so natürlich noch nicht schön. Die Funktionen sind fast nur zum Code-sparen drin. Programm sollte einfach ausführbar sein, wenn gegen GL, GLEW und SFML gelinkt wird. Verbesserungen sind gerne gesehen.
#include <SFML/Graphics.hpp>//for window handling
#include <GL/glew.h>
#include <iostream>
//The indices we use as stream names in the VAO
const unsigned VertexIndex=0;
const unsigned ColorIndex=1;
//just creates a vertex- or pixelshader from sourcecode.
unsigned createShader(unsigned type,char const** source,size_t linesOfCode)
{
unsigned shader=glCreateShader(type);
glShaderSource(shader,linesOfCode,source,NULL);
glCompileShader(shader);
return shader;
}
//this function creates a new vbo, and binds it to a previously activated vao,
//fills it with the vertex data and sets the streamindex.
unsigned createVBOforVAO(unsigned indexInVAO,size_t size,size_t floatsPerVertex,float* data)
{
//create vbo
unsigned int vbo;
glGenBuffers(1,&vbo);
//bind it to the vao
glBindBuffer(GL_ARRAY_BUFFER,vbo);
//fill it with data
glBufferData(GL_ARRAY_BUFFER,size*sizeof(float),data,GL_STATIC_DRAW);
//define the vertex stream
glVertexAttribPointer(indexInVAO,floatsPerVertex,GL_FLOAT,false,0,0);
//set the streamnumber of this vbo
glEnableVertexAttribArray(indexInVAO);
return vbo;
}
int main()
{
//set the opengl Version we want to use
sf::ContextSettings settings;
settings.MajorVersion=3;
settings.MinorVersion=1;//2 is not supported by glew on my machine :( -but feel free to try it!
// Create the window
sf::Window window(sf::VideoMode(800, 600), "SFML window",sf::Style::Default,settings);
//Print and Test the received OpenGL Version
settings=window.GetSettings();
std::cout<<"Used OpenGl Version: "<<settings.MajorVersion<<"."<<settings.MinorVersion<<std::endl;
if(settings.MajorVersion<3)//3 not supported?
{
std::cerr<<"OpenGl 3.0 and higher needed";
return EXIT_FAILURE;
}
glewInit();
if (!GLEW_ARB_vertex_array_object)//nearly all graphic cards should support VAOs
{
std::cerr << "ARB_vertex_array_object not available." << std::endl;
return EXIT_FAILURE;
}
//
//Vertex Data - a simple triangle which turns out not to be as simple to draw
//
float colors[] =
{
0.0, 0.0, 1.0, 1.0,
0.0, 1.0, 0.0, 1.0,
1.0, 0.0, 0.0, 1.0
};
float vertices[] =//only 2D Data
{
0.8, -0.8,
-0.8, -0.8,
0.0, 0.8,
};
//next we will define two VBOs, one for color, one for position,
//fill them with data and bind them to an VAO
//a VBO is something like an array on the graphics card
//a VAO is an array of VBOs which adds the information, how the
//graphics card should use a VBO during Rendering
//create the VAO and tell GL to bind it
unsigned int vao;
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);
//create VBOs and bind them to the VAO
unsigned int vertexVBO=createVBOforVAO(VertexIndex,6,2,vertices);
unsigned int colorVBO=createVBOforVAO(ColorIndex,12,4,colors);
//
//Setting up the Shader Units
//
//First the sources for 2 simple Shaders
//to see the effect of the shader, the triangle is scaled along the x-Axis with factor 0.5 - remove it for extra boringness :)
char const* vertexShaderSource[]=
{
"#version 150\n",//linebreak here seems to be mandatory.
"in vec2 vertex;",
"in vec4 color;",
"out vec4 frontColor;",
"void main()",
"{",
" frontColor = color;",
" gl_Position = vec4(0.5*vertex.x,vertex.y,0.0,1.0);",
"}"
};
//the fragment- or pixelshader just pipes its input through. How creative!
char const* fragmentShaderSource[]=
{
"#version 150\n",
"precision highp float;",
"in vec4 frontColor;",
"void main()",
"{",
" gl_FragColor = frontColor;",
"}"
};
//compile shaders
unsigned vertex=createShader(GL_VERTEX_SHADER,vertexShaderSource,sizeof(vertexShaderSource)/sizeof(char const**));
unsigned fragment=createShader(GL_FRAGMENT_SHADER,fragmentShaderSource,sizeof(fragmentShaderSource)/sizeof(char const**));
//create shaderProgram and tell it to use our shaders
unsigned program=glCreateProgram();
glAttachShader(program,vertex);
glAttachShader(program,fragment);
//now tell the shaderprogram, how it should interpret the datastreams of our VAO
glBindAttribLocation(program,VertexIndex,"vertex");
glBindAttribLocation(program,ColorIndex,"color");
//now link it
glLinkProgram(program);
//finally, use the shader
glUseProgram(program);
// Start the program loop
while (window.IsOpened())
{
// Process events
sf::Event event;
while (window.GetEvent(event))
{
// Close window -> exit
if (event.Type == sf::Event::Closed)
window.Close();
}
window.SetActive();
// Clear screen
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
//draw our incredible triangle
glDrawArrays(GL_TRIANGLES,0,3);
// Update the window
window.Display();
}
//shutdown:
//free all our resources
glUseProgram(0);
glDeleteProgram(program);
glDeleteShader(vertex);
glDeleteShader(fragment);
glDeleteBuffers(1,&colorVBO);
glDeleteBuffers(1,&vertexVBO);
glDeleteVertexArrays(1,&vao);
return EXIT_SUCCESS;
}