向shader中传递 unsigned_byte 顶点颜色值警惕小于0大于255的情况

在实现FadeIn效果过程中,遇到图片显示后突然消失的问题。原因在于Color.a值大于1.f,乘以255并转换为u32类型后超出范围自动变为0。调整Color.a值确保不超过1.f即可解决。
在实现FadeIn的过程中出现了图片显示后突然消失的情况,原来是 Color.a大于了 1.f,在乘完255后转换成了u32类型,传递给了shader中的color,超出后自动变成了0
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/time.h> #include <sys/types.h> #include <sys/shm.h> #include <gbm.h> #include <png.h> #include <EGL/egl.h> #include <GLES2/gl2.h> #include <EGL/egl.h> #include <GLES3/gl3.h> #include <stdio.h> #include <stdlib.h> #include <EGL/egl.h> #include <GLES3/gl3.h> #include <stdio.h> #include <stdlib.h> #include <queue> #include <thread> #include <mutex> #include <condition_variable> // 模拟 DMA 缓冲区(实际应使用 Rockchip 的 DRM/DMA-BUF 接口) typedef struct { int width; int height; uint8_t *nv12_data; } DMABuffer; // EGL 配置 EGLDisplay eglDisplay; EGLContext eglContext; EGLSurface eglSurface; // 初始化 EGL int init_egl(int width, int height) { eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (eglDisplay == EGL_NO_DISPLAY) return -1; EGLint major, minor; if (!eglInitialize(eglDisplay, &major, &minor)) return -1; EGLint configAttrs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; EGLConfig eglConfig; EGLint numConfigs; if (!eglChooseConfig(eglDisplay, configAttrs, &eglConfig, 1, &numConfigs)) return -1; EGLint surfaceAttrs[] = { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE }; eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttrs); if (eglSurface == EGL_NO_SURFACE) return -1; EGLint contextAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttrs); if (eglContext == EGL_NO_CONTEXT) return -1; if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) return -1; return 0; } GLuint y_texture, uv_texture; void load_nv12_texture(const DMABuffer &buf) { // Y 平面 glBindTexture(GL_TEXTURE_2D, y_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, buf.width, buf.height, 0, GL_RED, GL_UNSIGNED_BYTE, buf.nv12_data); // UV 平面 const uint8_t *uv_data = buf.nv12_data + buf.width * buf.height; glBindTexture(GL_TEXTURE_2D, uv_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, buf.width / 2, buf.height / 2, 0, GL_RG, GL_UNSIGNED_BYTE, uv_data); } GLuint compile_shader(GLenum type, const char *source) { GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, NULL); glCompileShader(shader); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (!status) { char log[1024]; glGetShaderInfoLog(shader, 1024, NULL, log); printf("Shader compile error: %s\n", log); glDeleteShader(shader); return 0; } return shader; } GLuint create_program(const char *vs_source, const char *fs_source) { GLuint vs = compile_shader(GL_VERTEX_SHADER, vs_source); GLuint fs = compile_shader(GL_FRAGMENT_SHADER, fs_source); GLuint program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); GLint status; glGetProgramiv(program, GL_LINK_STATUS, &status); if (!status) { char log[1024]; glGetProgramInfoLog(program, 1024, NULL, log); printf("Program link error: %s\n", log); glDeleteProgram(program); return 0; } glDeleteShader(vs); glDeleteShader(fs); return program; } const char *vertex_shader_source = R"( #version 300 es layout(location = 0) in vec2 position; layout(location = 1) in vec2 texCoord; out vec2 v_texCoord; void main() { gl_Position = vec4(position, 0.0, 1.0); v_texCoord = texCoord; } )"; const char *fragment_shader_source = R"( #version 300 es precision mediump float; in vec2 v_texCoord; out vec4 fragColor; uniform sampler2D y_texture; uniform sampler2D uv_texture; uniform vec2 texScale; // (target_width / src_width, target_height / src_height) void main() { // 缩放后的纹理坐标 vec2 scaledCoord = v_texCoord * texScale; // 采样 Y 平面 float y = texture(y_texture, scaledCoord).r; // 采样 UV 平面(NV12 的 UV 是 2x2 下采样的) vec2 uvCoord = scaledCoord * 0.5; vec2 uv = texture(uv_texture, uvCoord).rg; // 输出 NV12(实际需要分开处理,此处仅作示例) // 实际应用中,Y 和 UV 需要分别渲染到两个 FBO fragColor = vec4(y, uv, 0.0, 1.0); // 伪代码,实际需分开输出 } )"; // 模拟 DMA 输入队列(实际应使用 Rockchip 的 V4L2 或 DRM 接口) std::queue<DMABuffer> dma_input_queue; std::mutex dma_mutex; std::condition_variable dma_cv; // 模拟 DMA 数据生成线程(实际应替换为摄像头采集) void dma_producer_thread() { while (true) { DMABuffer buf; buf.width = 1920; buf.height = 1080; buf.nv12_data = (uint8_t *)malloc(buf.width * buf.height * 3 / 2); // ... 填充测试数据(实际应从摄像头读取) ... { std::lock_guard<std::mutex> lock(dma_mutex); dma_input_queue.push(buf); dma_cv.notify_one(); } std::this_thread::sleep_for(std::chrono::milliseconds(33)); // ~30FPS } } typedef struct { int width; int height; uint8_t *y_data; // Y 平面 uint8_t *uv_data; // UV 平面 } ScaledFrame; std::queue<ScaledFrame> output_queue; std::mutex output_mutex; std::condition_variable output_cv; GLuint fbo_y, fbo_uv; GLuint output_y, output_uv; void setup_fbo(int width, int height) { // Y 平面 FBO glGenFramebuffers(1, &fbo_y); glBindFramebuffer(GL_FRAMEBUFFER, fbo_y); glGenTextures(1, &output_y); glBindTexture(GL_TEXTURE_2D, output_y); glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, output_y, 0); // UV 平面 FBO glGenFramebuffers(1, &fbo_uv); glBindFramebuffer(GL_FRAMEBUFFER, fbo_uv); glGenTextures(1, &output_uv); glBindTexture(GL_TEXTURE_2D, output_uv); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width / 2, height / 2, 0, GL_RG, GL_UNSIGNED_BYTE, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, output_uv, 0); } void render_nv12(GLuint program, int src_width, int src_height, int target_width, int target_height) { glViewport(0, 0, target_width, target_height); // 渲染 Y 平面 glBindFramebuffer(GL_FRAMEBUFFER, fbo_y); glUseProgram(program); glUniform2f(glGetUniformLocation(program, "texScale"), (float)target_width / src_width, (float)target_height / src_height); glUniform1i(glGetUniformLocation(program, "y_texture"), 0); glUniform1i(glGetUniformLocation(program, "uv_texture"), 1); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, y_texture); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, uv_texture); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // 渲染 UV 平面 glBindFramebuffer(GL_FRAMEBUFFER, fbo_uv); glViewport(0, 0, target_width / 2, target_height / 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } void read_nv12_data(int width, int height, ScaledFrame &frame) { frame.y_data = (uint8_t *)malloc(width * height); frame.uv_data = (uint8_t *)malloc(width * height / 2); frame.width = width; frame.height = height; // 读取 Y 平面 glBindFramebuffer(GL_FRAMEBUFFER, fbo_y); glReadPixels(0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, frame.y_data); // 读取 UV 平面 glBindFramebuffer(GL_FRAMEBUFFER, fbo_uv); glReadPixels(0, 0, width / 2, height / 2, GL_RG, GL_UNSIGNED_BYTE, frame.uv_data); } void processing_loop(int target_width, int target_height) { GLuint program = create_program(vertex_shader_source, fragment_shader_source); setup_fbo(target_width, target_height); while (true) { DMABuffer input_buf; { std::unique_lock<std::mutex> lock(dma_mutex); dma_cv.wait(lock, [] { return !dma_input_queue.empty(); }); input_buf = dma_input_queue.front(); dma_input_queue.pop(); } // 加载纹理 load_nv12_texture(input_buf); // 渲染缩放 render_nv12(program, input_buf.width, input_buf.height, target_width, target_height); // 读取缩放后的数据 ScaledFrame output_frame; read_nv12_data(target_width, target_height, output_frame); // 存入输出队列 { std::lock_guard<std::mutex> lock(output_mutex); output_queue.push(output_frame); output_cv.notify_one(); } // 释放输入缓冲区 free(input_buf.nv12_data); } } void consumer_thread() { while (true) { ScaledFrame frame; { std::unique_lock<std::mutex> lock(output_mutex); output_cv.wait(lock, [] { return !output_queue.empty(); }); frame = output_queue.front(); output_queue.pop(); } // 合并为 NV12(可选) uint8_t *nv12_out = (uint8_t *)malloc(frame.width * frame.height * 3 / 2); memcpy(nv12_out, frame.y_data, frame.width * frame.height); memcpy(nv12_out + frame.width * frame.height, frame.uv_data, frame.width * frame.height / 2); // ... 处理 nv12_out(如编码、显示或写入文件) ... // 释放内存 free(frame.y_data); free(frame.uv_data); free(nv12_out); } } int main() { int target_width = 1280, target_height = 720; // 初始化 EGL + GLES3 if (init_egl(target_width, target_height) < 0) { printf("EGL init failed!\n"); return -1; } // 初始化纹理 glGenTextures(1, &y_texture); glGenTextures(1, &uv_texture); // 启动线程 std::thread producer(dma_producer_thread); std::thread processor(processing_loop, target_width, target_height); std::thread consumer(consumer_thread); producer.join(); processor.join(); consumer.join(); eglTerminate(eglDisplay); return 0; } 完善上述代码,并解释
07-13
#include "DisplayHandler.h" //加入三维顶点数据 两个三角形组成正方形 const float vers[] = { 1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, }; //加入材质坐标数据 const float txts[] = { 1.0f, 0.0f,//右下 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; #define GET_STR(x) #x //顶点着色器 glsl static const char *vertexShader = GET_STR( attribute vec4 aPosition;//顶点坐标 attribute vec2 aTexCoord;//材质顶点坐标 varying vec2 vTexCoord;//输出的材质坐标 输出给片元着色器 void main() { vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); gl_Position = aPosition;//显示顶点 } ); //片元着色器 NV12 // // glsl static const char *fragYUV = GET_STR( precision mediump float;//精度 varying vec2 vTexCoord;//顶点着色器传递的坐标 uniform sampler2D yTexture;//输入材质参数(不透明灰度,单像素) uniform sampler2D uvTexture;//输入材质参数 void main() { vec3 yuv; vec3 rgb; yuv.r = texture2D(yTexture, vTexCoord).r; yuv.g = texture2D(uvTexture, vTexCoord).r - 0.5; yuv.b = texture2D(uvTexture, vTexCoord).a - 0.5; rgb = mat3(1.0, 1.0, 1.0, 0.0, 0.39465, 2.03211, 1.13983, -0.5806, 0.0) * yuv; //输出像素颜色 gl_FragColor = vec4(rgb, 1.0); } ); DisplayHandler::DisplayHandler() { videoWidth = 1920; videoHeight = 1080; glProgram = 0; eglSurface = nullptr; eglContext = nullptr; eglDisplay = nullptr; } bool DisplayHandler::initEGL(EGLNativeWindowType *nwin) { //EGL //1 eglDisplay 显示 eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (eglDisplay == EGL_NO_DISPLAY) { printf("get eglDisplay failed!"); return false; } //初始化 后面两个参数是版本号 if (EGL_TRUE != eglInitialize(eglDisplay, 0, 0)) { printf("eglInitialize failed!"); return false; } //2 surface (关联原始窗口) //surface 配置 //输出配置 EGLConfig config; EGLint configNum; //输入配置 EGLint configSpec[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; if (EGL_TRUE != eglChooseConfig(eglDisplay, configSpec, &config, 1, &configNum)) { printf("eglChooseConfig failed!"); return false; } //创建surface (关联原始窗口) eglSurface = eglCreateWindowSurface(eglDisplay, config, nwin, 0); if (eglSurface == EGL_NO_SURFACE) { printf("eglCreateWindowSurface failed!"); return false; } //3 context 创建关联上下文 const EGLint ctxAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, ctxAttr); if (eglContext == EGL_NO_CONTEXT) { printf("eglCreateContext failed!"); return false; } //egl 关联 openGL if (EGL_TRUE != eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { printf("eglMakeCurrent failed!"); return false; } printf("EGL init success"); return true; } void DisplayHandler::deinitEGL() { EGLBoolean success; if (eglDisplay != nullptr && eglSurface != nullptr) { success = eglDestroySurface(eglDisplay, eglSurface); if (!success) { printf("eglDestroySurface failure."); } eglSurface = nullptr; } if (eglDisplay != nullptr && eglContext != nullptr) { success = eglDestroyContext(eglDisplay, eglContext); if (!success) { printf("eglDestroyContext failure."); } eglContext = nullptr; success = eglTerminate(eglDisplay); if (!success) { printf("eglTerminate failure."); } eglDisplay = nullptr; } if (glProgram != 0) { glDeleteProgram(glProgram); glProgram = 0; } } //初始化着色器 GLint DisplayHandler::initShader(const char *code, GLint type) { GLuint shader; GLint compiled; // Create an empty shader object, which maintain the source code strings that define a shader shader = glCreateShader(type); if (shader == 0) { return 0; } // Replaces the source code in a shader object glShaderSource(shader, 1, &code, nullptr); // Compile the shader object glCompileShader(shader); // Check the shader object compile status glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint infoLen = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { GLchar *infoLog = (GLchar *) malloc(sizeof(GLchar) * infoLen); glGetShaderInfoLog(shader, infoLen, nullptr, infoLog); printf("Error compiling shader:\n%s\n", infoLog); free(infoLog); } glDeleteShader(shader); return 0; } return shader; } GLuint DisplayHandler::loadProgram(const char *vShaderStr, const char *fShaderStr) { GLuint vertexShader; GLuint fragmentShader; GLuint programObject; GLint linked; // Load the vertex/fragment shaders vertexShader = initShader(vShaderStr, GL_VERTEX_SHADER); fragmentShader = initShader(fShaderStr, GL_FRAGMENT_SHADER); // Create the program object programObject = glCreateProgram(); if (programObject == 0) { return 0; } // Attaches a shader object to a program object glAttachShader(programObject, vertexShader); glAttachShader(programObject, fragmentShader); // Bind vPosition to attribute 0 glBindAttribLocation(programObject, 0, "vPosition"); // Link the program object glLinkProgram(programObject); // Check the link status glGetProgramiv(programObject, GL_LINK_STATUS, &linked); if (!linked) { GLint infoLen = 0; glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { GLchar *infoLog = (GLchar *) malloc(sizeof(GLchar) * infoLen); glGetProgramInfoLog(programObject, infoLen, NULL, infoLog); printf("Error linking program:\n%s\n", infoLog); free(infoLog); } glDeleteProgram(programObject); return GL_FALSE; } // Free no longer needed shader resources glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return programObject; } GLint DisplayHandler::createProgram() { GLuint programObject; // Load the shaders and get a linked program object programObject = loadProgram((const char *) vertexShader, (const char *) fragYUV); if (programObject == 0) { return GL_FALSE; } // Store the program object glProgram = programObject; glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glGenTextures(TEXTURE_NUM, mTextureID); for (int i = 0; i < TEXTURE_NUM; i++) { glBindTexture(GL_TEXTURE_2D, mTextureID[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); } //激活渲染程序 glUseProgram(glProgram); //获取shader中的顶点变量 GLuint apos = (GLuint) glGetAttribLocation(glProgram, "aPosition"); glEnableVertexAttribArray(apos); //传递顶点 /* * apos 传到哪 * 每一个点有多少个数据 * 格式 * 是否有法线向量 * 一个数据的偏移量 * 12 顶点有三个值(x,y,z)float存储 每个有4个字节 每一个值的间隔是 3*4 = 12 * ver 顶点数据 * */ glVertexAttribPointer(apos, 3, GL_FLOAT, GL_FALSE, 12, vers); GLuint atex = (GLuint) glGetAttribLocation(glProgram, "aTexCoord"); glEnableVertexAttribArray(atex); glVertexAttribPointer(atex, 2, GL_FLOAT, GL_FLOAT, 8, txts); //设置纹理层 glUniform1i(glGetUniformLocation(glProgram, "yTexture"), 0);//对于纹理第1层 glUniform1i(glGetUniformLocation(glProgram, "uvTexture"), 1);//对于纹理第2层 return 0; } void DisplayHandler::setVideoWH(int width, int height) { videoWidth = width; videoHeight = height; } int DisplayHandler::getVideoWidth() const { return videoWidth; } int DisplayHandler::getVideoHeight() const { return videoHeight; } void DisplayHandler::update(unsigned char *yuvBuf) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mTextureID[0]);//绑定纹理,下面的属性针对这个纹理设置 //设置纹理的格式和大小 /* * GL_TEXTURE_2D * 显示细节的级别 * 内部gpu 格式 亮度 灰度图 * 宽 * 高 * 边框 * 数据的像素格式 * 像素的数据类型 * 纹理数据 * */ glTexImage2D(GL_TEXTURE_2D, 0,//默认 GL_LUMINANCE, videoWidth, videoHeight, //尺寸要是2的次方 拉伸到全屏 0, GL_LUMINANCE,//数据的像素格式,要与上面一致 GL_UNSIGNED_BYTE,// 像素的数据类型 yuvBuf ); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, mTextureID[1]); glTexImage2D(GL_TEXTURE_2D, 0,//默认 GL_LUMINANCE_ALPHA, videoWidth / 2, videoHeight / 2, //尺寸要是2的次方 拉伸到全屏 0, GL_LUMINANCE_ALPHA,//数据的像素格式,要与上面一致 GL_UNSIGNED_BYTE,// 像素的数据类型 yuvBuf + (videoWidth * videoHeight) ); //三维绘制 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//从0顶点开始 一共4个顶点 //窗口显示 eglSwapBuffers(eglDisplay, eglSurface);//交换buf } 上述代码是正确,在main函数如何调用
07-13
#include "openglrenderer.h" OpenGLRenderer::OpenGLRenderer(QWidget *parent) :QOpenGLWidget(parent) ,m_program(nullptr), m_texture(nullptr) ,m_vbo(0), m_ebo(0), m_vao(0) ,m_textureInitialized(false) , m_textureWidth(0), m_textureHeight(0) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } OpenGLRenderer::~OpenGLRenderer() { makeCurrent(); if(m_texture) delete m_texture; if(m_program) delete m_program; glDeleteBuffers(1, &m_vbo); glDeleteBuffers(1, &m_ebo); glDeleteVertexArrays(1, &m_vao); doneCurrent(); } void OpenGLRenderer::updateFrame(const std::shared_ptr<VideoFrame> frame) { QMutexLocker locker(&m_frameMutex); m_currentFrame = frame; m_textureWidth = frame->width; m_textureHeight = frame->height; // 首次收到帧时发出尺寸信号, 初始化纹理 if (frame && !m_textureInitialized) { initTextures(); emit frameSizeChanged(m_textureWidth, m_textureHeight); } update(); } void OpenGLRenderer::initializeGL() { initializeOpenGLFunctions(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); initShaders(); // 创建顶点数组对象 glGenVertexArrays(1, &m_vao); glGenBuffers(1, &m_vbo); glGenBuffers(1, &m_ebo); glBindVertexArray(m_vao); // 顶点数据 glBindBuffer(GL_ARRAY_BUFFER, m_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_STATIC_DRAW); // 索引数据 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_indices), m_indices, GL_STATIC_DRAW); // 位置属性 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); glEnableVertexAttribArray(0); // 纹理坐标属性 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); glBindVertexArray(0); } void OpenGLRenderer::resizeGL(int w, int h) { glViewport(0, 0, w, h); } void OpenGLRenderer::paintGL() { glClear(GL_COLOR_BUFFER_BIT); if (!m_program || !m_texture) return; m_program->bind(); glBindVertexArray(m_vao); m_texture->bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_textureWidth, m_textureHeight, GL_RGB, GL_UNSIGNED_BYTE, m_currentFrame->data); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); m_program->release(); m_texture->release(); } void OpenGLRenderer::initShaders() { m_program = new QOpenGLShaderProgram(this); // 设置顶点着色器 m_program->addShaderFromSourceCode( QOpenGLShader::Vertex, "#version 440 core\n" "layout (location = 0) in vec3 aPos;\n" "layout (location = 1) in vec2 aTexCoord;\n" "out vec2 TexCoord;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos, 1.0);\n" " TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);\n" "}\n"); // 设置片段着色器 m_program->addShaderFromSourceCode( QOpenGLShader::Fragment, "#version 440 core\n" "in vec2 TexCoord;\n" "out vec4 FragColor;\n" "uniform sampler2D textureY;\n" "void main()\n" "{\n" " vec3 rgb = texture(textureY, TexCoord).rgb;\n" " FragColor = vec4(rgb, 1.0);\n" "}\n"); if (!m_program->link()) { qDebug() << "Shader linking error:" << m_program->log(); } } // 纹理将在第一帧到达时创建 void OpenGLRenderer::initTextures() { if (m_currentFrame->data) { m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D); m_texture->setFormat(QOpenGLTexture::RGB8_UNorm); m_texture->setSize(m_textureWidth, m_textureHeight); m_texture->allocateStorage(); m_texture->setMinificationFilter(QOpenGLTexture::Linear); m_texture->setMagnificationFilter(QOpenGLTexture::Linear); m_texture->setWrapMode(QOpenGLTexture::ClampToEdge); m_textureInitialized = true; } } void OpenGLRenderer::updateTexture() { QMutexLocker locker(&m_frameMutex); if (!m_currentFrame) return; if (m_texture && m_currentFrame->data) { m_texture->bind(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_textureWidth, m_textureHeight, GL_RGB, GL_UNSIGNED_BYTE, m_currentFrame->data); } } 注释上述代码
最新发布
09-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥游侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值