| @@ -0,0 +1,105 @@ | |||
| unit uglcArrayBuffer; | |||
| { Package: OpenGLCore | |||
| Prefix: glc - OpenGL Core | |||
| Beschreibung: diese Unit enthält eine Klassen-Kapselung für OpenGL Array Buffer } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| dglOpenGL, sysutils, uglcTypes; | |||
| type | |||
| EglcArrayBuffer = class(Exception); | |||
| TglcArrayBuffer = class(TObject) | |||
| private | |||
| fID: GLuint; | |||
| fTarget: TglcBufferTarget; | |||
| fUsage: TglcBufferUsage; | |||
| protected | |||
| fDataCount: Integer; | |||
| fDataSize: Integer; | |||
| public | |||
| property ID: gluInt read fID; | |||
| property Target: TglcBufferTarget read fTarget; | |||
| property Usage: TglcBufferUsage read fUsage; | |||
| property DataCount: Integer read fDataCount; | |||
| property DataSize: Integer read fDataSize; | |||
| procedure BufferData(const aDataCount, aDataSize: Cardinal; const aUsage: TglcBufferUsage; const aData: Pointer); | |||
| function MapBuffer(const aAccess: TglcBufferAccess): Pointer; | |||
| procedure UnmapBuffer; | |||
| procedure Bind; | |||
| procedure Unbind; | |||
| constructor Create(const aTarget: TglcBufferTarget); | |||
| destructor Destroy; override; | |||
| end; | |||
| implementation | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcArrayBuffer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| procedure TglcArrayBuffer.BufferData(const aDataCount, aDataSize: Cardinal; const aUsage: TglcBufferUsage; const aData: Pointer); | |||
| begin | |||
| glGetError(); //clear Errors | |||
| Bind; | |||
| fDataCount := aDataCount; | |||
| fDataSize := aDataSize; | |||
| fUsage := aUsage; | |||
| glBufferData(GLenum(fTarget), fDataCount * fDataSize, aData, GLenum(fUsage)); | |||
| glcCheckAndRaiseError; | |||
| end; | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| function TglcArrayBuffer.MapBuffer(const aAccess: TglcBufferAccess): Pointer; | |||
| begin | |||
| glGetError(); | |||
| result := nil; | |||
| if (fDataCount * fDataSize) <= 0 then | |||
| exit; | |||
| result := glMapBuffer(GLenum(fTarget), GLenum(aAccess)); | |||
| glcCheckAndRaiseError; | |||
| end; | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| procedure TglcArrayBuffer.UnmapBuffer; | |||
| begin | |||
| glUnmapBuffer(GLenum(fTarget)); | |||
| end; | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| procedure TglcArrayBuffer.Bind; | |||
| begin | |||
| glBindBuffer(GLenum(fTarget), fID); | |||
| end; | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| procedure TglcArrayBuffer.Unbind; | |||
| begin | |||
| glBindBuffer(GLenum(fTarget), 0); | |||
| end; | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| constructor TglcArrayBuffer.Create(const aTarget: TglcBufferTarget); | |||
| begin | |||
| if not GL_ARB_Vertex_Buffer_Object then | |||
| raise EglcArrayBuffer.Create('Create - VertexBuffer: not supported'); | |||
| inherited Create; | |||
| glGenBuffers(1, @fID); | |||
| fDataCount := 0; | |||
| fDataSize := 0; | |||
| fTarget := aTarget; | |||
| end; | |||
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c] | |||
| destructor TglcArrayBuffer.Destroy; | |||
| begin | |||
| glDeleteBuffers(1, @fID); | |||
| inherited Destroy; | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,254 @@ | |||
| unit uglcCamera; | |||
| { Package: OpenGLCore | |||
| Prefix: glc - OpenGL Core | |||
| Beschreibung: diese Unit enthält eine Klassen-Kapselung für OpenGL Frustum und Kamera } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, | |||
| ugluVector, ugluMatrix; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcFrustum = class(TObject) | |||
| private | |||
| function GetWidth: Single; | |||
| function GetHeight: Single; | |||
| function GetFOVAngle: Single; | |||
| function GetAspectRatio: Single; | |||
| protected | |||
| fIsOrthogonal: Boolean; | |||
| fTop, fBottom, fLeft, fRight, fNear, fFar: Single; | |||
| public | |||
| property Top : Single read fTop; | |||
| property Bottom : Single read fBottom; | |||
| property Left : Single read fLeft; | |||
| property Right : Single read fRight; | |||
| property Near : Single read fNear; | |||
| property Far : Single read fFar; | |||
| property Width : Single read GetWidth; | |||
| property Height : Single read GetHeight; | |||
| property FOVAngle : Single read GetFOVAngle; | |||
| property AspectRatio : Single read GetAspectRatio; | |||
| property IsOrthogonal: Boolean read fIsOrthogonal; | |||
| procedure Frustum(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single); | |||
| procedure Perspective(const aFOVAngle, aAspectRatio, aNear, aFar: Single); | |||
| procedure Ortho(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single); | |||
| procedure Activate; | |||
| procedure Render; | |||
| constructor Create; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcCamera = class(TglcFrustum) | |||
| private | |||
| fPosition: TgluMatrix4f; | |||
| public | |||
| property Position: TgluMatrix4f read fPosition write fPosition; | |||
| procedure Move(const aVec: TgluVector3f); | |||
| procedure Tilt(const aAngle: Single); | |||
| procedure Turn(const aAngle: Single); | |||
| procedure Roll(const aAngle: Single); | |||
| procedure Activate; | |||
| function GetRay(const aPos: TgluVector2f): TgluRayf; | |||
| constructor Create; | |||
| end; | |||
| implementation | |||
| uses | |||
| Math, dglOpenGL; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcFrustum/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrustum.GetWidth: Single; | |||
| begin | |||
| result := (fRight - fLeft); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrustum.GetHeight: Single; | |||
| begin | |||
| result := (fTop - fBottom); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrustum.GetFOVAngle: Single; | |||
| begin | |||
| result := arctan2(Height/2, fNear)/Pi*360; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrustum.GetAspectRatio: Single; | |||
| begin | |||
| result := Height / Width; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrustum.Frustum(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single); | |||
| begin | |||
| fIsOrthogonal := false; | |||
| fTop := aRight; | |||
| fBottom := aLeft; | |||
| fLeft := aBottom; | |||
| fRight := aTop; | |||
| fNear := aNear; | |||
| fFar := aFar; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrustum.Perspective(const aFOVAngle, aAspectRatio, aNear, aFar: Single); | |||
| begin | |||
| fIsOrthogonal := false; | |||
| fNear := aNear; | |||
| fFar := aFar; | |||
| fTop := fNear * tan(aFOVAngle / 360 * Pi); | |||
| fBottom := -fTop; | |||
| fRight := aAspectRatio * fTop; | |||
| fLeft := -fRight; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrustum.Ortho(const aLeft, aRight, aBottom, aTop, aNear, aFar: Single); | |||
| begin | |||
| fIsOrthogonal := true; | |||
| fLeft := aLeft; | |||
| fRight := aRight; | |||
| fTop := aTop; | |||
| fBottom := aBottom; | |||
| fNear := aNear; | |||
| fFar := aFar; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrustum.Activate; | |||
| begin | |||
| glMatrixMode(GL_PROJECTION); | |||
| glLoadIdentity; | |||
| if fIsOrthogonal then | |||
| glOrtho(fLeft, fRight, fBottom, fTop, fNear, fFar) | |||
| else | |||
| glFrustum(fLeft, fRight, fBottom, fTop, fNear, fFar); | |||
| glMatrixMode(GL_MODELVIEW); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrustum.Render; | |||
| var | |||
| min, max: TgluVector2f; | |||
| begin | |||
| min[0] := fLeft / fNear * fFar; | |||
| min[1] := fBottom / fNear * fFar; | |||
| max[0] := fRight / fNear * fFar; | |||
| max[1] := fTop / fNear * fFar; | |||
| glBegin(GL_LINE_LOOP); | |||
| glVertex3f(fLeft, fTop, -fNear); | |||
| glVertex3f(fLeft, fBottom, -fNear); | |||
| glVertex3f(fRight, fBottom, -fNear); | |||
| glVertex3f(fRight, fTop, -fNear); | |||
| glEnd; | |||
| glBegin(GL_LINE_LOOP); | |||
| glVertex3f(min[0], min[0], -fFar); | |||
| glVertex3f(min[0], max[0], -fFar); | |||
| glVertex3f(max[0], max[0], -fFar); | |||
| glVertex3f(max[0], min[0], -fFar); | |||
| glEnd; | |||
| glBegin(GL_LINES); | |||
| glVertex3f(0, 0, 0); glVertex3f(min[0], min[0], -fFar); | |||
| glVertex3f(0, 0, 0); glVertex3f(min[0], max[0], -fFar); | |||
| glVertex3f(0, 0, 0); glVertex3f(max[0], max[0], -fFar); | |||
| glVertex3f(0, 0, 0); glVertex3f(max[0], min[0], -fFar); | |||
| glEnd; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcFrustum.Create; | |||
| begin | |||
| inherited Create; | |||
| fTop := 0; | |||
| fBottom := 0; | |||
| fLeft := 0; | |||
| fRight := 0; | |||
| fNear := 0; | |||
| fFar := 0; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcCamera//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcCamera.Move(const aVec: TgluVector3f); | |||
| begin | |||
| fPosition := gluMatrixMult(gluMatrixTranslate(aVec), fPosition); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcCamera.Tilt(const aAngle: Single); | |||
| begin | |||
| fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(1,0,0), aAngle), fPosition); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcCamera.Turn(const aAngle: Single); | |||
| begin | |||
| fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(0,1,0), aAngle), fPosition); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcCamera.Roll(const aAngle: Single); | |||
| begin | |||
| fPosition := gluMatrixMult(gluMatrixRotate(gluVector3f(0,0,1), aAngle), fPosition); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcCamera.Activate; | |||
| begin | |||
| inherited Activate; | |||
| glLoadMatrixf(@fPosition[0, 0]); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcCamera.GetRay(const aPos: TgluVector2f): TgluRayf; | |||
| var | |||
| p: TgluVector3f; | |||
| begin | |||
| if (aPos[0] < 0) then | |||
| p[0] := -aPos[0] * fLeft | |||
| else | |||
| p[0] := aPos[0] * fRight; | |||
| if (aPos[1] < 0) then | |||
| p[1] := -aPos[1] * fBottom | |||
| else | |||
| p[1] := aPos[1] * fTop; | |||
| if (fIsOrthogonal) then begin | |||
| p[2] := 0; | |||
| result.p := fPosition * p; | |||
| result.v := fPosition * gluVector3f(0, 0, -1); | |||
| end else begin | |||
| p[2] := -fNear; | |||
| result.p := gluVector3f(0, 0, 0); | |||
| result.v := fPosition * p; | |||
| end; | |||
| result := gluRayNormalize(result); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcCamera.Create; | |||
| begin | |||
| inherited Create; | |||
| fPosition := gluMatrixIdentity; | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,622 @@ | |||
| unit uglcFrameBufferObject; | |||
| { Package: OpenGLCore | |||
| Prefix: glc - OpenGL Core | |||
| Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL FrameBufferObjekte } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, fgl, dglOpenGl, uglcTypes; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcBufferType = (btRenderBuffer, btTextureBuffer); | |||
| TglcBuffer = class(TObject) | |||
| private | |||
| fBufferType: TglcBufferType; | |||
| fWidth: Integer; | |||
| fHeight: Integer; | |||
| procedure SetWidth(const aValue: Integer); | |||
| procedure SetHeight(const aValue: Integer); | |||
| public | |||
| property Width : Integer read fWidth write SetWidth; | |||
| property Height: Integer read fHeight write SetHeight; | |||
| property BufferType: TglcBufferType read fBufferType; | |||
| procedure SetSize(const aWidth, aHeight: Integer); virtual; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| EglcRenderBuffer = class(Exception); | |||
| TglcRenderBuffer = class(TglcBuffer) | |||
| private | |||
| fID: gluInt; | |||
| fFormat: TglcInternalFormat; | |||
| procedure UpdateRenderBufferStorage; | |||
| procedure SetFormat(const aValue: TglcInternalFormat); | |||
| public | |||
| property ID: gluInt read fID; | |||
| property Format: TglcInternalFormat read fFormat write SetFormat; | |||
| procedure SetSize(const aWidth, aHeight: Integer); override; | |||
| procedure Bind; | |||
| procedure Unbind; | |||
| constructor Create(const aFormat: TglcInternalFormat); | |||
| destructor Destroy; override; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| EglcTextureBuffer = class(exception); | |||
| TglcTextureBuffer = class(TglcBuffer) | |||
| private | |||
| fID: GLuint; | |||
| fFormat: TglcFormat; | |||
| fInternalFormat: TglcInternalFormat; | |||
| fBorder: Boolean; | |||
| procedure UpdateTexImage; | |||
| procedure SetFormat(const aValue: TglcFormat); | |||
| procedure SetInternalFormat(const aValue: TglcInternalFormat); | |||
| procedure SetBorder(const aValue: Boolean); | |||
| public | |||
| property ID : GLuint read fID; | |||
| property Border : Boolean read fBorder write SetBorder; | |||
| property Format : TglcFormat read fFormat write SetFormat; | |||
| property InternalFormat: TglcInternalFormat read fInternalFormat write SetInternalFormat; | |||
| procedure SetSize(const aWidth, aHeight: Integer); override; | |||
| procedure Bind(const aEnableTextureUnit: Boolean = true); | |||
| procedure Unbind(const aDisableTextureUnit: Boolean = true); | |||
| constructor Create(const aFormat: TglcFormat; const aInternalFormat: TglcInternalFormat); | |||
| destructor Destroy; override; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| EglcFrameBufferObject = class(Exception); | |||
| TglcFrameBufferObject = class(TObject) | |||
| private type | |||
| TglcAttachmentContainer = class(TObject) | |||
| Buffer: TglcBuffer; | |||
| Attachment: TglcAttachment; | |||
| OwnsObject: Boolean; | |||
| constructor Create(const aBuffer: TglcBuffer; const aAttachment: TglcAttachment; const aOwnsObject: Boolean = true); | |||
| destructor Destroy; override; | |||
| end; | |||
| TglcAttachmentContainerList = specialize TFPGObjectList<TglcAttachmentContainer>; | |||
| private | |||
| fID: GLuint; | |||
| fOwnsObjects: Boolean; | |||
| fWidth: Integer; | |||
| fHeight: Integer; | |||
| fBuffers: TglcAttachmentContainerList; | |||
| function GetBuffer(const aIndex: Integer): TglcBuffer; | |||
| procedure SetBuffer(const aIndex: Integer; const aValue: TglcBuffer); | |||
| function GetAttachment(const aIndex: Integer): TglcAttachment; | |||
| procedure SetAttachment(const aIndex: Integer; const aValue: TglcAttachment); | |||
| function GetBufferCount: Integer; | |||
| procedure Attach(const aIndex: Integer); | |||
| procedure Detach(const aIndex: Integer); | |||
| procedure SetWidth(const aValue: Integer); | |||
| procedure SetHeight(const aValue: Integer); | |||
| procedure CheckFrameBufferStatus; | |||
| procedure UpdateAndCheckFBO; | |||
| public | |||
| property ID : GLuint read fID; | |||
| property Count : Integer read GetBufferCount; | |||
| property OwnsObjects: Boolean read fOwnsObjects; | |||
| property Width : Integer read fWidth write SetWidth; | |||
| property Height : Integer read fHeight write SetHeight; | |||
| property Attachments[const aIndex: Integer]: TglcAttachment read GetAttachment write SetAttachment; | |||
| property Buffers [const aIndex: Integer]: TglcBuffer read GetBuffer write SetBuffer; | |||
| procedure AddBuffer(const aBuffer: TglcBuffer; const aAttachment: TglcAttachment; const aOwnsBuffer: Boolean = true); | |||
| procedure DelBuffer(const aIndex: Integer); | |||
| function RemBuffer(const aBuffer: TglcBuffer): Integer; | |||
| function IndexOfBuffer(const aBuffer: TglcBuffer): Integer; | |||
| procedure SetSize(const aWidth, aHeight: Integer); | |||
| function CheckAttachment(const aAttachment: TglcAttachment): Boolean; | |||
| procedure Bind(const aSetViewport: Boolean = true); | |||
| procedure Unbind(const aResetViewport: Boolean = true); | |||
| constructor Create(const aOwnBuffers: Boolean = true); | |||
| destructor Destroy; override; | |||
| end; | |||
| implementation | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcBuffer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcBuffer.SetWidth(const aValue: Integer); | |||
| begin | |||
| SetSize(aValue, fHeight); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcBuffer.SetHeight(const aValue: Integer); | |||
| begin | |||
| SetSize(fWidth, aValue); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcBuffer.SetSize(const aWidth, aHeight: Integer); | |||
| begin | |||
| fWidth := aWidth; | |||
| fHeight := aHeight; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcRenderBuffer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcRenderBuffer.UpdateRenderBufferStorage; | |||
| begin | |||
| glGetError; //clear Erroros | |||
| Bind; | |||
| glRenderbufferStorage(GL_RENDERBUFFER, GLenum(fFormat), fWidth, fHeight); | |||
| Unbind; | |||
| glcCheckAndRaiseError; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcRenderBuffer.SetFormat(const aValue: TglcInternalFormat); | |||
| begin | |||
| fFormat := aValue; | |||
| UpdateRenderBufferStorage; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcRenderBuffer.SetSize(const aWidth, aHeight: Integer); | |||
| begin | |||
| if (aWidth <= 0) or (aHeight <= 0) then | |||
| raise EglcRenderBuffer.Create('invalid width or height'); | |||
| if (aWidth <> fWidth) or (aHeight <> fHeight) then begin | |||
| inherited SetSize(aWidth, aHeight); | |||
| UpdateRenderBufferStorage; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcRenderBuffer.Bind; | |||
| begin | |||
| glBindRenderbuffer(GL_RENDERBUFFER, fID); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcRenderBuffer.Unbind; | |||
| begin | |||
| glBindRenderbuffer(GL_RENDERBUFFER, 0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcRenderBuffer.Create(const aFormat: TglcInternalFormat); | |||
| begin | |||
| inherited Create; | |||
| fBufferType := btRenderBuffer; | |||
| glGenRenderbuffers(1, @fID); | |||
| fFormat := aFormat; | |||
| SetSize(64, 64); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TglcRenderBuffer.Destroy; | |||
| begin | |||
| glDeleteRenderbuffers(1, @fID); | |||
| inherited Destroy; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcTextureBuffer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.UpdateTexImage; | |||
| begin | |||
| glGetError; //clear errors | |||
| Bind(false); | |||
| glTexImage2D(GL_TEXTURE_2D, 0, GLenum(fInternalFormat), fWidth, fHeight, GLint(Byte(fBorder) and Byte(1)), GLenum(fFormat), GL_UNSIGNED_BYTE, nil); | |||
| Unbind(false); | |||
| glcCheckAndRaiseError; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.SetFormat(const aValue: TglcFormat); | |||
| begin | |||
| if (fFormat <> aValue) then begin | |||
| fFormat := aValue; | |||
| UpdateTexImage; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.SetInternalFormat(const aValue: TglcInternalFormat); | |||
| begin | |||
| if (fInternalFormat <> aValue) then begin | |||
| fInternalFormat := aValue; | |||
| UpdateTexImage; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.SetBorder(const aValue: Boolean); | |||
| begin | |||
| if (fBorder <> aValue) then begin | |||
| fBorder := aValue; | |||
| UpdateTexImage; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.SetSize(const aWidth, aHeight: Integer); | |||
| begin | |||
| if (aWidth <= 0) or (aHeight <= 0) then | |||
| raise EglcTextureBuffer.Create('invalid width or height'); | |||
| if (aWidth <> fWidth) or (aHeight <> fHeight) then begin | |||
| inherited SetSize(aWidth, aHeight); | |||
| UpdateTexImage; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.Bind(const aEnableTextureUnit: Boolean = true); | |||
| begin | |||
| if aEnableTextureUnit then | |||
| glEnable(GL_TEXTURE_2D); | |||
| glBindTexture(GL_TEXTURE_2D, fID); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcTextureBuffer.Unbind(const aDisableTextureUnit: Boolean = true); | |||
| begin | |||
| if aDisableTextureUnit then | |||
| glDisable(GL_TEXTURE_2D); | |||
| glBindTexture(GL_TEXTURE_2D, 0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcTextureBuffer.Create(const aFormat: TglcFormat; const aInternalFormat: TglcInternalFormat); | |||
| begin | |||
| inherited Create; | |||
| fBufferType := btTextureBuffer; | |||
| glGenTextures(1, @fID); | |||
| Bind(false); | |||
| 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_LINEAR); | |||
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
| Unbind(false); | |||
| fFormat := aFormat; | |||
| fInternalFormat := aInternalFormat; | |||
| SetSize(64, 64); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TglcTextureBuffer.Destroy; | |||
| begin | |||
| glDeleteTextures(1, @fID); | |||
| inherited Destroy; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcAttachment//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcFrameBufferObject.TglcAttachmentContainer.Create(const aBuffer: TglcBuffer; | |||
| const aAttachment: TglcAttachment; const aOwnsObject: Boolean); | |||
| begin | |||
| inherited Create; | |||
| Buffer := aBuffer; | |||
| Attachment := aAttachment; | |||
| OwnsObject := aOwnsObject; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TglcFrameBufferObject.TglcAttachmentContainer.Destroy; | |||
| begin | |||
| if OwnsObject then | |||
| Buffer.Free; | |||
| inherited Destroy; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcFrameBufferObject///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrameBufferObject.GetBuffer(const aIndex: Integer): TglcBuffer; | |||
| begin | |||
| if (aIndex >= 0) and (aIndex < fBuffers.Count) then | |||
| result := fBuffers[aIndex].Buffer | |||
| else | |||
| raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.SetBuffer(const aIndex: Integer; const aValue: TglcBuffer); | |||
| begin | |||
| if (aIndex < 0) or (aIndex >= fBuffers.Count) then | |||
| raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex)); | |||
| if not Assigned(aValue) then | |||
| raise EglcFrameBufferObject.Create('invalid buffer'); | |||
| Detach(aIndex); | |||
| fBuffers[aIndex].Buffer := aValue; | |||
| Attach(aIndex); | |||
| UpdateAndCheckFBO; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrameBufferObject.GetAttachment(const aIndex: Integer): TglcAttachment; | |||
| begin | |||
| if (aIndex >= 0) and (aIndex < fBuffers.Count) then | |||
| result := fBuffers[aIndex].Attachment | |||
| else | |||
| raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.SetAttachment(const aIndex: Integer; const aValue: TglcAttachment); | |||
| begin | |||
| if (aIndex < 0) or (aIndex >= fBuffers.Count) then | |||
| raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex)); | |||
| if not CheckAttachment(aValue) then | |||
| raise EglcFrameBufferObject.Create('Attachment already assigned'); | |||
| Detach(aIndex); | |||
| fBuffers[aIndex].Attachment := aValue; | |||
| Attach(aIndex); | |||
| UpdateAndCheckFBO; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.Attach(const aIndex: Integer); | |||
| var | |||
| a: TglcAttachment; | |||
| b: TglcBuffer; | |||
| begin | |||
| a := Attachments[aIndex]; | |||
| b := Buffers[aIndex]; | |||
| Bind(false); | |||
| if (b.BufferType = btRenderBuffer) then | |||
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GLenum(a), GL_RENDERBUFFER, (b as TglcRenderBuffer).ID) | |||
| else | |||
| glFramebufferTexture2D(GL_FRAMEBUFFER, GLenum(a), GL_TEXTURE_2D, (b as TglcTextureBuffer).ID, 0); | |||
| Unbind(false); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.Detach(const aIndex: Integer); | |||
| var | |||
| a: TglcAttachment; | |||
| b: TglcBuffer; | |||
| begin | |||
| a := Attachments[aIndex]; | |||
| b := Buffers[aIndex]; | |||
| Bind(false); | |||
| if (b.BufferType = btRenderBuffer) then | |||
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GLenum(a), GL_RENDERBUFFER, 0) | |||
| else | |||
| glFramebufferTexture2D(GL_FRAMEBUFFER, GLenum(a), GL_TEXTURE_2D, 0, 0); | |||
| Unbind(false); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //legt die neue Breite fest | |||
| //@Value: Breite; | |||
| procedure TglcFrameBufferObject.SetWidth(const aValue: Integer); | |||
| begin | |||
| SetSize(aValue, fHeight); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //legt die neue Höhe fest | |||
| //@Value: neue Höhe; | |||
| procedure TglcFrameBufferObject.SetHeight(const aValue: Integer); | |||
| begin | |||
| SetSize(fWidth, aValue); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.CheckFrameBufferStatus; | |||
| begin | |||
| case glCheckFramebufferStatus(GL_FRAMEBUFFER) of | |||
| GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: | |||
| raise EglcFrameBufferObject.Create('Incomplete attachment'); | |||
| GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: | |||
| raise EglcFrameBufferObject.Create('Missing attachment'); | |||
| GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: | |||
| raise EglcFrameBufferObject.Create('Incomplete dimensions'); | |||
| GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: | |||
| raise EglcFrameBufferObject.Create('Incomplete formats'); | |||
| GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: | |||
| raise EglcFrameBufferObject.Create('Incomplete draw buffer'); | |||
| GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: | |||
| raise EglcFrameBufferObject.Create('Incomplete read buffer'); | |||
| GL_FRAMEBUFFER_UNSUPPORTED: | |||
| raise EglcFrameBufferObject.Create('Framebufferobjects unsupported'); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //prüft das FrameBufferObjekt auf Fehler | |||
| procedure TglcFrameBufferObject.UpdateAndCheckFBO; | |||
| function IsColorAttachment(const a: TglcAttachment): Boolean; | |||
| begin | |||
| result := (GLenum(a) >= GL_COLOR_ATTACHMENT0) and (GLenum(a) <= GL_COLOR_ATTACHMENT15); | |||
| end; | |||
| var | |||
| buff: array of GLenum; | |||
| b: GLboolean; | |||
| i: Integer; | |||
| begin | |||
| if (fBuffers.Count = 0) then | |||
| exit; | |||
| Bind(false); | |||
| //find ColorBuffers | |||
| SetLength(buff, 0); | |||
| for i := 0 to fBuffers.Count-1 do | |||
| if IsColorAttachment(fBuffers[i].Attachment) then begin | |||
| SetLength(buff, Length(buff) + 1); | |||
| buff[High(buff)] := GLenum(fBuffers[i].Attachment); | |||
| end; | |||
| //set Read and Draw Buffer | |||
| if (Length(buff) = 0) then begin | |||
| glReadBuffer(GL_NONE); | |||
| glDrawBuffer(GL_NONE); | |||
| end else begin | |||
| glDrawBuffers(Length(buff), @buff[0]); | |||
| glGetBooleanv(GL_DOUBLEBUFFER, @b); | |||
| if b then | |||
| glReadBuffer(GL_BACK) | |||
| else | |||
| glReadBuffer(GL_FRONT); | |||
| end; | |||
| Unbind(false); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrameBufferObject.GetBufferCount: Integer; | |||
| begin | |||
| result := fBuffers.Count; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.AddBuffer(const aBuffer: TglcBuffer; | |||
| const aAttachment: TglcAttachment; const aOwnsBuffer: Boolean); | |||
| begin | |||
| if not Assigned(aBuffer) then | |||
| raise EglcFrameBufferObject.Create('invalid buffer'); | |||
| if not CheckAttachment(aAttachment) then | |||
| raise EglcFrameBufferObject.Create('attachment already assigned'); | |||
| fBuffers.Add(TglcAttachmentContainer.Create(aBuffer, aAttachment, fOwnsObjects and aOwnsBuffer)); | |||
| if OwnsObjects then | |||
| aBuffer.SetSize(fWidth, fHeight); | |||
| Attach(fBuffers.Count-1); | |||
| UpdateAndCheckFBO; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcFrameBufferObject.DelBuffer(const aIndex: Integer); | |||
| begin | |||
| if (aIndex >= 0) and (aIndex < fBuffers.Count) then begin | |||
| Detach(aIndex); | |||
| fBuffers.Delete(aIndex); | |||
| UpdateAndCheckFBO; | |||
| end else | |||
| raise EglcFrameBufferObject.Create('Index out of Bounds: ' + IntToStr(aIndex)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrameBufferObject.RemBuffer(const aBuffer: TglcBuffer): Integer; | |||
| begin | |||
| result := IndexOfBuffer(aBuffer); | |||
| if (result >= 0) then | |||
| DelBuffer(result); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrameBufferObject.IndexOfBuffer(const aBuffer: TglcBuffer): Integer; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| for i := 0 to fBuffers.Count-1 do | |||
| if (fBuffers[i].Buffer = aBuffer) then begin | |||
| result := i; | |||
| exit; | |||
| end; | |||
| result := -1; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //legt die Größe neu fest | |||
| //@Width: neue Breite; | |||
| //@Height: neue Höhe; | |||
| procedure TglcFrameBufferObject.SetSize(const aWidth, aHeight: Integer); | |||
| var | |||
| c: TglcAttachmentContainer; | |||
| begin | |||
| if (aWidth <= 0) or (aHeight <= 0) then | |||
| raise EglcFrameBufferObject.Create('invalid width or height'); | |||
| fWidth := aWidth; | |||
| fHeight := aHeight; | |||
| if OwnsObjects then | |||
| for c in fBuffers do | |||
| if c.OwnsObject then | |||
| c.Buffer.SetSize(fWidth, fHeight); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcFrameBufferObject.CheckAttachment(const aAttachment: TglcAttachment): Boolean; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| result := false; | |||
| for i := 0 to fBuffers.Count-1 do | |||
| if (fBuffers[i].Attachment = aAttachment) then | |||
| exit; | |||
| result := true; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //Bindet das FrameBufferObjekt | |||
| procedure TglcFrameBufferObject.Bind(const aSetViewport: Boolean = true); | |||
| begin | |||
| glBindFramebuffer(GL_FRAMEBUFFER, fID); | |||
| if aSetViewport then begin | |||
| glPushAttrib(GL_VIEWPORT_BIT); | |||
| glViewPort(0, 0, fWidth, fHeight); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //Entbindet das FrameBufferObjekt | |||
| procedure TglcFrameBufferObject.Unbind(const aResetViewport: Boolean = true); | |||
| begin | |||
| if aResetViewport then | |||
| glPopAttrib; | |||
| glBindFramebuffer(GL_FRAMEBUFFER, 0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //erzeugt das Objekt | |||
| constructor TglcFrameBufferObject.Create(const aOwnBuffers: Boolean = true); | |||
| begin | |||
| inherited Create; | |||
| glGenFramebuffers(1, @fID); | |||
| fWidth := 64; | |||
| fHeight := 64; | |||
| fOwnsObjects := aOwnBuffers; | |||
| fBuffers := TglcAttachmentContainerList.Create(true); //containers are always owned by this object! | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //gibt das Objekt frei | |||
| destructor TglcFrameBufferObject.Destroy; | |||
| begin | |||
| fBuffers.Free; | |||
| glDeleteFramebuffers(1, @fID); | |||
| inherited Destroy; | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,424 @@ | |||
| unit uglcLight; | |||
| { Package: OpenGLCore | |||
| Prefix: glc - OpenGL Core | |||
| Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL Licht- und Material-Objekte } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, dglOpenGL, ugluVector, uglcTypes; | |||
| type | |||
| TglcMaterialRec = packed record | |||
| Ambient: TgluVector4f; | |||
| Diffuse: TgluVector4f; | |||
| Specular: TgluVector4f; | |||
| Emission: TgluVector4f; | |||
| Shininess: GLfloat; | |||
| end; | |||
| PglcMaterialRec = ^TglcMaterialRec; | |||
| TglcLightType = (ltGlobal, ltPoint, ltSpot); | |||
| TglcLightRec = packed record | |||
| Ambient: TgluVector4f; | |||
| Diffuse: TgluVector4f; | |||
| Specular: TgluVector4f; | |||
| Position: TgluVector4f; | |||
| SpotDirection: TgluVector3f; | |||
| SpotExponent: GLfloat; | |||
| SpotCutoff: GLfloat; | |||
| ConstantAtt: GLfloat; | |||
| LinearAtt: GLfloat; | |||
| QuadraticAtt: GLfloat; | |||
| end; | |||
| PglcLightRec = ^TglcLightRec; | |||
| const | |||
| MAT_DEFAULT_AMBIENT: TgluVector4f = (0.2, 0.2, 0.2, 1.0); | |||
| MAT_DEFAULT_DIFFUSE: TgluVector4f = (0.8, 0.8, 0.8, 1.0); | |||
| MAT_DEFAULT_SPECULAR: TgluVector4f = (0.5, 0.5, 0.5, 1.0); | |||
| MAT_DEFAULT_EMISSION: TgluVector4f = (0.0, 0.0, 0.0, 1.0); | |||
| MAT_DEFAULT_SHININESS: GLfloat = 50.0; | |||
| LIGHT_DEFAULT_AMBIENT: TgluVector4f = (0.4, 0.4, 0.4, 1.0); | |||
| LIGHT_DEFAULT_DIFFUSE: TgluVector4f = (0.7, 0.7, 0.7, 1.0); | |||
| LIGHT_DEFAULT_SPECULAR: TgluVector4f = (0.9, 0.9, 0.9, 1.0); | |||
| LIGHT_DEFAULT_POSITION: TgluVector4f = (0.0, 0.0, 1.0, 0.0); | |||
| LIGHT_DEFAULT_SPOT_DIRECTION: TgluVector3f = (0.0, 0.0, -1.0); | |||
| LIGHT_DEFAULT_SPOT_EXPONENT: GLfloat = 0.0; | |||
| LIGHT_DEFAULT_SPOT_CUTOFF: GLfloat = 180.0; | |||
| LIGHT_DEFAULT_CONSTANT_ATT: GLfloat = 1.0; | |||
| LIGHT_DEFAULT_LINEAR_ATT: GLfloat = 0.0; | |||
| LIGHT_DEFAULT_QUADRATIC_ATT: GLfloat = 0.0; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcMaterial = class(TObject) | |||
| private | |||
| fData: TglcMaterialRec; | |||
| public | |||
| property Diffuse: TgluVector4f read fData.Diffuse write fData.Diffuse; | |||
| property Ambient: TgluVector4f read fData.Ambient write fData.Ambient; | |||
| property Specular: TgluVector4f read fData.Specular write fData.Specular; | |||
| property Emission: TgluVector4f read fData.Emission write fData.Emission; | |||
| property Shininess: GLfloat read fData.Shininess write fData.Shininess; | |||
| property Data: TglcMaterialRec read fData write fData; | |||
| procedure Bind(const aFace: TglcFace); | |||
| class procedure Bind(const aFace: TglcFace; const aMaterial: TglcMaterialRec); | |||
| class function DefaultValues: TglcMaterialRec; | |||
| constructor Create; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| EglcLight = class(Exception); | |||
| TglcLight = class(TObject) | |||
| private | |||
| function GetDataPtr: PglcLightRec; | |||
| protected | |||
| fData: TglcLightRec; | |||
| procedure SetAmbient (const aValue: TgluVector4f); virtual; | |||
| procedure SetDiffuse (const aValue: TgluVector4f); virtual; | |||
| procedure SetSpecular (const aValue: TgluVector4f); virtual; | |||
| procedure SetPosition4f (const aValue: TgluVector4f); virtual; | |||
| procedure SetSpotDirection(const aValue: TgluVector3f); virtual; | |||
| procedure SetSpotExponent (const aValue: GLfloat); virtual; | |||
| procedure SetSpotCutoff (const aValue: GLfloat); virtual; | |||
| procedure SetConstantAtt (const aValue: GLfloat); virtual; | |||
| procedure SetLinearAtt (const aValue: GLfloat); virtual; | |||
| procedure SetQuadraticAtt (const aValue: GLfloat); virtual; | |||
| procedure SetData (const aValue: TglcLightRec); virtual; | |||
| property Ambient: TgluVector4f read fData.Ambient write SetAmbient; | |||
| property Diffuse: TgluVector4f read fData.Diffuse write SetDiffuse; | |||
| property Specular: TgluVector4f read fData.Specular write SetSpecular; | |||
| property Position4f: TgluVector4f read fData.Position write SetPosition4f; | |||
| property SpotDirection: TgluVector3f read fData.SpotDirection write SetSpotDirection; | |||
| property SpotExponent: GLfloat read fData.SpotExponent write SetSpotExponent; | |||
| property SpotCutoff: GLfloat read fData.SpotCutoff write SetSpotCutoff; | |||
| property ConstantAtt: GLfloat read fData.ConstantAtt write SetConstantAtt; | |||
| property LinearAtt: GLfloat read fData.LinearAtt write SetLinearAtt; | |||
| property QuadraticAtt: GLfloat read fData.QuadraticAtt write SetQuadraticAtt; | |||
| public | |||
| property Data: TglcLightRec read fData write SetData; | |||
| property DataPtr: PglcLightRec read GetDataPtr; | |||
| procedure Bind(const aLightID: GLenum; const aEnableLighting: Boolean = false); virtual; abstract; | |||
| class procedure Bind(const aLightID: GLenum; const aLight: TglcLightRec; | |||
| const aEnableLighting: Boolean; const aLightType: TglcLightType); | |||
| class procedure Unbind(const aLightID: GLenum; const aDisableLighting: Boolean = true); | |||
| class function DefaultValues: TglcLightRec; virtual; | |||
| constructor Create; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcLightGlobal = class(TglcLight) | |||
| private | |||
| function GetDirection: TgluVector3f; | |||
| procedure SetDirection(aValue: TgluVector3f); | |||
| public | |||
| property Ambient; | |||
| property Diffuse; | |||
| property Specular; | |||
| property Direction: TgluVector3f read GetDirection write SetDirection; | |||
| procedure Bind(const aLightID: GLenum; const aEnableLighting: Boolean = false); override; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcLightPoint = class(TglcLight) | |||
| private | |||
| fMaxSize: Single; | |||
| fSizeFactor: Single; | |||
| function GetPosition: TgluVector3f; | |||
| procedure SetPosition(const aValue: TgluVector3f); | |||
| protected | |||
| procedure SetMaxSize (const aValue: Single); virtual; | |||
| procedure SetSizeFactor(const aValue: Single); virtual; | |||
| public | |||
| property Ambient; | |||
| property Diffuse; | |||
| property Specular; | |||
| property ConstantAtt; | |||
| property LinearAtt; | |||
| property QuadraticAtt; | |||
| property MaxSize: Single read fMaxSize write SetMaxSize; | |||
| property SizeFactor: Single read fSizeFactor write SetSizeFactor; | |||
| property Position: TgluVector3f read GetPosition write SetPosition; | |||
| procedure Bind(const aLightID: GLenum; const aEnableLighting: Boolean = false); override; | |||
| constructor Create; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcLightSpot = class(TglcLightPoint) | |||
| public | |||
| property SpotCutoff; | |||
| property SpotDirection; | |||
| property SpotExponent; | |||
| procedure Bind(const aLightID: GLenum; const aEnableLighting: Boolean = false); override; | |||
| end; | |||
| implementation | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcMaterial////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcMaterial.Bind(const aFace: TglcFace); | |||
| begin | |||
| Bind(aFace, fData); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class procedure TglcMaterial.Bind(const aFace: TglcFace; const aMaterial: TglcMaterialRec); | |||
| begin | |||
| glMaterialfv(GLenum(aFace), GL_AMBIENT, @aMaterial.Ambient[0]); | |||
| glMaterialfv(GLenum(aFace), GL_DIFFUSE, @aMaterial.Diffuse[0]); | |||
| glMaterialfv(GLenum(aFace), GL_EMISSION, @aMaterial.Emission[0]); | |||
| glMaterialfv(GLenum(aFace), GL_SPECULAR, @aMaterial.Specular[0]); | |||
| glMaterialfv(GLenum(aFace), GL_SHININESS, @aMaterial.Shininess); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class function TglcMaterial.DefaultValues: TglcMaterialRec; | |||
| begin | |||
| result.Ambient := MAT_DEFAULT_AMBIENT; | |||
| result.Diffuse := MAT_DEFAULT_DIFFUSE; | |||
| result.Specular := MAT_DEFAULT_SPECULAR; | |||
| result.Emission := MAT_DEFAULT_EMISSION; | |||
| result.Shininess := MAT_DEFAULT_SHININESS; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcMaterial.Create; | |||
| begin | |||
| inherited Create; | |||
| fData := DefaultValues; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcLight///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcLight.GetDataPtr: PglcLightRec; | |||
| begin | |||
| result := @fData; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetAmbient(const aValue: TgluVector4f); | |||
| begin | |||
| fData.Ambient := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetDiffuse(const aValue: TgluVector4f); | |||
| begin | |||
| fData.Diffuse := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetSpecular(const aValue: TgluVector4f); | |||
| begin | |||
| fData.Specular := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetPosition4f(const aValue: TgluVector4f); | |||
| begin | |||
| fData.Position := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetConstantAtt(const aValue: GLfloat); | |||
| begin | |||
| fData.ConstantAtt := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetLinearAtt(const aValue: GLfloat); | |||
| begin | |||
| fData.LinearAtt := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetQuadraticAtt(const aValue: GLfloat); | |||
| begin | |||
| fData.QuadraticAtt := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetSpotDirection(const aValue: TgluVector3f); | |||
| begin | |||
| fData.SpotDirection := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetSpotExponent(const aValue: GLfloat); | |||
| begin | |||
| fData.SpotExponent := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetSpotCutoff(const aValue: GLfloat); | |||
| begin | |||
| fData.SpotCutoff := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLight.SetData(const aValue: TglcLightRec); | |||
| begin | |||
| fData := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class procedure TglcLight.Bind(const aLightID: GLenum; const aLight: TglcLightRec; | |||
| const aEnableLighting: Boolean; const aLightType: TglcLightType); | |||
| begin | |||
| glEnable(aLightID); | |||
| if (aEnableLighting) then | |||
| glEnable(GL_LIGHTING); | |||
| if (aLightType in [ltGlobal, ltPoint, ltSpot]) then begin | |||
| glLightfv(aLightID, GL_AMBIENT, @aLight.Ambient[0]); | |||
| glLightfv(aLightID, GL_DIFFUSE, @aLight.Diffuse[0]); | |||
| glLightfv(aLightID, GL_SPECULAR, @aLight.Specular[0]); | |||
| glLightfv(aLightID, GL_POSITION, @aLight.Position[0]); | |||
| end else begin | |||
| glLightfv(aLightID, GL_AMBIENT, @LIGHT_DEFAULT_AMBIENT[0]); | |||
| glLightfv(aLightID, GL_DIFFUSE, @LIGHT_DEFAULT_DIFFUSE[0]); | |||
| glLightfv(aLightID, GL_SPECULAR, @LIGHT_DEFAULT_SPECULAR[0]); | |||
| glLightfv(aLightID, GL_POSITION, @LIGHT_DEFAULT_POSITION[0]); | |||
| end; | |||
| if (aLightType in [ltPoint, ltSpot]) then begin | |||
| glLightfv(aLightID, GL_CONSTANT_ATTENUATION, @aLight.ConstantAtt); | |||
| glLightfv(aLightID, GL_LINEAR_ATTENUATION, @aLight.LinearAtt); | |||
| glLightfv(aLightID, GL_QUADRATIC_ATTENUATION, @aLight.QuadraticAtt); | |||
| end else begin | |||
| glLightfv(aLightID, GL_CONSTANT_ATTENUATION, @LIGHT_DEFAULT_CONSTANT_ATT); | |||
| glLightfv(aLightID, GL_LINEAR_ATTENUATION, @LIGHT_DEFAULT_LINEAR_ATT); | |||
| glLightfv(aLightID, GL_QUADRATIC_ATTENUATION, @LIGHT_DEFAULT_QUADRATIC_ATT); | |||
| end; | |||
| if (aLightType in [ltSpot]) then begin | |||
| glLightfv(aLightID, GL_SPOT_DIRECTION, @aLight.SpotDirection[0]); | |||
| glLightfv(aLightID, GL_SPOT_EXPONENT, @aLight.SpotExponent); | |||
| glLightfv(aLightID, GL_SPOT_CUTOFF, @aLight.SpotCutoff); | |||
| end else begin | |||
| glLightfv(aLightID, GL_SPOT_DIRECTION, @LIGHT_DEFAULT_SPOT_DIRECTION[0]); | |||
| glLightfv(aLightID, GL_SPOT_EXPONENT, @LIGHT_DEFAULT_SPOT_EXPONENT); | |||
| glLightfv(aLightID, GL_SPOT_CUTOFF, @LIGHT_DEFAULT_SPOT_CUTOFF); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class procedure TglcLight.Unbind(const aLightID: GLenum; const aDisableLighting: Boolean); | |||
| begin | |||
| glDisable(aLightID); | |||
| if aDisableLighting then | |||
| glDisable(GL_LIGHTING); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class function TglcLight.DefaultValues: TglcLightRec; | |||
| begin | |||
| result.Ambient := LIGHT_DEFAULT_AMBIENT; | |||
| result.Diffuse := LIGHT_DEFAULT_DIFFUSE; | |||
| result.Specular := LIGHT_DEFAULT_SPECULAR; | |||
| result.Position := LIGHT_DEFAULT_POSITION; | |||
| result.SpotDirection := LIGHT_DEFAULT_SPOT_DIRECTION; | |||
| result.SpotExponent := LIGHT_DEFAULT_SPOT_EXPONENT; | |||
| result.SpotCutoff := LIGHT_DEFAULT_SPOT_CUTOFF; | |||
| result.ConstantAtt := LIGHT_DEFAULT_CONSTANT_ATT; | |||
| result.LinearAtt := LIGHT_DEFAULT_LINEAR_ATT; | |||
| result.QuadraticAtt := LIGHT_DEFAULT_QUADRATIC_ATT; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcLight.Create; | |||
| begin | |||
| inherited Create; | |||
| fData := DefaultValues; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcLightGlobal/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcLightGlobal.GetDirection: TgluVector3f; | |||
| begin | |||
| result := gluVector3f(Position4f); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightGlobal.SetDirection(aValue: TgluVector3f); | |||
| begin | |||
| Position4f := gluVector4f(aValue, 0.0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightGlobal.Bind(const aLightID: GLenum; const aEnableLighting: Boolean); | |||
| begin | |||
| TglcLight.Bind(aLightID, fData, aEnableLighting, ltGlobal); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcLightPoint//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcLightPoint.GetPosition: TgluVector3f; | |||
| begin | |||
| result := gluVector3f(fData.Position); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightPoint.SetPosition(const aValue: TgluVector3f); | |||
| begin | |||
| SetPosition4f(gluVector4f(aValue, 1.0)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightPoint.SetMaxSize(const aValue: Single); | |||
| begin | |||
| fMaxSize := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightPoint.SetSizeFactor(const aValue: Single); | |||
| begin | |||
| fSizeFactor := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightPoint.Bind(const aLightID: GLenum; const aEnableLighting: Boolean); | |||
| begin | |||
| TglcLight.Bind(aLightID, fData, aEnableLighting, ltPoint); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TglcLightPoint.Create; | |||
| begin | |||
| inherited Create; | |||
| Position := gluVector3f(0.0, 0.0, 0.0); | |||
| fMaxSize := 0; | |||
| fSizeFactor := 1.0; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TglcLightSpot///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcLightSpot.Bind(const aLightID: GLenum; const aEnableLighting: Boolean); | |||
| begin | |||
| TglcLight.Bind(aLightID, fData, aEnableLighting, ltSpot); | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,931 @@ | |||
| unit uglcShader; | |||
| { Package: OpenGLCore | |||
| Prefix: glc - OpenGL Core | |||
| Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL Shader Objekte } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, fgl, dglOpenGL, uglcTypes, ugluMatrix; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| EglcShader = class(Exception); | |||
| TglcShaderProgram = class; | |||
| TglcShaderLogEvent = procedure(aSender: TObject; const aMsg: String) of Object; | |||
| TglcShaderObject = class(TObject) | |||
| private | |||
| fAtachedTo: TglcShaderProgram; | |||
| fShaderObj: GLHandle; | |||
| fShaderType: TglcShaderType; | |||
| fCode: String; | |||
| fOnLog: TglcShaderLogEvent; | |||
| fAttachedTo: TglcShaderProgram; | |||
| function GetInfoLog(aObj: GLHandle): String; | |||
| function GetCompiled: Boolean; | |||
| procedure Log(const aMsg: String); | |||
| procedure CreateShaderObj; | |||
| procedure AttachTo(const aProgram: TglcShaderProgram); | |||
| public | |||
| property ShaderObj : GLHandle read fShaderObj; | |||
| property ShaderType: TglcShaderType read fShaderType; | |||
| property Compiled: Boolean read GetCompiled; | |||
| property AtachedTo: TglcShaderProgram read fAtachedTo; | |||
| property Code: String read fCode write fCode; | |||
| property OnLog: TglcShaderLogEvent read fOnLog write fOnLog; | |||
| procedure Compile; | |||
| constructor Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent = nil); | |||
| destructor Destroy; override; | |||
| end; | |||
| TglcShaderObjectList = specialize TFPGObjectList<TglcShaderObject>; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TglcShaderProgram = class(TglcShaderObjectList) | |||
| private | |||
| fProgramObj: GLHandle; | |||
| fOnLog: TglcShaderLogEvent; | |||
| fFilename: String; | |||
| fGeometryInputType: GLint; | |||
| fGeometryOutputType: GLint; | |||
| fGeometryVerticesOut: GLint; | |||
| function GetUniformLocation(const aName: String; out aPos: glInt): Boolean; | |||
| function GetInfoLog(Obj: GLHandle): String; | |||
| function GetCompiled: Boolean; | |||
| function GetLinked: Boolean; | |||
| procedure CreateProgramObj; | |||
| procedure Log(const msg: String); | |||
| procedure AttachShaderObj(const aShaderObj: TglcShaderObject); | |||
| public | |||
| property ProgramObj: glHandle read fProgramObj; | |||
| property Filename: String read fFilename; | |||
| property Compiled: Boolean read GetCompiled; | |||
| property Linked: Boolean read GetLinked; | |||
| property OnLog: TglcShaderLogEvent read fOnLog write fOnLog; | |||
| property GeometryInputType: GLint read fGeometryInputType write fGeometryInputType; | |||
| property GeometryOutputType: GLint read fGeometryOutputType write fGeometryOutputType; | |||
| property GeometryVerticesOut: GLint read fGeometryVerticesOut write fGeometryVerticesOut; | |||
| procedure Compile; | |||
| procedure Enable; | |||
| procedure Disable; | |||
| procedure Add(aShaderObj: TglcShaderObject); | |||
| procedure Delete(aID: Integer; aFreeOwnedObj: Boolean = True); | |||
| procedure Clear; | |||
| function Uniform1f(const aName: String; aP1: GLFloat): Boolean; | |||
| function Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean; | |||
| function Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean; | |||
| function Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean; | |||
| function Uniform1i(const aName: String; aP1: GLint): Boolean; | |||
| function Uniform2i(const aName: String; aP1, aP2: GLint): Boolean; | |||
| function Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean; | |||
| function Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean; | |||
| function Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| function Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| function Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| function Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| function Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| function Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| function Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| function Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| function UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean; | |||
| function UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean; | |||
| function UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean; | |||
| function GetUniformfv(const aName: String; aP: PGLfloat): Boolean; | |||
| function GetUniformfi(const aName: String; aP: PGLint): Boolean; | |||
| function HasUniform(const aName: String): Boolean; | |||
| procedure LoadFromFile(const aFilename: String); | |||
| procedure LoadFromStream(const aStream: TStream); | |||
| procedure SaveToFile(const aFilename: String); | |||
| procedure SaveToStream(const aStream: TStream); | |||
| constructor Create(aLogEvent: TglcShaderLogEvent = nil); | |||
| destructor Destroy; override; | |||
| end; | |||
| implementation | |||
| uses | |||
| RegExpr; | |||
| const | |||
| ERROR_STR_VAR_NAME: String = 'can''t find the variable ''%s'' in the program'; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //glShaderObject//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //ließt das Log eines OpenGL-Objekts aus | |||
| //@Obj: Handle des Objekts, dessen Log ausgelesen werden soll; | |||
| //@result: Log des Objekts; | |||
| function TglcShaderObject.GetInfoLog(aObj: GLHandle): String; | |||
| var | |||
| Msg: PChar; | |||
| bLen, sLen: GLint; | |||
| begin | |||
| bLen := 0; | |||
| glGetShaderiv(aObj, GL_INFO_LOG_LENGTH, @bLen); | |||
| if bLen > 1 then begin | |||
| GetMem(Msg, bLen * SizeOf(Char)); | |||
| glGetShaderInfoLog(aObj, bLen, sLen{%H-}, Msg); | |||
| result := PChar(Msg); | |||
| Dispose(Msg); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //ließt aus, ob der Shader ohne Fehler kompiliert wurde | |||
| //@result: TRUE wenn ohne Fehler kompiliert, sonst FALSE; | |||
| function TglcShaderObject.GetCompiled: Boolean; | |||
| var | |||
| value: glInt; | |||
| begin | |||
| glGetShaderiv(fShaderObj, GL_COMPILE_STATUS, @value); | |||
| result := (value = GL_TRUE); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //ruft das Log-Event auf, wenn es gesetzt ist | |||
| //@msg: Nachricht die geloggt werden soll; | |||
| procedure TglcShaderObject.Log(const aMsg: String); | |||
| begin | |||
| if Assigned(fOnLog) then begin | |||
| fOnLog(self, aMsg); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcShaderObject.CreateShaderObj; | |||
| begin | |||
| if (fShaderObj <> 0) then | |||
| exit; | |||
| fShaderObj := glCreateShader(GLenum(fShaderType)); | |||
| if fShaderObj = 0 then | |||
| raise EglcShader.Create('can''t create ShaderObject'); | |||
| Log('shader object created: #'+IntToHex(fShaderObj, 4)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcShaderObject.AttachTo(const aProgram: TglcShaderProgram); | |||
| begin | |||
| if (aProgram <> fAtachedTo) then begin | |||
| CreateShaderObj; | |||
| glAttachShader(aProgram.ProgramObj, fShaderObj); | |||
| fAttachedTo := aProgram; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //kompiliert das Shader-Objekt | |||
| procedure TglcShaderObject.Compile; | |||
| var | |||
| len, i: GLint; | |||
| List: TStringList; | |||
| c: PAnsiChar; | |||
| begin | |||
| CreateShaderObj; | |||
| len := Length(fCode); | |||
| if len > 0 then begin | |||
| c := PAnsiChar(fCode); | |||
| glShaderSource(fShaderObj, 1, @c, @len); | |||
| glCompileShader(fShaderObj); | |||
| List := TStringList.Create; | |||
| List.Text := GetInfoLog(fShaderObj); | |||
| for i := 0 to List.Count-1 do | |||
| Log(List[i]); | |||
| List.Free; | |||
| end else Log('error while compiling: no bound shader code'); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //erzeugt das Objekt | |||
| //@ShaderType: Typ des Shader-Objekts; | |||
| //@LogEvent: Event zum loggen von Fehlern und Ereignissen; | |||
| //@raise: EglcShader wenn der Shadertyp unbekannt oder ungültig ist; | |||
| constructor TglcShaderObject.Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent); | |||
| begin | |||
| inherited Create; | |||
| fCode := ''; | |||
| fOnLog := aLogEvent; | |||
| fShaderType := aShaderType; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //gibt das Objekt frei | |||
| destructor TglcShaderObject.Destroy; | |||
| begin | |||
| if (fShaderObj <> 0) then | |||
| glDeleteShader(fShaderObj); | |||
| inherited Destroy; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //glShaderProgram/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcShaderProgram.GetUniformLocation(const aName: String; out aPos: glInt): Boolean; | |||
| begin | |||
| aPos := glGetUniformLocation(fProgramObj, PChar(aName)); | |||
| result := (aPos <> -1); | |||
| if not result then | |||
| Log(StringReplace(ERROR_STR_VAR_NAME, '%s', aName, [rfIgnoreCase, rfReplaceAll])); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //ließt das Log eines OpenGL-Objekts aus | |||
| //@Obj: Handle des Objekts, dessen Log ausgelesen werden soll; | |||
| //@result: Log des Objekts; | |||
| function TglcShaderProgram.GetInfoLog(Obj: GLHandle): String; | |||
| var | |||
| Msg: PChar; | |||
| bLen, sLen: GLint; | |||
| begin | |||
| bLen := 0; | |||
| glGetProgramiv(Obj, GL_INFO_LOG_LENGTH, @bLen); | |||
| if bLen > 1 then begin | |||
| GetMem(Msg, bLen * SizeOf(Char)); | |||
| glGetProgramInfoLog(Obj, bLen, sLen{%H-}, Msg); | |||
| result := PChar(Msg); | |||
| Dispose(Msg); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //prüft ob alle Shader ohne Fehler compiliert wurden | |||
| //@result: TRUE wenn alle erfolgreich compiliert, sonst FALSE; | |||
| function TglcShaderProgram.GetCompiled: Boolean; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| result := (Count > 0); | |||
| for i := 0 to Count-1 do | |||
| result := result and Items[i].Compiled; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //prüft ob das Programm ohne Fehler gelinkt wurde | |||
| //@result: TRUE wenn linken erfolgreich, sonst FASLE; | |||
| function TglcShaderProgram.GetLinked: Boolean; | |||
| var | |||
| value: glInt; | |||
| begin | |||
| glGetProgramiv(fProgramObj, GL_LINK_STATUS, @value); | |||
| result := (value = GL_TRUE); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcShaderProgram.CreateProgramObj; | |||
| begin | |||
| if (fProgramObj = 0) then begin | |||
| if GL_LibHandle = nil then | |||
| raise EglcShader.Create('TglShaderProgram.Create - OpenGL not initialized'); | |||
| if (wglGetCurrentContext() = 0) or (wglGetCurrentDC() = 0) then | |||
| raise EglcShader.Create('TglShaderProgram.Create - no valid render context'); | |||
| fProgramObj := glCreateProgram(); | |||
| Log('shader program created: #'+IntToHex(fProgramObj, 4)); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //ruft das Log-Event auf, wenn es gesetzt ist | |||
| //@msg: Nachricht die geloggt werden soll; | |||
| procedure TglcShaderProgram.Log(const msg: String); | |||
| begin | |||
| if Assigned(fOnLog) then begin | |||
| fOnLog(self, msg); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcShaderProgram.AttachShaderObj(const aShaderObj: TglcShaderObject); | |||
| begin | |||
| CreateProgramObj; | |||
| aShaderObj.AttachTo(self); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //Kompiliert den Shader-Code | |||
| procedure TglcShaderProgram.Compile; | |||
| var | |||
| i: Integer; | |||
| l: TStringList; | |||
| begin | |||
| CreateProgramObj; | |||
| for i := 0 to Count-1 do begin | |||
| AttachShaderObj(Items[i]); | |||
| Items[i].Compile; | |||
| end; | |||
| glLinkProgram(fProgramObj); | |||
| l := TStringList.Create; | |||
| l.Text := GetInfoLog(fProgramObj); | |||
| for i := 0 to l.Count-1 do | |||
| Log(l[i]); | |||
| l.Free; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //aktiviert den Shader | |||
| procedure TglcShaderProgram.Enable; | |||
| begin | |||
| glUseProgram(fProgramObj); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //deaktiviert den Shader | |||
| procedure TglcShaderProgram.Disable; | |||
| begin | |||
| glUseProgram(0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //fügt der Liste einen Shader hinzu | |||
| //@ShaderObj: Objekt, das hinzugefügt werden soll; | |||
| procedure TglcShaderProgram.Add(aShaderObj: TglcShaderObject); | |||
| begin | |||
| inherited Add(aShaderObj); | |||
| if (fProgramObj <> 0) then | |||
| AttachShaderObj(aShaderObj); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //löscht ein ShaderObjekt aus der Liste | |||
| //@ID: Index des Objekts, das gelöscht werden soll; | |||
| //@FreeOwnedObj: wenn TRUE wird das gelöschte Objekt freigegeben; | |||
| procedure TglcShaderProgram.Delete(aID: Integer; aFreeOwnedObj: Boolean); | |||
| var | |||
| b: Boolean; | |||
| begin | |||
| if (aID >= 0) and (aID < Count) and (fProgramObj <> 0) then begin | |||
| glDetachShader(fProgramObj, Items[aID].fShaderObj); | |||
| Items[aID].fAttachedTo := nil; | |||
| end; | |||
| b := FreeObjects; | |||
| FreeObjects := aFreeOwnedObj; | |||
| inherited Delete(aID); | |||
| FreeObjects := b; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TglcShaderProgram.Clear; | |||
| begin | |||
| while (Count > 0) do | |||
| Delete(0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 1-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform1f(const aName: String; aP1: GLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform1f(pos, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 2-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@p2: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform2f(pos, aP1, aP2); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 3-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@p2: Wert der Variable, der gesetzt werden soll; | |||
| //@p3: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform3f(pos, aP1, aP2, aP3); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 4-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@p2: Wert der Variable, der gesetzt werden soll; | |||
| //@p3: Wert der Variable, der gesetzt werden soll; | |||
| //@p4: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform4f(pos, aP1, aP2, aP3, aP4); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 1-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform1i(const aName: String; aP1: GLint): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform1i(pos, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 2-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform2i(const aName: String; aP1, aP2: GLint): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform2i(pos, aP1, aP2); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 3-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@p2: Wert der Variable, der gesetzt werden soll; | |||
| //@p3: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform3i(pos, aP1, aP2, aP3); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen 4-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@p2: Wert der Variable, der gesetzt werden soll; | |||
| //@p3: Wert der Variable, der gesetzt werden soll; | |||
| //@p4: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform4i(pos, aP1, aP2, aP3, aP4); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 1-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform1fv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 2-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform2fv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 3-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform3fv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 4-Komponenten Float-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform4fv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 1-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform1iv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 2-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform2iv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 3-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform3iv(pos, aCount, aP1); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt einen oder mehrere 4-Komponenten Integer-Vektoren an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@count: Anzahl an Parametern auf die p1 zeigt; | |||
| //@p1: Zeiger auf den ersten Wert der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniform4iv(pos, aCount, aP1) ; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt eine oder mehrere 2x2-Matrizen an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert; | |||
| //@Count: Anzahl der zu übergebenden Elemente; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniformMatrix2fv(pos, aCount, aTranspose, PGLfloat(aP1)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt eine oder mehrere 3x3-Matrizen an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert; | |||
| //@Count: Anzahl der zu übergebenden Elemente; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniformMatrix3fv(pos, aCount, aTranspose, PGLfloat(aP1)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //übergibt eine oder mehrere 4x4-Matrizen an den Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gesetzt werden soll; | |||
| //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert; | |||
| //@Count: Anzahl der zu übergebenden Elemente; | |||
| //@p1: Wert der Variable, der gesetzt werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glUniformMatrix4fv(pos, aCount, aTranspose, PGLfloat(aP1)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //holt den Wert einer Float-Uniform-Variable aus dem Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gelesen werden soll; | |||
| //@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.GetUniformfv(const aName: String; aP: PGLfloat): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glGetUniformfv(fProgramObj, pos, aP); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //holt den Wert einer Integer-Uniform-Variable aus dem Shader | |||
| //!!!Der Shader muss dazu aktiviert sein!!! | |||
| //@Name: Name der Variablen die gelesen werden soll; | |||
| //@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll; | |||
| //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden); | |||
| function TglcShaderProgram.GetUniformfi(const aName: String; aP: PGLint): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| if result then | |||
| glGetUniformiv(fProgramObj, pos, aP); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TglcShaderProgram.HasUniform(const aName: String): Boolean; | |||
| var | |||
| pos: GLint; | |||
| begin | |||
| result := GetUniformLocation(aName, pos); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //läd den Shader aus einer Datei | |||
| //@Filename: Datei aus der gelesen werden soll; | |||
| //@raise: EglcShader, wenn Datei nicht vorhanden ist; | |||
| procedure TglcShaderProgram.LoadFromFile(const aFilename: String); | |||
| var | |||
| Stream: TFileStream; | |||
| begin | |||
| if FileExists(aFilename) then begin | |||
| Stream := TFileStream.Create(aFilename, fmOpenRead); | |||
| try | |||
| LoadFromStream(Stream); | |||
| fFilename := aFilename; | |||
| finally | |||
| Stream.Free; | |||
| end; | |||
| end else raise EglcShader.Create('TglShaderProgram.LoadFromFile - file not found: '+Filename); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //läd den Shader aus einem Stream | |||
| //@Stream: Stream aus dem gelesen werden soll; | |||
| //@raise: EglcShader wenn kein Stream-Objekt übergeben wurde; | |||
| procedure TglcShaderProgram.LoadFromStream(const aStream: TStream); | |||
| function GetShaderType(const aStr: String): TglcShaderType; | |||
| begin | |||
| if (aStr = 'GL_VERTEX_SHADER') then | |||
| result := TglcShaderType.stVertex | |||
| else if (aStr = 'GL_FRAGMENT_SHADER') then | |||
| result := TglcShaderType.stFragment | |||
| else if (aStr = 'GL_GEOMETRY_SHADER') then | |||
| result := TglcShaderType.stGeometry | |||
| else if (aStr = 'GL_TESS_CONTROL_SHADER') then | |||
| result := TglcShaderType.stTessControl | |||
| else if (aStr = 'GL_TESS_EVALUATION_SHADER') then | |||
| result := TglcShaderType.stTessEvaluation | |||
| else | |||
| raise Exception.Create('invalid shader type: ' + aStr); | |||
| end; | |||
| var | |||
| sl: TStringList; | |||
| s: String; | |||
| rx: TRegExpr; | |||
| LastMatchPos: PtrInt; | |||
| st: TglcShaderType; | |||
| o: TglcShaderObject; | |||
| procedure AddObj(const aPos: Integer); | |||
| begin | |||
| if (LastMatchPos > 0) then begin | |||
| o := TglcShaderObject.Create(st, fOnLog); | |||
| o.Code := Trim(Copy(s, LastMatchPos, aPos - LastMatchPos)); | |||
| Add(o); | |||
| end; | |||
| end; | |||
| begin | |||
| if not Assigned(aStream) then | |||
| raise EglcShader.Create('TglShaderProgram.SaveToStream - stream is nil'); | |||
| Clear; | |||
| sl := TStringList.Create; | |||
| rx := TRegExpr.Create; | |||
| try | |||
| sl.LoadFromStream(aStream); | |||
| s := sl.Text; | |||
| LastMatchPos := 0; | |||
| rx.Expression := '/\*\s*ShaderObject\s*:\s*(GL_[A-Z_]+)\s*\*/\s*$?'; | |||
| rx.InputString := s; | |||
| while rx.Exec(LastMatchPos+1) do begin | |||
| AddObj(rx.MatchPos[0]); | |||
| LastMatchPos := rx.MatchPos[0] + rx.MatchLen[0]; | |||
| st := GetShaderType(rx.Match[1]); | |||
| end; | |||
| AddObj(Length(s)); | |||
| finally | |||
| rx.Free; | |||
| sl.Free; | |||
| end; | |||
| { | |||
| if Assigned(aStream) then begin | |||
| Clear; | |||
| fFilename := ''; | |||
| reader := TutlStreamReader.Create(aStream); | |||
| try | |||
| if reader.ReadAnsiString <> GLSL_FILE_HEADER then | |||
| raise EglcShader.Create('TglShaderProgram.SaveToStream - incompatible file'); | |||
| v := reader.ReadInteger; | |||
| if v >= 100 then begin //version 1.00 | |||
| c := reader.ReadInteger; | |||
| for i := 0 to c-1 do begin | |||
| Add(TglcShaderObject.Create(Cardinal(reader.ReadInteger), fOnLog)); | |||
| Last.fCode := reader.ReadAnsiString; | |||
| end; | |||
| end; | |||
| finally | |||
| reader.Free; | |||
| end; | |||
| end else | |||
| } | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //speichert den Shader in einer Datei | |||
| //@Filename: Datei in die geschrieben werden soll; | |||
| procedure TglcShaderProgram.SaveToFile(const aFilename: String); | |||
| var | |||
| Stream: TFileStream; | |||
| begin | |||
| Stream := TFileStream.Create(aFilename, fmCreate); | |||
| try | |||
| SaveToStream(Stream); | |||
| fFilename := aFilename; | |||
| finally | |||
| Stream.Free; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //speichert den Shader in einen Stream | |||
| //@Stream: Stream in den geschrieben werden soll; | |||
| //@raise: EglcShader wenn kein Stream-Objekt übergeben wurde; | |||
| //@raise: EglcShader wenn ungültige Datei; | |||
| procedure TglcShaderProgram.SaveToStream(const aStream: TStream); | |||
| var | |||
| i: Integer; | |||
| sl: TStringList; | |||
| sObj: TglcShaderObject; | |||
| function GetShaderTypeStr(const aShaderType: TglcShaderType): String; | |||
| begin | |||
| case aShaderType of | |||
| TglcShaderType.stVertex: result := 'GL_VERTEX_SHADER'; | |||
| TglcShaderType.stFragment: result := 'GL_FRAGMENT_SHADER'; | |||
| TglcShaderType.stGeometry: result := 'GL_GEOMETRY_SHADER'; | |||
| TglcShaderType.stTessControl: result := 'GL_TESS_CONTROL_SHADER'; | |||
| TglcShaderType.stTessEvaluation: result := 'GL_TESS_EVALUATION_SHADER'; | |||
| else | |||
| result := 'UNKNOWN'; | |||
| end; | |||
| end; | |||
| begin | |||
| if not Assigned(aStream) then | |||
| raise EglcShader.Create('TglShaderProgram.LoadFromStream - stream is nil'); | |||
| fFilename := ''; | |||
| sl := TStringList.Create; | |||
| try | |||
| for i := 0 to Count-1 do begin | |||
| sObj := Items[i]; | |||
| sl.Add('/* ShaderObject: ' + GetShaderTypeStr(sObj.ShaderType) + ' */'); | |||
| sl.Add(sObj.Code); | |||
| end; | |||
| sl.SaveToStream(aStream); | |||
| finally | |||
| sl.Free; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //erzeugt das Objekt | |||
| //@LogEvent: Event zum loggen von Fehlern und Ereignissen; | |||
| //@raise: EglcShader wenn OpenGL nicht initialisiert werden konnte; | |||
| //@raise: | |||
| constructor TglcShaderProgram.Create(aLogEvent: TglcShaderLogEvent); | |||
| begin | |||
| inherited Create; | |||
| fOnLog := aLogEvent; | |||
| fFilename := ''; | |||
| fProgramObj := 0; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //gibt das Objekt frei | |||
| destructor TglcShaderProgram.Destroy; | |||
| begin | |||
| if (fProgramObj <> 0) then | |||
| glDeleteProgram(fProgramObj); | |||
| inherited Destroy; | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,318 @@ | |||
| unit uglcTypes; | |||
| { Package: OpenGLCore | |||
| Prefix: glc - OpenGL Core | |||
| Beschreibung: diese Unit definiert Enum-Typen die OpenGL Konstanten wrappen und stellt zusätzlich | |||
| Funktions-Wrapper zur verfügung die diese Enum-Typen als Parameter entgegen nehmen } | |||
| {$mode objfpc}{$H+} | |||
| {$MACRO ON} | |||
| {$SCOPEDENUMS ON} | |||
| interface | |||
| uses | |||
| dglOpenGL, sysutils; | |||
| type | |||
| TglcFace = ( | |||
| faFront = GL_FRONT, | |||
| faBack = GL_BACK, | |||
| faBoth = GL_FRONT_AND_BACK); | |||
| TglcPolygonMode = ( | |||
| pmPoint = GL_POINT, | |||
| pmLine = GL_LINE, | |||
| pmFill = GL_FILL); | |||
| TglcDepthFunc = ( | |||
| dfNever = GL_NEVER, | |||
| dfLess = GL_LESS, | |||
| dfEqual = GL_EQUAL, | |||
| dfLessEqual = GL_LEQUAL, | |||
| dfGreater = GL_GREATER, | |||
| dfNotEqual = GL_NOTEQUAL, | |||
| dfGreaterEqual = GL_GEQUAL, | |||
| dfAlways = GL_ALWAYS); | |||
| TglcClearBuffer = ( | |||
| cbDepthBuffer = GL_DEPTH_BUFFER_BIT, | |||
| cbAccumBuffer = GL_ACCUM_BUFFER_BIT, | |||
| cbStencilBuffer = GL_STENCIL_BUFFER_BIT, | |||
| cbColorBuffer = GL_COLOR_BUFFER_BIT); | |||
| TglcTextureMinFilter = ( | |||
| mfNearest = GL_NEAREST, | |||
| mfLinear = GL_LINEAR, | |||
| mfNearestMipmapNearest = GL_NEAREST_MIPMAP_NEAREST, | |||
| mfLinearMipmapNearest = GL_LINEAR_MIPMAP_NEAREST, | |||
| mfNearestMipmapLinear = GL_NEAREST_MIPMAP_LINEAR, | |||
| mfLinearMipmapLinear = GL_LINEAR_MIPMAP_LINEAR); | |||
| TglcTextureMagFilter = ( | |||
| mfNearest = GL_NEAREST, | |||
| mfLinear = GL_LINEAR); | |||
| TglcTextureWrap = ( | |||
| twClamp = GL_CLAMP, | |||
| twRepeat = GL_REPEAT, | |||
| twClampToBorder = GL_CLAMP_TO_BORDER, | |||
| twClampToEdge = GL_CLAMP_TO_EDGE, | |||
| twMirroredRepeat = GL_MIRRORED_REPEAT); | |||
| TglcBlendFactor = ( | |||
| bfZero = GL_ZERO, | |||
| bfOne = GL_ONE, | |||
| bfSrcColor = GL_SRC_COLOR, | |||
| bfOneMinusSrcColor = GL_ONE_MINUS_SRC_COLOR, | |||
| bfSrcAlpha = GL_SRC_ALPHA, | |||
| bfOneMinusSrcAlpha = GL_ONE_MINUS_SRC_ALPHA, | |||
| bfDstAlpha = GL_DST_ALPHA, | |||
| bfOneMinusDstAlpha = GL_ONE_MINUS_DST_ALPHA, | |||
| bfDstColor = GL_DST_COLOR, | |||
| bfOneMinusDstColor = GL_ONE_MINUS_DST_COLOR, | |||
| bfSrcAlphaSaturate = GL_SRC_ALPHA_SATURATE, | |||
| bgConstColor = GL_CONSTANT_COLOR, | |||
| bfOneMinusConstColor = GL_ONE_MINUS_CONSTANT_COLOR, | |||
| bfConstAlpha = GL_CONSTANT_ALPHA, | |||
| bfOneMinusConstAlpha = GL_ONE_MINUS_CONSTANT_ALPHA); | |||
| TglcBlendMode = ( | |||
| bmNone, | |||
| bmAlphaBlend, | |||
| bmAdditiveAlphaBlend, | |||
| bmAdditiveBlend); | |||
| TglcFormat = ( | |||
| fmUnknown = 0, | |||
| fmColorIndex = GL_COLOR_INDEX, | |||
| fmDepthComponent = GL_DEPTH_COMPONENT, | |||
| fmRed = GL_RED, | |||
| fmGreen = GL_GREEN, | |||
| fmBlue = GL_BLUE, | |||
| fmAlpha = GL_ALPHA, | |||
| fmRGB = GL_RGB, | |||
| fmRGBA = GL_RGBA, | |||
| fmLuminance = GL_LUMINANCE, | |||
| fmLuminanceAlpha = GL_LUMINANCE_ALPHA, | |||
| fmBGR = GL_BGR, | |||
| fmBGRA = GL_BGRA, | |||
| fmDepthStencil = GL_DEPTH_STENCIL); | |||
| TglcInternalFormat = ( | |||
| ifUnknown = 0, | |||
| ifDepthComponent = GL_DEPTH_COMPONENT, | |||
| ifAlpha = GL_ALPHA, | |||
| ifRGB = GL_RGB, | |||
| ifRGBA = GL_RGBA, | |||
| ifLuminance = GL_LUMINANCE, | |||
| ifLuminanceAlpha = GL_LUMINANCE_ALPHA, | |||
| ifR3G3B2 = GL_R3_G3_B2, | |||
| ifAlpha4 = GL_ALPHA4, | |||
| ifAlpha8 = GL_ALPHA8, | |||
| ifAlpha12 = GL_ALPHA12, | |||
| ifAlpha16 = GL_ALPHA16, | |||
| ifLuminance4 = GL_LUMINANCE4, | |||
| ifLuminance8 = GL_LUMINANCE8, | |||
| ifLuminance12 = GL_LUMINANCE12, | |||
| ifLuminance16 = GL_LUMINANCE16, | |||
| ifLuminance4Alpha4 = GL_LUMINANCE4_ALPHA4, | |||
| ifLuminance6Alpha2 = GL_LUMINANCE6_ALPHA2, | |||
| ifLuminance8Alpha8 = GL_LUMINANCE8_ALPHA8, | |||
| ifLuminance12Alpha4 = GL_LUMINANCE12_ALPHA4, | |||
| ifLuminance12Alpha12 = GL_LUMINANCE12_ALPHA12, | |||
| ifLuminance16Alpha16 = GL_LUMINANCE16_ALPHA16, | |||
| ifIntensity = GL_INTENSITY, | |||
| ifIntensity4 = GL_INTENSITY4, | |||
| ifIntensity8 = GL_INTENSITY8, | |||
| ifIntensity12 = GL_INTENSITY12, | |||
| ifIntensity16 = GL_INTENSITY16, | |||
| ifRGB4 = GL_RGB4, | |||
| ifRGB5 = GL_RGB5, | |||
| ifRGB8 = GL_RGB8, | |||
| ifRGB10 = GL_RGB10, | |||
| ifRGB12 = GL_RGB12, | |||
| ifRGB16 = GL_RGB16, | |||
| ifRGBA2 = GL_RGBA2, | |||
| ifRGBA4 = GL_RGBA4, | |||
| ifRGB5A1 = GL_RGB5_A1, | |||
| ifRGBA8 = GL_RGBA8, | |||
| ifRGB10A2 = GL_RGB10_A2, | |||
| ifRGBA12 = GL_RGBA12, | |||
| ifRGBA16 = GL_RGBA16, | |||
| ifDepthComponent16 = GL_DEPTH_COMPONENT16, | |||
| ifDepthComponent24 = GL_DEPTH_COMPONENT24, | |||
| ifDepthComponent32 = GL_DEPTH_COMPONENT32, | |||
| ifCompressedAlpha = GL_COMPRESSED_ALPHA, | |||
| ifCompressedLuminance = GL_COMPRESSED_LUMINANCE, | |||
| ifCompressedLuminanceAlpha = GL_COMPRESSED_LUMINANCE_ALPHA, | |||
| ifCompressedIntensity = GL_COMPRESSED_INTENSITY, | |||
| ifCompressedRGB = GL_COMPRESSED_RGB, | |||
| ifCompressedRGBA = GL_COMPRESSED_RGBA, | |||
| ifRGBA32f = GL_RGBA32F, | |||
| ifRGB32f = GL_RGB32F, | |||
| ifRGBA16F = GL_RGBA16F, | |||
| ifRGB16F = GL_RGB16F, | |||
| ifDepth24Stencil8 = GL_DEPTH24_STENCIL8, | |||
| ifSRGB = GL_SRGB, | |||
| ifSRGB8 = GL_SRGB8, | |||
| ifSRGBA = GL_SRGB_ALPHA, | |||
| ifSRGBA8 = GL_SRGB8_ALPHA8, | |||
| ifSLuminanceAlpha = GL_SLUMINANCE_ALPHA, | |||
| ifSLuminance8Alpha8 = GL_SLUMINANCE8_ALPHA8, | |||
| ifSLuminance = GL_SLUMINANCE, | |||
| ifSLuminance8 = GL_SLUMINANCE8, | |||
| ifDepth32fStencil8 = GL_DEPTH32F_STENCIL8, | |||
| ifStencil1 = GL_STENCIL_INDEX1, | |||
| ifStencil4 = GL_STENCIL_INDEX4, | |||
| ifStencil8 = GL_STENCIL_INDEX8, | |||
| ifStencil16 = GL_STENCIL_INDEX16); | |||
| TglcAttachment = ( | |||
| atDepthStencil = GL_DEPTH_STENCIL_ATTACHMENT, | |||
| atColor0 = GL_COLOR_ATTACHMENT0, | |||
| atColor1 = GL_COLOR_ATTACHMENT1, | |||
| atColor2 = GL_COLOR_ATTACHMENT2, | |||
| atColor3 = GL_COLOR_ATTACHMENT3, | |||
| atColor4 = GL_COLOR_ATTACHMENT4, | |||
| atColor5 = GL_COLOR_ATTACHMENT5, | |||
| atColor6 = GL_COLOR_ATTACHMENT6, | |||
| atColor7 = GL_COLOR_ATTACHMENT7, | |||
| atColor8 = GL_COLOR_ATTACHMENT8, | |||
| atColor9 = GL_COLOR_ATTACHMENT9, | |||
| atColor10 = GL_COLOR_ATTACHMENT10, | |||
| atColor11 = GL_COLOR_ATTACHMENT11, | |||
| atColor12 = GL_COLOR_ATTACHMENT12, | |||
| atColor13 = GL_COLOR_ATTACHMENT13, | |||
| atColor14 = GL_COLOR_ATTACHMENT14, | |||
| atColor15 = GL_COLOR_ATTACHMENT15, | |||
| atDepth = GL_DEPTH_ATTACHMENT, | |||
| atStencil = GL_STENCIL_ATTACHMENT); | |||
| TglcShaderType = ( | |||
| stFragment = GL_FRAGMENT_SHADER, | |||
| stVertex = GL_VERTEX_SHADER, | |||
| stGeometry = GL_GEOMETRY_SHADER, | |||
| stTessEvaluation = GL_TESS_EVALUATION_SHADER, | |||
| stTessControl = GL_TESS_CONTROL_SHADER); | |||
| TglcBufferTarget = ( | |||
| btArrayBuffer = GL_ARRAY_BUFFER, | |||
| btElementArrayBuffer = GL_ELEMENT_ARRAY_BUFFER); | |||
| TglcBufferUsage = ( | |||
| buStreamDraw = GL_STREAM_DRAW, | |||
| buStreamRead = GL_STREAM_READ, | |||
| buStreamCopy = GL_STREAM_COPY, | |||
| buStaticDraw = GL_STATIC_DRAW, | |||
| buStaticRead = GL_STATIC_READ, | |||
| buStaticCopy = GL_STATIC_COPY, | |||
| buDynamicDraw = GL_DYNAMIC_DRAW, | |||
| buDynamicRead = GL_DYNAMIC_READ, | |||
| buDynamicCopy = GL_DYNAMIC_COPY); | |||
| TglcBufferAccess = ( | |||
| baReadOnly = GL_READ_ONLY, | |||
| baWriteOnly = GL_WRITE_ONLY, | |||
| baReadWrite = GL_READ_WRITE); | |||
| EOpenGL = class(Exception) | |||
| private | |||
| fErrorCode: GLenum; | |||
| public | |||
| property ErrorCode: GLenum read fErrorCode; | |||
| constructor Create(const aErrorCode: GLenum); | |||
| constructor Create(const aMsg: String; const aErrorCode: GLenum); | |||
| end; | |||
| procedure glcRenderFace(const aValue: TglcFace); inline; | |||
| procedure glcPolygonMode(const aFace: TglcFace; const aValue: TglcPolygonMode); inline; | |||
| procedure glcDepthFunc(const aValue: TglcDepthFunc); inline; | |||
| procedure glcBlendFunc(const aSource, aDest: TglcBlendFactor); inline; overload; | |||
| procedure glcBlendFunc(const aMode: TglcBlendMode); inline; overload; | |||
| procedure glcCheckAndRaiseError; | |||
| implementation | |||
| type | |||
| TglcBlendModeValue = packed record | |||
| src, dst: TglcBlendFactor; | |||
| end; | |||
| const | |||
| BLEND_MODE_VALUES: array[TglcBlendMode] of TglcBlendModeValue = ( | |||
| (src: TglcBlendFactor.bfOne; dst: TglcBlendFactor.bfZero), //bmNone | |||
| (src: TglcBlendFactor.bfSrcAlpha; dst: TglcBlendFactor.bfOneMinusSrcAlpha), //bmAlphaBlend | |||
| (src: TglcBlendFactor.bfSrcAlpha; dst: TglcBlendFactor.bfOne), //bmAdditiveAlphaBlend | |||
| (src: TglcBlendFactor.bfOne; dst: TglcBlendFactor.bfOne)); //bmAdditiveBlend | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure glcRenderFace(const aValue: TglcFace); | |||
| begin | |||
| case aValue of | |||
| TglcFace.faBoth: begin | |||
| glDisable(GL_CULL_FACE); | |||
| end; | |||
| TglcFace.faFront: begin | |||
| glEnable(GL_CULL_FACE); | |||
| glCullFace(GL_BACK); | |||
| end; | |||
| TglcFace.faBack: begin | |||
| glEnable(GL_CULL_FACE); | |||
| glCullFace(GL_FRONT); | |||
| end; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure glcPolygonMode(const aFace: TglcFace; const aValue: TglcPolygonMode); | |||
| begin | |||
| glPolygonMode(GLenum(aFace), GLenum(aValue)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure glcDepthFunc(const aValue: TglcDepthFunc); | |||
| begin | |||
| glDepthFunc(GLenum(aValue)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure glcBlendFunc(const aSource, aDest: TglcBlendFactor); | |||
| begin | |||
| glBlendFunc(GLenum(aSource), GLenum(aDest)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure glcBlendFunc(const aMode: TglcBlendMode); overload; | |||
| begin | |||
| glBlendFunc(GLenum(BLEND_MODE_VALUES[aMode].src), GLenum(BLEND_MODE_VALUES[aMode].dst)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure glcCheckAndRaiseError; | |||
| var | |||
| e: GLenum; | |||
| begin | |||
| e := glGetError(); | |||
| if (e <> GL_NO_ERROR) then | |||
| raise EOpenGL.Create(e); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //EOpenGL/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor EOpenGL.Create(const aErrorCode: GLenum); | |||
| begin | |||
| fErrorCode := aErrorCode; | |||
| inherited Create(gluErrorString(fErrorCode)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor EOpenGL.Create(const aMsg: String; const aErrorCode: GLenum); | |||
| begin | |||
| fErrorCode := aErrorCode; | |||
| inherited Create(aMsg + ': ' + gluErrorString(fErrorCode)) | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,318 @@ | |||
| unit ugluMatrix; | |||
| { Package: OpenGLCore | |||
| Prefix: glu - OpenGL Utils | |||
| Beschreibung: diese Unit enthält Matrix-Typen und Methoden um diese zu erstellen und zu manipulieren } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, ugluVector; | |||
| type | |||
| //Matrixtypen | |||
| TgluMatrix2ub = array[0..1] of TgluVector2ub; | |||
| TgluMatrix2i = array[0..1] of TgluVector2i; | |||
| TgluMatrix2f = array[0..1] of TgluVector2f; | |||
| TgluMatrix2d = array[0..1] of TgluVector2d; | |||
| TgluMatrix3ub = array[0..2] of TgluVector3ub; | |||
| TgluMatrix3i = array[0..2] of TgluVector3i; | |||
| TgluMatrix3f = array[0..2] of TgluVector3f; | |||
| TgluMatrix3d = array[0..2] of TgluVector3d; | |||
| TgluMatrix4ub = array[0..3] of TgluVector4ub; | |||
| TgluMatrix4i = array[0..3] of TgluVector4i; | |||
| TgluMatrix4f = array[0..3] of TgluVector4f; | |||
| TgluMatrix4d = array[0..3] of TgluVector4d; | |||
| //MatrixPointer | |||
| PgluMatrix2ub = ^TgluMatrix2ub; | |||
| PgluMatrix2i = ^TgluMatrix2i; | |||
| PgluMatrix2f = ^TgluMatrix2f; | |||
| PgluMatrix2d = ^TgluMatrix2d; | |||
| PgluMatrix3ub = ^TgluMatrix3ub; | |||
| PgluMatrix3i = ^TgluMatrix3i; | |||
| PgluMatrix3f = ^TgluMatrix3f; | |||
| PgluMatrix3d = ^TgluMatrix3d; | |||
| PgluMatrix4ub = ^TgluMatrix4ub; | |||
| PgluMatrix4i = ^TgluMatrix4i; | |||
| PgluMatrix4f = ^TgluMatrix4f; | |||
| PgluMatrix4d = ^TgluMatrix4d; | |||
| //Konstructoren | |||
| function gluMatrix4d(const m: TgluMatrix4f): TgluMatrix4d; | |||
| //Matrixfunktionen | |||
| function gluMatrixTranslate(const v: TgluVector3f): TgluMatrix4f; | |||
| function gluMatrixScale(const v: TgluVector3f): TgluMatrix4f; overload; | |||
| function gluMatrixScale(const s: Single): TgluMatrix4f; overload; | |||
| function gluMatrixRotate(axis: TgluVector3f; const angle: Single): TgluMatrix4f; | |||
| function gluMatrixMult(const m1, m2: TgluMatrix4f): TgluMatrix4f; | |||
| function gluMatrixMultVec(const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f; | |||
| function gluMatrixTranspose(const m: TgluMatrix3f): TgluMatrix3f; overload; | |||
| function gluMatrixTranspose(const m: TgluMatrix4f): TgluMatrix4f; overload; | |||
| function gluMatrixSubMatrix(const m:TgluMatrix4f; const s, z: Integer): TgluMatrix3f; | |||
| function gluMatrixDeterminant(const m: TgluMatrix3f): Single; overload; | |||
| function gluMatrixDeterminant(const m: TgluMatrix4f): Single; overload; | |||
| function gluMatrixAdjoint(const m: TgluMatrix4f): TgluMatrix4f; | |||
| function gluMatrixInvert(const m: TgluMatrix4f): TgluMatrix4f; | |||
| operator * (const m1, m2: TgluMatrix4f): TgluMatrix4f; | |||
| operator * (const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f; | |||
| operator * (const m: TgluMatrix4f; const v: TgluVector3f): TgluVector3f; | |||
| const | |||
| maAxisX = 0; | |||
| maAxisY = 1; | |||
| maAxisZ = 2; | |||
| maPos = 3; | |||
| gluMatrixIdentity: TgluMatrix4f = ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)); | |||
| implementation | |||
| uses | |||
| Math; | |||
| operator * (const m1, m2: TgluMatrix4f): TgluMatrix4f; | |||
| begin | |||
| result := gluMatrixMult(m1, m2); | |||
| end; | |||
| operator * (const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f; | |||
| begin | |||
| result := gluMatrixMultVec(m, v); | |||
| end; | |||
| operator * (const m: TgluMatrix4f; const v: TgluVector3f): TgluVector3f; | |||
| begin | |||
| result := gluVector3f(gluMatrixMultVec(m, gluVEctor4f(v, 1.0))); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function gluMatrix4d(const m: TgluMatrix4f): TgluMatrix4d; | |||
| var | |||
| i, j: Integer; | |||
| begin | |||
| for i := 0 to 3 do | |||
| for j := 0 to 3 do | |||
| result[i, j] := m[i, j]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //erstellt eine Translationsmatrix | |||
| //@v: Vektor der Translationsmatrix; | |||
| function gluMatrixTranslate(const v: TgluVector3f): TgluMatrix4f; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| result := gluMatrixIdentity; | |||
| for i := 0 to 2 do | |||
| result[3, i] := v[i]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //erstellt eine Skalierungsmatrix | |||
| //@v: Vektor der Skalierungsmatrix; | |||
| function gluMatrixScale(const v: TgluVector3f): TgluMatrix4f; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| result := gluMatrixIdentity; | |||
| for i := 0 to 2 do | |||
| result[i, i] := v[i]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function gluMatrixScale(const s: Single): TgluMatrix4f; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| result := gluMatrixIdentity; | |||
| for i := 0 to 2 do | |||
| result[i, i] := s; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //erstellt eine Rotationsmatrix; | |||
| //@axis: Achse um die gedreht werden soll; | |||
| //@angle: Winkel mit dem gedreht werden soll; | |||
| function gluMatrixRotate(axis: TgluVector3f; const angle: Single): TgluMatrix4f; | |||
| var | |||
| X, Y, Z, a, s, c: Single; | |||
| begin | |||
| axis := gluVectorNormalize(axis); | |||
| X := axis[0]; | |||
| Y := axis[1]; | |||
| Z := axis[2]; | |||
| a := angle/180*Pi; | |||
| s := sin(a); | |||
| c := cos(a); | |||
| result := gluMatrixIdentity; | |||
| result[maAxisX] := gluVector4f( | |||
| SQR(X) + (1-SQR(X))*c, | |||
| X*Y*(1-c) + Z*s, | |||
| X*Z*(1-c) - Y*s, | |||
| 0); | |||
| result[maAxisY] := gluVector4f( | |||
| X*Y*(1-c) - Z*s, | |||
| SQR(Y) + (1-SQR(Y))*c, | |||
| Y*Z*(1-c) + X*s, | |||
| 0); | |||
| result[maAxisZ] := gluVector4f( | |||
| X*Z*(1-c) + Y*s, | |||
| Y*Z*(1-c) - X*s, | |||
| SQR(Z) + (1-SQR(Z))*c, | |||
| 0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //Mutlipliziert Matrix1 mit Matrix2 | |||
| //@Matrix1: 1. Multiplikator; | |||
| //@Matrix2: 2. Multiplikator; | |||
| //@result: Matrix1 * Matrix2 | |||
| function gluMatrixMult(const m1, m2: TgluMatrix4f): TgluMatrix4f; | |||
| var | |||
| x, y, i: Integer; | |||
| sum: Single; | |||
| begin | |||
| for x := 0 to 3 do begin | |||
| for y := 0 to 3 do begin | |||
| sum := 0; | |||
| for i := 0 to 3 do | |||
| sum := sum + m1[i, y] * m2[x, i]; | |||
| result[x, y] := sum; | |||
| end; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //Multiplizerit eine Matrix mit einem Vektor | |||
| //@m: Matrix mit der multipliziert werden soll; | |||
| //@v: Vektor mit dem multipliziert werden soll; | |||
| //@result: Ergebnis der Multiplikation | |||
| function gluMatrixMultVec(const m: TgluMatrix4f; const v: TgluVector4f): TgluVector4f; | |||
| var | |||
| i, j: Integer; | |||
| sum: Single; | |||
| begin | |||
| for i := 0 to 3 do begin | |||
| sum := 0; | |||
| for j := 0 to 3 do | |||
| sum := sum + m[j,i] * v[j]; | |||
| result[i] := sum; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //berechnet die Transponierte Matrix | |||
| //@m: Matrix die Transponiert werden soll; | |||
| //@result: Transponierte Matrix; | |||
| function gluMatrixTranspose(const m: TgluMatrix3f): TgluMatrix3f; | |||
| var | |||
| i, j: Integer; | |||
| begin | |||
| for i := 0 to 2 do | |||
| for j := 0 to 2 do | |||
| result[i, j] := m[j, i]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //berechnet die Transponierte Matrix | |||
| //@m: Matrix die Transponiert werden soll; | |||
| //@result: Transponierte Matrix; | |||
| function gluMatrixTranspose(const m: TgluMatrix4f): TgluMatrix4f; | |||
| var | |||
| i, j: Integer; | |||
| begin | |||
| for i := 0 to 3 do | |||
| for j := 0 to 3 do | |||
| result[i, j] := m[j, i]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //ermittelt die Untermatrix einer Matrix | |||
| //@m: Matrix derren Untermatrix berechnet werden soll; | |||
| //@s: Spalte die gelöscht werden soll; | |||
| //@z: Zeile die gelöscht werden soll; | |||
| //@result: Untermatrix von m | |||
| function gluMatrixSubMatrix(const m: TgluMatrix4f; const s, z: Integer): TgluMatrix3f; | |||
| var | |||
| x, y, i, j: Integer; | |||
| begin | |||
| for i := 0 to 2 do | |||
| for j := 0 to 2 do begin | |||
| x := i; | |||
| y := j; | |||
| if (i >= s) then | |||
| inc(x); | |||
| if (j >= z) then | |||
| inc(y); | |||
| result[i, j] := m[x, y]; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //berechnet die Determinante einer Matrix | |||
| //@m: Matrix derren Determinaten berechnet werden soll; | |||
| //@result: Determinante von m | |||
| function gluMatrixDeterminant(const m: TgluMatrix3f): Single; | |||
| begin | |||
| result := | |||
| m[0,0] * m[1,1] * m[2,2] + | |||
| m[1,0] * m[2,1] * m[0,2] + | |||
| m[2,0] * m[0,1] * m[1,2] - | |||
| m[2,0] * m[1,1] * m[0,2] - | |||
| m[1,0] * m[0,1] * m[2,2] - | |||
| m[0,0] * m[2,1] * m[1,2]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //berechnet die Determinante einer Matrix | |||
| //@m: Matrix derren Determinaten berechnet werden soll; | |||
| //@result: Determinante von m | |||
| function gluMatrixDeterminant(const m: TgluMatrix4f): Single; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| result := 0; | |||
| for i := 0 to 3 do | |||
| result := result + power(-1, i) * m[i, 0] * gluMatrixDeterminant(gluMatrixSubMatrix(m, i, 0)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //berechnet die Adjunkte einer Matrix | |||
| //@m: Matrix derren Adjunkte berechnet werden soll; | |||
| //@result: Adjunkte von m | |||
| function gluMatrixAdjoint(const m: TgluMatrix4f): TgluMatrix4f; | |||
| var | |||
| i, j: Integer; | |||
| begin | |||
| for i := 0 to 3 do | |||
| for j := 0 to 3 do | |||
| result[i, j] := power(-1, i+j) * gluMatrixDeterminant(gluMatrixSubMatrix(m, i, j)); | |||
| result := gluMatrixTranspose(result); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //berechnet die inverse Matrix einer Matrix | |||
| //@m: Matrix derren Inverse berechnet werden soll; | |||
| //@result: Inverse Matrix von m; | |||
| function gluMatrixInvert(const m: TgluMatrix4f): TgluMatrix4f; | |||
| var | |||
| d: Single; | |||
| i, j: Integer; | |||
| begin | |||
| d := gluMatrixDeterminant(m); | |||
| result := gluMatrixAdjoint(m); | |||
| for i := 0 to 3 do | |||
| for j := 0 to 3 do | |||
| result[i,j] := result[i,j] / d; | |||
| end; | |||
| end. | |||
| @@ -0,0 +1,384 @@ | |||
| unit ugluQuaternion; | |||
| { Package: OpenGLCore | |||
| Prefix: glu - OpenGL Utils | |||
| Beschreibung: diese Unit enthält Quaternion-Typen und Methoden um diese zu erstellen und zu manipulieren } | |||
| {$mode objfpc}{$H+} | |||
| interface | |||
| uses | |||
| Classes, SysUtils, ugluVector, ugluMatrix; | |||
| type | |||
| TgluQuaternion = type TgluVector4f; // w,x,y,z | |||
| { | |||
| Winkel : rad, außer glRotate-Komponenten | |||
| Absolute Werte : Orientation | |||
| Relative Werte/"Drehanweisungen" : Rotation | |||
| To/FromVector : Position im R^4 | |||
| Alle Funktionen nehmen an, dass die Quaternion nur zur Rotation verwendet wird (kein Scale), | |||
| mathematisch also normalisiert ist. Es findet keine Überprüfung statt. | |||
| } | |||
| //Quaternion Konstruktoren | |||
| function gluQuaternion(const W, X, Y, Z: Single): TgluQuaternion; | |||
| function gluQuaternionNormalize(const q: TgluQuaternion): TgluQuaternion; | |||
| procedure gluQuaternionNormalizeInplace(var q: TgluQuaternion); | |||
| function gluQuaternionToVector(const q: TgluQuaternion): TgluVector3f; | |||
| function gluVectorToQuaternion(const v: TgluVector3f): TgluQuaternion; | |||
| //Arithmetic | |||
| function gluQuaternionConjugate(const q: TgluQuaternion): TgluQuaternion; | |||
| function gluQuaternionMultiply(const l,r: TgluQuaternion): TgluQuaternion; | |||
| function gluQuaternionAdd(const a,b: TgluQuaternion): TgluQuaternion; | |||
| function gluQuaternionSubtract(const l,r: TgluQuaternion): TgluQuaternion; | |||
| function gluQuaternionScale(const q: TgluQuaternion; const f: Single): TgluQuaternion; | |||
| //To/From RotationMatrix | |||
| function gluQuaternionToMatrix(const q: TgluQuaternion): TgluMatrix4f; | |||
| function gluMatrixToQuaternion(const m: TgluMatrix4f): TgluQuaternion; | |||
| //To/From Axis/Angle {WINKEL IN °DEG} | |||
| function gluQuaternionToRotation(const q: TgluQuaternion; out angle: Single): TgluVector3f; | |||
| function gluRotationToQuaternion(const angle: Single; const axis: TgluVector3f): TgluQuaternion; | |||
| //Transforms | |||
| function gluQuaternionTransformVec(const q: TgluQuaternion; const v: TgluVector3f): TgluVector3f; | |||
| function gluQuaternionLookAt(const Location, Target, UpVector: TgluVector3f): TgluQuaternion; | |||
| //Rotation zw. Richtungen: Wie muss a modifiziert werden um b zu bekommen? | |||
| function gluVectorRotationTo(const a, b: TgluVector3f): TgluQuaternion; | |||
| //Modifying Quaternions | |||
| function gluQuaternionHalfAngle(const q: TgluQuaternion): TgluQuaternion; | |||
| function gluQuaternionAngleBetween(const a, b: TgluQuaternion): double; | |||
| function gluQuaternionSlerpOrientation(const a, b: TgluQuaternion; const t: single): TgluQuaternion; | |||
| function gluQuaternionNlerpOrientation(const a, b: TgluQuaternion; const t: single): TgluQuaternion; | |||
| operator +(const a, b: TgluQuaternion): TgluQuaternion; | |||
| operator -(const l, r: TgluQuaternion): TgluQuaternion; | |||
| operator *(const l, r: TgluQuaternion): TgluQuaternion; | |||
| operator *(const q: TgluQuaternion; const s: Sigle): TgluQuaternion; | |||
| const | |||
| quW = 0; | |||
| quX = 1; | |||
| quY = 2; | |||
| quZ = 3; | |||
| gluQuaternionIdentity: TgluQuaternion = (1,0,0,0); | |||
| implementation | |||
| uses | |||
| Math; | |||
| operator +(const a, b: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| result := gluQuaternionAdd(a, b); | |||
| end; | |||
| operator -(const l, r: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| result := gluQuaternionSubtract(l, r); | |||
| end; | |||
| operator *(const l, r: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| result := gluQuaternionMultiply(l, r); | |||
| end; | |||
| operator *(const q: TgluQuaternion; const s: Sigle): TgluQuaternion; | |||
| begin | |||
| result := gluQuaternionScale(q, s); | |||
| end; | |||
| function gluQuaternion(const W, X, Y, Z: Single): TgluQuaternion; | |||
| begin | |||
| Result:= gluVector4f(W,X,Y,Z); | |||
| end; | |||
| function gluQuaternionNormalize(const q: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| Result:= q; | |||
| gluQuaternionNormalizeInplace(Result); | |||
| end; | |||
| procedure gluQuaternionNormalizeInplace(var q: TgluQuaternion); | |||
| var | |||
| s: Double; | |||
| begin | |||
| s:= sqr(q[quX])+sqr(q[quY])+sqr(q[quZ])+sqr(q[quW]); | |||
| // already normalized? | |||
| if IsZero(s - 1) then | |||
| exit; | |||
| s:= 1/sqrt(s); | |||
| q[quX]:= q[quX] * s; | |||
| q[quY]:= q[quY] * s; | |||
| q[quZ]:= q[quZ] * s; | |||
| q[quW]:= q[quW] * s; | |||
| end; | |||
| function gluQuaternionToVector(const q: TgluQuaternion): TgluVector3f; | |||
| begin | |||
| Result:= gluVector3f(q[quX], q[quY], q[quZ]); | |||
| end; | |||
| function gluVectorToQuaternion(const v: TgluVector3f): TgluQuaternion; | |||
| begin | |||
| Result:= gluQuaternion(0, v[0], v[1], v[2]); | |||
| end; | |||
| function gluQuaternionConjugate(const q: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| Result[quW] := q[quW]; | |||
| Result[quX] := -q[quX]; | |||
| Result[quY] := -q[quY]; | |||
| Result[quZ] := -q[quZ]; | |||
| end; | |||
| function gluQuaternionMultiply(const l, r: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| Result[quW] := -l[qux] * r[qux] - l[quy] * r[quy] - l[quz] * r[quz] + l[quw] * r[quw]; | |||
| Result[quX] := l[qux] * r[quw] + l[quy] * r[quz] - l[quz] * r[quy] + l[quw] * r[qux]; | |||
| Result[quY] := -l[qux] * r[quz] + l[quy] * r[quw] + l[quz] * r[qux] + l[quw] * r[quy]; | |||
| Result[quZ] := l[qux] * r[quy] - l[quy] * r[qux] + l[quz] * r[quw] + l[quw] * r[quz]; | |||
| end; | |||
| function gluQuaternionAdd(const a, b: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| Result[quW] := a[quW] + b[quW]; | |||
| Result[quX] := a[quX] + b[quX]; | |||
| Result[quY] := a[quY] + b[quY]; | |||
| Result[quZ] := a[quZ] + b[quZ]; | |||
| end; | |||
| function gluQuaternionSubtract(const l, r: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| Result[quW] := l[quW] - r[quW]; | |||
| Result[quX] := l[quX] - r[quX]; | |||
| Result[quY] := l[quY] - r[quY]; | |||
| Result[quZ] := l[quZ] - r[quZ]; | |||
| end; | |||
| function gluQuaternionScale(const q: TgluQuaternion; const f: Single): TgluQuaternion; | |||
| begin | |||
| Result[quW] := q[quW] * f; | |||
| Result[quX] := q[quX] * f; | |||
| Result[quY] := q[quY] * f; | |||
| Result[quZ] := q[quZ] * f; | |||
| end; | |||
| // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm | |||
| function gluQuaternionToMatrix(const q: TgluQuaternion): TgluMatrix4f; | |||
| var | |||
| qx,qy,qz,qw: Single; | |||
| begin | |||
| qw:= q[quW]; | |||
| qx:= q[quX]; | |||
| qy:= q[quY]; | |||
| qz:= q[quZ]; | |||
| Result:= gluMatrixIdentity; | |||
| Result[maAxisX] := gluVector4f( | |||
| 1 - 2*SQR(qy) - 2*SQR(qz), | |||
| 2*qx*qy + 2*qz*qw, | |||
| 2*qx*qz - 2*qy*qw, | |||
| 0); | |||
| Result[maAxisY] := gluVector4f( | |||
| 2*qx*qy - 2*qz*qw, | |||
| 1 - 2*SQR(qx) - 2*SQR(qz), | |||
| 2*qy*qz + 2*qx*qw, | |||
| 0); | |||
| Result[maAxisZ] := gluVector4f( | |||
| 2*qx*qz + 2*qy*qw, | |||
| 2*qy*qz - 2*qx*qw, | |||
| 1 - 2*SQR(qx) - 2*SQR(qy), | |||
| 0); | |||
| end; | |||
| // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm | |||
| function gluMatrixToQuaternion(const m: TgluMatrix4f): TgluQuaternion; | |||
| var | |||
| trace, s: double; | |||
| q: TgluQuaternion; | |||
| begin | |||
| trace := m[0][0] + m[1][1] + m[2][2]; // I removed + 1.0f; see discussion with Ethan | |||
| if( trace > 0 ) then begin// I changed M_EPSILON to 0 | |||
| s := 0.5 / SQRT(trace+ 1.0); | |||
| q[quW] := 0.25 / s; | |||
| q[quX] := ( m[2][1] - m[1][2] ) * s; | |||
| q[quY] := ( m[0][2] - m[2][0] ) * s; | |||
| q[quZ] := ( m[1][0] - m[0][1] ) * s; | |||
| end else begin | |||
| if ( m[0][0] > m[1][1]) and (m[0][0] > m[2][2] ) then begin | |||
| s := 2.0 * SQRT( 1.0 + m[0][0] - m[1][1] - m[2][2]); | |||
| q[quW] := (m[2][1] - m[1][2] ) / s; | |||
| q[quX] := 0.25 * s; | |||
| q[quY] := (m[0][1] + m[1][0] ) / s; | |||
| q[quZ] := (m[0][2] + m[2][0] ) / s; | |||
| end else if (m[1][1] > m[2][2]) then begin | |||
| s := 2.0 * SQRT( 1.0 + m[1][1] - m[0][0] - m[2][2]); | |||
| q[quW] := (m[0][2] - m[2][0] ) / s; | |||
| q[quX] := (m[0][1] + m[1][0] ) / s; | |||
| q[quY] := 0.25 * s; | |||
| q[quZ] := (m[1][2] + m[2][1] ) / s; | |||
| end else begin | |||
| s := 2.0 * SQRT( 1.0 + m[2][2] - m[0][0] - m[1][1] ); | |||
| q[quW] := (m[1][0] - m[0][1] ) / s; | |||
| q[quX] := (m[0][2] + m[2][0] ) / s; | |||
| q[quY] := (m[1][2] + m[2][1] ) / s; | |||
| q[quZ] := 0.25 * s; | |||
| end; | |||
| end; | |||
| Result:= q; | |||
| end; | |||
| // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm | |||
| function gluQuaternionToRotation(const q: TgluQuaternion; out angle: Single): TgluVector3f; | |||
| var | |||
| s: double; | |||
| begin | |||
| angle := radtodeg(2 * arccos(q[quW])); | |||
| s := sqrt(1-q[quW]*q[quW]); // assuming quaternion normalised then w is less than 1, so term always positive. | |||
| if (s < 0.001) then begin // test to avoid divide by zero, s is always positive due to sqrt | |||
| // if s close to zero then direction of axis not important | |||
| Result[0] := q[quX]; // if it is important that axis is normalised then replace with x=1; y=z=0; | |||
| Result[1] := q[quY]; | |||
| Result[2] := q[quZ]; | |||
| end else begin | |||
| Result[0] := q[quX] / s; // normalise axis | |||
| Result[1] := q[quY] / s; | |||
| Result[2] := q[quZ] / s; | |||
| end; | |||
| end; | |||
| function gluRotationToQuaternion(const angle: Single; const axis: TgluVector3f): TgluQuaternion; | |||
| var | |||
| a: single; | |||
| begin | |||
| a:= degtorad(angle) / 2; | |||
| Result:= gluQuaternion( | |||
| cos(a), | |||
| sin(a) * axis[0], | |||
| sin(a) * axis[1], | |||
| sin(a) * axis[2]); | |||
| end; | |||
| // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm | |||
| function gluQuaternionTransformVec(const q: TgluQuaternion; const v: TgluVector3f): TgluVector3f; | |||
| var | |||
| p: TgluQuaternion; | |||
| begin | |||
| //Pout = q * Pin * q' | |||
| p:= gluQuaternionMultiply(q, gluVectorToQuaternion(v)); | |||
| p:= gluQuaternionMultiply(p, gluQuaternionConjugate(q)); | |||
| Result:= gluQuaternionToVector(p); | |||
| end; | |||
| // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/halfAngle.htm | |||
| function gluQuaternionHalfAngle(const q: TgluQuaternion): TgluQuaternion; | |||
| begin | |||
| Result:= q; | |||
| Result[quW]:= Result[quW] + 1; | |||
| gluQuaternionNormalizeInplace(Result); | |||
| end; | |||
| function gluQuaternionAngleBetween(const a, b: TgluQuaternion): double; | |||
| var | |||
| cosHalfTheta: double; | |||
| begin | |||
| cosHalfTheta:= a[quW] * b[quW] + a[quX] * b[quX] + a[quY] * b[quY] + a[quZ] * b[quZ]; | |||
| Result:= arccos(cosHalfTheta) * 2; | |||
| end; | |||
| // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/index.htm | |||
| function gluQuaternionSlerpOrientation(const a, b: TgluQuaternion; const t: single): TgluQuaternion; | |||
| var | |||
| qa,qb: TgluQuaternion; | |||
| cosHalfTheta, sinHalfTheta, | |||
| halfTheta, | |||
| ratioA, ratioB: double; | |||
| begin | |||
| qa:= a; | |||
| qb:= b; | |||
| // Calculate angle between them. | |||
| cosHalfTheta:= a[quW] * b[quW] + a[quX] * b[quX] + a[quY] * b[quY] + a[quZ] * b[quZ]; | |||
| if (cosHalfTheta < 0) then begin | |||
| qb:= gluQuaternion( | |||
| -b[quW], | |||
| -b[quX], | |||
| -b[quY], | |||
| b[quZ] | |||
| ); | |||
| cosHalfTheta:= -cosHalfTheta; | |||
| end; | |||
| // if qa=qb or qa=-qb then theta = 0 and we can return qa | |||
| if abs(cosHalfTheta) >= 1.0 then begin | |||
| Result:= qa; | |||
| Exit; | |||
| end; | |||
| // Calculate temporary values. | |||
| halfTheta := arccos(cosHalfTheta); | |||
| sinHalfTheta := sqrt(1.0 - sqr(cosHalfTheta)); | |||
| // if theta = 180 degrees then result is not fully defined | |||
| // we could rotate around any axis normal to qa or qb | |||
| if (abs(sinHalfTheta) < 0.001) then begin | |||
| Result:= gluQuaternionAdd(gluQuaternionScale(qa, 0.5), gluQuaternionScale(qb, 0.5)); | |||
| exit | |||
| end; | |||
| ratioA := sin((1 - t) * halfTheta) / sinHalfTheta; | |||
| ratioB := sin(t * halfTheta) / sinHalfTheta; | |||
| //calculate Quaternion. | |||
| Result:= gluQuaternionAdd(gluQuaternionScale(qa, ratioA), gluQuaternionScale(qb, ratioB)); | |||
| end; | |||
| function gluQuaternionNlerpOrientation(const a, b: TgluQuaternion; const t: single): TgluQuaternion; | |||
| begin | |||
| Result:= gluQuaternionAdd(a, gluQuaternionScale(gluQuaternionSubtract(b,a), t)); | |||
| gluQuaternionNormalizeInplace(Result); | |||
| end; | |||
| function gluQuaternionLookAt(const Location, Target, UpVector: TgluVector3f): TgluQuaternion; | |||
| var | |||
| front, up, right: TgluVector3f; | |||
| w4_recip: Single; | |||
| begin | |||
| front:= gluVectorSubtract(Location, Target); // eigentlich falschrum. don't ask. | |||
| up:= UpVector; | |||
| gluVectorOrthoNormalize(front, up); | |||
| right:= gluVectorProduct(up, front); | |||
| Result[quW]:= SQRT(1 + right[0] + up[1] + front[2]) * 0.5; | |||
| w4_recip:= 1 / (4 * Result[quW]); | |||
| Result[quX]:= (front[1] - up[2]) * w4_recip; | |||
| Result[quY]:= (right[2] - front[0]) * w4_recip; | |||
| Result[quZ]:= (up[0] - right[1]) * w4_recip; | |||
| end; | |||
| function gluVectorRotationTo(const a, b: TgluVector3f): TgluQuaternion; | |||
| var | |||
| d, qw: single; | |||
| ax: TgluVector3f; | |||
| begin | |||
| d:=gluVectorScalar(a, b); | |||
| ax:= gluVectorProduct(a, b); | |||
| qw:= gluVectorLength(a) * gluVectorLength(b) + d; | |||
| if (qw < 0.0001) then begin // vectors are 180 degrees apart | |||
| Result:= gluQuaternion(0, -a[2],a[1],a[0]); | |||
| end else begin | |||
| Result:= gluQuaternion(qw, ax[0],ax[1],ax[2]); | |||
| end; | |||
| gluQuaternionNormalizeInplace(Result); | |||
| end; | |||
| end. | |||