| @@ -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. | |||||