QOpenGLWidget not rendring on macos Ventura 13 [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last month.
Improve this question
I'm using qt 6.4 to create a application rendering yuv image with QOpenGLWidget. The code worked properly on windows 10, but didn't rendering anything on my macbook pro (intel chip, Ventura 13.1), and didn't report any error.
Here is my code:
in main.cpp:
#include "mainwindow.h"
#include <QApplication>
#include <QSurfaceFormat>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
QSurfaceFormat glFormat;
glFormat.setVersion(4, 1);
glFormat.setProfile(QSurfaceFormat::CoreProfile);
glFormat.setSwapBehavior (QSurfaceFormat::DoubleBuffer);
glFormat.setRenderableType (QSurfaceFormat::OpenGL);
QSurfaceFormat::setDefaultFormat(glFormat);
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
FrmScreen.h:
#include "QtOpenGLWidgets/qopenglwidget.h"
#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
#include <QTimer>
#include <QFile>
namespace Ui {
class FrmScreen;
}
#define GET_STR(x) #x
#define A_VER 3
#define T_VER 4
class FrmScreen : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit FrmScreen(QWidget *parent = nullptr);
~FrmScreen();
void displayImage(QString imgPath);
void displayYuvImage(QString yuvPath);
protected:
void initializeGL() Q_DECL_OVERRIDE;
void resizeGL(int w, int h) Q_DECL_OVERRIDE;
void paintGL() Q_DECL_OVERRIDE;
private:
Ui::FrmScreen *ui;
QString _img_path;
QOpenGLShaderProgram program;
GLuint unis[3] = {0};
GLuint texs[3] = {0};
int width = 2688;
int height = 1520;
QFile m_file;
QByteArray m_buf;
};
#endif // FRMSCREEN_H
FrmScreen.cpp:
#include "FrmScreen.h"
#include "QtGui/qpainter.h"
#include "ui_FrmScreen.h"
FrmScreen::FrmScreen(QWidget *parent) :
QOpenGLWidget(parent),
ui(new Ui::FrmScreen)
{
_img_path = "./frames/frame000.yuv";
ui->setupUi(this);
}
const char* vString =
"#version 410\n"
"in vec4 vertexIn;\n"
"in vec2 textureIn;\n"
"out vec2 textureOut;\n"
"void main(void)\n"
"{\n"
" gl_Position = vertexIn;\n"
" textureOut = textureIn;\n"
"}";
const char* tString = "#version 410\n"
"in vec2 textureOut;\n"
"out vec4 fragColor;\n"
"uniform sampler2D tex_y;\n"
"uniform sampler2D tex_u;\n"
"uniform sampler2D tex_v;\n"
"void main(void)\n"
"{\n"
" vec3 yuv;\n"
" vec3 rgb;\n"
" yuv.x = texture(tex_y, textureOut).r;\n"
" yuv.y = texture(tex_u, textureOut).r - 0.5;\n"
" yuv.z = texture(tex_v, textureOut).r - 0.5;\n"
" rgb = mat3( 1, 1, 1,\n"
" 0, -0.21482, 2.12798,\n"
" 1.28033, -0.38059, 0) * yuv;\n"
" fragColor = vec4(rgb, 1);\n"
"}";
FrmScreen::~FrmScreen()
{
delete ui;
}
void FrmScreen::initializeGL()
{
initializeOpenGLFunctions();
qDebug() << "load fragment:" <<program.addShaderFromSourceCode(QOpenGLShader::Fragment, tString);
qDebug() << "load shader:" <<program.addShaderFromSourceCode(QOpenGLShader::Vertex, vString);
program.bindAttributeLocation("vertexIn", A_VER);
program.bindAttributeLocation("textureIn", T_VER);
qDebug() << "compile shader:" << program.link();
qDebug() << "bind shader:" << program.bind();
static const GLfloat ver[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
static const GLfloat tex[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);
glEnableVertexAttribArray(A_VER);
glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);
glEnableVertexAttribArray(T_VER);
unis[0] = program.uniformLocation("tex_y");
unis[1] = program.uniformLocation("tex_u");
unis[2] = program.uniformLocation("tex_v");
glGenTextures(3, texs);
// Y
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
// U
glBindTexture(GL_TEXTURE_2D, texs[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height/ 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, texs[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glClearColor(0.3, 0.3, 0.3, 0.0);
m_file.setFileName(_img_path);
if(!m_file.open(QIODevice::ReadOnly))
{
qDebug() << "open yuv file failed";
return;
}
}
void FrmScreen::paintGL()
{
if(m_file.atEnd())
{
m_file.seek(0);
}
QByteArray buf = m_file.read(width * height);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, buf.data());
glUniform1i(unis[0], 0);
buf = m_file.read(width * height / 4);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texs[1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, buf.data());
glUniform1i(unis[1], 1);
buf = m_file.read(width * height / 4);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texs[2]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, buf.data());
glUniform1i(unis[2], 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
return;
}
void FrmScreen::resizeGL(int width, int height)
{
if (height == 0)
{
height = 1;
}
glViewport(0, 0, width, height);
}
void FrmScreen::displayYuvImage(QString yuvPath)
{
_img_path = yuvPath;
update();
}
void FrmScreen::displayImage(QString imgPath)
{
_img_path = imgPath;
update();
}
Why the code not working properly on macos?

On a Mac, you must use an OpenGL 4.1 Core profile context with the forward compatibility flag set. With Qt 6 this can be achieved by turning off QSurfaceFormat::DeprecatedFunctions:
QSurfaceFormat glFormat;
glFormat.setVersion(4, 1);
glFormat.setProfile(QSurfaceFormat::CoreProfile);
glFormat.setOption(QSurfaceFormat::DeprecatedFunctions, false);
glFormat.setRenderableType(QSurfaceFormat::OpenGL);
The shader version should be #version 410 core.

Related

OpenGL texture barely visible (very dark)

I've started messing around with textures in opengl, and when rendering my first texture, I saw a black screen. Then I realized that the screen in't black, rather the texture was very dim. Why is this happening? Here is the code:
Texture class (.cpp):
Texture::Texture(void* data, unsigned int width, unsigned int height)
:texture(0), curslot(32), width(width), height(height)
{
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
Texture::~Texture(){
glDeleteTextures(1, &texture);
}
void Texture::bind(unsigned char slot){
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, texture);
curslot = slot;
}
Texture class declaration (if you need it):
class Texture{
private:
unsigned int texture;
unsigned char curslot;
unsigned int width;
unsigned int height;
public:
Texture(void* data, unsigned int width, unsigned int height);
~Texture();
void bind(unsigned char slot=0);
};
Shaders:
Vertex Shader:
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texpos;
out vec2 texCoord;
void main(){
gl_Position = position;
texCoord = texpos;
}
Fragment Shader:
#version 330 core
layout(location=0) out vec4 color;
uniform sampler2D u_Texture;
in vec2 texCoord;
void main(){
vec4 texColor = texture(u_Texture, texCoord);
color = texColor;
}
Renderer class declaration (you won't need the implementation although if you want it, I'll be happy to add it, just ask):
class Renderer{
private:
Renderer(){}
public:
static Renderer* renderer;
Renderer(const Renderer& r) = delete;
void draw(VertexArray* va, IndexBuffer* ib, Shader* shader, void (*uniformCallback)(Shader*, void*), void* uniformCallbackParams) const; //Fourth parameter is a function pointer that executes every time the draw function is called. It enables the user of the class to declare their uniforms. First three parameters are abstracted classes. Final parameter is a void pointer that is passed into the uniform function
};
Main Application (simplified):
typedef struct{
float x;
float y;
float texCoord_x;
float texCoord_y;
} vertex_t;
static GLFWwindow* window;
static void uniformCallback(Shader* program, void* params){
program->useUniform1i("u_Texture", 0); //Setting the sampler2D uniform for the texture slot
}
int main(){
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(500, 500, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
glewInit();
VertexArray* va = new VertexArray(); //Abstracted vertex array
va->bind();
VertexBuffer* vb = new VertexBuffer(); //Abstracted vertex buffer
IndexBuffer* ib = new IndexBuffer(); //Abstracted index buffer
unsigned char t[16] = { //Texture pixels, RGBA form. Made this simple 'image' just for testing purposes
1, 0, 0, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 0, 0, 1
};
Texture* texture = new Texture(t, 2, 2); //Texture class (abstracted)
texture->bind();
Shader* program = new Shader(2, "vs.glsl", "fs.glsl"); //Abstracted shader
vertex_t data[4] = {
{-0.5, 0.5, 0.0f, 1.0f},
{ 0.5, 0.5, 1.0f, 1.0f},
{-0.5, -0.5, 0.0f, 0.0f},
{ 0.5, -0.5, 1.0f, 0.0f}
};
unsigned int indicies[6] = {
0, 1, 2,
1, 2, 3
};
vb->setBufferData(data, 4*sizeof(vertex_t));
ib->setBufferData(indicies, 6);
vb->bind();
ib->bind();
va->addAttrib(GL_FLOAT, 2); //equivalent of glEnableAttribArray and glVertexAttribPointer
va->addAttrib(GL_FLOAT, 2);
while(!glfwWindowShouldClose(window)){
glClear(GL_COLOR_BUFFER_BIT);
Renderer::renderer->draw(va, ib, program, uniformCallback, NULL); //Refer to renderer class declaration
glfwSwapBuffers(window);
glfwPollEvents();
}
//Clean-up code (freeing pointers, etc.)
glfwTerminate();
return 0;
}
Each color channel of the texture is coded in a byte. Hence, the color values are in range [0, 255]. Change the values of t[16]:
unsigned char t[16] = {
255, 0, 0, 255,
255, 255, 255, 255,
255, 255, 255, 255,
255, 0, 0, 255
};
Note that when specifying the two-dimensional texture image, the data type of the pixel data is specified by GL_UNSIGNED_BYTE:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, this->width, this->height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, data);

Multiple cube map textures behaving strangely when amount of textures increases [duplicate]

This question already has answers here:
In a fragment shader, why can't I use a flat input integer to index a uniform array of sampler2D?
(1 answer)
Why are glsl variables not working as expected?
(2 answers)
Why are Uniform variables not working in GLSL?
(1 answer)
Closed 2 years ago.
So I've managed to successfully implement batching into my engine, but have come across some weird behavior with the array of samplerCubes in my fragment shader. The batch renderer works fine with 2 texture units - I can successfully draw cubes with the right textures if I only bind 2 textures, but as soon as I add a 3rd to the mTextures vector, and use glUniform1i for that index in the samplerCube array, the wrong texture is displayed, even though the texture id (TexID) is correct (I checked this in the fragment shader).
The issue appears to be with my understanding of OpenGL as for some reason, the texture what should be displayed by textureCubes[2] (fragment shader uniform) is displayed by textureCubes[1], and textureCubes[2] displays the same texture as textureCubes[0]. What should be displayed by textureCubes[1] just doesn't exist with the 3rd texture bound.
Here's my code:
Main.cpp
#include "Window.h"
#include "Block.h"
#include "BatchRenderer.h"
#include "Shader.h"
#include "Camera.h"
void Submit(gfx::BatchRenderer* renderer, float height) //temporary to test batching
{
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
gfx::Block* block = new gfx::Block(j % 2 == 0 ? (i % 2 == 0 ? gfx::BlockType::DIRT : gfx::BlockType::GRASS) : gfx::BlockType::COBBLE, math::Vec3f(i * 5.0, height, j * 5.0));
renderer->Submit(block);
}
}
}
int main()
{
gfx::Window* window = new gfx::Window("MineClone", 800, 800);
gfx::Shader* shader = new gfx::Shader();
shader->FromFile(GL_VERTEX_SHADER, "Resources/ModelTest.vert");
shader->FromFile(GL_FRAGMENT_SHADER, "Resources/ModelTest.frag");
shader->RefreshProgram();
math::Mat4f projection = math::Mat4f::Perspective(70.0, window->GetWidth() / window->GetHeight(), 0.1, 1000.0);
gfx::Camera* camera = new gfx::Camera(projection, 0.05, 0.0015);
gfx::BatchRenderer* renderer = new gfx::BatchRenderer();
gfx::TextureCube* grass = new gfx::TextureCube("Resources/top.png", "Resources/dirt.png", "Resources/sides.png");
renderer->Submit(grass);
gfx::TextureCube* dirt = new gfx::TextureCube("Resources/dirt.png");
renderer->Submit(dirt);
gfx::TextureCube* cobble = new gfx::TextureCube("Resources/cobble.png");
renderer->Submit(cobble);
Submit(renderer, 0.0);
Submit(renderer, 5.0);
Submit(renderer, 10.0);
Submit(renderer, 15.0);
Submit(renderer, 20.0);
Submit(renderer, 25.0);
Submit(renderer, 30.0);
Submit(renderer, 35.0);
while (!window->IsClosed())
{
window->Update();
if (window->GetInputHandler()->IsKeyDown(VK_ESCAPE))
window->SwitchMouseState();
if (window->IsSynced())
camera->Update(window->GetInputHandler());
shader->Bind();
math::Mat4f projection = camera->GetProjection();
shader->SetUniform("projection", projection);
math::Mat4f view = camera->GetView();
shader->SetUniform("view", view);
shader->SetUniform("cubeTextures[0]", 0);
shader->SetUniform("cubeTextures[1]", 1);
shader->SetUniform("cubeTextures[2]", 2);
renderer->Render();
shader->Unbind();
}
return 0;
}
BatchRenderer.cpp
#include "BatchRenderer.h"
namespace gfx
{
BatchRenderer::BatchRenderer()
: mMesh(NULL)
{
}
BatchRenderer::~BatchRenderer()
{
mBlocks.clear();
mTextures.clear();
delete mMesh;
}
void BatchRenderer::Submit(Block* block)
{
MeshData data = block->GetMesh();
mMeshData.vertices.insert(mMeshData.vertices.end(),
data.vertices.begin(),
data.vertices.end());
for (int i = 0; i < 36; i++)
{
data.indices[i] += mBlocks.size() * 8;
}
mMeshData.indices.insert(mMeshData.indices.end(),
data.indices.begin(),
data.indices.end());
mMesh = Mesh::Make(mMeshData);
mBlocks.push_back(block);
}
void BatchRenderer::Submit(TextureCube* texture)
{
mTextures.push_back(texture);
}
void BatchRenderer::Render()
{
for (int i = 0; i < mTextures.size(); i++)
{
mTextures[i]->Bind(i);
}
mMesh->Render();
for (int i = 0; i < mTextures.size(); i++)
{
mTextures[i]->Unbind(i);
}
}
}
TextureCube.cpp
#include "TextureCube.h"
namespace gfx
{
TextureCube::TextureCube(std::string paths[6])
: Texture(TextureEnum::TEXTURE_CUBE)
{
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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);
for (int i = 0; i < 6; i++)
{
std::vector<byte> pixels;
lodepng::decode(pixels, mWidth, mHeight, paths[i].c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
TextureCube::TextureCube(std::string path)
: Texture(TextureEnum::TEXTURE_CUBE)
{
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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);
std::vector<byte> pixels;
lodepng::decode(pixels, mWidth, mHeight, path.c_str());
for (int i = 0; i < 6; i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
}
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
TextureCube::TextureCube(std::string top, std::string bottom, std::string sides)
: Texture(TextureEnum::TEXTURE_CUBE)
{
glGenTextures(1, &mHandle);
glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
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);
std::vector<byte> topPixels;
lodepng::decode(topPixels, mWidth, mHeight, top.c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, topPixels.data());
std::vector<byte> bottomPixels;
lodepng::decode(bottomPixels, mWidth, mHeight, bottom.c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, bottomPixels.data());
std::vector<byte> sidesPixels;
lodepng::decode(sidesPixels, mWidth, mHeight, sides.c_str());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, sidesPixels.data());
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
TextureCube::~TextureCube()
{
glDeleteTextures(1, &mHandle);
mHandle = NULL;
}
void TextureCube::Bind(uint32_t slot)
{
glBindTextureUnit(slot, mHandle);
}
void TextureCube::Unbind(uint32_t slot)
{
glBindTextureUnit(slot, 0);
}
}
ModelTest.vert
#version 450 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 offset;
layout (location = 3) in float textureID;
uniform mat4 projection;
uniform mat4 view;
out vec3 TexPos;
out flat float TexID;
void main()
{
gl_Position = projection * view * vec4(position, 1.0);
TexPos = position - offset;
TexID = textureID;
}
ModelTest.frag
#version 450 core
out vec4 FragColour;
in vec3 TexPos;
in flat float TexID;
uniform samplerCube cubeTextures[3];
void main()
{
vec3 norm = normalize(TexPos);
int id = int(TexID);
FragColour = texture(cubeTextures[id], norm);
}
For anyone looking for a solution, it took me a while but I found it (I'm relatively new to OpenGL). The issue was I was setting the texture sampler slots individually using glUniform1i. To fix this, as cubeTextures is an array of samplerCubes, I created a struct for sampler data containing an int array and a length, and set the texture sampler slots using glUniform1iv.

GTK3 OpenGL video rendering is mostly green (YUV420P)

I'm trying to render an video through OpenGL in GTK3 on linux. These Vertex and Fragment shaders were used with succes on QT. Actually all the opengl function calls are the same from working examples on Qt.
Anyone knows why? Is it possible that GLEW coordinates are different from coordinates in QT OpenGL?
The video is in YUV420P format, so that's why the fragment shader does matrix multiplication. Is it possible that my fragment coordinates are wrong?
Anyways, here's the video:
My Vertex Shader:
#version 130
attribute vec4 vertexIn;
attribute vec2 textureIn;
varying vec2 textureOut;
void main(void)
{
gl_Position = vertexIn;
textureOut = textureIn;
}
My Fragment Shader:
#version 130
varying vec2 textureOut;
uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;
void main(void)
{
vec3 yuv;
vec3 rgb;
yuv.x = texture2D(tex_y, textureOut).r;
yuv.y = texture2D(tex_u, textureOut).r - 0.5;
yuv.z = texture2D(tex_v, textureOut).r - 0.5;
rgb = mat3(1.0, 1.0, 1.0,
0.0, -0.39465, 2.03211,
1.13983, -0.58060, 0.0) * yuv;
gl_FragColor = vec4(rgb, 1.0);
}
My rendering code:
static const GLfloat ver[] = {
-1.0f,-1.0f,
1.0f,-1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
static const GLfloat tex[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
void OpenGLArea::init()
{
std::cout << "OpenGLArea init" << std::endl;
set_size_request(640, 360);
Singleton::instance()->getStream("cam1").mediaStream->ffmpegDecoder->setVideoReceiver(this);
}
void OpenGLArea::receiveVideo(unsigned char **videoBuffer, int frameWidth, int frameHeight)
{
this->frameWidth = frameWidth;
this->frameHeight = frameHeight;
//Before first render, datas pointer isn't even created yet
if (!firstFrameReceived)
{
buffer[0] = new unsigned char[frameWidth * frameHeight]; //Y
buffer[1] = new unsigned char[frameWidth * frameHeight / 4]; //U
buffer[2] = new unsigned char[frameWidth * frameHeight / 4]; //V
firstFrameReceived = true;
}
else
{
memcpy(buffer[0], videoBuffer[0], frameWidth * frameHeight);
memcpy(buffer[1], videoBuffer[1], frameWidth * frameHeight / 4);
memcpy(buffer[2], videoBuffer[2], frameWidth * frameHeight / 4);
}
//glDraw();
}
void OpenGLArea::glInit()
{
int frameWidth = 640;
int frameHeight = 360;
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
Shader vertex_shader(ShaderType::Vertex, "vertex.shader");
Shader fragment_shader(ShaderType::Fragment, "fragment.shader");
program = new Program();
program->attach_shader(vertex_shader);
program->attach_shader(fragment_shader);
program->link();
glGenTextures(3, texs);//TODO: delete texture
//Y
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frameWidth, frameHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//U
glBindTexture(GL_TEXTURE_2D, texs[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frameWidth / 2, frameHeight / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//V
glBindTexture(GL_TEXTURE_2D, texs[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, frameWidth / 2, frameHeight / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void OpenGLArea::glDraw()
{
program->use();
glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);
glEnableVertexAttribArray(A_VER);
glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);
glEnableVertexAttribArray(T_VER);
unis[0] = glGetAttribLocation(program->get_id(), "tex_y");
unis[1] = glGetAttribLocation(program->get_id(), "tex_u");
unis[2] = glGetAttribLocation(program->get_id(), "tex_v");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frameWidth, frameHeight, GL_RED, GL_UNSIGNED_BYTE, buffer[0]);
glUniform1i(unis[0], 0);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texs[1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frameWidth / 2, frameHeight / 2, GL_RED, GL_UNSIGNED_BYTE, buffer[1]);
glUniform1i(unis[1], 1);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, texs[2]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frameWidth / 2, frameHeight / 2, GL_RED, GL_UNSIGNED_BYTE, buffer[2]);
glUniform1i(unis[2], 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
class GLWindow : public Gtk::Window
{
public:
GLWindow()
{
vbox = new Gtk::VBox;
drawing_area = new OpenGLArea();
vbox->pack_start(*drawing_area, true, true);
add(*vbox);
}
private:
Gtk::Button *button;
Gtk::VBox *vbox;
OpenGLArea *drawing_area;
};
Also, I'm only getting image updates when I resize or refocus on the screen. It's possible that I'm forgetting to call some function when the video is updated. Anyone knows which function is this?
ps: OpenGLArea is subclass of Gtk::DrawingArea
UPDATE:
I just noticed that in the lines
unis[0] = glGetAttribLocation(program->get_id(), "tex_y");
unis[1] = glGetAttribLocation(program->get_id(), "tex_u");
unis[2] = glGetAttribLocation(program->get_id(), "tex_v");
unis[i] always have the same value: 4294967295, so glGetAttribLocation isn't returning anything
GLEW is a library that is used for retrieving the function pointers to OpenGL functions. It's needed for OGL version > 1.1.
So, don't think of Glew as the culprit of your vertices issue. If you need to change the order of vertices is due to Winding order.
The order also may be the cause of drawing a texture upside-down.
glGetAttribLocation is used for attributes. In your VS these are vertexIn and textureIn.
For uniforms (your tex_XXX) you must use glGetUniformLocation
For the resizing issue, this question may be useful.
In short, you must connect a callback for the "configure-event" and use glViewport

How to use fragment shader with an image

I'm trying to perform simple color correction operations using GLSL(orange book).
I'm struggling to apply the shaders to images. This is my fragment shader to adjust saturation, stolen from the Orange book. I don't understand how to use this with an image?
const vec3 lumCoeff = vec3(0.2125,0.7154,0.0721);
uniform float Alpha;
void main()
{
vec3 intensity = vec3(dot(gl_Color.rgb, lumCoeff));
vec3 color = mix(intensity, gl_color.rgb, Alpha);
gl_FragColor = vec4(color, 1.0);
}
And then my vertex shader is
void main(void)
{
gl_Position = ftransform();
}
I've been trying to read an image in using OpenCv and then I use glTexImage2d to turn it into a texture but, I dont understand how shaders are used in OpenGL and C++.
When and how do I apply the shaders to the images?
Here is the code I am trying to run.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
//#include <GL/glew.h>
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include "textfile.h"
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#define VIEWPORT_WIDTH 320 // 1280
#define VIEWPORT_HEIGHT 320 // 800
IplImage *Image;
static GLuint texName;
GLuint v,f,f2,p;
float lpos[4] = {1,0.5,1,0};
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
float ratio = 1.0* w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
}
void renderScene(void) {
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glGenTextures(1, &texName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPixelStorei (GL_UNPACK_ALIGNMENT, Image->align);
glPixelStorei (GL_UNPACK_ROW_LENGTH, Image->widthStep / Image->nChannels);
glTexImage2D(GL_TEXTURE_2D, 0, 3, Image->width, Image->height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->imageData);
glViewport(0, 0, VIEWPORT_WIDTH , VIEWPORT_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, VIEWPORT_WIDTH , 0, VIEWPORT_HEIGHT, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texName);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex3f(0, 0, 0);
glTexCoord2f(0, 1); glVertex3f(0, VIEWPORT_HEIGHT, 0);
glTexCoord2f(1, 1); glVertex3f(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, 0);
glTexCoord2f(1, 0); glVertex3f(VIEWPORT_WIDTH, 0, 0);
char *vs = NULL,*fs = NULL,*fs2 = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
//f2 = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("toon.vert");
fs = textFileRead("toon.frag");
//fs2 = textFileRead("toon2.frag");
const char * ff = fs;
//const char * ff2 = fs2;
const char * vv = vs;
glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);
//glShaderSource(f2, 1, &ff2,NULL);
free(vs);free(fs);
glCompileShader(v);
glCompileShader(f);
//glCompileShader(f2);
p = glCreateProgram();
glAttachShader(p,f);
//glAttachShader(p,f2);
glAttachShader(p,v);
glLinkProgram(p);
glUseProgram(p);
glEnd();
glFlush();
glDisable(GL_TEXTURE_2D);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glLoadIdentity();
// gluLookAt(0.0,0.0,5.0,
// 0.0,0.0,-1.0,
// 0.0f,1.0f,0.0f);
// glLightfv(GL_LIGHT0, GL_POSITION, lpos);
// glutSolidTeapot(1);
glutSwapBuffers();
}
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
}
void setShaders() {
char *vs = NULL,*fs = NULL,*fs2 = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
//f2 = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("toon.vert");
fs = textFileRead("toon.frag");
//fs2 = textFileRead("toon2.frag");
const char * ff = fs;
//const char * ff2 = fs2;
const char * vv = vs;
glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);
//glShaderSource(f2, 1, &ff2,NULL);
free(vs);free(fs);
glCompileShader(v);
glCompileShader(f);
//glCompileShader(f2);
p = glCreateProgram();
glAttachShader(p,f);
//glAttachShader(p,f2);
glAttachShader(p,v);
glLinkProgram(p);
glUseProgram(p);
}
int main(int argc, char **argv) {
Image = cvLoadImage("lena.tiff",1);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("MM 2004-05");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
// glEnable(GL_CULL_FACE);
// glewInit();
// if (glewIsSupported("GL_VERSION_2_0"))
// printf("Ready for OpenGL 2.0\n");
// else {
// printf("OpenGL 2.0 not supported\n");
// exit(1);
// }
//setShaders();
glutMainLoop();
// just for compatibiliy purposes
return 0;
}
You have not passed any uniform sampler to your shader.
Well there are many things that you should notice.
You need not to dump all initialization code in render loop. Your are just killing your program.
like this texture generation code. It only needs to execute once. Just move it to some init() function.
glGenTextures(1, &texName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glPixelStorei (GL_UNPACK_ALIGNMENT, Image->align);
glPixelStorei (GL_UNPACK_ROW_LENGTH, Image->widthStep / Image->nChannels);
glTexImage2D(GL_TEXTURE_2D, 0, 3, Image->width, Image->height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->imageData);
then this shader program creation, compilation and linking this this is usually done at application start-up and only once. After that you can just call glUseProgram(handle) in your render loop.
char *vs = NULL,*fs = NULL,*fs2 = NULL;
v = glCreateShader(GL_VERTEX_SHADER);
f = glCreateShader(GL_FRAGMENT_SHADER);
//f2 = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("toon.vert");
fs = textFileRead("toon.frag");
//fs2 = textFileRead("toon2.frag");
const char * ff = fs;
//const char * ff2 = fs2;
const char * vv = vs;
glShaderSource(v, 1, &vv,NULL);
glShaderSource(f, 1, &ff,NULL);
//glShaderSource(f2, 1, &ff2,NULL);
free(vs);free(fs);
glCompileShader(v);
glCompileShader(f);
//glCompileShader(f2);
p = glCreateProgram();
glAttachShader(p,f);
//glAttachShader(p,f2);
glAttachShader(p,v);
glLinkProgram(p);
Its important to check for errors while shader initialization. Follow these excellent tutorials to know how do that.
You need to pass texture that you created using OpenCV as a Uniform Variable to shader. See here to know what uniform variables are.

problems generating texture

Update 2 works, it was a wrong allert
Update 2 (using vbo vertex- and fragment-shaders) but it still don't works
#include "GL/glxew.h"
#include "GL/glext.h"
#include "GL/glu.h"
#include "GL/freeglut.h"
#include <iostream>
GLint attribute;
GLuint program;
void gen_texture(GLuint &texture, int width, int height)
{
GLuint fb;
glGenFramebuffers(1, &fb);
glGenTextures(1, &texture);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width, height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(attribute);
GLfloat vertex_data[]
{
1.0f, 0.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
glVertexAttribPointer(
attribute,
2,
GL_FLOAT,
GL_FALSE,
0,
vertex_data
);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(attribute);
}
void init_layout()
{
GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
GLuint vs, fs;
vs = glCreateShader(GL_VERTEX_SHADER);
const char *vs_source =
"#version 120\n" // OpenGL 2.1
"attribute vec2 coord2d; "
"void main(void) { "
" gl_Position = vec4(coord2d, 0.0, 1.0); "
"}";
glShaderSource(vs, 1, &vs_source, 0);
glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);
if (0 == compile_ok)
{
std::cerr << "[texture_layout/init_layout] fehler im vertex shader\n";
exit(1);
}
fs = glCreateShader(GL_FRAGMENT_SHADER);
const char *fs_source =
"#version 120\n" // OpenGL 2.1
"void main(void) { "
" gl_FragColor[0] = 0.8f; "
" gl_FragColor[1] = 0.5f;"
" gl_FragColor[2] = 0.0f; "
"}";
glShaderSource(fs, 1, &fs_source, 0);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok);
if (0 == compile_ok)
{
std::cerr << "[texture_layout/init_layout] fehler im fragment shader\n";
exit(1);
}
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (!link_ok)
{
std::cerr << "[texture_layout/init_layout] fehler in glLinkProgram\n";
exit(1);
}
const char* attribute_name = "coord2d";
attribute = glGetAttribLocation(program, attribute_name);
if (attribute == -1) {
std::cerr << "Could not bind attribute " << attribute_name << "\n";
exit(1);
}
}
int main(int argc, char **argv)
{
glutInit (&argc, argv);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize (500, 500);
glutCreateWindow ("");
glewExperimental=GL_TRUE;
GLenum err=glewInit();
if(err!=0)
{
std::cerr << glewGetErrorString(err) << std::endl;
exit(1);
}
GLenum error;
GLuint texture;
while ( ( error = glGetError() ) != GL_NO_ERROR)
{
std::cerr << std::hex << error << "\n";
}
init_layout();
gen_texture(texture, 200, 200);
GLvoid *tex_data = new GLubyte[4*200*200];
glBindTexture(GL_TEXTURE_2D, texture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
return 0;
}
Update 1 (using vbo instead of glBegin)
now my code should draw a red triangle using vbo, but it doesn't
void gen_texture(GLuint &color, int width, int height)
{
GLuint fb;
glGenFramebuffers(1, &fb);
glGenTextures(1, &color);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width, height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glViewport(0,0,width,height);
glOrtho(0,width,0,height,0,128);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
//glDisable(GL_CULL_FACE);
glColor3f(1.f, .0f, .0f);
GLfloat vertices[6] =
{
0, 0,
0, (GLfloat)height,
(GLfloat)width, (GLfloat)height,
};
unsigned short indices[] = {0, 1, 2};
GLuint vbo;
glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 6*sizeof(GLfloat), vertices, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, vertices);
}
Original 2:
I have a function that should draw a red square into a texture with the glBegin directive. But the only thing I got to work is
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
I've tested it with multiple colors. But that part do not work:
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glViewport(0,0,width,height);
glOrtho(0,width,0,height,0,128);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glColor3f(1.f, .0f, .0f);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glVertex2f(0, height);
glVertex2f(width, height);
glVertex2f(width, 0);
glEnd();
Here is the full function:
void gen_texture(GLuint &color, int width, int height)
{
GLuint fb;
glGenFramebuffers(1, &fb);
glGenTextures(1, &color);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glBindTexture(GL_TEXTURE_2D, color);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width, height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glViewport(0,0,width,height);
glOrtho(0,width,0,height,0,128);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
//glDisable(GL_CULL_FACE);
glColor3f(1.f, .0f, .0f);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glVertex2f(0, height);
glVertex2f(width, height);
glVertex2f(width, 0);
glEnd();
}
Original Post:
I have a function that should draw a red square into a texture, but when I call the function for generating the texture and then I want to check the generated texture data, with the glGetTexImage function, I get a null-pointer.
#include "GL/glxew.h"
#include "GL/glext.h"
#include "GL/glu.h"
#include "GL/freeglut.h"
#include <iostream>
GLuint texture;
GLvoid *tex_data;
void gen_texture(GLuint &color, int width, int height)
{
GLuint fb;
glGenFramebuffers(1, &fb);
glGenTextures(1, &color);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width, height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glEnable(GL_TEXTURE_2D);
glBindFramebuffer(GL_FRAMEBUFFER, fb);
glViewport(0, 0, width, height);
glClearColor(1,1,1,0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, width, height, 0, 0, 1);
glMatrixMode (GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glColor4f(1.f, .0f, .0f, .5f);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glVertex2f(0, height);
glVertex2f(width, height);
glVertex2f(width, 0);
glEnd();
}
int main(int argc, char **argv)
{
glutInit (&argc, argv);
glutInitContextVersion(3, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize (500, 500);
glutCreateWindow ("");
glewExperimental=GL_TRUE;
GLenum err=glewInit();
if(err!=0)
{
std::cerr << glewGetErrorString(err) << std::endl;
exit(1);
}
GLenum error;
while ( ( error = glGetError() ) != GL_NO_ERROR)
{
std::cerr << std::hex << error << "\n";
}
gen_texture(texture, 200, 200);
glBindTexture(GL_TEXTURE_2D, texture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_data);
if (tex_data == 0)
std::cerr << "Captain, eine Null an Board!\n";
return 0;
}
the tex_data is now a null-pointer
what am I doing wrong???
glutInitContextVersion(3, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
^^^^^^^^^^^^^^^^^ ok...
....
glBegin(GL_QUADS);
^^^^^^^^ wat
glBegin() and friends aren't valid calls in a Core context.
You'll have to get spun up on shaders and VBOs if you insist on Core.