Texture loaded and bound, but fragment shader doesn't render it - opengl

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

Related

How to use keyboard and mouse input to navigate a figure

I'm working on a project involving viewing a 3D from different viewpoints using mouse and keyboard input. When I submitted my first draft, I received the following feedback:
"Your object did not react to any of the buttons I pressed to change the camera view! The object of this project is to have the user control the camera by being able to change different views but your object didn't give me that ability!"
I currently have it coded to zoom in on the object when pressing the up key and out when pressing the down key. The camera view is supposed to move up and down when moving the mouse.
I've tried using some previous code that involved the cameraPosition variable, but it does not function properly when utilized in the pressSpecialKey function or in the rendering function.
/*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 "Final Project: Spoon" //Window title Macro
/*Shader program Macro*/
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif
//Global variable declarations
int view_state = 1;
/*Variable declarations for shader, window size initialization, buffer and array objects*/
GLint spoonShaderProgram, lampShaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, SpoonVAO, LightVAO, texture;
GLfloat cameraSpeed = 0.0005f; //Movement speed per frame
//TODO: Remove unnessary code
GLchar currentKey; //Will store key pressed
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.5f; //Used for mouse / camera rotation sensitivity
bool mouseDetected = true; //Initially true when mouse movement is detected
//Global vector declarations
glm::vec3 cameraPosition = glm::vec3(-2.0f, 1.0f, 2.0f); //Initial camera position.
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
//Subject position and scale
glm::vec3 spoonPosition(0.0f, 0.0f, 0.0f);
glm::vec3 spoonScale(2.0f);
//spoon and light color
glm::vec3 objectColor(1.0f, 1.0f, 1.0f);
glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
//Light position and scale
glm::vec3 lightPosition(0.5f, 0.5f, 3.0f);
glm::vec3 lightScale(0.3f);
/*Function prototypes*/
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
void pressSpecialKey(int key, int xx, int yy);
void UMouseMove(int x, int y);
void UGenerateTexture(void);
/*Spoon Vertex Shader Course Code*/
const GLchar * spoonVertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position; //Vertex data from Vertex Attrib Pointer 0
layout (location = 1) in vec3 normal; //VAP for normals from Vertex Attrib Pointer 1
layout (location = 2) in vec2 textureCoordinate; //Texture vertex data from Vertex Attrib Pointer 2
out vec3 FragmentPos; //For outgoing color / pixels to fragment shader
out vec3 Normal; //For outgoing normals to fragment shader
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
FragmentPos = vec3(model * vec4(position, 1.0f)); //Gets fragment / pixel position in world space only (exclude view and projection)
Normal = mat3(transpose(inverse(model))) * normal; //get normal vectors in world space only and exclude normal translation properties
mobileTextureCoordinate = vec2(textureCoordinate.x, 1 - textureCoordinate.y); //flips the texture horizontal
}
);
/*Spoon Fragment Shader Source Code*/
const GLchar * spoonFragmentShaderSource = GLSL(330,
in vec3 FragmentPos; //For incoming fragment position
in vec3 Normal; //For incoming normals
in vec2 mobileTextureCoordinate;
out vec4 spoonColor; //For outgoing spoon color to the GPU
//Uniform / Global variables for object color, light color, light position, and camera/view position
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPosition;
uniform sampler2D uTexture; //Useful when working with multiple textures
void main(){
/*Phong lighting model calculations to generate ambient, diffuse, and specular components*/
//Calculate Ambient Lighting
float ambientStrength = 0.1f; //Set ambient or global lighting strength
vec3 ambient = ambientStrength * lightColor; //Generate ambient light color
//Calculate Diffuse Lighting
vec3 norm = normalize(Normal); //Normalize vectors to 1 unit
vec3 lightDirection = normalize(lightPos - FragmentPos); //Calculate distance (light direction) between light source and fragments/pixels on
float impact = max(dot(norm, lightDirection), 0.0); //Calculate diffuse impact by generating dot product of normal and light
vec3 diffuse = impact * lightColor; //Generate diffuse light color
//Calculate Specular lighting
float specularIntensity = 1.6f; //Set specular light strength
float highlightSize = 128.0f; //Set specular highlight size
vec3 viewDir = normalize(viewPosition - FragmentPos); //Calculate view direction
vec3 reflectDir = reflect(-lightDirection, norm); //Calculate reflection vector
//Calculate specular component
float specularComponent = pow(max(dot(viewDir, reflectDir), 0.0), highlightSize);
vec3 specular = specularIntensity * specularComponent * lightColor;
//Calculate phong result
vec3 objectColor = texture(uTexture, mobileTextureCoordinate).xyz;
vec3 phong = (ambient + diffuse) * objectColor + specular;
spoonColor = vec4(phong, 1.0f); //Send lighting results to GPU
}
);
/*Lamp Shader Source Code*/
const GLchar * lampVertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position; //VAP position 0 for vertex position data
//Uniform / 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 into clip coordinates
}
);
/*Lamp Fragment Shader Source Code*/
const GLchar * lampFragmentShaderSource = GLSL(330,
out vec4 color; //For outgoing lamp color (smaller spoon) to the GPU
void main()
{
color = vec4(1.0f); //Set color to white (1.0f, 1.0f, 1.0f) with alpha 1.0
}
);
/*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();
glClearColor(0.8f, 0.8f, 0.8f, 1.0f); //Set background color
glutDisplayFunc(URenderGraphics);
glutSpecialFunc(pressSpecialKey); //Detects key press
glutPassiveMotionFunc(UMouseMove);
glutMainLoop();
//Destroys Buffer objects once used
glDeleteVertexArrays(1, &SpoonVAO);
glDeleteVertexArrays(1, &LightVAO);
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
GLint uTextureLoc, lightColorLoc, lightPositionLoc, viewPositionLoc;
/*********Use the Spoon Shader to activate the Spoon Vertex Array Object for rendering and transforming*********/
glUseProgram(spoonShaderProgram);
glBindVertexArray(SpoonVAO);
CameraForwardZ = front; //Replaces camera forward vector with Radians normalized as a 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
//Transform the camera
glm::mat4 view;
view = glm::lookAt(cameraPosition - CameraForwardZ, cameraPosition, CameraUpY);
//Creates a perspective projection
glm::mat4 projection;
if(view_state == 1){
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
}else if(view_state == 0){
projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);
}
//Reference matrix uniforms from the spoon Shader program
GLint modelLoc = glGetUniformLocation(spoonShaderProgram, "model");
GLint viewLoc = glGetUniformLocation(spoonShaderProgram, "view");
GLint projLoc = glGetUniformLocation(spoonShaderProgram, "projection");
//Pass matrix data to the spoon Shader program's matrix uniforms
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));
//Reference matrix uniforms from the spoon Shader program for the spoon color, light color, light position, and camera position
uTextureLoc = glGetUniformLocation(spoonShaderProgram, "uTexture");
lightColorLoc = glGetUniformLocation(spoonShaderProgram, "lightColor");
lightPositionLoc = glGetUniformLocation(spoonShaderProgram, "lightPos");
viewPositionLoc = glGetUniformLocation(spoonShaderProgram, "viewPosition");
//Pass color, light, and camera data to the spoon Shader programs corresponding uniforms
glUniform1i(uTextureLoc, 0); // texture unit 0
glUniform3f(lightColorLoc, lightColor.r, lightColor.g, lightColor.b);
glUniform3f(lightPositionLoc, lightPosition.x, lightPosition.y, lightPosition.z);
glUniform3f(viewPositionLoc, cameraPosition.x, cameraPosition.y, cameraPosition.z);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLES, 0, 126); //Draw the primitives / spoon
glBindVertexArray(0); //Deactivate the spoon Vertex Array Object
/***************Use the Lamp Shader and activate the Lamp Vertex Array Object for rendering and transforming ************/
glUseProgram(lampShaderProgram);
glBindVertexArray(LightVAO);
//Transform the smaller spoon used as a visual cue for the light source
model = glm::translate(model, lightPosition);
model = glm::scale(model, lightScale);
//Reference matrix uniforms from the Lamp Shader program
modelLoc = glGetUniformLocation(lampShaderProgram, "model");
viewLoc = glGetUniformLocation(lampShaderProgram, "view");
projLoc = glGetUniformLocation(lampShaderProgram, "projection");
//Pass matrix uniforms from the Lamp Shader Program
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));
//Draws the triangles
glDrawArrays(GL_TRIANGLES, 0, 126);
glBindVertexArray(0); //Deactivate the Vertex Array Object
glutPostRedisplay();
glutSwapBuffers(); //Flips the back buffer with the front buffer every frame. Similar to GL Flush
}
/*Creates the Shader program*/
void UCreateShader()
{
//Spoon Vertex shader
GLint spoonVertexShader = glCreateShader(GL_VERTEX_SHADER); //Create the Vertex shader
glShaderSource(spoonVertexShader, 1, &spoonVertexShaderSource, NULL); //Attaches the vertex shader to the source code
glCompileShader(spoonVertexShader); //Compiles the Vertex shader
//Spoon Fragment shader
GLint spoonFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //Create the Fragment shader
glShaderSource(spoonFragmentShader, 1, &spoonFragmentShaderSource, NULL); //Attaches the Fragment shader to the source code
glCompileShader(spoonFragmentShader); //Compiles the Fragment shader
//Spoon Shader program
spoonShaderProgram = glCreateProgram(); //Creates the Shader program and returns an id
glAttachShader(spoonShaderProgram, spoonVertexShader); //Attach Vertex shader to the Shader program
glAttachShader(spoonShaderProgram, spoonFragmentShader); //Attach Fragment shader to the Shader program
glLinkProgram(spoonShaderProgram); //Link Vertex and Fragment shaders to Shader program
//Delete the Vertex and Fragment shaders once linked
glDeleteShader(spoonVertexShader);
glDeleteShader(spoonFragmentShader);
//Lamp Vertex shader
GLint lampVertexShader = glCreateShader(GL_VERTEX_SHADER); //Creates the Vertex shader
glShaderSource(lampVertexShader, 1, &lampVertexShaderSource, NULL); //Attaches the Vertex shader to the source code
glCompileShader(lampVertexShader); //Compiles the Vertex shader
//Lamp Fragment shader
GLint lampFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //Creates the Fragment shader
glShaderSource(lampFragmentShader, 1, &lampFragmentShaderSource, NULL); //Attaches the Fragment shader to the source code
glCompileShader(lampFragmentShader); //Compiles the Fragment shader
//Lamp Shader Program
lampShaderProgram = glCreateProgram(); //Creates the Shader program and returns an id
glAttachShader(lampShaderProgram, lampVertexShader); //Attach Vertex shader to the Shader program
glAttachShader(lampShaderProgram, lampFragmentShader); //Attach Fragment shader to the Shader program
glLinkProgram(lampShaderProgram); //Link Vertex and Fragment shaders to the Shader program
//Delete the lamp shaders once linked
glDeleteShader(lampVertexShader);
glDeleteShader(lampFragmentShader);
}
void UCreateBuffers()
{
GLfloat vertices[] = {
//Position //Normals //Texture //Point Name
//Front of Scoop //Positive Z
-0.4f, 0.05f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 1.0f, //Q
-0.4f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 0.0f, //R
-0.6f, 0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, //U
-0.4f, 0.05f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 1.0f, //Q
-0.2f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //W
-0.4f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 0.0f, //R
-0.4f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.3f, 0.0f, //R
-0.2f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //A
-0.2f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //W
-0.2f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //W
-0.2f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 0.0f, //A_1
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //A
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //A
-0.2f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.6f, 1.0f, //A_1
0.0f, -0.05f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //B
//Bottom of Scoop Slant //Negative X
-0.6f, 0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.6f, //U
-0.6f, 0.1f, -0.1f, -1.0f, 0.0f, 0.0f, 0.0f, 0.3f, //V
-0.4f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 0.3f, 1.0f, //R
-0.4f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 0.3f, 1.0f, //R
-0.4f, -0.1f, -0.2f, -1.0f, 0.0f, 0.0f, 0.3f, 0.0f, //T
-0.6f, 0.1f, -0.1f, -1.0f, 0.0f, 0.0f, 0.0f, 0.3f, //V
//Bottom of Scoop //Negative Y
-0.4f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.3f, 0.0f, //T
-0.4f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.3f, 1.0f, //R
-0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.6f, 0.0f, //B_1
-0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.6f, 0.0f, //B_1
-0.4f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.3f, 1.0f, //R
-0.2f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.6f, 1.0f, //A_1
-0.2f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.6f, 1.0f, //A_1
-0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.3f, 0.0f, //B_1
0.0f, -0.05f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.6f, //B
-0.2f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.6f, 0.0f, //B_1
0.0f, -0.05f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.6f, //B
0.0f, -0.05f, -0.1f, 0.0f, -1.0f, 0.0f, 1.0f, 0.3f, //D
//Back of Scoop //Negative Z
-0.6f, 0.1f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, //V
-0.4f, 0.05f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 1.0f, //S
-0.4f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 0.0f, //T
-0.4f, 0.05f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 1.0f, //S
-0.4f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 0.0f, //T
-0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1
-0.4f, 0.05f, -0.2f, 0.0f, 0.0f, -1.0f, 0.3f, 1.0f, //S
-0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1
-0.2f, 0.0f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 1.0f, //Z
-0.2f, 0.0f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 1.0f, //Z
-0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1
0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //C
0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //C
-0.2f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.6f, 0.0f, //B_1
0.0f, -0.05f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, //D
//Top of Scoop //Positive Y
-0.6f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.3f, //U
-0.6f, 0.1f, -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 0.6f, //V
-0.4f, 0.05f, -0.2f, 0.0f, 1.0f, 0.0f, 0.3f, 1.0f, //S
-0.6f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.3f, //U
-0.4f, 0.05f, -0.2f, 0.0f, 1.0f, 0.0f, 0.3f, 1.0f, //S
-0.4f, 0.05f, 0.1f, 0.0f, 1.0f, 0.0f, 0.3f, 0.0f, //Q
-0.4f, 0.05f, -0.2f, 0.0f, 1.0f, 0.0f, 0.3f, 1.0f, //S
-0.4f, 0.05f, 0.1f, 0.0f, 1.0f, 0.0f, 0.3f, 0.0f, //Q
-0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z
-0.4f, 0.05f, 0.1f, 0.0f, 1.0f, 0.0f, 0.3f, 0.0f, //Q
-0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z
-0.2f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, 0.6f, 0.0f, //W
-0.2f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, 0.6f, 0.0f, //W
-0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.3f, //A
-0.2f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.6f, 1.0f, //Z
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.3f, //A
0.0f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 1.0f, 0.6f, //C
//Front of Handle //Positive Z
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.1f, //A
0.0f, -0.05f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //B
0.6f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //E
0.6f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //E
0.0f, -0.05f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //B
0.6f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //F
//Bottom of Handle //Negative Y
0.0f, -0.05f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, //B
0.0f, -0.05f, -0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, //D
0.6f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, //F
0.0f, -0.05f, -0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, //D
0.6f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, //F
0.6f, -0.1f, -0.1f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, //H
//Back of Handle //Negative Z
0.0f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, //C
0.0f, -0.05f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //D
0.6f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //G
0.0f, -0.05f, -0.1f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //D
0.6f, 0.0f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //G
0.6f, -0.1f, -0.1f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, //H
//Top of Handle //Positive Y
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, //A
0.0f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //C
0.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, //E
0.0f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //C
0.6f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, //E
0.6f, 0.0f, -0.1f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //G
//Grip Connection //Negative X
0.6f, 0.0f, 0.1f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //I
0.6f, 0.0f, -0.2f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, //J
0.6f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, //K
0.6f, 0.0f, -0.2f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, //J
0.6f, -0.1f, 0.1f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, //K
0.6f, -0.1f, -0.2f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //L
//Front to Grip //Positive Z
0.6f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, //I
1.0f, 0.0f, 0.05f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //M
0.6f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //K
1.0f, 0.0f, 0.05f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, //M
0.6f, -0.1f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, //K
1.0f, -0.1f, 0.05f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //N
//Bottom to Grip //Negative Y
0.6f, -0.1f, 0.1f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, //K
1.0f, -0.1f, 0.05f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, //N
0.6f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, //L
1.0f, -0.1f, 0.05f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, //N
0.6f, -0.1f, -0.2f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, //L
1.0f, -0.1f, -0.15f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, //P
//Back to Grip //Negative Z
0.6f, 0.0f, -0.2f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, //J
0.6f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //L
1.0f, 0.0f, -0.15f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //O
0.6f, -0.1f, -0.2f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, //L
1.0f, 0.0f, -0.15f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, //O
1.0f, -0.1f, -0.15f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, //P
//Top to Grip //Positive Y
1.0f, 0.0f, -0.15f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //O
1.0f, 0.0f, 0.05f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, //M
0.6f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //J
1.0f, 0.0f, 0.05f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0, //M
0.6f, 0.0f, -0.2f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, //J
0.6f, 0.0f, 0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, //I
//Base of Grip //Positive X
1.0f, 0.0f, 0.05f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, //M
1.0f, -0.1f, 0.05f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //N
1.0f, 0.0f, -0.15f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //O
1.0f, -0.1f, 0.05f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //N
1.0f, 0.0f, -0.15f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, //O
1.0f, -0.1f, -0.15f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f //P
};
//Generate buffer ids
glGenVertexArrays(1, &SpoonVAO);
glGenBuffers(1, &VBO);
//Activate the Vertex Array Object before binding and setting any VBOs and Vertex Attribute Pointers.
glBindVertexArray(SpoonVAO);
//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, 8 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); //Enables vertex attribute
//Set attribute pointer 1 to hold Normal data
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1); //Enables vertex attribute
//Set attribute pointer 2 to hold Texture coordinate data
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0); //Deactivate the Spoon VAO which is good practice
}
void pressSpecialKey(int key, int xx, int yy)
{
switch(key){
//Zoom object in
case GLUT_KEY_UP:
front.x += 0.1f;
front.y += 0.1f;
front.z += 0.1f;
break;
//Zoom object out
case GLUT_KEY_DOWN:
front.x -= 0.1f;
front.y -= 0.1f;
front.z -= 0.1f;
break;
//Change view to orthogonal state
case GLUT_KEY_LEFT:
view_state = 0;
break;
//Change view to perspective state
case GLUT_KEY_RIGHT:
view_state = 1;
break;
}
}
/*Implements the UMouseMove function*/
void UMouseMove(int x, int y)
{
//Immediately replaces center locked coordinated 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;
//Maintains a 90 degree pitch for gimbal lock
if(pitch > 89.0f)
pitch = 89.0f;
if(pitch < -89.0f)
pitch = -89.0f;
//Converts mouse coordinates / degrees into Radians, then to vectors
front.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw));
front.y = sin(glm::radians(pitch));
front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
}
/*Generate and load the texture*/
void UGenerateTexture(){
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
int width, height;
unsigned char* image = SOIL_load_image("spoon.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
}
Expected: Spoon in center of the screen, mousemovement changes the camera view (horizontally and vertically), up arrow causes camera to zoom in, and down arrow causes camera to zoom out.
Actual: Spoon not in center. Mousemovement causes the object to move (horizontally and vertically). Arrows not detected (?).
Zooming at perspective projection can be achieved by shifting the the camera position along the line of sight:
void pressSpecialKey(int key, int xx, int yy)
{
switch(key){
case GLUT_KEY_UP: cameraPosition += front * 0.1f; break;
case GLUT_KEY_DOWN: cameraPosition -= front * 0.1f; break;
// [...]
}
or by changing the field of view angle:
float fov_angle = 45.0f;
projection = glm::perspective(glm::radians(fov_angle),
(GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
void pressSpecialKey(int key, int xx, int yy)
{
switch(key){
case GLUT_KEY_UP: fov_angle -= 0.1f; break;
case GLUT_KEY_DOWN: fov_angle += 0.1f; break;
// [...]
}
If you want to keep the spoon in the center of the view ant to orbit around the spoon, then you've to change the camera position according to the viewing direction:
void UMouseMove(int x, int y)
{
// [...]
cameraPosition = - front * glm::length( cameraPosition );
}
The matrices of the OpenGL Mathematics (GLM) have to be initialized. An identity matrix can be initialized by the single parameter 1.0:
e.g.
glm::mat4 model(1.0f);
The angles which are passed to the OpenGL Mathematics (GLM) library functions have to be set in radians rather than degrees. (In glm version 0.9.4 or less this was different).
glm::perspective():
LM_FUNC_DECL tmat4x4<T, defaultp> glm::perspective(T fovy, T aspect, T near, T far)
Creates a matrix for a symetric perspective-view frustum based on the default handedness.
Parameters
fovy Specifies the field of view angle in the y direction. Expressed in radians.
glm::rotate()
GLM_FUNC_DECL mat<4, 4, T, Q> glm::rotate (mat< 4, 4, T, Q > const & m, T angle, vec<3, T, Q> const & axis)
Builds a rotation 4 * 4 matrix created from an axis vector and an angle.
Parameters
angle Rotation angle expressed in radians.
Initialize the matrices and use glm::radians() to convert from degree to radians:
//Transforms the object
glm::mat4 model(1.0f); // <--- init
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));
model = glm::rotate(model, glm::radians(45.0f), glm:: vec3(0.0, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); //Increase the object size by a scale of 2
//Transform the camera
glm::mat4 view(1.0f); // <--- init
view = glm::lookAt(cameraPosition - CameraForwardZ, cameraPosition, CameraUpY);
//Creates a perspective projection
glm::mat4 projection(1.0f); // <--- init
if(view_state == 1){
// projection = glm::perspective(45.0f,
(GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
projection = glm::perspective(glm::radians(45.0f),
(GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
} else if(view_state == 0){
projection = glm::ortho(-5.0f, 5.0f, -5.0f, 5.0f, 0.1f, 100.0f);
}

How to rotate Cubemap face without memory copy in OpenGL?

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).

OpenGL - Going 3D

I have a script that I am unable to make fully 3D. So far on ortho the background shows up only. In perspective, almost nothing shows up but when I move the camera it does change color.
projection = glm::perspective(glm::radians(44.0f), static_cast<GLfloat>(Width) / static_cast<GLfloat>(Height), 0.1f, 100.0f);
projection = glm::ortho(0.0f, static_cast<GLfloat>(Width), static_cast<GLfloat>(Height), 0.0f, -1.0f, 1.0f);
See below for images:
Image 1:
3D version - Ortho
Image 2:
3D version - Ortho
Image 3:
2D version - Stable and works perfectly
Here is my code that creates and renders sprites:
#ifndef SPRITE_H
#define SPRITE_H
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "ShaderClass.h"
#include "TextureClass.h"
class Sprite
{
public:
Shader shader;
// Set up Vertex Array Object && Vertex Buffer Object
GLuint VAO,
VBO;
// Constructor
Sprite(Shader &shader){ this->shader = shader; setBuffers(); }
// Deconstructor
~Sprite(){ glDeleteVertexArrays(1, &VAO); }
// Initializes and configures the buffers and vertex attributes
void setBuffers()
{
// Define vertices for the sprite
GLfloat vertices[] = {
// x y z u v
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 0.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,
0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.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, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.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,
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, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
//
// OpenGL buffers
// Initialization code using Vertex Array Object (VAO) (done once (unless the object frequently changes))
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Copy our vertices array in a buffer for OpenGL to use
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Bind Vertex Array Object
glBindVertexArray(VAO);
//Attributes
glEnableVertexAttribArray(0); // location = 0
glVertexAttribPointer(
0, // location = 0
3, // 3 components (x, y, z)
GL_FLOAT, GL_FALSE,
5 * sizeof(GLfloat), // stride: 5 * float (x, y, z, u, v)
(GLvoid*)0); // offset: 0
glEnableVertexAttribArray(1); // location = 1
glVertexAttribPointer(
1, // location = 1
2, // 2 components (u, v)
GL_FLOAT, GL_FALSE,
5 * sizeof(GLfloat), // stride: 5 * float (x, y, z, u, v)
(GLvoid*)(3 * sizeof(GLfloat))); // offset: 3 * float (x, y, z)
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Unbind the VAO
glBindVertexArray(0);
}
// Renders the sprite
void DrawSprite(Texture &texture, glm::vec2 position, glm::vec2 size = glm::vec2(10, 10), GLfloat rotate = 0.0f, glm::vec3 colour = glm::vec3(1.0f))
{
// Apply the shader
this->shader.Use();
// Transform the object
glm::mat4 transformObject;
transformObject = glm::translate(transformObject, glm::vec3(position, 0.0f));
transformObject = glm::translate(transformObject, glm::vec3(0.5f * size.x, 0.5f * size.y, 0.0f));
transformObject = glm::rotate(transformObject, rotate, glm::vec3(0.0f, 0.0f, 1.0f));
transformObject = glm::translate(transformObject, glm::vec3(-0.5f * size.x, -0.5f * size.y, 0.0f));
transformObject = glm::scale(transformObject, glm::vec3(size, 1.0f));
this->shader.SetVector3f("spriteColour", colour);
this->shader.SetMatrix4("transformObject", transformObject);
glActiveTexture(GL_TEXTURE0);
// Bind the appropriate texture to *this* model
texture.Bind();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36 * 5);
glBindVertexArray(0);
}
};
#endif
These are the shaders that I am using:
Vertex shader:
#version 440 core
layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoords;
uniform mat4 transformObject;
uniform mat4 view;
uniform mat4 projection;
void main()
{
TexCoords = vec2(texCoord.x, texCoord.y);
gl_Position = projection * view * transformObject * vec4(Position.x, Position.y, Position.z, 1.0);
}
Fragment shader:
#version 440 core
in vec2 TexCoords;
out vec4 colour;
uniform sampler2D tex;
uniform vec3 spriteColour;
void main()
{
colour = vec4(spriteColour, 1.0) * texture(tex, TexCoords);
}

OpenGL : second VBO spoiling first VBO

I have a code that initially had one shader (ourShader), one VAO and one VBO. It would render a scene with a textured cube and its reflection on the ground using Stencil testing. Now, I wanted to add a framebuffer for post-processing so I needed a second shader. I added a second shader (screenShader) and a second VBO. I don't use them in my drawing yet, but the simple fact that I'm adding them makes my code render a black, red triangle instead of the usual scene.
My code looks like this :
Shader ourShader(string("core.vs"), string("core.frag")); // shader class creating a shader program from vertex shader and fragment shader source files.
Shader screenShader(string("core2.vs"), string("core2.frag"));
// Setting up attributes, VAO, VBO
GLuint VAO;
array<GLuint, 2> VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(2, &VBO[0]);
glBindVertexArray(VAO);
// Data for first shader and first VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesCube), verticesCube, GL_STATIC_DRAW);
GLint posAttribLoc = glGetAttribLocation(ourShader.Program, "position");
glVertexAttribPointer(posAttribLoc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0); // specify (to the active VAO) how to retrieve the values for the attribute "position" from the data stored ("vertices" here) on the active VBO (GPU)
glEnableVertexAttribArray(posAttribLoc); // enable attribute for rendering
GLint colAttribLoc = glGetAttribLocation(ourShader.Program, "color");
glVertexAttribPointer(colAttribLoc, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(colAttribLoc);
GLint texAttribLoc = glGetAttribLocation(ourShader.Program, "texCoord");
glVertexAttribPointer(texAttribLoc, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(texAttribLoc);
// ##### PART GIVING A WEIRD RESULT #####
// Data for second shader and second VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(verticesRectangle), verticesRectangle, GL_STATIC_DRAW);
GLint posAttribLoc2 = glGetAttribLocation(screenShader.Program, "position");
glVertexAttribPointer(posAttribLoc2, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); // specify (to the active VAO) how to retrieve the values for the attribute "position" from the data stored ("vertices" here) on the active VBO (GPU)
glEnableVertexAttribArray(posAttribLoc2); // enable attribute for rendering
GLint texAttribLoc2 = glGetAttribLocation(screenShader.Program, "texCoord");
glVertexAttribPointer(texAttribLoc2, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(texAttribLoc2);
// ##### END #####
// Setting up texture that will be used for the first shader
GLuint texture;
int width, height;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture); // makes "texture" the current texture and attaches it to texture unit 0
// Set the wrapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// Set the filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
// Unbind VBO, texture before main loop
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glfwSwapInterval(1);
glfwSetKeyCallback(window, Input::keyCallback); // Input is a singleton class handling inputs. It works well.
glfwSetCursorPosCallback(window, Input::mouseCallback);
glfwSetScrollCallback(window, Input::scrollCallback);
while (glfwWindowShouldClose(window) == GLFW_FALSE) {
// MAIN LOOP
// ...
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(2, &VBO[0]);
The mainloop is not important I think. What I want to say is that if I remove the few lines dealing with the the second VBO, then the scene renders well. Otherwise, I get a weird-colored triangle.
And my two shaders use those source files for their respective vertex shader and fragment shader. By the way, I get no compilation errors from my shaders.
core.vs :
#version 330 core
in vec3 position;
in vec2 texCoord;
in vec3 color;
out vec2 TexCoord;
out vec3 Color;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection*view*model*vec4(position, 1.0);
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y);
Color = color;
}
core.frag :
#version 330 core
in vec2 TexCoord;
in vec3 Color;
out vec4 outColor;
uniform sampler2D ourTexture0;
void main()
{
outColor = vec4(Color, 1)*texture(ourTexture0, TexCoord);
}
core2.vs :
#version 330 core
in vec2 position;
in vec2 texCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
TexCoord = texCoord;
}
core2.frag :
#version 330 core
in vec2 TexCoord;
out vec4 outColor;
uniform sampler2D texFramebuffer;
void main()
{
outColor = texture(texFramebuffer, TexCoord);
}
The vertices look like this (but only the way to read them is important) :
GLfloat verticesRectangle[] = {
// position // texture coordinates
-0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 1.0f, 1.0f
};
GLfloat verticesCube[] = {
// position // color // texture coordinates
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // reflection surface // not a part of the cube itself
-1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1.0f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
};
I've already looked at Binding a second vertex buffer seems to spoil my first vertex buffer, OpenGL OES ios 5.1 but the person had this problem because he didn't use his VAO correctly.
Most probably two of your attribute locations have the same value. Since you use just one VAO, you override some of the bindings. The correct way of using multiple independent geometries is to use on VAO per geometry.
The correct code has to look somehow like this:
glBindVertexArray(vao1);
glBindBuffer(VBO[0])
glVertexAttribPointer...
glEnableVertexAttribArray...
//Setup all attributes for first VBO
glBindVertexArray(vao2);
glBindBuffer(VBO[1])
glVertexAttribPointer...
glEnableVertexAttribArray...
//Setup all attributes for second VBO
When rendering do the following:
glBindVertexArray(vao1);
glDraw*... //Draw VAO1
glBindVertexArray(vao2);
glDraw*.... //Draw VAO2

OpenGL: Skybox magnified too much

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