I am trying to upload volumetric data as a 3D texture via OpenGL. However, when specifying the formats and data itself through glTexImage3D, an GL_INVALID_OPERATION error is thrown.
The code (including the debugging code I added to find out where the error was comming from) is the following:
void Texture3D::upload()
{
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenTextures(1, &_textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glBindTexture(GL_TEXTURE_3D, _textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexStorage3D(GL_TEXTURE_3D, 6, GL_R8, _width, _height, _depth);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, _width, _height, _depth, 0, GL_RED, GL_UNSIGNED_BYTE, _data);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenerateMipmap(GL_TEXTURE_3D);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
}
I thought it might be an GL_INVALID_VALUE for any of the format, internal format, or pixel format I am specifying in the glTexImage3D, however I have checked with the documentation of glTexImage3D and everything seems correct.
I have created a minimal, verifiable example (using GLFW and GLEW)
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLFWwindow * _window = nullptr;
unsigned int _textureId = GL_INVALID_VALUE;
void initGLFWContext()
{
if (!glfwInit())
{
std::cerr << "GLFW: Couldnt initialize" << std::endl;
exit(-1);
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
_window = glfwCreateWindow(1024, 1024, "Test Window", NULL, NULL);
if (!_window)
{
std::cerr << "GLFW Error: Couldnt create window" << std::endl;
glfwTerminate();
exit(-1);
}
//glfwSetKeyCallback(_window, kbCb);
//glfwSetCursorPosCallback(_window, mmCb);
//glfwSetMouseButtonCallback(_window, mCb);
//glfwSetFramebufferSizeCallback(_window, resizeCb);
glfwMakeContextCurrent(_window);
glfwSetWindowPos(_window, 0, 0);
glfwSwapInterval(1);
// Initializes glew
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
std::cerr << "GLEW Error: " << glewGetErrorString(err) << std::endl;
exit(-1);
}
}
void initOpenGL()
{
glEnable(GL_DEPTH_TEST);
//glEnable(GL_BLEND);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glFrontFace(GL_CCW);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_CULL_FACE);
}
void minimalVerifiableExample()
{
initGLFWContext();
initOpenGL();
const unsigned int volSide = 256;
const unsigned int volumeSize = volSide * volSide * volSide;
unsigned char * volumeData = new unsigned char[volumeSize]();
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenTextures(1, &_textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glBindTexture(GL_TEXTURE_3D, _textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexStorage3D(GL_TEXTURE_3D,
6,
GL_R8,
volSide,
volSide,
volSide);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexImage3D(GL_TEXTURE_3D,
0,
GL_R8,
volSide,
volSide,
volSide,
0,
GL_RED,
GL_UNSIGNED_BYTE,
volumeData);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenerateMipmap(GL_TEXTURE_3D);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
while(!glfwWindowShouldClose(_window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwPollEvents();
glfwSwapBuffers(_window);
}
glfwDestroyWindow(_window);
glfwTerminate();
delete[] volumeData;
}
int main(int argc, char ** argv)
{
(void) argc;
(void) argv;
minimalVerifiableExample();
return 0;
}
And this is the output I get:
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 1282
TEX GL ERROR: 0
Am I doing something wrong when uploading the texture or anywhere else?
1282 is a GL_INVALID_OPERATION and is caused by the combination of
glTexStorage3D
glTexImage3D
It is not allowed to recreate the storage for an immutable storage texture object. After calling glTexStorage3D, the texture uses immutable storage. glTexImage3D requests a new storage which is not allowed anymore.
If you try to upload data to the immutable storage texture object, you'll have to use glTexSubImage3D instead which will upload data but not request new storage.
Related
Using the normalized [-1,1] points A = (0.5, 0.5), B = (0.5, -0.5), C = (-0.5, -0.5), and D = (-0.5, 0.5), I'm drawing these points as pixels with glDrawArrays(GL_POINTS, 0, 4). I found that when I also call glDrawArrays(GL_LINES, 0, 4) to draw the 2 lines AB and CD there's a 1 pixel difference in the x-direction between the points and the endpoints of the 2 lines. Here's a screenshot of what I'm seeing:
I was also able to get this problem to go away if I changed the window size from 800x600 to 850x600. I'm thinking this might have to do with odd or even size window width, but I'm not sure. In my code, you can comment out #define SHOW_PROBLEM to change the window size where the problem doesn't occur. Any ideas would be greatly appreciated!
Here's my complete code for reference:
#include <bits/stdc++.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
void framebuffer_size_callback(GLFWwindow * window, int width, int height);
void processInput(GLFWwindow * window);
#define SHOW_PROBLEM
#ifdef SHOW_PROBLEM
// These dimensions show the problem
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#else
// These dimensions DO NOT show the problem
#define WINDOW_WIDTH 850
#define WINDOW_HEIGHT 600
#endif
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow * window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "OpenGLDemo", nullptr, nullptr);
if (!window)
{
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Failed to create GLFW window!"
<< std::nounitbuf << std::endl;
glfwTerminate();
std::abort();
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)))
{
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Failed to initialize GLAD!"
<< std::nounitbuf << std::endl;
std::abort();
}
// vertex shader
const char * vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Vertex shader compilation failed!"
<< "\n[ERROR] " << infoLog
<< std::nounitbuf << std::endl;
std::abort();
}
// fragment shader
const char * fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Fragment shader compilation failed!"
<< "\n[ERROR] " << infoLog
<< std::nounitbuf << std::endl;
std::abort();
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Shader program linking failed!"
<< "\n[ERROR] " << infoLog
<< std::nounitbuf << std::endl;
std::abort();
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
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, 3 * sizeof(float), reinterpret_cast<void *>(0));
glEnableVertexAttribArray(0);
// 6. render loop
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
while (!glfwWindowShouldClose(window))
{
processInput(window);
// background
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glDrawArrays(GL_POINTS, 0, 4);
glDrawArrays(GL_LINES, 0, 4);
// check and call events and swap the buffers
glfwPollEvents();
glfwSwapBuffers(window);
}
// de-allocate all resources once they've outlived their purpose:
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow * window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow * window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
}
This may also be useful:
OpenGL vendor string: Intel
OpenGL renderer string: Mesa Intel(R) UHD Graphics 620 (KBL GT2)
OpenGL core profile version string: 4.6 (Core Profile) Mesa 20.0.8
OpenGL core profile shading language version string: 4.60
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.6 (Compatibility Profile) Mesa 20.0.8
OpenGL shading language version string: 4.60
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 20.0.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:
for GL_LINES the rasterizer would have to interpolate across two vertices, and with any other interpolated values from the vertex to fragment shaders, you should not rely on some kind of equality between hardcoded values and the interpolated. The resizing of windows tells you that the difference is just due to this interpolation/float error. If you goal is to color the vertices, try adding logic in your shader to check whether the current pixel fragment is very close to the 2 vertices it's interpolated from and color accordingly.
I recently started following an OpenGL tutorial series by TheCherno on youtube.
Here is my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
struct ShaderProgramSource {
std::string VertexSource;
std::string FragmentSource;
};
static ShaderProgramSource ParseShader(const std::string& filepath) {
std::ifstream stream(filepath);
enum class ShaderType {
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line)) {
if (line.find("#shader") != std::string::npos) {
if (line.find("vertex") != std::string::npos)
type = ShaderType::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = ShaderType::FRAGMENT;
} else {
ss[(int)type] << line << '\n';
}
}
return { ss[0].str(), ss[1].str() };
}
static unsigned int CompileShader(unsigned int type, const std::string& source) {
std::cout << "Compiling " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader..." << std::endl;
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
std::cout << glGetError() << std::endl;
glCompileShader(id);
std::cout << glGetError() << std::endl;
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
std::cout << glGetError() << std::endl;
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
std::cout << glGetError() << std::endl;
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << glGetError() << std::endl;
std::cout << "Failed to compile" << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
std::cout << glGetError() << std::endl;
return 0;
}
std::cout << "Successfully compiled " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl << std::endl;
return id;
}
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {
std::cout << "Creating shader..." << std::endl << std::endl;
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
std::cout << glGetError() << std::endl;
std::cout << "Attached vertex shader" << std::endl;
glAttachShader(program, fs);
std::cout << glGetError() << std::endl;
std::cout << "Attached fragment shader" << std::endl;
glLinkProgram(program);
std::cout << glGetError() << std::endl;
glValidateProgram(program);
std::cout << glGetError() << std::endl;
std::cout << "Linked and validated program" << std::endl;
glDeleteShader(vs);
std::cout << glGetError() << std::endl;
std::cout << "Deleted vertex shader" << std::endl;
glDeleteShader(fs);
std::cout << glGetError() << std::endl;
std::cout << "Deleted fragment shader" << std::endl;
std::cout << "Succesfully created shader!" << std::endl << std::endl;
return program;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
std::cout << "Error!" << std::endl;
}
std::cout << glGetString(GL_VERSION) << std::endl;
float positions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
std::cout << glGetError() << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, buffer);
std::cout << glGetError() << std::endl;
glBufferData(GL_ARRAY_BUFFER, 6*sizeof(float), positions, GL_STATIC_DRAW);
std::cout << glGetError() << std::endl;
glDisableVertexAttribArray(0);
std::cout << glGetError() << std::endl;
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, 0);
std::cout << glGetError() << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, 0);
std::cout << glGetError() << std::endl;
ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");
std::cout << "VERTEX" << std::endl;
std::cout << source.VertexSource << std::endl;
std::cout << "FRAGMENT" << std::endl;
std::cout << source.FragmentSource << std::endl;
//unsigned int shader = CreateShader(vertexShader, fragmentShader);
///glUseProgram(shader);
// render loop
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
//glDeleteProgram(shader);
glfwTerminate();
return 0;
}
Here's the Basic.shader file:
#shader vertex
#version 330 core
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
#shader fragment
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 0.0, 0.0, 1.0);
}
I have tried using glGetError and it doesn't output any errors.
You need to enable the generic vertex attribute array instead of disabling it (see glEnableVertexAttribArray):
glDisableVertexAttribArray(0);
glEnableVertexAttribArray(0);
Furthermore, the code which compiles, linkes and installs the sahder is commented out:
//unsigned int shader = CreateShader(vertexShader, fragmentShader);
///glUseProgram(shader);
unsigned int shader = CreateShader(source.VertexSource, source.FragmentSource);
glUseProgram(shader);
I believe #Rabbid76's answer is correct. If it still does not work, make sure you are using compatible OpenGL context or create a VAO to hold the state.
Compatible OpenGL context can be set with:
//Before glfwCreateWindow call, after glfwInit
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
The default value is GLFW_OPENGL_ANY_PROFILE and this could mean CORE if COMPAT is not available. This ensures that a default VAObject always exist and is bound. Meaning that your glVertexAttribPointer calls actually have a place to store that information. I did not see these Cherno's tutorials, it's quite possible that VAOs are covered in the future tutorials. In CORE there will not be one and it might not draw anything.
While we are here, it is not a bad idea to set minimal OpenGL version required precisely. If for some reason it is not available on the target machine, the window creation will fail. This is more preferable than getting "random" seg faults when calling unsupported functions.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
My preferred way would be to create an actual VAO and go with GLFW_OPENGL_CORE_PROFILE. But feel free to go with tutorials, the ones I've seen from him are really high-quality.
//Put these before the vertex buffer initialization
int VAO;
glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
I just migrated it an single animation app (just one model) from GLFW+AntTweakBar to SDL2+ImGui .
OpenGL code is the same but i am seem to experiencing more than half of FPS drop
with SDL2+ImGui .
While on GLFW i have an average fps of 100 and on SDL2 i have an average of 30-40.
SDL/GL init code is below :
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, ¤t);
gWindow = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (gWindow == NULL)
{
std::cout << "Window could not be created! SDL Error: " << SDL_GetError() << std::endl;
success = false;
}
else
{
std::cout << std::endl << "Yay! Created window sucessfully!" << std::endl << std::endl;
//Create context
gContext = SDL_GL_CreateContext(gWindow);
if (gContext == NULL)
{
std::cout << "OpenGL context could not be created! SDL Error: " << SDL_GetError() << std::endl;
success = false;
}
else
{
//Initialize GLEW
glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if (glewError != GLEW_OK)
{
std::cout << "Error initializing GLEW! " << glewGetErrorString(glewError) << std::endl;
}
//Use Vsync
if (SDL_GL_SetSwapInterval(1) < 0)
{
std::cout << "Warning: Unable to set Vsync! SDL Error: " << SDL_GetError << std::endl;
}
If i try setting SDL_GL_SetSwapInterval(0) for immediate update i get an average of 60FPS but it still doesn't look smooth and there is small tearing on the model.
I tried removing the ImGui code and it's a better as it ought to be but still much worse performance .
Is this normal ?
if i try to load a Texture i get this error:
Access violation reading location.
Unhandled exception at 0x651B5A17 (nvcuda.dll) in nsighttest.exe: 0xC0000005: Access violation reading location 0x00000010.
image:
http://img5.fotos-hochladen.net/uploads/error1wlbsuf0iv.png
Debug image:
http://img5.fotos-hochladen.net/uploads/debugatc1xerob5.png
unsigned int loadTexture(const char* filename, texProperties properties)
{
GLint numberofcolors = 0;
GLenum format;
SDL_Surface * img = IMG_Load(filename);
cout << "Image height: " << img->h << endl;
cout << "Image width: " << img->w << endl;
cout << "Images Pixels: " << img->pixels << endl;
cout << "Images BitsPerPixel: " << img->format->BitsPerPixel << endl;
cout << "Images Rmask: " << img->format->Rmask << endl;
cout << "Images Surface: " << img << endl;
if(!(&img)) { std::cout << "Fehler beim laden des bildes: " << filename; std::cout << std::endl; }
if(img->format->BitsPerPixel == 4) {
if(img->format->Rmask == 0x000000ff) { format = GL_RGBA; }
else { format = GL_BGRA; }
numberofcolors = 4;
} else {
if(img->format->Rmask == 0x000000ff) { format = GL_RGB; }
else { format = GL_BGR; }
numberofcolors = 3;
}
unsigned int id;
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, properties.getMagFilter());
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, properties.getMinFilter());
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, properties.getTextureWrap());
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, properties.getTextureWrap());
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, properties.getAnisotropy());
glTexImage2D(GL_TEXTURE_2D, 0 , numberofcolors=4?GL_RGBA:GL_RGB, img->w, img->w, 0, format, GL_UNSIGNED_BYTE, img->pixels);
SDL_FreeSurface(img);
return id;
}
The error comes from "glTexImage2D(...)".
Looking at the glTexImage2D() function, it looks like you are using
img->w twice, rather than using img->h for the second one.
Try calling
glTexImage2D(GL_TEXTURE_2D, 0 , numberofcolors=4?GL_RGBA:GL_RGB, img->w, /*Use height as second parameter, rather than width!*/img->h, 0, format, GL_UNSIGNED_BYTE, img->pixels);
Instead.
I am trying to hide the marker im artoolkit and in my research i found this code for alvar, it's a free AR toolkit made by a research technical center in finland.
This code helps hiding the marker but its in opencv, but i want to do the same in simpleVRML example.
Any help how can i change this code for the artoolkit example?
#include "CvTestbed.h"
#include "MarkerDetector.h"
#include "GlutViewer.h"
#include "Shared.h"
using namespace alvar;
using namespace std;
#define GLUT_DISABLE_ATEXIT_HACK // Needed to compile with Mingw?
#include <GL/gl.h>
const double margin = 1.0;
std::stringstream calibrationFilename;
// Own drawable for showing hide-texture in OpenGL
struct OwnDrawable : public Drawable {
unsigned char hidingtex[64*64*4];
virtual void Draw() {
glPushMatrix();
glMultMatrixd(gl_mat);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glEnable(GL_TEXTURE_2D);
int tex=0;
glBindTexture(GL_TEXTURE_2D, tex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,64,0,GL_RGBA,GL_UNSIGNED_BYTE,hidingtex);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBegin(GL_QUADS);
glTexCoord2d(0.0,0.0);
glVertex3d(-margin,-margin,0);
glTexCoord2d(0.0,1.0);
glVertex3d(-margin,margin,0);
glTexCoord2d(1.0,1.0);
glVertex3d(margin,margin,0);
glTexCoord2d(1.0,0.0);
glVertex3d(margin,-margin,0);
glEnd();
glPopAttrib();
glPopMatrix();
}
};
void videocallback(IplImage *image)
{
static bool init=true;
static const int marker_size=15;
static Camera cam;
static OwnDrawable d[32];
static IplImage *hide_texture;
bool flip_image = (image->origin?true:false);
if (flip_image) {
cvFlip(image);
image->origin = !image->origin;
}
static IplImage* bg_image = 0;
if(!bg_image) bg_image = cvCreateImage(cvSize(512, 512), 8, 3);
if(image->nChannels == 3)
{
bg_image->origin = 0;
cvResize(image, bg_image);
GlutViewer::SetVideo(bg_image);
}
if (init) {
init = false;
cout<<"Loading calibration: "<<calibrationFilename.str();
if (cam.SetCalib(calibrationFilename.str().c_str(), image->width, image->height)) {
cout<<" [Ok]"<<endl;
} else {
cam.SetRes(image->width, image->height);
cout<<" [Fail]"<<endl;
}
double p[16];
cam.GetOpenglProjectionMatrix(p,image->width,image->height);
GlutViewer::SetGlProjectionMatrix(p);
hide_texture = CvTestbed::Instance().CreateImage("hide_texture", cvSize(64, 64), 8, 4);
}
static MarkerDetector<MarkerData> marker_detector;\
marker_detector.Detect(image, &cam, false, false);
GlutViewer::DrawableClear();
for (size_t i=0; i<marker_detector.markers->size(); i++) {
if (i >= 32) break;
GlutViewer::DrawableAdd(&(d[i]));
}
for (size_t i=0; i<marker_detector.markers->size(); i++) {
if (i >= 32) break;
// Note that we need to mirror both the y- and z-axis because:
// - In OpenCV we have coordinates: x-right, y-down, z-ahead
// - In OpenGL we have coordinates: x-right, y-up, z-backwards
// TODO: Better option might be to use OpenGL projection matrix that matches our OpenCV-approach
Pose p = (*(marker_detector.markers))[i].pose;
BuildHideTexture(image, hide_texture, &cam, d[i].gl_mat, PointDouble(-margin, -margin), PointDouble(margin, margin));
//DrawTexture(image, hide_texture, &cam, d[i].gl_mat, PointDouble(-0.7, -0.7), PointDouble(0.7, 0.7));
p.GetMatrixGL(d[i].gl_mat);
for (int ii=0; ii<64*64; ii++) {
d[i].hidingtex[ii*4+0] = hide_texture->imageData[ii*4+2];
d[i].hidingtex[ii*4+1] = hide_texture->imageData[ii*4+1];
d[i].hidingtex[ii*4+2] = hide_texture->imageData[ii*4+0];
d[i].hidingtex[ii*4+3] = hide_texture->imageData[ii*4+3];
}
}
if (flip_image) {
cvFlip(image);
image->origin = !image->origin;
}
}
int main(int argc, char *argv[])
{
try {
// Output usage message
std::string filename(argv[0]);
filename = filename.substr(filename.find_last_of('\\') + 1);
std::cout << "SampleMarkerHide" << std::endl;
std::cout << "================" << std::endl;
std::cout << std::endl;
std::cout << "Description:" << std::endl;
std::cout << " This is an example of how to detect 'MarkerData' markers, similarly" << std::endl;
std::cout << " to 'SampleMarkerDetector', and hide them using the 'BuildHideTexture'" << std::endl;
std::cout << " and 'DrawTexture' classes." << std::endl;
std::cout << std::endl;
std::cout << "Usage:" << std::endl;
std::cout << " " << filename << " [device]" << std::endl;
std::cout << std::endl;
std::cout << " device integer selecting device from enumeration list (default 0)" << std::endl;
std::cout << " highgui capture devices are prefered" << std::endl;
std::cout << std::endl;
std::cout << "Keyboard Shortcuts:" << std::endl;
std::cout << " q: quit" << std::endl;
std::cout << std::endl;
// Initialise GlutViewer and CvTestbed
GlutViewer::Start(argc, argv, 640, 480, 15);
CvTestbed::Instance().SetVideoCallback(videocallback);
// Enumerate possible capture plugins
CaptureFactory::CapturePluginVector plugins = CaptureFactory::instance()->enumeratePlugins();
if (plugins.size() < 1) {
std::cout << "Could not find any capture plugins." << std::endl;
return 0;
}
// Display capture plugins
std::cout << "Available Plugins: ";
outputEnumeratedPlugins(plugins);
std::cout << std::endl;
// Enumerate possible capture devices
CaptureFactory::CaptureDeviceVector devices = CaptureFactory::instance()->enumerateDevices();
if (devices.size() < 1) {
std::cout << "Could not find any capture devices." << std::endl;
return 0;
}
// Check command line argument for which device to use
int selectedDevice = defaultDevice(devices);
if (argc > 1) {
selectedDevice = atoi(argv[1]);
}
if (selectedDevice >= (int)devices.size()) {
selectedDevice = defaultDevice(devices);
}
// Display capture devices
std::cout << "Enumerated Capture Devices:" << std::endl;
outputEnumeratedDevices(devices, selectedDevice);
std::cout << std::endl;
// Create capture object from camera
Capture *cap = CaptureFactory::instance()->createCapture(devices[selectedDevice]);
std::string uniqueName = devices[selectedDevice].uniqueName();
// Handle capture lifecycle and start video capture
// Note that loadSettings/saveSettings are not supported by all plugins
if (cap) {
std::stringstream settingsFilename;
settingsFilename << "camera_settings_" << uniqueName << ".xml";
calibrationFilename << "camera_calibration_" << uniqueName << ".xml";
cap->start();
if (cap->loadSettings(settingsFilename.str())) {
std::cout << "Loading settings: " << settingsFilename.str() << std::endl;
}
std::stringstream title;
title << "SampleMarkerHide (" << cap->captureDevice().captureType() << ")";
CvTestbed::Instance().StartVideo(cap, title.str().c_str());
if (cap->saveSettings(settingsFilename.str())) {
std::cout << "Saving settings: " << settingsFilename.str() << std::endl;
}
cap->stop();
delete cap;
}
else if (CvTestbed::Instance().StartVideo(0, argv[0])) {
}
else {
std::cout << "Could not initialize the selected capture backend." << std::endl;
}
return 0;
}
catch (const std::exception &e) {
std::cout << "Exception: " << e.what() << endl;
}
catch (...) {
std::cout << "Exception: unknown" << std::endl;
}
}