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

MCP

Alter Hase

  • »MCP« ist der Autor dieses Themas

Beiträge: 513

Wohnort: Paderborn

Beruf: Software-Entwickler

  • Private Nachricht senden

1

27.01.2011, 23:17

[OpenGL] Vertex hat keine Farben sondern, wird nur weiß gerendert.

Hallo Leute,

ich dachte mir, ich versuche mich mal ein wenig an OpenGL. Ich hab nix großes vor damit, sondern will lediglich ein paar Erfahrungen sammeln. Dafür will ich eine Klasse schreiben, die mir ein Fenster unter Windows initialisiert und darin etwas rendert. Anfangen wollte ich mit einem Dreieck und den üblichen Bunt gemischten Farben.
Nun ist es so, dass das Dreieck (bzw. zwei Dreiecke) gerendert wird, jedoch ist es nur weiß. Von Farbe keine Spur.

Kann mir vielleicht jemand Hinweise geben, wo ich etwas falsch gemacht habe?
Das Ganze ist ein Win32 Konsolenprojekt (!) in dem ich zur Laufzeit mit der Windows API ein Fenster erstelle. Dabei habe ich mich an einem Tutorial aus der OpenGL Wiki orientiert: Link
Eine weitere Informationsquelle war: Link
Hier die relevanten Codezeilen:

Die Klassendefinition von COpenGL

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
class COpenGL
{
public:
COpenGL();
~COpenGL();
void showWindow();
bool createOpenGLContext();
void prepareScene();
void setData();
void setViewport(int w, int h);
void DrawScene();
void DestroyScene();

private:
std::vector<GLuint> vertexObject;
std::vector<GLuint> vertexBuffer;
GLuint program;
HWND hWnd;
MSG msg;
HDC hDC;
HGLRC hRC;
RECT rect;

protected:
static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
};


Die Methode der Klasse COpenGL, die das Fenster erstellt. Sie holt sich zuerst das Fenster Handle von dem Konsolenfenster und erzeugt dann mit CreateWindow() ein neues Fenster, in welches gerendert wird.

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
void COpenGL::showWindow()
{
HWND hWndConsole = GetConsoleWindow();

HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hWndConsole, GWL_HINSTANCE);

WNDCLASS wc;
wc.hbrBackground =(HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = StaticWndProc;
wc.lpszClassName = L"Game1";
wc.style = CS_OWNDC;
wc.lpszMenuName = NULL;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;

if(!RegisterClass(&wc))
{
    std::cout << "Die Fensterklasse konnte nicht registriert werden." << std::endl;
    return;
}

//hWnd ist ein Attribut der Klasse vom Typ HWND und beinhaltet das Handle zu dem Fenster in welches gerendert wird.
hWnd = CreateWindow(L"Game1", L"Game 1", WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE, 520, 20, 300, 300,
                NULL, NULL, hInstance, this);

hDC = GetDC(hWnd);
if(!hDC)
return;

ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);

//Hier wird der OpenGL Kontext erzeugt, siehe unten...
if(!createOpenGLContext())
{
std::cout << "Fehler beim Initialisieren von OpenGL" << std::endl;
return;
}

GetClientRect(hWnd, &rect);

setData();//Hier werden die Vertexbuffer initialisiert
prepareScene();//Vorbereitungen für die Scene
setViewport(rect.right, rect.bottom);

while(1)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE) 
{ 
if(GetMessage(&msg, NULL, 0, 0)) 
{ 
TranslateMessage(&msg); 
DispatchMessage(&msg); 
}
else
{ 
return ; 
} 
}
//rendern...
DrawScene();
}

if (hRC)
    wglDeleteContext(hRC);
if (hDC)
    ReleaseDC(hWnd, hDC);
hRC = 0;
hDC = 0;

DestroyScene();
}


In dieser Methode erzeuge ich den OpenGL Kontext, damit in dem Fenster gerendert werden kann.

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
59
bool COpenGL::createOpenGLContext()
{
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;//24, wenn der Stencil Buffer 8 Bits bekommt.
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;

int pixelFormat = ChoosePixelFormat(hDC, &pfd);
if(!pixelFormat)
return false;

if(!SetPixelFormat(hDC, pixelFormat, &pfd))
return false;

//Hier wird ein temporärer RenderContext erzeugt. Zum initialisieren und als Fallback.
HGLRC tempRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, tempRC);

GLenum error = glewInit();
if(GLEW_OK != error)
{
MessageBox(NULL, L"Glew konnte nicht initialisiert werden.", L"Error", MB_OK);
}

int attributes[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0};

if(wglewIsSupported("WGL_ARB_create_context") == 1)
{
hRC = wglCreateContextAttribsARB(hDC, 0, attributes);
wglMakeCurrent(0, 0);
wglDeleteContext(tempRC);
wglMakeCurrent(hDC, hRC);
}
else //Fallback: 3.1 wird nicht unterstützt -> Rückfall auf 2.1
{
hRC = tempRC;
}

int OpenGLVersion[2];
glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);

if(!hRC)
return false;

std::cout << "OpenGL wurde erfolreich Initiatlisiert! Version: " << OpenGLVersion[0] << "." << OpenGLVersion[1] << std::endl;

return true;
}


Hier wird der VertexShader und der Fragment Shader geladen.

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
void COpenGL::prepareScene()
{
glClearColor(0.0, 0.0, 0.0, 0.0);

//Shader laden
std::string vertexShaderCode = "#version 140\n"
"in  vec3 in_Position;\n"
"in  vec3 in_Color;\n"
"out vec3 ex_Color;\n"
"void main(void)\n"
"{\n"
"gl_Position = vec4(in_Position, 1.0);\n"
"ex_Color = in_Color;\n}";

std::string fragmentShaderCode = "#version 140\n"
"precision highp float; // needed only for version 1.30\n"
"in  vec3 ex_Color;\n"
"out vec4 out_Color;\n"
"void main(void)\n"
"{\n"
"out_Color = vec4(ex_Color,1.0);\n"
"}\n";

GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

const char* v = vertexShaderCode.c_str();
GLint vlen = vertexShaderCode.length();

glShaderSource(vertexShader, 1, &v, &vlen);

const char* f = fragmentShaderCode.c_str();
GLint flen = fragmentShaderCode.length();

glShaderSource(fragmentShader, 1, &f, &flen);

glCompileShader(vertexShader);
GLint compiled;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
std::cout << "Vertex Shader konnte nicht kompiliert werden!\n";
int infoLogLen = 0;
int charsWritten = 0;
GLchar *infoLog;

glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLen);

if (infoLogLen > 0)
{
infoLog = new GLchar[infoLogLen];
glGetShaderInfoLog(vertexShader,infoLogLen, &charsWritten, infoLog);
std::cout << "Infolog des Vertex Shaders:" << std::endl << infoLog << std::endl;
delete [] infoLog;
}
}

glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
std::cout << "Fragment Shader konnte nicht kompiliert werden!\n";
int infoLogLen = 0;
int charsWritten = 0;
GLchar *infoLog;

glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLen);

if (infoLogLen > 0)
{
infoLog = new GLchar[infoLogLen];
glGetShaderInfoLog(fragmentShader, infoLogLen, &charsWritten, infoLog);
std::cout << "Infolog des Fragment Shaders:" << std::endl << infoLog << std::endl;
delete [] infoLog;
}
}

program = glCreateProgram();
glBindAttribLocation(program, 0, "in_Position");
glBindAttribLocation(program, 0, "in_Color");

glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);

glLinkProgram(program);
glUseProgram(program);
}



In setData werden die Vertexbuffer initialisiert.

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 COpenGL::setData()
{
// First simple object
std::vector<float> vert(9);
std::vector<float> col(9);// color array

//x, y, z
//x: -1 -> 1
//y: 1 -> -1
vert[0] = .5f; vert[1] = .5f; vert[2] = 0.f;//1. Punkt
vert[3] = 0.f; vert[4] = -.5f; vert[5] = 0.f;//2. Punkt
vert[6] = -.5f; vert[7] = .5f; vert[8]= 0.f;//3. Punkt

col[0] = 1.f; col[1] = 0.0f; col[2] = 0.0f;
col[3] = 0.0f; col[4] = 1.0f; col[5] = 0.0f;
col[6] = 0.0f; col[7] = 0.0f; col[8] = 1.0f;

// Second simple object
std::vector<float> vert2(9);// vertex array

vert2[0] = 0.5f; vert2[1] = -.5f; vert2[2] = 0.f;//1. Punkt
vert2[3] = 0.f; vert2[4] = -.8f; vert2[5] = 0.f;//2. Punkt
vert2[6] = -.5f; vert2[7] = -.5f; vert2[8]= 0.f;//3. Punkt

// Two VAOs allocation
//vertexArray
vertexObject.resize(2);
glGenVertexArrays(2, &vertexObject[0]);

// First VAO setup
glBindVertexArray(vertexObject[0]);

vertexBuffer.resize(3);
glGenBuffers(2, &vertexBuffer[0]);

//Let's go
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), &vert[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(0);

//Color
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), &col[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);

// Second VAO setup
glBindVertexArray(vertexObject[1]);
glGenBuffers(1, &vertexBuffer[2]);

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), &vert2[0], GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
glEnableVertexAttribArray(0);

glBindVertexArray(0);
}


Und zum Schluss die Methode in der der Rendervorgang stattfindent

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void COpenGL::DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT);

glBindVertexArray(vertexObject[0]);// select first VAO
glDrawArrays(GL_TRIANGLES, 0, 3);// draw first object

glBindVertexArray(vertexObject[1]);// select second VAO
glVertexAttrib3f((GLuint)1, 1.0, 0.0, 0.0); // set constant color attribute
glDrawArrays(GL_TRIANGLES, 0, 3);// draw second object

glBindVertexArray(0);

SwapBuffers(hDC);
}


Das Design des Klassenaufbaus ist noch nicht ganz final, es ist eben noch WIP.
Ich hoffe, dass es nicht zu viel Code ist und verständlich ist. Wenn ihr noch Fragen habt, immer her damit.

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

2

28.01.2011, 09:07

Howdi, auf die schnelle habe ich nur das hier gesehen:

glBindAttribLocation(program, 0, "in_Position");
glBindAttribLocation(program, 0, "in_Color");

hier scheintst du Aliasing zu benutzen, also ein und das selbe Attribut unter verschiedenen Namen zu binden. Deine Farbwerte werden damit auch keinem Attribut zugewiesen.


Vom Rest des Codes her ist beim ersten drüber schauen alles soweit ok.

MCP

Alter Hase

  • »MCP« ist der Autor dieses Themas

Beiträge: 513

Wohnort: Paderborn

Beruf: Software-Entwickler

  • Private Nachricht senden

3

28.01.2011, 18:07

In der Tat! Es war wirklich nur dieser Fehler, jetzt wirf alles wie erwartet gerendert.
Manchmal sieht man den Wald vor lauter Bäumen nicht. ^^ Ich danke (D/G)ir. ^^

Werbeanzeige