在 C++ 中显示无边框透明背景的图像/ OpenGL

发布于 2024-12-04 06:38:10 字数 4219 浏览 8 评论 0原文

我正在寻找一种方法来在透明背景无边框的窗口上显示两个 png 图像(事实上,它将是数字,我的目标是创建一个用于实时流媒体的叠加层以显示玩家得分和一些其他附加内容)。这样我们就可以看到后面窗口上的分数。

有什么办法可以做类似的事情吗?我已经用 SDL、纹理尝试了很多东西,但没有任何结果能让我满意。我发现的最好的结果是一些脏代码几乎可以工作但完全无法使用。

如果可能,该解决方案可以添加这样的功能:当您在 2 个分数之一上向左或向右单击时,它会增加或减少。

编辑:这是我当前的代码。我开始新的工作,没有任何以前的脏代码,因为我想了解我在做什么。我将 2 个数字显示为纹理,现在我想删除窗口的边框和标题栏,并使背景透明。

#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <windows.h>
#include <windowsx.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "sdlglutils.h"

#include <assert.h>
#include <tchar.h>

using namespace std;

int overlay;
int TimerEnabled;
GLfloat posX, posY, posZ;
GLuint texture_0, texture_1, texture_2, texture_3;

void Initialize()
{
    glEnable(GL_ALPHA_TEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0, 0, 0, 0);

    glEnable(GL_TEXTURE_2D);
}

void Reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)w/(GLfloat)h,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    texture_0 = loadTexture("0.png");
    texture_1 = loadTexture("1.png");
    texture_2 = loadTexture("2.png");
    texture_3 = loadTexture("3.png");

    return;
}

void Draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    glTranslatef(posX,posY,posZ);

    glScalef(1.0f,1.0f,1.0f);
    glPushMatrix();
        glTranslated(-6, 8, 0);
        glBindTexture(GL_TEXTURE_2D, texture_1);
        glBegin(GL_QUADS);
            glTexCoord2d(0,0);      glVertex2d(0,0);
            glTexCoord2d(1,0);      glVertex2d(1,0);
            glTexCoord2d(1,1);      glVertex2d(1,1);
            glTexCoord2d(0,1);      glVertex2d(0,1);
        glEnd();
    glPopMatrix();

    glPushMatrix();
        glTranslated(6, 8, 0);
        glBindTexture(GL_TEXTURE_2D, texture_2);
        glBegin(GL_QUADS);
            glTexCoord2d(0,0);      glVertex2d(0,0);
            glTexCoord2d(1,0);      glVertex2d(1,0);
            glTexCoord2d(1,1);      glVertex2d(1,1);
            glTexCoord2d(0,1);      glVertex2d(0,1);
        glEnd();
    glPopMatrix();

    glFlush();
}

void Display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    Draw();

    glutSwapBuffers();
}

void KeyboardSpecialEvent( int key, int x, int y)
{
    switch(key)
    {
        case(GLUT_KEY_UP) :
        {
            posY += 0.3;
        }break;

        case(GLUT_KEY_DOWN) :
        {
            posY -= 0.3;
        }break;

        case(GLUT_KEY_LEFT) :
        {
            posX -= 0.3;
        }break;

        case(GLUT_KEY_RIGHT) :
        {
            posX += 0.3;
        }break;
    }
}
void MouseEvent( int button, int state, int x, int y){ };
void MotionMouseEvent( int x, int y ){  };
void IdleEvent(){  };
void TimerEvent(int time)
{
    glutPostRedisplay();

    if(TimerEnabled)
        glutTimerFunc(10, TimerEvent, time);
}

void KeyboardEvent( unsigned char key, int x, int y)
{
    switch(key)
    {
        case ' ' :
        {
            TimerEnabled = !TimerEnabled;
            if (TimerEnabled)
                glutTimerFunc(40, TimerEvent, 0);
        }
        break;

        case 'q' :
        {
            exit(0);
        }
        break;
    }
}

int main(int argc, char** argv)
{
    posX = 0;
    posY = 0;
    posZ = -25;
    TimerEnabled = 1;

    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGBA);

    glutInitWindowSize(1600,900);
    glutInitWindowPosition(0,0);

    overlay = glutCreateWindow("ScoreOverlay");
    //glutFullScreen();

    Initialize();

    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutKeyboardFunc(KeyboardEvent);
    glutSpecialFunc(KeyboardSpecialEvent);
    glutMouseFunc(MouseEvent);
    glutMotionFunc(MotionMouseEvent);
    glutIdleFunc(IdleEvent);
    glutTimerFunc(40, TimerEvent, 0);

    glutMainLoop();

    return 0;
}

I am looking for a way to display two png images (in fact, it will be numbers, my aim is to create an overlay for live streaming to display players score and some further additional content) on a window with transparent background with no border. So that we just see the score over the window placed behind.

Is there any way to do something like that ? I have already tried many things with SDL, textures, but nothing led me to any satisfying result. The best I found was some dirty code almost working but completely unusable.

If possible, the solution may let possible to add the functionality that when you click left or right on one of the 2 scores, it is incremented or decremented.

Edit: Here is my current code. I started new without any bit of the dirty code I had before, because I would like to understand what I am doing. I have my 2 numbers displayed as textures, now I would like to remove borders and title bar of my window, and make my background transparent.

#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <windows.h>
#include <windowsx.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "sdlglutils.h"

#include <assert.h>
#include <tchar.h>

using namespace std;

int overlay;
int TimerEnabled;
GLfloat posX, posY, posZ;
GLuint texture_0, texture_1, texture_2, texture_3;

void Initialize()
{
    glEnable(GL_ALPHA_TEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0, 0, 0, 0);

    glEnable(GL_TEXTURE_2D);
}

void Reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (GLfloat)w/(GLfloat)h,0.1f,100.0f);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    texture_0 = loadTexture("0.png");
    texture_1 = loadTexture("1.png");
    texture_2 = loadTexture("2.png");
    texture_3 = loadTexture("3.png");

    return;
}

void Draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    glTranslatef(posX,posY,posZ);

    glScalef(1.0f,1.0f,1.0f);
    glPushMatrix();
        glTranslated(-6, 8, 0);
        glBindTexture(GL_TEXTURE_2D, texture_1);
        glBegin(GL_QUADS);
            glTexCoord2d(0,0);      glVertex2d(0,0);
            glTexCoord2d(1,0);      glVertex2d(1,0);
            glTexCoord2d(1,1);      glVertex2d(1,1);
            glTexCoord2d(0,1);      glVertex2d(0,1);
        glEnd();
    glPopMatrix();

    glPushMatrix();
        glTranslated(6, 8, 0);
        glBindTexture(GL_TEXTURE_2D, texture_2);
        glBegin(GL_QUADS);
            glTexCoord2d(0,0);      glVertex2d(0,0);
            glTexCoord2d(1,0);      glVertex2d(1,0);
            glTexCoord2d(1,1);      glVertex2d(1,1);
            glTexCoord2d(0,1);      glVertex2d(0,1);
        glEnd();
    glPopMatrix();

    glFlush();
}

void Display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    Draw();

    glutSwapBuffers();
}

void KeyboardSpecialEvent( int key, int x, int y)
{
    switch(key)
    {
        case(GLUT_KEY_UP) :
        {
            posY += 0.3;
        }break;

        case(GLUT_KEY_DOWN) :
        {
            posY -= 0.3;
        }break;

        case(GLUT_KEY_LEFT) :
        {
            posX -= 0.3;
        }break;

        case(GLUT_KEY_RIGHT) :
        {
            posX += 0.3;
        }break;
    }
}
void MouseEvent( int button, int state, int x, int y){ };
void MotionMouseEvent( int x, int y ){  };
void IdleEvent(){  };
void TimerEvent(int time)
{
    glutPostRedisplay();

    if(TimerEnabled)
        glutTimerFunc(10, TimerEvent, time);
}

void KeyboardEvent( unsigned char key, int x, int y)
{
    switch(key)
    {
        case ' ' :
        {
            TimerEnabled = !TimerEnabled;
            if (TimerEnabled)
                glutTimerFunc(40, TimerEvent, 0);
        }
        break;

        case 'q' :
        {
            exit(0);
        }
        break;
    }
}

int main(int argc, char** argv)
{
    posX = 0;
    posY = 0;
    posZ = -25;
    TimerEnabled = 1;

    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGBA);

    glutInitWindowSize(1600,900);
    glutInitWindowPosition(0,0);

    overlay = glutCreateWindow("ScoreOverlay");
    //glutFullScreen();

    Initialize();

    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutKeyboardFunc(KeyboardEvent);
    glutSpecialFunc(KeyboardSpecialEvent);
    glutMouseFunc(MouseEvent);
    glutMotionFunc(MotionMouseEvent);
    glutIdleFunc(IdleEvent);
    glutTimerFunc(40, TimerEvent, 0);

    glutMainLoop();

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千寻… 2024-12-11 06:38:10

这是一个可以帮助您的工作基础示例(使用带有 clr 支持的 c++)。

您需要根据您的需要进行调整(例如使用 DrawImage 而不是 FillEllipse)

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;

ref class MyForm : public Form
{
public:

    MyForm()
    {
        this->m_brush = gcnew SolidBrush(Color::Blue);

        this->m_canvas = gcnew System::Windows::Forms::Panel();
        this->m_canvas->BackColor = Color::Pink;
        this->m_canvas->Dock = System::Windows::Forms::DockStyle::Fill;
        this->m_canvas->Location = System::Drawing::Point(0, 0);
        this->m_canvas->Margin = System::Windows::Forms::Padding(0);
        this->m_canvas->Name = "Canvas";
        this->m_canvas->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::canvas_Paint);
        this->m_canvas->TabIndex = 0;

        this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
        this->BackColor = Color::Pink;
        this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
        this->ClientSize = System::Drawing::Size(200, 200);
        this->Controls->Add(this->m_canvas);
        this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &MyForm::form_KeyDown);
        this->TransparencyKey = Color::Pink;
        this->Name = "MyForm";
        this->Text = "MyForm";
    }

private:

    void canvas_Paint(Object^ sender, PaintEventArgs^ e) {
        e->Graphics->FillEllipse(this->m_brush, Rectangle(50, 50, 100, 100));
    }

    void form_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) {
        // Test key ...
        this->m_canvas->Invalidate();
        // ...
    }

    Brush^ m_brush;
    Panel^ m_canvas;
};

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Enabling Windows XP visual effects before any controls are created
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false); 

    // Create the main window and run it
    Application::Run(gcnew MyForm());
    return 0;
}

Here is a working base sample (using c++ with clr support) that could help you.

You need to adapt it to your need (for example use DrawImage instead of FillEllipse)

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;

ref class MyForm : public Form
{
public:

    MyForm()
    {
        this->m_brush = gcnew SolidBrush(Color::Blue);

        this->m_canvas = gcnew System::Windows::Forms::Panel();
        this->m_canvas->BackColor = Color::Pink;
        this->m_canvas->Dock = System::Windows::Forms::DockStyle::Fill;
        this->m_canvas->Location = System::Drawing::Point(0, 0);
        this->m_canvas->Margin = System::Windows::Forms::Padding(0);
        this->m_canvas->Name = "Canvas";
        this->m_canvas->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::canvas_Paint);
        this->m_canvas->TabIndex = 0;

        this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
        this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
        this->BackColor = Color::Pink;
        this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
        this->ClientSize = System::Drawing::Size(200, 200);
        this->Controls->Add(this->m_canvas);
        this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &MyForm::form_KeyDown);
        this->TransparencyKey = Color::Pink;
        this->Name = "MyForm";
        this->Text = "MyForm";
    }

private:

    void canvas_Paint(Object^ sender, PaintEventArgs^ e) {
        e->Graphics->FillEllipse(this->m_brush, Rectangle(50, 50, 100, 100));
    }

    void form_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) {
        // Test key ...
        this->m_canvas->Invalidate();
        // ...
    }

    Brush^ m_brush;
    Panel^ m_canvas;
};

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Enabling Windows XP visual effects before any controls are created
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false); 

    // Create the main window and run it
    Application::Run(gcnew MyForm());
    return 0;
}
蓝眼泪 2024-12-11 06:38:10

看起来您在 Windows 上需要这个。您看过分层Windows吗?

除非您出于某种原因需要 OpenGL 来处理图形,否则我认为您最好将图像作为常规位图加载并直接将它们传输到分层窗口。使用 OpenGL,您需要绘制纹理贴图,然后获取该纹理并将其传输到分层窗口。

It looks like you need this on Windows. Have you looked at Layered Windows?

Unless you need OpenGL for the graphics for some reason I think you'll be better off loading your images as regular bitmaps and blitting them to the layered window directly. Using OpenGL you would need to draw to a texture map, then take that texture and blit it to the layered window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文