Wie mit OpenGL anfangen?



  • Hallo.

    Ich hab jetzt einige Zeit mit diversen Libs (zuerst SDL, dann SFML) gearbeitet und paar kleine Spiele programmiert. Jetzt reitzt es mich aber nach OpenGL. Dazu einige Fragen:

    Wo bekomme ich aktuelle Tutorials her? Vor allem für "höhere" OpenGL Versionen, also ab 2.1 und höher (die nehe Tutorials behandeln doch nur 1.1 Grundlagen oder? Ich suche später auch nach Tutorials für die GLSL).

    Und wo bekomme ich entsprechende "Libararys" her? Ich hab auf der offiziellen OpenGL Homepage nachgeschaut, aber da finde ich sowas nicht (ihr wisst schon, ein Pack aus *.h und den lib/dll Dateien dazu, Sourcecode interessiert mich nicht).

    Mit SFML kann man ein Fenster erzeugen und Input etc. behandeln. Unterstützt SFML auch OpenGL in höheren Versionen?

    Und zuletzt: Womit soll ich anfangen? Mit 3.0 wird ja alles über den Haufen geschmissen (gibts dafür überhaupt schon Implementierungen? Soweit ich mich erinnern kann, ist das im Moment noch im Spezifikations-pur Status, oder bin ich da nicht up-to-date), lohnt sich da 2.1 und niedriger noch?

    grüße,
    johnny



  • Es gibt schon neue NeHe Tutorials.
    Du kannst dir auch das neueste Red Book ansehen.

    Alles andere (GLSL...) findest du sehr leicht über Google.



  • Warum ist es nur so schwer, google zu benutzen ...

    http://www.glprogramming.com/red/
    http://www.lighthouse3d.com/opengl/tutorials.shtml
    http://www.glprogramming.com/manpages/opengl-quick-reference-card.pdf

    lohnt sich da 2.1 und niedriger noch?

    Warum nicht ...



  • OpenGL hat keine direkte SDK wie DirectX. Das liegt daran, dass OpenGL nur eine Spezifikation ist. Allerdings ist OpenGL auf Windows nur maximal bis Version 1.5 ohne Treiber verfügbar. Den Rest stellen die Grafikkartenhersteller in Ihren Treibern zur Verfügung. Geladen werden OpenGL-Funktionen oberhalb 1.5 direkt aus der OpenGL.dll mit Hilfe von wglGetProcAdress. Es gibt hierzu allerdings eine Library, die das für Dich erledigt und die ich auch gerne verwende:
    http://glew.sf.net
    Das ist reiner C-Code und für alle OS verfügbar.

    3.0 wird derzeit von ATI und von NVidia in den Treibern unterstützt.
    Hier die VersionStrings aus meinem Programm:

    OpenGL Vendor String: ATI Technologies Inc.
    OpenGL Version: 3.2.9252 Compatibility Profile Context
    OpenGL Renderer: ATI Radeon HD 4800 Series
    OpenGL Shader Version: 1.50

    Der Code dazu:

    void NLWindowGL::dumpInfos()
    {
        char* gl_ven    = (char*)glGetString(GL_VENDOR);
        char* gl_ver    = (char*)glGetString(GL_VERSION);
    	char* gl_render = (char*)glGetString(GL_RENDERER);
    	char* gl_glslang= (char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
        char* glew_ver  = (char*)glewGetString(GLEW_VERSION);
    
    	if ( gl_ven )		{ NLMessage(std::string("OpenGL Vendor String: ") + gl_ven);	  }
    	if ( gl_ver )		{ NLMessage(std::string("OpenGL Version: ") + gl_ver);			  }
    	if ( gl_render  )	{ NLMessage(std::string("OpenGL Renderer: ") + gl_render);		  }
    	if ( gl_glslang )	{ NLMessage(std::string("OpenGL Shader Version: ") + gl_glslang); }
    	if ( glew_ver )		{ NLMessage(std::string("GLew Version: ") + glew_ver);			  }    
    	NLMessage(NLTextureLoader::getInfo());
        NLMessage(ss);
    }
    

    Zu Deiner Frage wie man am besten anfängt.. Lerne erstmal mit der State-Machine von OpenGL umzugehen und dabei ist es erstmal egal ob Du veraltete Features nutzt oder nicht. Der immediate Mode über glBegin() und glEnd() ist veraltet, ja, aber er funktioniert immer noch. Was derzeit standard ist, ist die Vertexes über Arrays zu rendern.
    Beispiel-Code:

    glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
        glVertexPointer(3, GL_FLOAT, 0, &m_vertices[0]);
        glTexCoordPointer(2, GL_FLOAT, 0, &m_texCoords[0]);   
        glColorPointer(4, GL_FLOAT, 0, &m_simple_color[0]);
        glDrawArrays(m_drawmode, 0, 4);
    
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
    

    Nehe hat hierzu auch ein neues Tutorial geschrieben. Der ist sowas wie der Godfather of OpenGL-Tutorials als Tutorials dazu noch nicht so verbreitet waren:
    http://nehe.gamedev.net/wiki/NewLesson2.ashx

    Und wie gesagt kannst Du sowohl mit SDL als auch mit SFML einen OpenGL-Kontext erzeugen. Und mit 3.0 wurde nicht wirklich alles über einen Haufen geworfen, es wurden nur einige alte Sachen als veraltet erklärt. Funktionieren tun sie trotzdem weiterhin. Es liegt an den Herstellern der Grafikkarten dies zu ändern. Wird aber keiner tun, weil sonst eventuell ältere Spiele die derzeit noch laufen gnadenlos abstürzen würden, weil sie die Funktionen nicht aus den DLL laden können.
    HTH.
    rya.



  • 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;
    }
    

Log in to reply