As the title says, I'm trying to render a cube using the code below (plus a custom Shader class and the actual shaders omitted for brevity) to render a tilted cube turning on the Y axis.
The problem is with the texture: if I just download some .png
from Google Images it renders just fine, but if I create some random texture using MS Paint and only change the file path to said MS Paint texture I get an Exception thrown at 0x00007FFA3BEADB68 (nvoglv64.dll) in Untitled_OpenGL_Project.exe: 0xC0000005: Access violation reading location 0x000001F6A94A2000.
exception.
What is the problem? Is it something to do with the value for transparent pixels or something? (grasping at straws here)
main.cpp:
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Shader.h"
#include "utils.h"
#include "stb_image.h"
int main()
{
// Setup
if (!Utility::glfwSetup())
return -1;
GLFWwindow* window = Utility::glfwOpenWindow(Utility::SCREEN_WIDTH, Utility::SCREEN_HEIGHT, "GLFW Window");
glfwMakeContextCurrent(window);
if (!Utility::gladSetup())
return -1;
glfwSetKeyCallback(window, Utility::key_callback);
glEnable(GL_DEPTH_TEST);
// Program
glViewport(0, 0, 800, 600);
float vertices[] = {
// Position // Texel
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f
};
unsigned int indices[] = {
0, 1, 3,
0, 2, 3,
4, 5, 7,
4, 6, 7,
8, 9, 11,
8, 10, 11,
12, 13, 15,
12, 14, 15,
16, 17, 19,
16, 18, 19,
20, 21, 23,
20, 22, 23
};
// Buffer setup
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
float tiltAngle = 70.0f;
// MVP
glm::mat4 model = glm::mat4(1.0f);
glm::vec3 zAxis = glm::vec3(0.0f, 0.0f, 1.0f);
model = glm::rotate(model, (float) glm::radians(tiltAngle), zAxis);
glm::mat4 view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float) Utility::SCREEN_WIDTH / Utility::SCREEN_HEIGHT, 0.1f, 100.0f);
// Texture
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
Utility::texSetup(GL_REPEAT, GL_REPEAT, GL_NEAREST, GL_LINEAR);
int width, height, numChannels;
unsigned char* data = stbi_load("res/textures/BlackFrame.png", &width, &height, &numChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
// Shader setup
Shader shader("res/shaders/VertexShader.shader", "res/shaders/FragShader.shader");
glUseProgram(shader.ID);
shader.setUniformMat4f(model, "model");
shader.setUniformMat4f(view, "view");
shader.setUniformMat4f(proj, "proj");
shader.setUniform1i(0, "texture1");
// Time
float prevTime = (float)glfwGetTime();
while (!glfwWindowShouldClose(window))
{
// Setup
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Input
Utility::processInput(window);
// Rendering
float curTime = (float)glfwGetTime();
float deltaTime = curTime - prevTime;
prevTime = curTime;
// Rotate around Y axis
glm::vec3 yAxis = glm::vec3(0.0f, 1.0f, 0.0f);
model = glm::rotate(model, (float)glm::radians(-tiltAngle), zAxis);
model = glm::rotate(model, deltaTime, yAxis);
model = glm::rotate(model, (float)glm::radians(tiltAngle), zAxis);
shader.setUniformMat4f(model, "model");
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
// Clean-up
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
utils.cpp:
int Utility::glfwSetup()
{
if (!glfwInit())
{
std::cerr << "Failed to initialize GLFW" << std::endl;
return 0;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, VERSION_MAJOR);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, VERSION_MINOR);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
std::cout << "GLFW " << VERSION_MAJOR << "." << VERSION_MINOR << " initialized successfully." << std::endl;
return 1;
}
int Utility::gladSetup()
{
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
glfwTerminate();
return 0;
}
return 1;
}
void Utility::texSetup(int wrapParamS, int wrapParamT, int minParam, int magParam)
{
stbi_set_flip_vertically_on_load(true);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapParamS);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapParamT);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magParam);
}
GLFWwindow* Utility::glfwOpenWindow(int width, int height, const char* title)
{
GLFWwindow* window = glfwCreateWindow(width, height, title, NULL, NULL);
if (window == NULL)
{
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return NULL;
}
return window;
}
void Utility::processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
CodePudding user response:
It is not guaranteed that a PNG file has 4 channels or that stbi_load
will return an image with 4 channels.
stbi_load
can be forced to generate an image with 4 color channels, by explicitly pass 4 to the last parameter:
unsigned char* data = stbi_load("BlackFrame.png", &width, &height, &numChannels, 0);
unsigned char* data = stbi_load("BlackFrame.png", &width, &height, &numChannels, 4);
See stb_image.h:
Basic usage (see HDR discussion below for HDR usage): int x,y,n; unsigned char *data = stbi_load(filename, &x, &y, &n, 0); // ... process data if not NULL ... // ... x = width, y = height, n = # 8-bit components per pixel ... // ... replace '0' with '1'..'4' to force that many components per pixel // ... but 'n' will always be the number that it would have been if you said 0 stbi_image_free(data);