Ich versuche, einen 3D-Würfel mit VBO/VAOs texturieren. Allerdings habe ich nur 4/6 Flächen auf dem Würfel richtig texturiert. Ich habe mehrere Lösungen versucht (von der Definition der Scheitelpunkte, bis zum Versuch Cubemapping - die bei Verwendung einer Lösung von einem Dozenten führt nur zum vollständigen Verschwinden des Würfels aus)OpenGL Cube ist nicht richtig texturieren
Zunächst konnte ich die Front richtig texturieren, Rücken-, Ober- und Unterseite. Aber nach ein paar Stunden, in denen ich mit den Koordinaten rumgespielt habe, habe ich es nicht geschafft, die vorderen, hinteren, linken und rechten Flächen zu texturieren (aber nicht oben oder unten).
Wenn mir jemand helfen könnte (und freundlich zu erklären, wie Textur coords tatsächlich funktionieren - ich die Idee, auf einem 2D-Quad, aber nicht auf einem 3D-VBO - oder sogar eine gute Qualität Tutorial besser etc :))
Unten ist der Code;
VBO Einstellungen
// Per-Vertex-Positionsvektoren
static float pyramidVertices[] =
{
//Front
0.0f, 0.0f, 0.0f, 1.0f, //BtmLeft
1.0f, 0.0f, 0.0f, 1.0f, //BtmRight
1.0f, 1.0f, 0.0f, 1.0f, //TopRight
0.0f, 1.0f, 0.0f, 1.0f, //TopLeft
//Back
0.0f, 1.0f, -1.0f, 1.0f, //TopLeft
1.0f, 1.0f, -1.0f, 1.0f, //TopRight
1.0f, 0.0f, -1.0f, 1.0f, //BottomRight
0.0f, 0.0f, -1.0f, 1.0f //BottomLeft
};
#pragma region Pyramid Data
// Per-vertex colours (RGBA) floating point values
static float pyramidColours[32] =
{
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f
};
// 5 faces each with 3 vertices (each face forms a triangle)
static unsigned short pyramidVertexIndices[] =
{
//Front
0, 1, 2,
2, 3, 0,
//Left
0, 3, 7,
7, 3, 4,
//Back
4, 5, 6,
6, 7, 4,
//Top
4, 3, 5,
5, 3, 2,
//Right
2, 1, 5,
5, 1, 6,
//Bottom
6, 1, 7,
7, 1, 0
};
#pragma endregion
static float pyramidTexCoordArray[] =
{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
Initialization
void init(void) {
// Request an OpenGL 4.3 context with the Compatibility profile
glutInitContextVersion(4, 3);
glutInitContextProfile(GLUT_COMPATIBILITY_PROFILE);
// Setup OpenGL Display mode - include MSAA x4
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE);
[...]
[...]
[...]
texturedQuad = new CGTexturedQuad(wstring(L"Common\\Resources\\Textures\\bumblebee.png"));
pyramidTexture = TextureLoader::fiLoadTexture(wstring(L"Common\\Resources\\Textures\\VBO\\sandstone.png"));
exampleModel = new CGModel();
importGSF(L"Common\\Resources\\Models\\dropship.gsf", exampleModel);
// Setup VAO for pyramid object
glGenVertexArrays(1, &pyramidVAO);
glBindVertexArray(pyramidVAO);
// Setup VBO for vertex position data
glGenBuffers(1, &pyramidVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, pyramidVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidVertices), pyramidVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0); // attribute 0 gets data from bound VBO (so assign vertex position buffer to attribute 0)
// Setup VBO for vertex colour data
glGenBuffers(1, &pyramidColourBuffer);
glBindBuffer(GL_ARRAY_BUFFER, pyramidColourBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidColours), pyramidColours, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, 0, (const GLvoid*)0); // attribute 1 gets colour data
glGenBuffers(1, &pyramidTexCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, pyramidTexCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidTexCoordArray), pyramidTexCoordArray, GL_STATIC_DRAW);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
// Enable vertex position and colour attribute arrays
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(3);
// Setup VBO for face index array
glGenBuffers(1, &pyramidIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pyramidIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pyramidVertexIndices), pyramidVertexIndices, GL_STATIC_DRAW);
// Unbind pyramid VAO (or bind another VAO for another object/effect)
// If we didn't do this, we may alter the bindings created above.
glBindVertexArray(0);
glEnable(GL_NORMALIZE); // If we scale objects, ensure normal vectors are re-normalised to length 1.0 to keep lighting calculations correct (see lecture notes)
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Best colour interpolation results
// Setup GL_LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); // Setup ambient light
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); // Setup diffuse light
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular); // Setup specular light
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, ca);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, la);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, qa);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 15.0f);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0.0);
// OpenGL provides a global ambient light component - we don't want this so set to zero
GLfloat global_ambient[] = { 0.15f, 0.15f, 0.15f, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
//
// Load the shader we'll use for the pyramid object
//
err = ShaderLoader::createShaderProgram(string("Common\\Resources\\Shaders\\basic_texture.vs"), string("Common\\Resources\\Shaders\\basic_texture.fs"), &basicShader);
}
Anzeige Funktion
void display(void) {
// Clear the screen
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set viewport to the client area of the current window
glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
// Get view-projection transform as a GUMatrix4
GUMatrix4 T = mainCamera->projectionTransform() * mainCamera->viewTransform();
if (principleAxes)
principleAxes->render(T);
if (texturedQuad)
texturedQuad->render(T * GUMatrix4::translationMatrix(0.5f, 0.5f, 0.0f));
// Fixed function rendering (Compatability profile only) - use this since CGImport is written against OpenGL 2.1
glUseProgram(0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMultMatrixf((const float*)mainCamera->projectionTransform().M);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMultMatrixf((const float*)mainCamera->viewTransform().M);
glMultMatrixf((const float*)GUMatrix4::translationMatrix(0.0f, -0.15f, 0.0f).M);
glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT, GL_FILL);
if (exampleModel)
exampleModel->renderTexturedModel();
glDisable(GL_TEXTURE_2D);
//Define position and direction (so appear at fixed point in scene)
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
// enable texturing
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//
// Pyramid VBO rendering
//
// Use basic shader for rendering pyramid (we'll look at this in more detail next week)
glUseProgram(basicShader);
static GLint mvpLocationPyramid = glGetUniformLocation(basicShader, "mvpMatrix");
glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(T.M));
GUMatrix4 pyramidModelTransform = GUMatrix4::translationMatrix(-0.0f, 0.0f, 0.0f) * GUMatrix4::scaleMatrix(2.0f, 2.0f, 2.0f);
GUMatrix4 mvpPyramid = T * pyramidModelTransform;
glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(mvpPyramid.M));
// Bind VAO that contains all relevant pyramid VBO buffer and attribute pointer bindings
glBindVertexArray(pyramidVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, pyramidTexture);
// Draw pyramid
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (const GLvoid*)0);
// Unbind pyramid VAO (or bind another VAO)
glBindVertexArray(0);
glutSwapBuffers();
}
Fragment Shader
#version 330
uniform sampler2D texture;
in vec2 texCoord;
layout (location=0) out vec4 fragColour;
void main(void) {
vec4 texColor = texture2D(texture, texCoord);
fragColour = texColor;
}
Vertex Shader
#version 330
uniform mat4 mvpMatrix;
layout (location=0) in vec4 vertexPos;
layout (location=3) in vec2 vertexTexCoord;
out vec2 texCoord;
void main(void) {
mat4 M;
M[0] = vec4(1.0);
ivec2 a = ivec2(1, 2);
//vec3 b = vec3(2.0, 4.0, 1.0) + a;
texCoord = vertexTexCoord;
gl_Position = mvpMatrix * vertexPos;
}
CUBE ENTSTEHEN (ignorieren die grauen Bits, es ist nur das 3D-Modell importiert "dropship.gsf")
Vielen Dank! Ich habe buchstäblich angefangen, daran zu arbeiten, wie du es erwähnst! Ich werde dich wissen lassen, wie es läuft. Ich entschuldige mich für die Benennung, mein endgültiges Ziel ist es, eine Pyramide nicht zu einem Würfel zu machen, sondern Probleme mit der Pyramide, so dass Gedankenwürfel einfacher wäre, also habe ich vorübergehend einen Würfel gemacht (zu dem Zeitpunkt, als es funktionierte) verwandle es in eine Pyramide - aber ich überspringe diese Stufe jetzt und gehe direkt auf die Pyramide. Nochmals vielen Dank!) – NeoKuro
Etwas, das Sie auch (später) betrachten können, ist, alle Attribute in ein verschachteltes Array zu setzen - so haben Sie etwas wie 'float VertexData [] [8] = {..., {x, y, z, r, g, b, u, v}, ...};'. Das bedeutet, dass Sie nur einen Vertex-Puffer anstelle von drei benötigen und das Kopieren und Einfügen von Vertex-Daten in Ihrem Quellcode erleichtern kann. Alles, was Sie tun müssen, ist die letzten beiden Parameter von 'glVertexAttribPointer' zu ändern, damit es funktioniert. –
Ein Geometrieshader würde auch funktionieren, dies wäre eine gute (einfache) Anwendung, um sie zu lernen. –