gpt4 book ai didi

c++ - GTK3 OpenGL 视频渲染大部分为绿色 (YUV420P)

转载 作者:行者123 更新时间:2023-11-30 04:45:37 25 4
gpt4 key购买 nike

我正在尝试在 Linux 上通过 GTK3 中的 OpenGL 渲染视频。这些顶点着色器和片段着色器在 QT 上成功使用。实际上,所有 opengl 函数调用都与 Qt 上的工作示例相同。

谁知道为什么? GLEW 坐标是否可能与 QT OpenGL 中的坐标不同?

视频是YUV420P格式,所以片段着色器做矩阵乘法。有没有可能是我的片段坐标错了?

无论如何,这是视频:

enter image description here

我的顶点着色器:

#version 130

attribute vec4 vertexIn;
attribute vec2 textureIn;
varying vec2 textureOut;
void main(void)
{
gl_Position = vertexIn;
textureOut = textureIn;
}

我的片段着色器:

#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);
}

我的渲染代码:

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;
};

此外,我只有在调整屏幕大小或重新聚焦屏幕时才会收到图像更新。更新视频时,我可能忘记调用某些函数。谁知道这是什么函数?

ps: OpenGLAreaGtk::DrawingArea 的子类

更新:

我刚刚注意到在行中

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] 始终具有相同的值:4294967295,因此 glGetAttribLocation 不会返回任何内容

最佳答案

GLEW 是一个用于检索指向 OpenGL 函数的函数指针的库。 OGL 版本 > 1.1 需要它。

因此,不要将 Glew 视为顶点问题的罪魁祸首。如果您需要更改顶点的顺序是由于 Winding order .
顺序也可能是绘制纹理颠倒的原因。


glGetAttribLocation 用于属性。在您的 VS 中,它们是 vertexIntextureIn
对于uniforms(你的tex_XXX)你必须使用glGetUniformLocation


对于大小调整问题,this question可能有用。简而言之,您必须为“configure-event”连接一个回调并使用glViewport

关于c++ - GTK3 OpenGL 视频渲染大部分为绿色 (YUV420P),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57173060/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com