我正在尝试在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;
}
最佳答案
顶点属性数组由具有3个分量(x,y,z)的顶点坐标和具有2个分量(u,v)的纹理坐标组成。因此,属性元组具有5个分量(x,y,z,u,v)。
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)));
关于c++ - 导致问题的纹理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63408743/