PDA

View Full Version : Window - independent rendering contexts



skippyj777
08-13-2000, 02:41 PM
I am using OpenGL on Windows. How can I create a rendering context that is independent of a window? I do not want to render directly to a window, I would rather have OpenGL render directly to an offscreen surface such as a DIB, a block of RGB memory, or to an IDirectDrawSurface. How could I do this?

NewROmancer
08-13-2000, 09:56 PM
I don't think you can because when you create the window you have to specify the pixel format. Just now I'm studyind the same problem and please if you can make something from it say it on the forum because I'm interested.

NewROmancer

Kilam Malik
08-14-2000, 05:36 AM
Look here:

http://www.opengl.org/discussion_boards/ubb/Forum2/HTML/001072.html


[This message has been edited by Kilam Malik (edited 08-14-2000).]

skippyj777
08-14-2000, 05:42 AM
Thanks, this looks like it will work for me. I'll post a description of the results.

skippyj777
08-14-2000, 04:56 PM
I used the code from post #8 on the forum you mentioned and it worked the very first time!! Thanks a million!!!

skippyj777
08-14-2000, 04:59 PM
Here's my source code. It won't compile because it uses some of my own units but if you take out the unused stuff it will work. The program was written using Delphi 5.

This is actually the beginnings of an OpenGL wrapper I have been working on for a few days. OpenGL programming is way easier than DirectDraw and Direct3DRM!!! Stuff actually does what it is suppose to do!

skippyj777
08-14-2000, 05:01 PM
unit MainForm;

interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OpenGL12, Oogle
;

type
TfrmMain = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);

public
rc: IOogleRenderDest;

end;

var
frmMain: TfrmMain;

implementation
{$R *.DFM}

procedure TfrmMain.FormPaint(Sender: TObject);
begin
rc.Start;
try
glBegin(GL_TRIANGLES);
glColor3F(1, 1, 1);
glVertex3F(0, 0, 0);
glVertex3F(0.9, 0, 0);
glVertex3F(1, 1, 0);
glEnd;
finally
rc.Finish;
end;
rc.BitBlt(Canvas.Handle, 0, 0);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
InitOpenGL;
rc := TOogleRenderDestBitmap.Create(ClientWidth, ClientHeight);
end;

end.


[This message has been edited by skippyj777 (edited 08-14-2000).]

[This message has been edited by skippyj777 (edited 08-14-2000).]

skippyj777
08-14-2000, 05:02 PM
unit MainForm;
// This code was originally formatted with tabs and spacing.

interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OpenGL12, Oogle
;

type
TfrmMain = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);

public
ogl: IOogle;
rc: IOogleRenderDest;

end;

var
frmMain: TfrmMain;

implementation
{$R *.DFM}

procedure TfrmMain.FormPaint(Sender: TObject);
begin
rc.Start;
try
glBegin(GL_TRIANGLES);
glColor3F(1, 1, 1);
glVertex3F(0, 0, 0);
glVertex3F(0.9, 0, 0);
glVertex3F(1, 1, 0);
glEnd;
finally
rc.Finish;
end;
rc.BitBlt(Canvas.Handle, 0, 0);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
OogleCreate(ogl);
rc := TOogleRenderDestBitmap.Create(ClientWidth, ClientHeight);
end;

end.

skippyj777
08-14-2000, 05:09 PM
unit Oogle;
{$Z+,B-}

// Object-oriented Open GL wrapper. Copyright 2000 Potts Development.

interface
uses
Windows, OpenGL12, Classes
;

type
IOogleObject = interface;
IOogleRenderDest = interface;

OOGLE_DESTROYCALLBACK = procedure(Sender: IOogleObject; Arg: Pointer) of object;
pOOGLE_DESTROYCALLBACK_DATA = ^OOGLE_DESTROYCALLBACK_DATA;
OOGLE_DESTROYCALLBACK_DATA = record
Callback: OOGLE_DESTROYCALLBACK;
Arg: Pointer;
end;

pOOGLE_APPDATA = ^OOGLE_APPDATA;
OOGLE_APPDATA = record
ID: TGUID;
Data: Pointer;
end;

IOogleObject = interface(IUnknown)
['{D8866DE5-B56D-4A83-892E-07C17B18F49D}']
function GetAppData(const ID: TGUID): Pointer;
procedure SetAppData(const ID: TGUID; Value: Pointer);
procedure AddDestroyCallback(cb: OOGLE_DESTROYCALLBACK; Arg: Pointer);
function GetName: WideString;
procedure SetName(Value: WideString);
end;

IOogleRenderDest = interface(IOogleObject)
['{17479C51-020C-40FE-85DC-F4CC2394DF66}']
procedure Start;
procedure Finish;
procedure BitBlt(DestDC: HDC; DestX, DestY: Integer);
end;

TOogleObject = class(TInterfacedObject, IOogleObject)
protected
FDestroyCallbacks: TList;
FAppData: TList;
FName: WideString;

procedure ClearAppData;

public
constructor Create; virtual;
destructor Destroy; override;

function GetAppData(const ID: TGUID): Pointer;
procedure SetAppData(const ID: TGUID; Value: Pointer);
procedure AddDestroyCallback(cb: OOGLE_DESTROYCALLBACK; Arg: Pointer);
function GetName: WideString;
procedure SetName(Value: WideString);

end;

TOogleRenderDest = class(TOogleObject, IOogleRenderDest)
protected
FRenderContext: HGLRC;
FStartCount: DWORD;

public
constructor Create; override;
destructor Destroy; override;

procedure Start; virtual;
procedure Finish; virtual;
procedure BitBlt(DestDC: HDC; DestX, DestY: Integer); virtual; abstract;

end;

TOogleRenderDestBitmap = class(TOogleRenderDest)
protected
FRenderContext: HGLRC;
FBitmapDC: HDC;

//FMemoryDC: HDC;
FBitDepth: Integer;
FBitmap: HBITMAP;

FBitmapInfo: BITMAP;

FPixelFormat: PIXELFORMATDESCRIPTOR;
FPixelFormatIndex: Integer;

public
constructor Create(w, h: Integer); reintroduce;
destructor Destroy; override;
procedure Start; override;
procedure Finish; override;
procedure BitBlt(DestDC: HDC; DestX, DestY: Integer); override;

end;

implementation
uses
SysUtils, Messages
;

constructor TOogleObject.Create;
begin
FAppData := TList.Create;
FDestroyCallbacks := TList.Create;
end;

destructor TOogleObject.Destroy;
var
i: Integer;
dc: pOOGLE_DESTROYCALLBACK_DATA;
begin
try
try
for i := 0 to FDestroyCallbacks.Count - 1 do begin
try
dc := FDestroyCallbacks[i];
dc.Callback(Self, dc.Arg);
Dispose(dc);
except
// Ignore
end;
end;
finally
FDestroyCallbacks.Free;
end;
try
ClearAppData;
finally
FAppData.Free;
end;
finally
inherited;
end;
end;

procedure TOogleObject.ClearAppData;
var
i: Integer;
begin
try
for i := 0 to FAppData.Count - 1 do begin
Dispose(FAppData[i]);
end;
finally
FAppData.Clear;
end;
end;

function TOogleObject.GetAppData(const ID: TGUID): Pointer;
var
i: Integer;
ad: pOOGLE_APPDATA;
begin
for i := 0 to FAppData.Count - 1 do begin
ad := FAppData[i];
if PDCompareGUIDs(ID, ad^.ID) then begin
Result := ad^.Data;
Exit;
end;
end;
Result := nil;
end;

procedure TOogleObject.SetAppData(const ID: TGUID; Value: Pointer);
var
i: Integer;
ad: pOOGLE_APPDATA;
begin
for i := 0 to FAppData.Count - 1 do begin
ad := FAppData[i];
if PDCompareGUIDs(ID, ad^.ID) then begin
ad^.Data := Value;
Exit;
end;
end;
New(ad);
try
ad^.ID := ID;
ad^.Data := Value;
FAppData.Add(ad);
except
Dispose(ad);
raise;
end;
end;

procedure TOogleObject.AddDestroyCallback(cb: OOGLE_DESTROYCALLBACK; Arg: Pointer);
var
dc: pOOGLE_DESTROYCALLBACK_DATA;
begin
New(dc);
try
dc^.Callback := cb;
dc^.Arg := Arg;
FDestroyCallbacks.Add(dc);
except
Dispose(dc);
raise;
end;
end;

function TOogleObject.GetName: WideString;
begin
Result := FName;
end;

procedure TOogleObject.SetName(Value: WideString);
begin
FName := Value;
end;

constructor TOogleRenderDest.Create;
begin
inherited;
// Do nothing for now
end;

destructor TOogleRenderDest.Destroy;
begin
try
wglDeleteContext(FRenderContext); // Automatically makes context noncurrent before deleting it
finally
inherited;
end;
end;

procedure TOogleRenderDest.Start;
begin
Inc(FStartCount);
end;

procedure TOogleRenderDest.Finish;
begin
if FStartCount > 0 then Dec(FStartCount);
end;

constructor TOogleRenderDestBitmap.Create(w, h: Integer);
var
FMemoryDC: HDC;
begin
inherited Create;

FMemoryDC := CreateCompatibleDC(0);
FBitDepth := GetDeviceCaps(FMemoryDC, BITSPIXEL);
FBitmap := CreateBitmap(w, h, 1, FBitDepth, nil);
SelectObject(FMemoryDC, FBitmap);
FBitmapDC := FMemoryDC;

GetObject(FBitmap, SizeOf(BITMAP), @FBitmapInfo);

FPixelFormat.nSize := SizeOf(FPixelFormat);
FPixelFormat.nVersion := 1;
FPixelFormat.dwFlags := PFD_DRAW_TO_BITMAP or PFD_SUPPORT_OPENGL or PFD_TYPE_RGBA;
FPixelFormat.iPixelType := PFD_TYPE_RGBA;
FPixelFormat.cColorBits := FBitmapInfo.bmBitsPixel;
FPixelFormat.cDepthBits := 32; // 32-bit depth buffer
FPixelFormat.iLayerType := PFD_MAIN_PLANE;

FPixelFormatIndex := ChoosePixelFormat(FBitmapDC, @FPixelFormat);
if not SetPixelFormat(FBitmapDC, FPixelFormatIndex, @FPixelFormat) then raise Exception.Create('Unable to set pixel format');

FRenderContext := wglCreateContext(FBitmapDC);
if FRenderContext = 0 then raise Exception.Create('Unable to create render context');
end;

destructor TOogleRenderDestBitmap.Destroy;
begin
try
wglDeleteContext(FRenderContext);
DeleteObject(FBitmap);
DeleteDC(FBitmapDC);
finally
inherited;
end;
end;

procedure TOogleRenderDestBitmap.Start;
begin
inherited;
if FStartCount = 1 then wglMakeCurrent(FBitmapDC, FRenderContext);
end;

procedure TOogleRenderDestBitmap.Finish;
begin
if FStartCount = 1 then wglMakeCurrent(FBitmapDC, 0);
inherited;
end;

procedure TOogleRenderDestBitmap.BitBlt(DestDC: HDC; DestX, DestY: Integer);
begin
if not Windows.BitBlt(DestDC, DestX, DestY, FBitmapInfo.bmWidth, FBitmapInfo.bmHeight, FBitmapDC, 0, 0, SRCCOPY) then raise Exception.Create('Windows.BitBlt() failed');
end;

end.


[This message has been edited by skippyj777 (edited 08-14-2000).]

NewROmancer
08-14-2000, 11:53 PM
I'll try to look over your code. Thanks anyway.

NewROmancer