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.