**关闭。**此题需要debugging details。目前不接受答复。
编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答这个问题。
昨天关门了。
Improve this question
我有一个大小为1920x1080的背景图像和第二个305x3132的图像。第二个图像是由12个高度为261px的标志创建的。两个图像都是32位位图,并且具有透明度。背景图像没有透明部分。大部分东西都能正常工作,但我有两个问题。这是我的代码。OpenGL的所有代码都在单独的单元中,在这里。
unit OpenGLProc;
interface
uses
Winapi.Windows, Vcl.Graphics, OpenGL, Gifimg, Pngimage;
type
TTexture = record
Handle : GLuint;
Width : integer;
Height : integer;
end;
procedure InitOpenGL(DCin : HDC; FGLContext : HGLRC);
procedure LoadTexture(image : TBitmap; offsetX, offsetY, texWidth, texHeight : integer; mode : integer; out text : TTexture);
procedure DrawTexture(texIn : TTexture; width, height, winWidth, winHeight, texOffsetX, texOffsetY, offsetX, offsetY : single; flipped : integer);
procedure BindFramebufferTex(texIn : TTexture);
procedure FramebufferTexture2DTex(texIn : TTexture);
procedure UpdateTexture(inTex : TTexture; offsetXsrc, offsetYsrc, offsetXdst, offsetYdst, width, height : integer; outTex : TTexture);
type
TglGenFramebuffers = procedure(n: GLsizei; framebuffers: PGLuint); {$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
TglBindFramebuffer = procedure(target: GLenum; framebuffer: GLuint); {$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
TglFramebufferTexture2D = procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
TglCopyImageSubData = procedure(srcName: GLuint; srcTarget: GLenum; srcLevel: GLint; srcX: GLint; srcY: GLint; srcZ: GLint; dstName: GLuint; dstTarget: GLenum; dstLevel: GLint; dstX: GLint; dstY: GLint; dstZ: GLint; width: GLsizei; height: GLsizei; depth: GLsizei); {$IFDEF MSWINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
var
glGenFramebuffers : TglGenFramebuffers = nil;
glBindFramebuffer : TglBindFramebuffer = nil;
glFramebufferTexture2D : TglFramebufferTexture2D = nil;
glCopyImageSubData : TglCopyImageSubData = nil;
FGLMainContext : HGLRC;
screenTex : TTexture;
screenFB : TTexture;
bckTex, signsTex : TTexture;
const
GL_FRAMEBUFFER = $8D40;
GL_COLOR_ATTACHMENT0 = $8CE0;
implementation
type
TRGBA = packed record
R, G, B, A : Byte;
end;
PRGBA = ^TRGBA;
procedure InitOpenGL(DCin : HDC; FGLContext : HGLRC);
var
pfd : TPixelFormatDescriptor;
pf : integer;
glc : HGLRC;
begin
ZeroMemory(@pfd, SizeOf(TPixelFormatDescriptor));
pfd.nSize := SizeOf(TPixelFormatDescriptor);
pfd.nVersion := 1;
pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
pfd.iPixelType := PFD_TYPE_RGBA;
pfd.cColorBits := 24;
pfd.cDepthBits := 32;
pf := ChoosePixelFormat(DCin, @pfd);
SetPixelFormat(DCin, pf, @pfd);
glc := wglCreateContext(DCin);
wglMakeCurrent(DCin, glc);
FGLContext := glc;
// Enable blending
glEnable(GL_BLEND);
// Set the blend function to take alpha into account
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Enable texturing
glEnable(GL_TEXTURE_2D);
// Initialize OpnenGL functions
glGenFramebuffers := TglGenFramebuffers(wglGetProcAddress('glGenFramebuffers'));
glBindFramebuffer := TglBindFramebuffer(wglGetProcAddress('glBindFramebuffer'));
glFramebufferTexture2D := TglFramebufferTexture2D(wglGetProcAddress('glFramebufferTexture2D'));
glCopyImageSubData := TglCopyImageSubData(wglGetProcAddress('glCopyImageSubData'));
end;
procedure LoadTexture(image : TBitmap; offsetX, offsetY, texWidth, texHeight : integer; mode : integer; out text : TTexture);
var
PixelData : PByte;
Pixel : PRGBA;
x, y : integer;
row : pRGBQuadArray;
begin
case mode of
0: // empty texture will be created
begin
try
// Create and bind the texture object
glGenTextures(1, @text.Handle);
glBindTexture(GL_TEXTURE_2D, text.Handle);
text.Width := texWidth;
text.Height := texHeight;
// Set the texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Load the texture data into the texture object
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
finally
end;
end;
1: // New texture will be created and populated
begin
// Allocate memory for the texture data
GetMem(PixelData, texWidth * texHeight * SizeOf(TRGBA));
try
// Copy the bitmap image data into the texture data
Pixel := PRGBA(PixelData);
for y := offsetY to texHeight - 1 do
begin
row := image.ScanLine[y];
for x := offsetX to texWidth - 1 do
begin
Pixel^.R := row[x].rgbRed;
Pixel^.G := row[x].rgbGreen;
Pixel^.B := row[x].rgbBlue;
Pixel^.A := row[x].rgbReserved;
Inc(Pixel);
end;
end;
// Create and bind the texture object
glGenTextures(1, @text.Handle);
glBindTexture(GL_TEXTURE_2D, text.Handle);
text.Width := texWidth;
text.Height := texHeight;
// Set the texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// Load the texture data into the texture object
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, PixelData);
finally
FreeMem(PixelData);
end;
end;
end;
end;
procedure DrawTexture(texIn : TTexture; width, height, winWidth, winHeight, texOffsetX, texOffsetY, offsetX, offsetY : single; flipped : integer);
begin
glPushMatrix();
glTranslatef(-1 + (offsetX / winWidth * 2.0) + (width / winWidth), 1 - (offsetY / WinHeight * 2.0) - (height / winHeight), 0.0);
// Unbind the screen texture and framebuffer
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, texIn.Handle);
glBegin(GL_QUADS);
glTexCoord2f(texOffsetX / texIn.Width, (texOffsetY + height) / texIn.Height); glVertex2f(-width / winWidth, -height / winHeight);
glTexCoord2f((texOffsetX + width) / texIn.Width, (texOffsetY + height) / texIn.Height); glVertex2f(width / winWidth, -height / winHeight);
glTexCoord2f((texOffsetX + width) / texIn.Width, texOffsetY / texIn.Height); glVertex2f(width / winWidth, height / winHeight);
glTexCoord2f(texOffsetX / texIn.Width, texOffsetY / texIn.Height); glVertex2f(-width / winWidth, height / winHeight);
glEnd;
glFlush;
glPopMatrix();
end;
procedure BindFramebufferTex(texIn : TTexture);
begin
glBindFramebuffer(GL_FRAMEBUFFER, texIn.Handle);
end;
procedure FramebufferTexture2DTex(texIn : TTexture);
begin
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texIn.Handle, 0);
end;
procedure UpdateTexture(inTex : TTexture; offsetXsrc, offsetYsrc, offsetXdst, offsetYdst, width, height : integer; outTex : TTexture);
begin
glCopyImageSubData(inTex.Handle, GL_TEXTURE_2D, 0,
offsetXsrc, offsetYsrc, 0,
outTex.Handle, GL_TEXTURE_2D, 0,
offsetXdst, offsetYdst, 0,
width, height, 1);
end;
end.
现在在主要形式中我称这些过程。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, OpenGLProc, Vcl.StdCtrls;
type
TForm1 = class(TForm)
btnClose: TButton;
btnDrawBck: TButton;
btnDrawCol: TButton;
btnDrawColOver: TButton;
procedure FormCreate(Sender: TObject);
procedure btnCloseClick(Sender: TObject);
procedure btnDrawBckClick(Sender: TObject);
procedure btnDrawColClick(Sender: TObject);
procedure btnDrawColOverClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
background, signs : TBitmap;
colTex : TTexture;
DC : HDC;
const
signHeight = 261;
implementation
{$R *.dfm}
procedure TForm1.btnCloseClick(Sender: TObject);
begin
Form1.Close;
end;
procedure TForm1.btnDrawBckClick(Sender: TObject);
begin
UpdateTexture(bckTex, 0, 0, 0, 0, bckTex.Width, bckTex.Height, screenTex);
DrawTexture(screenTex, screenTex.Width, screenTex.Height, Form1.Width, Form1.Height, 0, 0, 0, 0, 1);
SwapBuffers(Canvas.Handle);
end;
procedure TForm1.btnDrawColClick(Sender: TObject);
begin
UpdateTexture(bckTex, 0, 0, 0, 0, bckTex.Width, bckTex.Height, screenTex);
UpdateTexture(signsTex, 0, 1827, 198, 120, signsTex.Width, 3 * signHeight, screenTex);
DrawTexture(screenTex, screenTex.Width, screenTex.Height, Form1.Width, Form1.Height, 0, 0, 0, 0, 1);
SwapBuffers(Canvas.Handle);
end;
procedure TForm1.btnDrawColOverClick(Sender: TObject);
begin
UpdateTexture(signsTex, 0, 0, 0, 0, 305, signHeight, colTex);
UpdateTexture(signsTex, 0, 9 * signHeight, 0, signHeight, 305, signHeight, colTex);
UpdateTexture(signsTex, 0, 8 * signHeight, 0, 2 * signHeight - 8, 305, signHeight, colTex);
UpdateTexture(colTex, 0, 0, 503, 120, signsTex.Width, 3 * signHeight, screenTex);
DrawTexture(screenTex, screenTex.Width, screenTex.Height, Form1.Width, Form1.Height, 0, 0, 0, 0, 1);
SwapBuffers(Canvas.Handle);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
background := TBitmap.Create;
background.LoadFromFile('back1.bmp');
signs := TBitmap.Create;
signs.LoadFromFile('znakovi.bmp');
DC := GetDC(Handle);
Sleep(200);
InitOpenGL(DC, FGLMainContext);
// Create the texture for the framebuffer
LoadTexture(background, 0, 0, background.Width, background.Height, 0, screenTex);
// Set up the framebuffer
if Assigned(glGenFramebuffers) then
begin
glGenFramebuffers(1, @screenFB);
end
else
begin
ShowMessage('glGenFramebuffers is not initialized!');
end;
BindFramebufferTex(screenFB);
FramebufferTexture2DTex(screenTex);
LoadTexture(background, 0, 0, background.Width, background.Height, 1, bckTex);
LoadTexture(signs, 0, 0, signs.Width, signs.Height, 1, signsTex);
LoadTexture(signs, 0, 0, signs.Width, signs.Height, 0, colTex);
end;
end.
我的问题是。
当我只点击按钮btnDrawCol第二个纹理的透明部分在屏幕上是黑色的。背景纹理是可以的,第二个纹理的非透明部分是可以的,但为什么透明部分是黑色的?
奇怪的是,当我第一次点击按钮btnDrawBck(这只在屏幕上绘制背景),然后点击按钮btnDrawCol,一切正常。为什么?
第二个更大的问题。我想削减部分第二纹理和创造第三纹理从他们。一切都很好(除了上面的问题),直到我尝试重叠部分。例如,我剪了三个部分,第三部分是重叠的,第二部分的最后8px是完全透支的,即使第三部分的线条是透明的。
我贴了一张图片作为例子。左侧为重叠。我需要的只是非透明部分,上面的内容(黄色框架应在触摸)。
这里是黑色区域和透明的图像。
这也是我尝试创作的一些作品。它们太大了,所以我必须将位图转换为PNG(并更改加载图像的代码部分)。
下面是“FormCreate”过程中更改的部分代码。
{background := TBitmap.Create;
background.LoadFromFile('back1-test.bmp');
signs := TBitmap.Create;
signs.LoadFromFile('znakovi-test.bmp');}
png := TPngImage.Create;
png.LoadFromFile('back1.png');
background := TBitmap.Create;
background.PixelFormat := pf32bit;
background.SetSize(png.Width, png.Height);
background.Canvas.Brush.Color := RGB(0, 0, 0);
background.Canvas.FillRect(background.Canvas.ClipRect);
png.Draw(background.Canvas, background.Canvas.ClipRect);
png.Free;
png := TPngImage.Create;
png.LoadFromFile('znakovi.png');
signs := TBitmap.Create;
signs.PixelFormat := pf32bit;
signs.SetSize(png.Width, png.Height);
signs.Canvas.Brush.Color := RGB(0, 0, 0);
signs.Canvas.FillRect(signs.Canvas.ClipRect);
png.Draw(signs.Canvas, signs.Canvas.ClipRect);
png.Free;
1条答案
按热度按时间qacovj5a1#
glCopyImageSubData
执行原始数据复制,但不混合图像。此函数不关心Alpha通道。这是错误的功能为您的任务。您需要使用着色器程序绘制图像并启用混合。