Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

1

24.08.2008, 18:49

Brauche Hilfe bei Shader (glSlang)

Hallo Leute,

ich hab bsi her noch kein OpenGL Test Programm zum Laufen gebracht das mit der OpenGL Shading Language arbeitet.
Das Grundprinzip von Shadern hab ich glaub ich verstanden.
Könnt ihr mir sagen was an diesem Programm Teil falsch sein könnte?!

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL;

GLhandleARB ProgramObject, VertexShaderObject, FragmentShaderObject;

glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)wglGetProcAddress("glDetachObjectARB");

ProgramObject = glCreateProgramObjectARB();
VertexShaderObject = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
FragmentShaderObject = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

/* "opengl.vert" laden und char* ShaderTextVert[...] füllen */

/* "opengl.frag" laden und char* ShaderTextFrag[...] füllen */

glShaderSourceARB(VertexShaderObject, lines1, ShaderTextVert, NULL);
glShaderSourceARB(FragmentShaderObject, lines2, ShaderTextFrag, NULL);

glCompileShaderARB(VertexShaderObject);
glCompileShaderARB(FragmentShaderObject);

glAttachObjectARB(ProgramObject, VertexShaderObject);
glAttachObjectARB(ProgramObject, FragmentShaderObject);

glDeleteObjectARB(VertexShaderObject);
glDeleteObjectARB(FragmentShaderObject);

glLinkProgramARB(ProgramObject);

Zum Beispiel weiß ich jetzt auch nicht ob, und wenn ja dann welche Funktion, muss in jedem Durchlauf des Prgoramms aufgerufen werden um ein Shader auf ein Objekt zu beziehen??

Danke schon mal :)

2

25.08.2008, 12:54

Also bei dir sieht das reichlihc kompliziert aus, den ganzen Kram am Anfang benutze ich z.B. schonmal nicht.
Außerdem musst du auch nciht unbedingt die Extension namen benutzen, sondern kannst die schönen offiziellen nehmen.

Ich lese zur Zeit folgendes Tutorial und finde es eigentlich ganz ok:
http://www.lighthouse3d.com/opengl/glsl/index.php?intro
Lieber dumm fragen, als dumm bleiben!

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

3

25.08.2008, 13:17

Naja, da gibts ein oder zwei Dinge die du evtl etwas umstrukturieren könntest und einige Teile sind nicht ganz richtig:

Zum einen würde ich, an deiner Stelle, für die Deklarationen den bereitgestellten Header "glext.h" verwenden. Dann brauchst du deine ganze Funktionszeigerdefinition nicht mehr. Einen entsprechenden Link findest du z.B. unter: http://www.opengl.org/registry/

Falls du eine Opengl Version >= 2.0 verwendest brauchst du den ganzen Extensionhaufen gar nicht mehr. Ansonsten musst du, wie du das bereits richtig machst, die Funktionen erstmal 'laden'.

Der grundlegende Ablauf ist bei dir auch richtig. Allerdings könntest du hier- und da ein wenig mehr auf potentielle Fehler achten.

Hier mal ein kleines Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
void LoadSource( const char* file, GLhandleARB handle )
{
    if ( !file )
        return;

    FILE* fp = fopen( file, "rb" );

    if ( !fp )
        return;

    fseek( fp, 0, SEEK_END );
    long len = ftell( fp );
    fseek( fp, 0, SEEK_SET );

    int compiled = 0;
    char* buffer = new char[ len+1 ];
    memset( buffer, 0, len+1 );
    fread( buffer, len, 1, fp );

    // Shader Sourcecode laden

    glShaderSourceARB( handle, 1, ( const GLcharARB** )&buffer, NULL );

    // Shader compilieren

    glCompileShaderARB( handle );

    // Prüfen ob Fehler beim Compilieren auftraten

    glGetObjectParameterivARB( handle, GL_OBJECT_COMPILE_STATUS_ARB, &compiled );

    if  ( !compiled )
        printf( "compile error...\n" );

    delete [] buffer;
    fclose( fp );
}

// ... snip ...


// Vertex Shader laden

g_pVertexShader = glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
LoadSource( "shader.vert", g_pVertexShader );

// Fragment Shader laden

g_pFragmentShader = glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB );
LoadSource( "shader.frac", g_pFragmentShader );

// Programmobjekt erzeugen und jeweils den Vertex- und Fragmentshader

// an das Objekt binden. Zum Schluss noch alles linken

g_pShaderProg = glCreateProgramObjectARB();
glAttachObjectARB( g_pShaderProg, g_pVertexShader );
glAttachObjectARB( g_pShaderProg, g_pFragmentShader );
glLinkProgramARB( g_pShaderProg );

// Prüfen ob fehler beim Linken auftraten

int linked = 0;
glGetObjectParameterivARB( g_pShaderProg, GL_OBJECT_LINK_STATUS_ARB, &linked );

if ( !linked )
    printf( "link error...\n" );


Das Programm musst du, bevor es von OpenGL verwendet wird, erst 'aktivieren'.

C-/C++-Quelltext

1
glUseProgramObjectARB( g_pShaderProg );


Danach kannst du, wie gehabt, deine Szene rendern (ohne die Shader erneut zu initialisieren). Solang du nicht OpenGL explizit[/i] mitteilst, dass du den Shader deaktivieren willst, oder einen anderen Shader verwenden willst, bleibt der Shader aktiv.

Am Schluss, wenn du den/die Shader nicht mehr brauchst, musst du die Resourcen noch frei geben:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
// Erstmal die Shader vom Programmobjekt abkoppeln

glDetachObjectARB( g_pShaderProg, g_pVertexShader );
glDetachObjectARB( g_pShaderProg, g_pFragmentShader );

// Und dann noch schön aufräumen

glDeleteObjectARB( g_pVertexShader );
glDeleteObjectARB( g_pFragmentShader );
glDeleteObjectARB( g_pShaderProg );
@D13_Dreinig

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

4

25.08.2008, 14:11

Ich hab OpenGL 2.1.2 aber wenn ich die Funktionalität von "glext.h" nutzen will - soll heißen wenn ich "glLinkProgram()" ohne ARB aufrufen will - muss ich erst mal GL_GLEXT_PROTOTYPES definieren bevor ich "glext.h" lade, damit in dem Header die Prüfung "#ifdef GL_GLEXT_PROTOTYPES" wahr wird und die Funktionen deklariert werden.
Wie macht ichr das denn?
Und dann weiß ich nicht welche Bibliopthek ich verlinken muss damit Funktionen auch bekannt sind. Sonst meckert mein Compiler nämlich er kennt diese ganzen Funktionen nicht. Nicht glLinkProgram und auch nicht die ARB Varianten?!

Dann noch mal zu dem glUseProgramObjectARB:
Muss ich das immer dann, wenn ich das Objekt zeichnen will auf das der Shader angewändet werden soll, aktivieren und dann wieder deaktivieren?
Wenn ich das einmal am Anfagn des Programms aktiviere seh ich nur die Farbe des glClearColor?!

PS: Danke schon mal für eure bisherige hilfe :)

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

25.08.2008, 14:18

Zitat von »"LukasBanana"«


Dann noch mal zu dem glUseProgramObjectARB:
Muss ich das immer dann, wenn ich das Objekt zeichnen will auf das der Shader angewändet werden soll, aktivieren und dann wieder deaktivieren?
Wenn ich das einmal am Anfagn des Programms aktiviere seh ich nur die Farbe des glClearColor?!


Du aktivierst den Shader immer dann wenn du ihn brauchst. Wenn du die komplette Szene mit einem Shader rendern willst reicht es den Shader einmal zu aktivieren. Wenn du Objekte mit verschiedenen Shadern rendern willst musst du eben, für das jeweilige Objekt, die verschiedenen Shader, vor dem Rendern des Objekts, aktivieren.
@D13_Dreinig

6

25.08.2008, 14:36

Zitat von »"LukasBanana"«

Ich hab OpenGL 2.1.2 aber wenn ich die Funktionalität von "glext.h" nutzen will - soll heißen wenn ich "glLinkProgram()" ohne ARB aufrufen will - muss ich erst mal GL_GLEXT_PROTOTYPES definieren bevor ich "glext.h" lade, damit in dem Header die Prüfung "#ifdef GL_GLEXT_PROTOTYPES" wahr wird und die Funktionen deklariert werden.
Wie macht ichr das denn?

Du solltest bei deiner IDE bei den Projektoptionen globale defines angeben können. Ansonsten sollte auch ein "#define GL_GLEXT_PROTOTYPES" im Quellcode helfen.
Lieber dumm fragen, als dumm bleiben!

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

7

25.08.2008, 14:38

Mhh, vielleicht stimmt ja auch was mit dem Shader nicht, aber eigentlich habe ich die Shader Dateien (opengl.vert und opengl.frag) aus dem IrrlichtEngine Tutorial genommen und da funktioniert es ja auch.

In meinem Programm sehe ich das Objetk nicht, wenn ich den Shader darafu anwenden will :cry:

@Jonathan_Klein: aber welche lib bzw. dll brauche ich für die extensions?

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

8

25.08.2008, 15:06

Zitat von »"LukasBanana"«

Mhh, vielleicht stimmt ja auch was mit dem Shader nicht, aber eigentlich habe ich die Shader Dateien (opengl.vert und opengl.frag) aus dem IrrlichtEngine Tutorial genommen und da funktioniert es ja auch.

In meinem Programm sehe ich das Objetk nicht, wenn ich den Shader darafu anwenden will :cry:


Ich kenn leider sowohl dein Programm, als auch deinen Shader nicht.
@D13_Dreinig

LukasBanana

Alter Hase

  • »LukasBanana« ist der Autor dieses Themas

Beiträge: 1 097

Beruf: Shader Tools Programmer

  • Private Nachricht senden

9

25.08.2008, 15:16

opengl.frag:

Quellcode

1
2
3
4
5
6
7
8
uniform sampler2D myTexture;

void main (void)
{
    vec4 col = texture2D(myTexture, vec2(gl_TexCoord[0]));
    col *= gl_Color;
    gl_FragColor = col * 4.0;
}

Und opengl.vert:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform vec3 mLightPos;
uniform vec4 mLightColor;

void main(void)
{
    gl_Position = mWorldViewProj * gl_Vertex;
    
    vec4 normal = vec4(gl_Normal, 0.0);
    normal = mInvWorld * normal;
    normal = normalize(normal);
    
    vec4 worldpos = gl_Vertex * mTransWorld;
    
    vec4 lightVector = worldpos - vec4(mLightPos,1.0);
    lightVector = normalize(lightVector);
    
    float tmp2 = dot(-lightVector, normal);
    
    vec4 tmp = mLightColor * tmp2;
    gl_FrontColor = gl_BackColor = vec4(tmp.x, tmp.y, tmp.z, 0.0);
    
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

So sollte das Ergebniss aussehen, wie in dem Tutorial:
http://irrlicht.sourceforge.net/images/tutorials/010shot.jpg

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

10

25.08.2008, 15:19

Ich würd erstmal was ganz minimalistisches versuchen. Das macht die Fehlersuche einfacher:

Vertexprogramm:

C-/C++-Quelltext

1
2
3
4
5
void main()
{
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
  gl_FrontColor = gl_Color;
}


Fragmentprogramm:

C-/C++-Quelltext

1
2
3
4
void main()
{
  gl_FragColor = gl_Color;
}
@D13_Dreinig

Werbeanzeige