导致问题的纹理
Posted
技术标签:
【中文标题】导致问题的纹理【英文标题】:Textures causing problems 【发布时间】:2020-08-14 07:53:06 【问题描述】:我正在尝试在 OpenGL 中制作一个表格并将纹理放置到表格上。当我使用 OpenGL 颜色而不是纹理创建表格时,它工作得很好。但是,当我添加纹理代码时,一切都崩溃了。现在这张桌子看起来就像一张被压成球的纸。看起来程序不明白顶点应该去哪里?
这是我写的代码:
// Header Inclusions
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// SOIL Image loader Inclusion
#include "SOIL2/SOIL2.h"
using namespace std; // Standard namespace
#define WINDOW_TITLE "Zane's CameraOrbit" // Window title Macro
// Shader program Macro
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif
// Variable declarations for shader, window size initialization, buffer and array objects
GLint shaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, VAO, texture;
GLfloat degrees = glm::radians(-45.0f); // Converts float to degrees
GLfloat cameraSpeed = 0.0005f; // Movement speed per frame
GLchar currentKey; // will store key pressed
bool proj = true;
GLfloat lastMouseX = 400, lastMouseY = 300; // Locks mouse cursor at the center of the screen
GLfloat mouseXOffset, mouseYOffset, yaw = 0.0f, pitch = 0.0f; // mouse offset, yaw, and pitch variables
GLfloat sensitivity = 0.005f; // Used for mouse / camera rotation sensitivity
bool mouseDetected = true; // Initially true when mouse movement is detected
// Global vector declarations
glm::vec3 cameraPosition = glm::vec3(0.0f, 0.0f, 0.0f); // Initial camera position. Placed 5 units in Z
glm::vec3 CameraUpY = glm::vec3(0.0f, 1.0f, 0.0f); // Temporary y unit vector
glm::vec3 CameraForwardZ = glm::vec3(0.0f, 0.0f, -1.0f); // Temporary Z unit vector
glm::vec3 front; // Temporary Z unit vector for mouse
// Function prototypes
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void UGenerateTexture(void);
void UKeyboard(unsigned char key, int x, int y);
void UKeyReleased(unsigned char key, int x, int y);
void UMouseMove(int x, int y);
// Vertex Shader Source Code
const GLchar * vertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout (location = 2) in vec2 textureCoordinate;
out vec2 mobileTextureCoordinate;
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates
mobileTextureCoordinate = vec2(textureCoordinate.x, 1.0f - textureCoordinate.y); // flips the texture horizontal
);
// Fragment Shader Source Code
const GLchar * fragmentShaderSource = GLSL(330,
in vec2 mobileTextureCoordinate;
out vec4 gpuTexture; // Variable to pass color data to the GPU
uniform sampler2D uTexture; // Useful when working with multiple textures
void main()
gpuTexture = texture(uTexture, mobileTextureCoordinate);
);
// Main program
int main(int argc, char* argv[])
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
UCreateShader();
UCreateBuffers();
UGenerateTexture();
// Use the Shader program
glUseProgram(shaderProgram);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color
glutDisplayFunc(URenderGraphics);
glutKeyboardFunc(UKeyboard);
glutKeyboardUpFunc(UKeyReleased);
glutPassiveMotionFunc(UMouseMove); // Detects mouse movement
glutMainLoop();
// Destroys Buffer objects once used
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
return 0;
// Resizes the window
void UResizeWindow(int w, int h)
WindowWidth = w;
WindowHeight = h;
glViewport(0, 0, WindowWidth, WindowHeight);
// Renders graphics
void URenderGraphics(void)
glEnable(GL_DEPTH_TEST); // Enable z-depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen
glBindVertexArray(VAO); // Activates the vertex array object before rednering and transforming them
CameraForwardZ = front; // Replaces camera forward vector with Radians normalized as unit vector
//Transforms the object
glm::mat4 model;
model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f)); // Place the object at the center of the viewport
model = glm::rotate(model, 45.0f, glm::vec3(0.0, 1.0f, 0.0f)); // Rotate the object 45 degrees on the X
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); // Increase the object size by a scale of 2
// Transforms the camera THIS DIFFERS FROM TUTORIAL
glm::mat4 view;
view = glm::lookAt(CameraForwardZ, cameraPosition, CameraUpY);
// Creates a perspective projection THIS DIFFERS FROM TUTORIAL
glm::mat4 projection;
if(proj)
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
else
projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);
// Retrieves and passes transform matrices to the shader program
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projLoc = glGetUniformLocation(shaderProgram, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glutPostRedisplay();
glBindTexture(GL_TEXTURE_2D, texture);
// Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, 156);
glBindVertexArray(0); // Deactivate the Vertex Array Object
glutSwapBuffers(); // Flips the back buffer with the front buffer every frame.
// Creates the Shader program
void UCreateShader()
// Vertex shader
GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the Vertex shader
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Attaches the Vertex shader to the source code
glCompileShader(vertexShader); // Compiles the Vertex shader
// Fragment shader
GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the Fragment shader
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); // Attaches the fragment shader to the source code
glCompileShader(fragmentShader); // Compiles the fragment shader
//Shader program
shaderProgram = glCreateProgram(); // Creates the Shader program and returns an id
glAttachShader(shaderProgram, vertexShader); // Attach Vertex shader to the shader program
glAttachShader(shaderProgram, fragmentShader);; // Attach Fragment shader to the Shader program
glLinkProgram(shaderProgram); // Link Vertex and Fragment shaders to Shader program
// Delete the Veretx and Fragment shaders once linked
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
void UCreateBuffers()
GLfloat vertices[] =
//Positions //Color
//Back
-0.80f, -0.5f, -1.0f, 0.0f, 0.0f,
0.80f, -0.5f, -1.0f, 1.0f, 0.0f,
0.80f, 0.10f, -1.0f, 1.0f, 1.0f,
0.80f, 0.10f, -1.0f, 1.0f, 1.0f,
-0.80f, 0.10f, -1.0f, 0.0f, 1.0f,
-0.80f, -0.5f, -1.0f, 0.0f, 0.0f,
//Front
-0.80f, -0.5f, 1.0f, 0.0f, 0.0f,
0.80f, -0.5f, 1.0f, 1.0f, 0.0f,
0.80f, 0.10f, 1.0f, 1.0f, 1.0f,
0.80f, 0.10f, 1.0f, 1.0f, 1.0f,
-0.80f, 0.10f, 1.0f, 0.0f, 1.0f,
-0.80f, -0.5f, 1.0f, 0.0f, 0.0f,
//Left side
-0.80f, 0.10f, 1.0f, 1.0f, 0.0f,
-0.80f, 0.10f, -1.0f, 1.0f, 1.0f,
-0.80f, -0.5f, -1.0f, 0.0f, 1.0f,
-0.80f, -0.5f, -1.0f, 0.0f, 1.0f,
-0.80f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.80f, 0.10f, 1.0f, 1.0f, 0.0f,
//Right side
0.80f, 0.10f, 1.0f, 1.0f, 0.0f,
0.80f, 0.10f, -1.0f, 1.0f, 1.0f,
0.80f, -0.5f, -1.0f, 0.0f, 1.0f,
0.80f, -0.5f, -1.0f, 0.0f, 1.0f,
0.80f, -0.5f, 1.0f, 0.0f, 0.0f,
0.80f, 0.10f, 1.0f, 1.0f, 0.0f,
//Bottom
-0.80f, -0.5f, -1.0f, 0.0f, 1.0f,
0.80f, -0.5f, -1.0f, 1.0f, 1.0f,
0.80f, -0.5f, 1.0f, 1.0f, 0.0f,
0.80f, -0.5f, 1.0f, 1.0f, 0.0f,
-0.80f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.80f, -0.5f, -1.0f, 0.0f, 1.0f,
//Top
-0.80f, 0.10f, -1.0f, 0.0f, 1.0f,
0.80f, 0.10f, -1.0f, 1.0f, 1.0f,
0.80f, 0.10f, 1.0f, 1.0f, 0.0f,
0.80f, 0.10f, 1.0f, 1.0f, 0.0f,
-0.80f, 0.10f, 1.0f, 0.0f, 0.0f,
-0.80f, 0.10f, -1.0f, 0.0f, 1.0f,
/*BOTTOM LEFT LEG(1)*/
// bottom left leg(1) left
-0.60f, -0.5f, -0.80f, 1.0f, 0.0f,
-0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
-0.80f, -0.80f, -0.60f, 0.0f, 1.0f,
-0.80f, -0.80f, -0.60f, 0.0f, 1.0f,
-0.60f, -0.5f, -0.60f, 0.0f, 0.0f,
-0.60f, -0.5f, -0.80f, 1.0f, 0.0f,
// bottom left leg(1) front
-0.60f, -0.5f, -0.60f, 0.0f, 0.0f,
-0.80f, -0.80f, -0.60f, 1.0f, 0.0f,
-0.70f, -0.80f, -0.60f, 1.0f, 1.0f,
-0.70f, -0.80f, -0.60f, 1.0f, 1.0f,
-0.45f, -0.5f, -0.60f, 0.0f, 1.0f,
-0.60f, -0.5f, -0.60f, 0.0f, 0.0f,
// bottom left leg(1) right
-0.45f, -0.5f, -0.60f, 1.0f, 0.0f,
-0.70f, -0.80f, -0.60f, 1.0f, 1.0f,
-0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
-0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
-0.45f, -0.5f, -0.80f, 0.0f, 0.0f,
-0.45f, -0.5f, -0.60f, 1.0f, 0.0f,
// bottom left leg(1) back
-0.45f, -0.5f, -0.80f, 0.0f, 0.0f,
-0.70f, -0.80f, -0.80f, 1.0f, 0.0f,
-0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
-0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
-0.60f, -0.5f, -0.80f, 0.0f, 1.0f,
-0.45f, -0.5f, -0.80f, 0.0f, 0.0f,
// bottom left leg(1) bottom
-0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
-0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
-0.80f, -0.80f, -0.60f, 1.0f, 0.0f,
-0.80f, -0.80f, -0.60f, 1.0f, 0.0f,
-0.70f, -0.80f, -0.60f, 0.0f, 0.0f,
-0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
/*BOTTOM RIGHT LEG(1)*/
// bottom right leg(1) left
0.60f, -0.5f, -0.80f, 1.0f, 0.0f,
0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
0.80f, -0.80f, -0.60f, 0.0f, 1.0f,
0.80f, -0.80f, -0.60f, 0.0f, 1.0f,
0.60f, -0.5f, -0.60f, 0.0f, 0.0f,
0.60f, -0.5f, -0.80f, 1.0f, 0.0f,
// bottom right leg(1) front
0.60f, -0.5f, -0.60f, 0.0f, 0.0f,
0.80f, -0.80f, -0.60f, 1.0f, 0.0f,
0.70f, -0.80f, -0.60f, 1.0f, 1.0f,
0.70f, -0.80f, -0.60f, 1.0f, 1.0f,
0.45f, -0.5f, -0.60f, 0.0f, 1.0f,
0.60f, -0.5f, -0.60f, 0.0f, 0.0f,
// bottom left leg(1) right
0.45f, -0.5f, -0.60f, 1.0f, 0.0f,
0.70f, -0.80f, -0.60f, 1.0f, 1.0f,
0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
0.45f, -0.5f, -0.80f, 0.0f, 0.0f,
0.45f, -0.5f, -0.60f, 1.0f, 0.0f,
// bottom left leg(1) back
0.45f, -0.5f, -0.80f, 0.0f, 0.0f,
0.70f, -0.80f, -0.80f, 1.0f, 0.0f,
0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
0.60f, -0.5f, -0.80f, 0.0f, 1.0f,
0.45f, -0.5f, -0.80f, 0.0f, 0.0f,
// bottom left leg(1) bottom
0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
0.80f, -0.80f, -0.80f, 1.0f, 1.0f,
0.80f, -0.80f, -0.60f, 1.0f, 0.0f,
0.80f, -0.80f, -0.60f, 1.0f, 0.0f,
0.70f, -0.80f, -0.60f, 0.0f, 0.0f,
0.70f, -0.80f, -0.80f, 0.0f, 1.0f,
/*BOTTOM LEFT LEG(2)*/
// bottom left leg(2) left
-0.60f, -0.5f, 0.60f, 1.0f, 0.0f,
-0.80f, -0.80f, 0.60f, 1.0f, 1.0f,
-0.80f, -0.80f, 0.80f, 0.0f, 1.0f,
-0.80f, -0.80f, 0.80f, 0.0f, 1.0f,
-0.60f, -0.5f, 0.80f, 0.0f, 0.0f,
-0.60f, -0.5f, 0.60f, 1.0f, 0.0f,
// bottom left leg(2) front
-0.60f, -0.5f, 0.80f, 0.0f, 0.0f,
-0.80f, -0.80f, 0.80f, 1.0f, 0.0f,
-0.70f, -0.80f, 0.80f, 1.0f, 1.0f,
-0.70f, -0.80f, 0.80f, 1.0f, 1.0f,
-0.45f, -0.5f, 0.80f, 0.0f, 1.0f,
-0.60f, -0.5f, 0.80f, 0.0f, 0.0f,
// bottom left leg(2) right
-0.45f, -0.5f, 0.80f, 1.0f, 0.0f,
-0.70f, -0.80f, 0.80f, 1.0f, 1.0f,
-0.70f, -0.80f, 0.60f, 0.0f, 1.0f,
-0.70f, -0.80f, 0.60f, 0.0f, 1.0f,
-0.45f, -0.5f, 0.60f, 0.0f, 0.0f,
-0.45f, -0.5f, 0.80f, 1.0f, 0.0f,
// bottom left leg(2) back
-0.60f, -0.5f, 0.60f, 0.0f, 0.0f,
-0.80f, -0.80f, 0.60f, 1.0f, 0.0f,
-0.70f, -0.80f, 0.60f, 1.0f, 1.0f,
-0.70f, -0.80f, 0.60f, 1.0f, 1.0f,
-0.45f, -0.5f, 0.60f, 0.0f, 1.0f,
-0.60f, -0.5f, 0.60f, 0.0f, 0.0f,
// bottom left leg(2) bottom
-0.80f, -0.80f, 0.60f, 0.0f, 1.0f,
-0.80f, -0.80f, 0.80f, 1.0f, 1.0f,
-0.70f, -0.80f, 0.80f, 1.0f, 0.0f,
-0.70f, -0.80f, 0.80f, 1.0f, 0.0f,
-0.70f, -0.80f, 0.60f, 0.0f, 0.0f,
-0.80f, -0.80f, 0.60f, 0.0f, 1.0f,
/*BOTTOM RIGHT LEG(2)*/
// bottom right leg(2) left
0.60f, -0.5f, 0.60f, 1.0f, 0.0f,
0.80f, -0.80f, 0.60f, 1.0f, 1.0f,
0.80f, -0.80f, 0.80f, 0.0f, 1.0f,
0.80f, -0.80f, 0.80f, 0.0f, 1.0f,
0.60f, -0.5f, 0.80f, 0.0f, 0.0f,
0.60f, -0.5f, 0.60f, 1.0f, 0.0f,
// bottom right leg(2) front
0.60f, -0.5f, 0.80f, 0.0f, 0.0f,
0.80f, -0.80f, 0.80f, 1.0f, 0.0f,
0.70f, -0.80f, 0.80f, 1.0f, 1.0f,
0.70f, -0.80f, 0.80f, 1.0f, 1.0f,
0.45f, -0.5f, 0.80f, 0.0f, 1.0f,
0.60f, -0.5f, 0.80f, 0.0f, 0.0f,
// bottom right leg(2) right
0.45f, -0.5f, 0.80f, 1.0f, 0.0f,
0.70f, -0.80f, 0.80f, 1.0f, 1.0f,
0.70f, -0.80f, 0.60f, 0.0f, 1.0f,
0.70f, -0.80f, 0.60f, 0.0f, 1.0f,
0.45f, -0.5f, 0.60f, 0.0f, 0.0f,
0.45f, -0.5f, 0.80f, 1.0f, 0.0f,
// bottom right leg(2) back
0.60f, -0.5f, 0.60f, 0.0f, 0.0f,
0.80f, -0.80f, 0.60f, 1.0f, 0.0f,
0.70f, -0.80f, 0.60f, 1.0f, 1.0f,
0.70f, -0.80f, 0.60f, 1.0f, 1.0f,
0.45f, -0.5f, 0.60f, 0.0f, 1.0f,
0.60f, -0.5f, 0.60f, 0.0f, 0.0f,
// bottom right leg(2) bottom
0.80f, -0.80f, 0.60f, 0.0f, 1.0f,
0.80f, -0.80f, 0.80f, 1.0f, 1.0f,
0.70f, -0.80f, 0.80f, 1.0f, 0.0f,
0.70f, -0.80f, 0.80f, 1.0f, 0.0f,
0.70f, -0.80f, 0.60f, 0.0f, 0.0f,
0.80f, -0.80f, 0.60f, 0.0f, 1.0f
;
//Generate buffer ids
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Activates the Vertex Array Object before binding and setting any VBOs and Vertex Attribute Pointers.
glBindVertexArray(VAO);
//Activate the VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Copy vertices to VBO
// Set attribute pointer 0 to hold Position data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // Enables vertex attribute
// Set attribute pointer 2 to hold Color data
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(2); // Enables vertex attribute
glBindVertexArray(0); // Deactivates the VAO which is good practice
/*Generate and load the texture*/
void UGenerateTexture()
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height;
unsigned char* image = SOIL_load_image("woodTable.jpg", &width, &height, 0, SOIL_LOAD_RGB); // Loads texture file
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind the texture
void UKeyboard(unsigned char key, GLint x, GLint y)
switch(key)
case 'o':
currentKey = key;
proj = !proj;
break;
void UKeyReleased(unsigned char key, GLint x, GLint y)
cout<<"Key released" <<endl;
currentKey = '0';
// Implements the UMouseMove function
void UMouseMove(int x, int y)
// Immediately replaces center locked coordinates with new mouse coordinates
if(mouseDetected)
lastMouseX = x;
lastMouseY = y;
mouseDetected = false;
// Gets the direction the mouse was moved in x and y
mouseXOffset = x - lastMouseX;
mouseYOffset = lastMouseY - y; // Inverted Y
//Updates with new mouse coordinates
lastMouseX = x;
lastMouseY = y;
// Applies sensitivity to mouse direction
mouseXOffset *= sensitivity;
mouseYOffset *= sensitivity;
// Accumulates the yaw and pitch variables
yaw += mouseXOffset;
pitch += mouseYOffset;
// Orbits around the center
front.x = 10.0f * cos(yaw);
front.y = 10.0f * sin(pitch);
front.z = sin(yaw) * cos(pitch) * 10.f;
【问题讨论】:
【参考方案1】:顶点属性数组由3个分量的顶点坐标(x、y、z)和2个分量的纹理坐标(u,v)。因此,一个属性元组有 5 个组件(x、y、z、u、v em>)。glVertexAttribPointer
的 stride 参数指定连续通用顶点属性之间的字节偏移量。因此参数必须是5 * sizeof(GLfloat)
((3 + 2) * sizeof(GLfloat)
) 而不是6 * sizeof(GLfloat)
:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
和
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
【讨论】:
您好!非常感谢您的回复!有效!如果可以,我可以再问一个问题吗?正如我所说,我对此很陌生,所以当您说“顶点属性数组由具有 5 个组件的元组组成”时,这是什么意思?以及我如何知道何时在另一种情况下使用不同的号码?再次,非常感谢! @ZaneBrown "顶点属性数组由 5 个组件的元组组成"你错过了重要的部分 "(x, y, z, u, v)" 。您的数组由具有 3 个分量(x、y、z)的顶点坐标和具有 2 个分量(u、v)的纹理坐标组成。 stride 参数指定连续通用顶点属性之间的字节偏移量。在你的情况下(3+2)*sizeof(GLfloat)
.以上是关于导致问题的纹理的主要内容,如果未能解决你的问题,请参考以下文章
我的OpenGL学习进阶之旅关于OpenGL ES 绘制纹理,因为加载纹理坐标设置错误,导致纹理无法渲染的问题