Related
I'm trying to create a toggle to change between ortho and perspective views. I have successfully coded buttons to initiate camera movement but can't figure out how to code a button to perform this change.
How I would toggle the projection modes here?
My code so far:
#include <iostream> // cout, cerr
#include <cstdlib> // EXIT_FAILURE
#include <GL/glew.h> // GLEW library
#include <GLFW/glfw3.h> // GLFW library
// GLM Math Header inclusions
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
//Camera class
#include <learnOpengl/camera.h>
using namespace std; // Standard namespace
/*Shader program Macro*/
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version " core \n" #Source
#endif
// Unnamed namespace
namespace
{
const char* const WINDOW_TITLE = "Milestone 4-5"; // Macro for window title
// Variables for window width and height
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
// Stores the GL data relative to a given mesh
struct GLMesh
{
GLuint vao; // Handle for the vertex array object
GLuint vbo; // Handles for the vertex buffer objects
GLuint nVertices; // Number of indices of the mesh
};
// Main GLFW window
GLFWwindow* gWindow = nullptr;
// Triangle mesh data
GLMesh gMesh;
// Shader program
GLuint gProgramId;
// camera
Camera gCamera(glm::vec3(0.0f, 0.0f, 3.0f));
float gLastX = WINDOW_WIDTH / 2.0f;
float gLastY = WINDOW_HEIGHT / 2.0f;
bool gFirstMouse = true;
glm::vec3 gCameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 gCameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 gCameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
// timing
float gDeltaTime = 0.0f; // time between current frame and last frame
float gLastFrame = 0.0f;
}
/* User-defined Function prototypes to:
* initialize the program, set the window size,
* redraw graphics on the window when resized,
* and render graphics on the screen
*/
bool UInitialize(int, char* [], GLFWwindow** window);
void UResizeWindow(GLFWwindow* window, int width, int height);
void UProcessInput(GLFWwindow* window);
void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos);
void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
void UCreateMesh(GLMesh& mesh);
void UDestroyMesh(GLMesh& mesh);
void URender();
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId);
void UDestroyShaderProgram(GLuint programId);
/* Vertex Shader Source Code*/
const GLchar* vertexShaderSource = GLSL(440,
layout(location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0
layout(location = 1) in vec4 color; // Color data from Vertex Attrib Pointer 1
out vec4 vertexColor; // variable to transfer color data to the fragment shader
//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
vertexColor = color; // references incoming color data
}
);
/* Fragment Shader Source Code*/
const GLchar* fragmentShaderSource = GLSL(440,
in vec4 vertexColor; // Variable to hold incoming color data from vertex shader
out vec4 fragmentColor;
void main()
{
fragmentColor = vec4(vertexColor);
}
);
int main(int argc, char* argv[])
{
if (!UInitialize(argc, argv, &gWindow))
return EXIT_FAILURE;
// Create the mesh
UCreateMesh(gMesh); // Calls the function to create the Vertex Buffer Object
// Create the shader program
if (!UCreateShaderProgram(vertexShaderSource, fragmentShaderSource, gProgramId))
return EXIT_FAILURE;
// Sets the background color of the window to black (it will be implicitly used by glClear)
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// render loop
// -----------
while (!glfwWindowShouldClose(gWindow))
{
// per-frame timing
// --------------------
float currentFrame = glfwGetTime();
gDeltaTime = currentFrame - gLastFrame;
gLastFrame = currentFrame;
// input
// -----
UProcessInput(gWindow);
// Render this frame
URender();
glfwPollEvents();
}
// Release mesh data
UDestroyMesh(gMesh);
// Release shader program
UDestroyShaderProgram(gProgramId);
exit(EXIT_SUCCESS); // Terminates the program successfully
}
// Initialize GLFW, GLEW, and create a window
bool UInitialize(int argc, char* argv[], GLFWwindow** window)
{
// GLFW: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// GLFW: window creation
// ---------------------
* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
if (*window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return false;
}
glfwMakeContextCurrent(*window);
glfwSetFramebufferSizeCallback(*window, UResizeWindow);
glfwSetCursorPosCallback(*window, UMousePositionCallback);
glfwSetScrollCallback(*window, UMouseScrollCallback);
glfwSetMouseButtonCallback(*window, UMouseButtonCallback);
// tell GLFW to capture our mouse
glfwSetInputMode(*window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// GLEW: initialize
// ----------------
// Note: if using GLEW version 1.13 or earlier
glewExperimental = GL_TRUE;
GLenum GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult)
{
std::cerr << glewGetErrorString(GlewInitResult) << std::endl;
return false;
}
// Displays GPU OpenGL version
cout << "INFO: OpenGL Version: " << glGetString(GL_VERSION) << endl;
return true;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
void UProcessInput(GLFWwindow* window)
{
static const float cameraSpeed = 2.5f;
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
gCamera.ProcessKeyboard(FORWARD, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
gCamera.ProcessKeyboard(BACKWARD, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
gCamera.ProcessKeyboard(LEFT, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
gCamera.ProcessKeyboard(RIGHT, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
gCamera.ProcessKeyboard(UP, gDeltaTime);
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
gCamera.ProcessKeyboard(DOWN, gDeltaTime);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
void UResizeWindow(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void UMousePositionCallback(GLFWwindow* window, double xpos, double ypos)
{
if (gFirstMouse)
{
gLastX = xpos;
gLastY = ypos;
gFirstMouse = false;
}
float xoffset = xpos - gLastX;
float yoffset = gLastY - ypos; // reversed since y-coordinates go from bottom to top
gLastX = xpos;
gLastY = ypos;
gCamera.ProcessMouseMovement(xoffset, yoffset);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void UMouseScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
gCamera.ProcessMouseScroll(yoffset);
}
// glfw: handle mouse button events
// --------------------------------
void UMouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
{
switch (button)
{
case GLFW_MOUSE_BUTTON_LEFT:
{
if (action == GLFW_PRESS)
cout << "Left mouse button pressed" << endl;
else
cout << "Left mouse button released" << endl;
}
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
{
if (action == GLFW_PRESS)
cout << "Middle mouse button pressed" << endl;
else
cout << "Middle mouse button released" << endl;
}
break;
case GLFW_MOUSE_BUTTON_RIGHT:
{
if (action == GLFW_PRESS)
cout << "Right mouse button pressed" << endl;
else
cout << "Right mouse button released" << endl;
}
break;
default:
cout << "Unhandled mouse button event" << endl;
break;
}
}
// Functioned called to render a frame
void URender()
{
// Enable z-depth
glEnable(GL_DEPTH_TEST);
// Clear the frame and z buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. Scales the object by 0.5
glm::mat4 scale = glm::scale(glm::vec3(0.5f, 0.5f, 0.5f));
// 2. Rotates shape by 37 degrees
glm::mat4 rotation = glm::rotate(37.0f, glm::vec3(1.0, 0.4f, 1.0f));
// 3. Place object at the origin
glm::mat4 translation = glm::translate(glm::vec3(0.0f, 0.0f, 0.0f));
// Model matrix: transformations are applied right-to-left order
glm::mat4 model = translation * rotation * scale;
// camera/view transformation
glm::mat4 view = gCamera.GetViewMatrix();
// Creates a perspective projection
glm::mat4 projection = glm::perspective(glm::radians(gCamera.Zoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
// Set the shader to be used
glUseProgram(gProgramId);
// Retrieves and passes transform matrices to the Shader program
GLint modelLoc = glGetUniformLocation(gProgramId, "model");
GLint viewLoc = glGetUniformLocation(gProgramId, "view");
GLint projLoc = glGetUniformLocation(gProgramId, "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));
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.vao);
// Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, gMesh.nVertices);
// Deactivate the Vertex Array Object
glBindVertexArray(0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
glfwSwapBuffers(gWindow); // Flips the the back buffer with the front buffer every frame.
}
// Implements the UCreateMesh function
void UCreateMesh(GLMesh& mesh)
{
// Position and Color data
GLfloat verts[] = {
// Vertex Positions // Colors (r,g,b,a)
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
-0.8f, 0.2f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
-0.8f, 0.2f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 0.2f, -1.0f, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top left 3
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
-0.8f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // bottom left 2
-0.8f, 0.2f, -1.0, 0.2f, 0.2f, 0.5f, 1.0f, // 6 back bot left
-0.8f, 2.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 7 back top left
2.8f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top right 0
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
2.8f, 0.2f, 0.0f, 0.5f, 1.0f, 1.0f, 1.0f, // bottom right 1
2.8f, 2.0f, -1.0f, 0.5f, 0.5f, 1.0f, 1.0f, // 4 back top right
2.8f, 0.2f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // 5 back bot right
1.6f, 1.8f, 0.1f, 0.0f, 1.0f, 1.0f, 1.0f, // 8 top of vent pyramid
2.2f, 1.0f, 0.1f, 1.0f, 0.0f, 1.0f, 1.0f, // 9 right side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.6f, 0.2f, 0.1f, 1.0f, 1.0f, 0.0f, 1.0f, // 10 bottom of vent pyramid
2.2f, 1.0f, 0.1f, 1.0f, 0.0f, 1.0f, 1.0f, // 9 right side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.6f, 0.2f, 0.1f, 1.0f, 1.0f, 0.0f, 1.0f, // 10 bottom of vent pyramid
1.1f, 1.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f, // 12 left side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.1f, 1.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f, // 12 left side of vent pyramid
1.5f, 1.2f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, // 11 center apex
1.6f, 1.8f, 0.1f, 0.0f, 1.0f, 1.0f, 1.0f, // 8 top of vent pyramid
-4.0f, 4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
4.0f, 4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
-4.0f, -4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
4.0f, 4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
4.0f, -4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
-4.0f, -4.0f, -1.0f, 0.0f, 0.25f, 0.25f, 1.0f,
};
const GLuint floatsPerVertex = 3;
const GLuint floatsPerColor = 4;
mesh.nVertices = sizeof(verts) / (sizeof(verts[0]) * (floatsPerVertex + floatsPerColor));
glGenVertexArrays(1, &mesh.vao); // we can also generate multiple VAOs or buffers at the same time
glBindVertexArray(mesh.vao);
// Create VBO
glGenBuffers(1, &mesh.vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo); // Activates the buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); // Sends vertex or coordinate data to the GPU
// Strides between vertex coordinates
GLint stride = sizeof(float) * (floatsPerVertex + floatsPerColor);
// Create Vertex Attribute Pointers
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
}
void UDestroyMesh(GLMesh& mesh)
{
glDeleteVertexArrays(1, &mesh.vao);
glDeleteBuffers(1, &mesh.vbo);
}
// Implements the UCreateShaders function
bool UCreateShaderProgram(const char* vtxShaderSource, const char* fragShaderSource, GLuint& programId)
{
// Compilation and linkage error reporting
int success = 0;
char infoLog[512];
// Create a Shader program object.
programId = glCreateProgram();
// Create the vertex and fragment shader objects
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
// Retrive the shader source
glShaderSource(vertexShaderId, 1, &vtxShaderSource, NULL);
glShaderSource(fragmentShaderId, 1, &fragShaderSource, NULL);
// Compile the vertex shader, and print compilation errors (if any)
glCompileShader(vertexShaderId); // compile the vertex shader
// check for shader compile errors
glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShaderId, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
// compile the fragment shader
glCompileShader(fragmentShaderId);
// check for shader compile errors
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShaderId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
return false;
}
// Attached compiled shaders to the shader program
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId); // links the shader program
// check for linking errors
glGetProgramiv(programId, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(programId, sizeof(infoLog), NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
return false;
}
glUseProgram(programId); // Uses the shader program
return true;
}
void UDestroyShaderProgram(GLuint programId)
{
glDeleteProgram(programId);
}
Simply change your
glm::mat4 projection = glm::perspective(glm::radians(gCamera.Zoom), (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f);
to use glm::ortho depending on your game state.
You'll likely have to tinker a bit with the view projection as well.
So far I've learned how to create a cube with textures in OpenGL.
Now I want to change this code for texturing a Quad. I've changed the vertices + indices from a cube to a quad.
And the Quad looks like this:
The texture is completely distorted and the upper triangle is missing...
This is the code I'm using:
1.
GLfloat vertices[] = {
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
unsigned int indices[]{
0,1,2,
1,2,3,
};
2.
for (size_t o = 0; o < 6; o++) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, breite_komplett);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, ausschnitt_x_counter);
glPixelStorei(GL_UNPACK_SKIP_ROWS, ausschnitt_y_counter);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(
GL_TEXTURE_CUBE_MAP_POSITIVE_X + o, 0, GL_RGBA, ausschnitt_breite, ausschnitt_höhe, 0, GL_RGBA, GL_UNSIGNED_BYTE, sprite_image.getPixelsPtr());
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glEnable(GL_TEXTURE_2D);
Do you have an ideas what I need to change?
Edit:
unsigned int indices[]{
0,1,2,
0,2,3
};
This is my object builder:
glGenVertexArrays(1, &obj_vao);
glBindVertexArray(obj_vao);
glGenBuffers(1, &obj_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies[0])* indicies_count, indicies, GL_STATIC_DRAW);
glGenBuffers(1, &obj_vbo);
glBindBuffer(GL_ARRAY_BUFFER, obj_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * count_vertices, vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 5, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]) * 5, (void*)(sizeof(vertices[0]) * 3));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Edit:
If the vertices would be like this:
GLfloat vertices[] = {
1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
1.0f, -1.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
};
Everything would be fine and the Quad looks like this:
But I need the Quad in the origin like this:
GLfloat vertices[] = {
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
With this vertices the texture is distorted...
The indices of the 2 triangle primitives do not form a quad. The indices have to be:
unsigned int indices[]{ 0, 1, 2, 1, 2, 3 };
unsigned int indices[]{ 0, 1, 2, 0, 2, 3 };
3 0
+-----+ +
| / / |
| / / |
+ +-----+
2 1
When you crate the texture, the you mix GL_TEXTURE_CUBE_MAP and GL_TEXTURE_2D. That makes no sense. Either create a cubemap texture and set the parameters for the GL_TEXTURE_CUBE_MAP or create a 2 dimensional texture.
Anyway if you want to create a cubemap texture, then you have to use GL_TEXTURE_CUBE_MAP, when you set the parameters, too.
The texture coordinate for a texture cube is a 3 dimensional vector. Change the vertex coordinates for the side of the cube. e.g:
(You don't need the texture coordinates at all)
GLfloat vertices[] = {
// x y z
1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.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
};
The center of the cube is (0, 0, 0), so you can use the vertex coordinates for the texture, too:
Vertex shader
in vec3 position;
out vec3 cubeCoord;
void main()
{
cubeCoord = position;
// [...]
}
Fragment shader:
in vec3 cubeCoord;
uniform samplerCube cubeTex;
void main()
{
vec4 color = texture(cubeTex, cubeCoord);
// [...]
}
Alternatively you can use separate 3 dimensional texture coordinates for the cubemap texture:
GLfloat vertices[] = {
// x y z u v w
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 1.0f,
};
Update for the question:
In the prior question description, I had made several serious mistakes which made the question very hard to understand and to solve. Now I will share my newest code that works.
My prior description about the direction of each face was wrong. The correct direction is as follows:
The right face is rotated 90 degrees clockwise, and the top face is rotated 180 degrees clockwise.
So when setting up the texture coordinates for the right face which is composed of two triangles (3-7-8 and 8-4-3), we need to rotate the face in the 90 degrees counter clockwise, so 3 will use 7's coordinate, 7 -> 8, 8 -> 4, 4 -> 3. When setting up the texture coordinates for the top face which is composed of two triangles(1-4-8 and 8-6-1), we need to rotate the face in 90 degrees counter clockwise, so 1 will use 8's coordinate, 4 -> 6, 8 -> 1, 6 -> 4.
The code that works:
bool setupCoordinates() {
this->vertexCount = 36;
float skyboxVertices[] = {
// positions
// back
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
// Left
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Right
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
// Front
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Top
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
// Bottom
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
float skyboxTextures[] = {
// positions
// Back same as skyboxVertices
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
// Left same as skyboxVertices
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Right rotate in 90 ccw
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
// Front same as skyboxVertices
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Top rotate in 180 ccw
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
// Bottom same as skyboxVertices
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
glGenVertexArrays(1, &sceneVAO);
glBindVertexArray(sceneVAO);
glGenBuffers(1, &sceneVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, sceneVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glGenBuffers(1, &sceneUVBuffer);
glBindBuffer(GL_ARRAY_BUFFER, sceneUVBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxTextures), &skyboxTextures, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glBindVertexArray(0);
return true;
}
void drawFrame() {
glBindTexture(GL_TEXTURE_CUBE_MAP, sceneTextureID);
glPixelStorei(GL_UNPACK_ROW_LENGTH, videoFrameWidth);
int width = videoFrameWidth / 3;
int height = width;
// back
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// left
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// front
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// bottom
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// right
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB,width,width,0,GL_RGB,GL_UNSIGNED_BYTE, textureData);
// top
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
}
------------------------------------------------Original question------------------------------------------------
I have a 360 video which is in cubemap3x2 format, and I want to render it using cubemap texture in OpenGL. However, the back and the top face of the cube, are rotated in different directions. The back face is rotated 90 degrees clockwise, and the top face is rotated 180 degrees clockwise. Now I can render the cubemap correctly by memory copy, but I wonder if there is a way to avoid this by using OpenGL's builtin capability?
The frame that I need to render:
The vertex shader:
#version 410 core
uniform mat4 matrix;
out vec3 TexCoords;
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 textureIn;
void main() {
TexCoords = textureIn;
gl_Position = matrix * position;
}
The fragment shader:
#version 410 core
varying vec3 TexCoords;
uniform samplerCube mytexture;
void main() {
gl_FragColor = texture(mytexture, TexCoords);
}
The code that I use to render:
void Player::SetupScene() {
this->m_sceneVertexCount = 36;
float skyboxVertices[] = {
// positions
// Back
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
// Left
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Right
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
// Front
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Top
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
// Bottom
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
float skyboxTextures[] = {
// positions
// Back
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
// Left
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Right
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
// Front
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Top
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
// Bottom
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
glGenVertexArrays(1, &m_SceneVAO);
glBindVertexArray(m_SceneVAO);
glGenBuffers(1, &m_sceneVertBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_sceneVertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glGenBuffers(1, &m_sceneTexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_sceneTexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxTextures), &skyboxTextures, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glBindVertexArray(0);
}
void Player::SetupTexture(unsigned char *textureData) {
int width = frameWidth / 3;
glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_sceneTextureID);
// Render left face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render front face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render right face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render bottom face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Rotate the back face 90 degrees counter clockwise
uint8_t *start = textureData + rowLength * height * 3 + width * 3;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 0] = *(start + i * 3 + 0);
m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 1] = *(start + i * 3 + 1);
m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 2] = *(start + i * 3 + 2);
}
start += rowLength * 3;
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pRightFaceBuffer);
// Rotate the bottom face 180 degrees counter clockwise
start = textureData + rowLength * height * 3 + width * 2 * 3;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 0] = *(start + (i) * 3);
m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 1] = *(start + (i) * 3 + 1);
m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 2] = *(start + (i) * 3 + 2);
}
start += rowLength * 3;
}
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pUpFaceBuffer);
}
The coordinate that I use to build the cubemap:
You can directly specify the sides of the cubemap by glTexImage2D:
glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth);
// Render left face
[...]
// Render front face
[...]
// Render right face
[...]
// Render bottom face
[...]
// Render back face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render top face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width*2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
But you have to change the texture coordinates for right and top side. Note you messed up the mapping of the cube map sides to the sides of the cube, but anyway it works:
float skyboxTextures[] = {
// positions
// Back
// [...]
// Left
// [...]
// Right
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
// Front
// [...]
// Top
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
// Bottom
// [...]
};
See the result:
Since the mapping of the sides seems to be messed up, I would prefer to load the sides like this:
glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth);
// Render back face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render left face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render right face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render front face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render top face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width*2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
// Render bottom face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);
and to use the following texture coordinates:
float skyboxTextures[] = {
// positions
// Back
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
// Left
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Right
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
// Front
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
// Top
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
// Bottom
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f
};
But note, the y and the z axis are still swapped. I assume this is because the world space up vector in your scene is (0, 1, 0).
I'm attempting to implement a skybox in a game. The image I am using is:
Unfortunately, it is extremely magnified, only showing a few of the pixels of the texture. It looks like this:
here's my code for creating the skybox:
SkyBox::SkyBox()
{
programID = LoadShaders("Resources/Shaders/skybox.vert", "Resources/Shaders/skybox.frag");
pID = glGetUniformLocation(programID, "P");
vID = glGetUniformLocation(programID, "V");
float points[] =
{
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
glGenBuffers (1, &vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER, sizeof (points), points, GL_STATIC_DRAW);
const char *pth = "/Users/uonibr/Documents/Programming/Space Shooter/Space Shooter/Space Shooter/Resources/space.jpg";
createCubeMap(pth, pth, pth, pth, pth, pth);
}
bool load_cube_map_side (GLuint texture, GLenum side_target, const char* file_name)
{
glBindTexture (GL_TEXTURE_CUBE_MAP, texture);
int x, y;
unsigned char* image_data = SOIL_load_image(file_name, &x, &y, 0, SOIL_LOAD_RGBA);
if (!image_data) {
fprintf (stderr, "ERROR: could not load %s\n", file_name);
return false;
}
// non-power-of-2 dimensions check
if ((x & (x - 1)) != 0 || (y & (y - 1)) != 0) {
fprintf (
stderr, "WARNING: image %s is not power-of-2 dimensions\n", file_name
);
}
// copy image data into 'target' side of cube map
glTexImage2D (
side_target,
0,
GL_RGBA,
x,
y,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image_data
);
free (image_data);
return true;
}
void SkyBox::createCubeMap ( const char* front, const char* back, const char* top, const char* bottom, const char* left,const char* right)
{
// generate a cube-map texture to hold all the sides
glActiveTexture (GL_TEXTURE0);
glGenTextures (1, &cubeMap);
// load each image and copy into a side of the cube-map texture
assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, front));
assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, back));
assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, top));
assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, bottom));
assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, left));
assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_POSITIVE_X, right));
// format cube map texture
glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
and here's the rendering code for the skybox:
void SkyBox::render(const Camera &camera) const
{
glDepthMask (GL_FALSE);
glUseProgram (programID);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_CUBE_MAP, cubeMap);
glUniformMatrix4fv(pID, 1, GL_FALSE, &camera.getProjectionMatrix()[0][0]);
glm::mat4 view = camera.getRotationMatrix();
glUniformMatrix4fv(vID, 1, GL_FALSE, &view[0][0]);
glEnableVertexAttribArray (0);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(
0, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glDrawArrays (GL_TRIANGLES, 0, 36);
glDisableVertexAttribArray(0);
glDepthMask (GL_TRUE);
glCullFace(GL_BACK);
}
the fragment shader is simple:
#version 330 core
in vec3 texcoords;
uniform samplerCube cube_texture;
out vec4 frag_color;
void main () {
frag_color = texture (cube_texture, texcoords);
}
as is the vertex shader:
#version 330 core
in vec3 vp;
uniform mat4 P, V;
out vec3 texcoords;
void main () {
texcoords = vp;
gl_Position = P * V * vec4 (vp, 1.0);
}
EDIT:
here's my code for producing the projection matrix:
glm::mat4 Camera::getProjectionMatrix() const
{
return glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);
}
and here is my FoV:
float FoV = 3.14159 * 65. / 180;
I determined the issue:
I was passing radians into the glm::perspective() function when I should have passed degrees. Therefore, as was commented on the question, the answer was a small FoV
I'm trying to draw a cube with an FBO texture. The texture is rendered to correctly (which I can see in gDebugger), but it doesn't render on the cube. I thought that this might be a problem with the FBO texture so I loaded an ordinary texture and tried it as well, but I get the same problem, just a black cube.
Stepping through the program in gDebugger, I can see that the texture is both loaded correctly and bound, but nothing is drawn. There also doesn't seem to be any problems with the texcoords. Note that I've also tried to output a solid color in the fragment shader which works correctly.
This is my vertex shader:
#version 420
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec2 texcoord;
out vec2 f_texcoord;
void main() {
gl_Position = projection * view * model * vec4(vertex, 1.0);
f_texcoord = texcoord;
}
And this is my fragment shader:
#version 420
uniform sampler2D tex;
in vec2 f_texcoord;
out vec4 gl_FragColor;
void main() {
gl_FragColor = texture2D(tex, f_texcoord);
}
And this is where I draw the cube:
ShaderManager::Get("world")->Use();
glBindVertexArray(cube_vao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
I must be blind, because I see no errors.
(Also, please note that I am using SFML and GLEW for context creation and extensions.)
EDIT:
I don't know if this will be helpful, but this is how I set up the cube VBO, uniforms, etc.:
glClearColor(1.0, 0.0, 0.0, 1.0);
glEnable(GL_DEPTH_TEST);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
sf::Image img;
img.LoadFromFile("test.png");
img.FlipVertically();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.GetWidth(), img.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.GetPixelsPtr());
glBindTexture(GL_TEXTURE_2D, 0);
ShaderTime = 0.0;
camz = -4.0f;
rotation_y = 0.0f;
Shader* shader = ShaderManager::Load("shader", "fx.vert", "fx.frag");
Shader* world = ShaderManager::Load("world", "world.vert", "world.frag");
shader->Use();
glUniform1f(glGetUniformLocation(shader->GetId(), "time"), ShaderTime);
world->Use();
glm::mat4 proj = glm::perspective(60.0f, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 1000.0f);
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, camz));
glm::mat4 model;
glUniformMatrix4fv(glGetUniformLocation(world->GetId(), "projection"), 1, GL_FALSE, glm::value_ptr(proj));
glUniformMatrix4fv(glGetUniformLocation(world->GetId(), "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(world->GetId(), "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform1i(glGetUniformLocation(world->GetId(), "tex"), 0);
glGenVertexArrays(1, &cube_vao);
glBindVertexArray(cube_vao);
glGenBuffers(1, &cube_vbo);
glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);
GLfloat* data = new GLfloat[5 * 36] {
// Front
-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f,
// Back
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
// Top
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
// Bottom
-1.0f, -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
// Left
-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f,
// Right
1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f
};
glBufferData(GL_ARRAY_BUFFER, (5 * 36) * sizeof(GLfloat), data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)(0));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLvoid*)(sizeof(GLfloat) * 3));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
===EDIT===
It looks like you're missing the texture setup for the minification filter, which is a problem if you're not using a mipmapped texture. See here: http://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture