diff --git a/examples/simple/TextSuiteTest.lpi b/examples/simple/TextSuiteTest.lpi index 0c018cf..30a9336 100644 --- a/examples/simple/TextSuiteTest.lpi +++ b/examples/simple/TextSuiteTest.lpi @@ -44,7 +44,6 @@ - @@ -72,7 +71,6 @@ - @@ -85,17 +83,14 @@ - - - @@ -112,7 +107,7 @@ - + diff --git a/examples/simple/TextSuiteTest.lps b/examples/simple/TextSuiteTest.lps index 0a19193..a96c285 100644 --- a/examples/simple/TextSuiteTest.lps +++ b/examples/simple/TextSuiteTest.lps @@ -4,7 +4,7 @@ - + @@ -18,7 +18,6 @@ - @@ -28,8 +27,10 @@ - - + + + + @@ -37,10 +38,8 @@ - - - - + + @@ -54,10 +53,11 @@ - - - + + + + @@ -70,10 +70,8 @@ - - - + @@ -97,7 +95,6 @@ - @@ -106,7 +103,6 @@ - @@ -116,7 +112,6 @@ - @@ -124,13 +119,33 @@ + + + + + + + + + + + + + + + + + + + + - - + + @@ -143,237 +158,236 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -383,252 +397,249 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + + + - - - + + + - + - - + + - - + - - + + - - + + - + - - + + - + - - + + - - + + - - + + - + - + - - + + - + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + diff --git a/utsFontCreatorFreeType.pas b/utsFontCreatorFreeType.pas index 0222580..4789631 100644 --- a/utsFontCreatorFreeType.pas +++ b/utsFontCreatorFreeType.pas @@ -5,7 +5,7 @@ unit utsFontCreatorFreeType; interface uses - Classes, SysUtils, syncobjs, dynlibs, + Classes, SysUtils, utsTextSuite, utsTypes, utsFreeType; type @@ -315,7 +315,7 @@ begin if (err <> 0) then raise EtsException.Create('unable to set char size: error=' + IntToStr(err)); - FillByte(prop, SizeOf(prop), 0); + FillByte(prop{%H-}, SizeOf(prop), 0); prop.AntiAliasing := tsAANormal; prop.FaceName := face^.family_name; prop.StyleName := face^.style_name; diff --git a/utsOpenGLUtils.pas b/utsOpenGLUtils.pas index 56cf9c3..39bd380 100644 --- a/utsOpenGLUtils.pas +++ b/utsOpenGLUtils.pas @@ -5,19 +5,16 @@ unit utsOpenGLUtils; interface uses - Classes, SysUtils, syncobjs, + Classes, SysUtils, utsTextSuite, utsTypes; type - TtsQuadPosF = array[0..3] of TtsPositionF; TtsCharRenderRefOpenGL = class(TtsCharRenderRef) public TextureID: Integer; // ID of OpenGL texture where the char is stored in - TexCoordSize: TtsPositionF; // size of the char in texture coords (0.0 - 1.0) - TexCoordPos: TtsPositionF; // position of the char in texture coords (0.0 - 1.0) - VertexSize: TtsPositionF; // size of the char in world coords - VertexPos: TtsPositionF; // size of the char in world coords - + Size: TtsPosition; + TexMat: TtsMatrix4f; + VertMat: TtsMatrix4f; constructor Create; end; @@ -61,9 +58,8 @@ type function CreateNewTexture: PtsFontTexture; virtual; procedure FreeTexture(var aTexture: PtsFontTexture); virtual; - procedure UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; - const aCharImage: TtsImage; const X, Y: Integer); virtual; + procedure UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; const aCharImage: TtsImage; const X, Y: Integer); virtual; protected function CreateRenderRef(const aChar: TtsChar; const aCharImage: TtsImage): TtsCharRenderRef; override; procedure FreeRenderRef(const aCharRef: TtsCharRenderRef); override; @@ -92,10 +88,9 @@ constructor TtsCharRenderRefOpenGL.Create; begin inherited Create; TextureID := 0; - FillByte(TexCoordPos, SizeOf(TexCoordPos), 0); - FillByte(TexCoordSize, SizeOf(TexCoordSize), 0); - FillByte(VertexPos, SizeOf(VertexPos), 0); - FillByte(VertexSize, SizeOf(VertexSize), 0); + FillByte(TexMat, SizeOf(TexMat), 0); + FillByte(VertMat, SizeOf(VertMat), 0); + FillByte(Size, SizeOf(Size), 0); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -152,8 +147,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TtsBaseOpenGL.UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; - const aCharImage: TtsImage; const X, Y: Integer); +procedure TtsBaseOpenGL.UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; const aCharImage: TtsImage; const X, Y: Integer); begin // DUMMY end; @@ -211,21 +205,22 @@ var item := InsertToTree(aTexture^.Usage, 0, 0, aTexture^.Size, aTexture^.Size, x, y); if not Assigned(item) then raise EtsRendererOpenGL.Create('unable to add glyph to texture'); + item^.ref := TtsCharRenderRefOpenGL.Create; result := item^.ref; - // Text Coords - result.TextureID := aTexture^.ID; - result.TexCoordPos.x := x / aTexture^.Size; - result.TexCoordPos.y := y / aTexture^.Size; - result.TexCoordSize.x := aCharImage.Width / aTexture^.Size; - result.TexCoordSize.y := aCharImage.Height / aTexture^.Size; - - // Vertex Coords - result.VertexPos.x := -aChar.GlyphRect.Left; - result.VertexPos.y := -aChar.GlyphRect.Top - aChar.GlyphOrigin.y; - result.VertexSize.x := aCharImage.Width; - result.VertexSize.y := aCharImage.Height; + result.TextureID := aTexture^.ID; + result.Size := tsPosition(aCharImage.Width, aCharImage.Height); + result.TexMat := tsMatrix4f( + tsVector4f(aCharImage.Width / aTexture^.Size, 0.0, 0.0, 0.0), + tsVector4f(0.0, aCharImage.Height / aTexture^.Size, 0.0, 0.0), + tsVector4f(0.0, 0.0, 1.0, 0.0), + tsVector4f(x / aTexture^.Size, y / aTexture^.Size, 0.0, 1.0)); + result.VertMat := tsMatrix4f( + tsVector4f(aCharImage.Width, 0.0, 0.0, 0.0), + tsVector4f(0.0, aCharImage.Height, 0.0, 0.0), + tsVector4f(0.0, 0.0, 1.0, 0.0), + tsVector4f(-aChar.GlyphRect.Left, -aChar.GlyphRect.Top - aChar.GlyphOrigin.y, 0.0, 1.0)); UploadTexData(result, aCharImage, x, y); end; @@ -281,8 +276,8 @@ var w := X2 - X1; h := Y2 - Y1; if not Assigned(aItem) or - (w < ref.VertexSize.x) or - (h < ref.VertexSize.y) then + (w < ref.Size.x) or + (h < ref.Size.y) then exit; result := (aItem^.ref = ref); diff --git a/utsRendererOpenGL.pas b/utsRendererOpenGL.pas index 8ac0d31..2087a04 100644 --- a/utsRendererOpenGL.pas +++ b/utsRendererOpenGL.pas @@ -184,13 +184,11 @@ begin glMatrixMode(GL_TEXTURE); glPushMatrix; glLoadIdentity; - glTranslatef(ref.TexCoordPos.x, ref.TexCoordPos.y, 0); - glScalef(ref.TexCoordSize.x, ref.TexCoordSize.y, 1); + glMultMatrixf(@ref.TexMat[0, 0]); glMatrixMode(GL_MODELVIEW); glPushMatrix; - glTranslatef(ref.VertexPos.x, ref.VertexPos.y, 0); - glScalef(ref.VertexSize.x, ref.VertexSize.y, 1); + glMultMatrixf(@ref.VertMat[0, 0]); glBindBuffer(GL_ARRAY_BUFFER, fVBO); glEnableClientState(GL_VERTEX_ARRAY); diff --git a/utsRendererOpenGLES.pas b/utsRendererOpenGLES.pas new file mode 100644 index 0000000..4fadc57 --- /dev/null +++ b/utsRendererOpenGLES.pas @@ -0,0 +1,417 @@ +unit utsRendererOpenGLES; + +{$mode objfpc}{$H+} +{.$DEFINE DEBUG} + +interface + +uses + Classes, SysUtils, + utsTextSuite, utsTypes, utsOpenGLUtils, dglOpenGLES; + +type + TtsRendererOpenGLES = class(TtsBaseOpenGL) + private + fModelViewMatrix: TtsMatrix4f; + fProjMatrix: TtsMatrix4f; + fShaderProgram: GLuint; + fVBO: GLuint; + fShader: GLuint; + + fCharPosLocation: GLint; + fCharTexPosLocation: GLint; + fCharOffsetLocation: GLint; + + procedure SetModelViewMatrix(aValue: TtsMatrix4f); + procedure SetProjectionMatrix(aValue: TtsMatrix4f); + procedure SetShaderProgram(aValue: GLuint); + + function LoadShader: GLuint; + + procedure UpdateUniformProjMat; + procedure UpdateUniformModelMat; + procedure UpdateUniformCharOffset; + protected + function CreateNewTexture: PtsFontTexture; override; + procedure FreeTexture(var aTexture: PtsFontTexture); override; + procedure UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; + const aCharImage: TtsImage; const X, Y: Integer); override; + + procedure BeginRender; override; + + procedure SetDrawPos(const X, Y: Integer); override; + procedure MoveDrawPos(const X, Y: Integer); override; + procedure SetColor(const aColor: TtsColor4f); override; + procedure Render(const aCharRef: TtsCharRenderRef); override; + public + property ShaderProgram: GLuint read fShaderProgram write SetShaderProgram; + property ProjectionMatrix: TtsMatrix4f read fProjMatrix write SetProjectionMatrix; + property ModelViewMatrix: TtsMatrix4f read fModelViewMatrix write SetModelViewMatrix; + + constructor Create(const aContext: TtsContext; const aFormat: TtsFormat); + destructor Destroy; override; + end; + +implementation + +type + TVertex = packed record + pos: array[0..1] of GLfloat; + tex: array[0..1] of GLfloat; + end; + +const + ATTRIB_LOCATION_POSITION = 0; + ATTRIB_LOCATION_TEXCOORD = 1; + ATTRIB_NAME_POSITION = 'inPosition'; + ATTRIB_NAME_TEXCOORD = 'inTexCoord'; + UNIFORM_NAME_TEXTURE = 'uTexture'; + UNIFORM_NAME_MODELVIEWMAT = 'uModelViewMat'; + UNIFORM_NAME_PROJMAT = 'uProjMat'; + UNIFORM_NAME_CHARTEXPOS = 'uCharTexPos'; + UNIFORM_NAME_CHARPOS = 'uCharPos'; + UNIFORM_NAME_CHAROFFSET = 'uCharOffset'; + VERTEX_SHADER = + 'attribute vec2 inPosition;' + + 'attribute vec2 inTexCoord;' + + 'varying vec2 vTexCoord;' + + 'uniform mat4 uModelViewMat;' + + 'uniform mat4 uProjMat;' + + 'uniform mat4 uCharTexPos;' + + 'uniform mat4 uCharPos;' + + 'uniform ivec2 uCharOffset;' + + 'void main() {' + + ' vec4 pos = uCharPos * vec4(inPosition, 0.0, 1.0);' + + ' pos += vec4(uCharOffset, 0.0, 0.0);' + + ' gl_Position = uProjMat * uModelViewMat * pos;' + + ' vTexCoord = (uCharTexPos * vec4(inTexCoord, 0.0, 1.0)).st;' + + '}'; + FRAGMENT_SHADER = + 'uniform sampler2D uTexture;' + + 'varying vec2 vTexCoord;' + + 'void main() {' + + ' gl_FragColor = texture2D(uTexture, vTexCoord);' + + '}'; + + FORMAT_TYPES: array[TtsFormat] of packed record + InternalFormat: GLenum; + Format: GLenum; + DataFormat: GLenum; + end = ( + ( //tsFormatEmpty + InternalFormat: 0; + Format: 0; + DataFormat: 0), + ( //tsFormatRGBA8 + InternalFormat: GL_RGBA; + Format: GL_RGBA; + DataFormat: GL_UNSIGNED_BYTE), + ( //tsFormatLumAlpha8 + InternalFormat: GL_LUMINANCE_ALPHA; + Format: GL_LUMINANCE_ALPHA; + DataFormat: GL_UNSIGNED_BYTE), + ( //tsFormatAlpha8 + InternalFormat: GL_ALPHA; + Format: GL_ALPHA; + DataFormat: GL_UNSIGNED_BYTE), + ( //tsFormatAlpha8 + InternalFormat: GL_LUMINANCE; + Format: GL_LUMINANCE; + DataFormat: GL_UNSIGNED_BYTE) + ); + + VBO_DATA: array[0..3] of TVertex = ( + (pos: (0.0, 0.0); tex: (0.0, 0.0)), + (pos: (0.0, 1.0); tex: (0.0, 1.0)), + (pos: (1.0, 0.0); tex: (1.0, 0.0)), + (pos: (1.0, 1.0); tex: (1.0, 1.0)) + ); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TtsRendererOpenGLES/////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.SetModelViewMatrix(aValue: TtsMatrix4f); +begin + fModelViewMatrix := aValue; + UpdateUniformModelMat; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.SetProjectionMatrix(aValue: TtsMatrix4f); +begin + fProjMatrix := aValue; + UpdateUniformProjMat; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.SetShaderProgram(aValue: GLuint); +begin + if (fShaderProgram = aValue) then + exit; + + fShaderProgram := aValue; + fCharPosLocation := glGetUniformLocation(fShaderProgram, UNIFORM_NAME_CHARPOS); + fCharTexPosLocation := glGetUniformLocation(fShaderProgram, UNIFORM_NAME_CHARTEXPOS); + fCharOffsetLocation := glGetUniformLocation(fShaderProgram, UNIFORM_NAME_CHAROFFSET); + + UpdateUniformProjMat; + UpdateUniformModelMat; + UpdateUniformCharOffset; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TtsRendererOpenGLES.LoadShader: GLuint; + +{$IFDEF DEBUG} + procedure PrintShaderInfo(const aObj: GLuint); + var + msg: PChar; + bLen: GLint; + sLen: GLsizei; + begin + bLen := 0; + glGetShaderiv(aObj, GL_INFO_LOG_LENGTH, @bLen); + if bLen > 1 then begin + GetMem(msg, bLen * SizeOf(Char)); + try + glGetShaderInfoLog(aObj, bLen, @sLen, msg); + WriteLn(String(msg)); + finally + FreeMem(msg); + end; + end; + end; + + procedure PrintProgramInfo(const aObj: GLuint); + var + msg: PChar; + bLen: GLint; + sLen: GLsizei; + begin + bLen := 0; + glGetProgramiv(aObj, GL_INFO_LOG_LENGTH, @bLen); + if bLen > 1 then begin + GetMem(msg, bLen * SizeOf(Char)); + try + glGetProgramInfoLog(aObj, bLen, @sLen, msg); + WriteLn(String(msg)); + finally + FreeMem(msg); + end; + end; + end; +{$ENDIF} + + function CreateObj(const aCode: String; const aType: GLenum): GLuint; + var + code: PAnsiChar; + len: GLint; + begin + result := glCreateShader(aType); + len := Length(aCode); + code := PAnsiChar(aCode); + glShaderSource(result, 1, @code, @len); + glCompileShader(result); + {$IFDEF DEBUG}PrintShaderInfo(result);{$ENDIF} + end; + +var + fragObj, vertObj: GLuint; + uLoc: Integer; +begin + result := glCreateProgram(); + vertObj := CreateObj(VERTEX_SHADER, GL_VERTEX_SHADER); + fragObj := CreateObj(FRAGMENT_SHADER, GL_FRAGMENT_SHADER); + glAttachShader(result, vertObj); + glAttachShader(result, fragObj); + glLinkProgram(result); +{$IFDEF DEBUG}PrintProgramInfo(result);{$ENDIF} + glBindAttribLocation(result, ATTRIB_LOCATION_POSITION, ATTRIB_NAME_POSITION); + glBindAttribLocation(result, ATTRIB_LOCATION_TEXCOORD, ATTRIB_NAME_TEXCOORD); + uLoc := glGetUniformLocation(result, UNIFORM_NAME_TEXTURE); + if (uLoc >= 0) then begin + glUseProgram(result); + glUniform1i(uLoc, 0); + glUseProgram(0); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.UpdateUniformProjMat; +var + loc: Integer; +begin + loc := glGetUniformLocation(fShaderProgram, UNIFORM_NAME_PROJMAT); + if (loc >= 0) then begin + glUseProgram(fShaderProgram); + glUniformMatrix4fv(loc, 1, false, @fProjMatrix[0, 0]); + glUseProgram(0); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.UpdateUniformModelMat; +var + loc: Integer; +begin + loc := glGetUniformLocation(fShaderProgram, UNIFORM_NAME_MODELVIEWMAT); + if (loc >= 0) then begin + glUseProgram(fShaderProgram); + glUniformMatrix4fv(loc, 1, false, @fModelViewMatrix[0, 0]); + glUseProgram(0); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.UpdateUniformCharOffset; +begin + if (fCharOffsetLocation >= 0) then begin + glUseProgram(fShaderProgram); + glUniform2iv(fCharOffsetLocation, 1, @RenderPos.x); + glUseProgram(0); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TtsRendererOpenGLES.CreateNewTexture: PtsFontTexture; +begin + new(result); + try + FillByte(result^, SizeOf(result^), 0); + new(result^.Usage); + FillByte(result^.Usage^, SizeOf(result^.Usage^), 0); + result^.Size := TextureSize; + + glGenTextures(1, @result^.ID); + glBindTexture(GL_TEXTURE_2D, result^.ID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D( + GL_TEXTURE_2D, + 0, + FORMAT_TYPES[Format].InternalFormat, + result^.Size, + result^.Size, + 0, + FORMAT_TYPES[Format].Format, + FORMAT_TYPES[Format].DataFormat, + nil); + + PushTexture(result); + except + if Assigned(result^.Usage) then + Dispose(result^.Usage); + Dispose(result); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.FreeTexture(var aTexture: PtsFontTexture); +begin + if Assigned(aTexture) then + glDeleteTextures(1, @aTexture^.ID); + inherited FreeTexture(aTexture); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.UploadTexData(const aCharRef: TtsCharRenderRefOpenGL; const aCharImage: TtsImage; const X, Y: Integer); +begin + glBindTexture(GL_TEXTURE_2D, aCharRef.TextureID); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glTexSubImage2D(GL_TEXTURE_2D, 0, + x, y, aCharImage.Width, aCharImage.Height, + FORMAT_TYPES[aCharImage.Format].Format, + FORMAT_TYPES[aCharImage.Format].DataFormat, + aCharImage.Data); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.BeginRender; +begin + inherited BeginRender; + glColor4f(Color.r, Color.g, Color.b, Color.a); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.SetDrawPos(const X, Y: Integer); +begin + inherited SetDrawPos(X, Y); + UpdateUniformCharOffset; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.MoveDrawPos(const X, Y: Integer); +begin + inherited MoveDrawPos(X, Y); + UpdateUniformCharOffset; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.SetColor(const aColor: TtsColor4f); +begin + inherited SetColor(aColor); + glColor4f(Color.r, Color.g, Color.b, Color.a); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TtsRendererOpenGLES.Render(const aCharRef: TtsCharRenderRef); +var + ref: TtsCharRenderRefOpenGL; +begin + if Assigned(aCharRef) and (aCharRef is TtsCharRenderRefOpenGL) then begin + ref := (aCharRef as TtsCharRenderRefOpenGL); + + glBindTexture(GL_TEXTURE_2D, ref.TextureID); + glBindBuffer(GL_ARRAY_BUFFER, fVBO); + glEnableVertexAttribArray(ATTRIB_LOCATION_POSITION); + glVertexAttribPointer(ATTRIB_LOCATION_POSITION, 2, GL_FLOAT, false, SizeOf(TVertex), Pointer(0)); + glEnableVertexAttribArray(ATTRIB_LOCATION_TEXCOORD); + glVertexAttribPointer(ATTRIB_LOCATION_TEXCOORD, 2, GL_FLOAT, false, SizeOf(TVertex), Pointer(8)); + glUseProgram(fShaderProgram); + + if (fCharPosLocation >= 0) then + glUniformMatrix4fv(fCharPosLocation, 1, false, @ref.VertMat); + if (fCharTexPosLocation >= 0) then + glUniformMatrix4fv(fCharTexPosLocation, 1, false, @ref.TexMat); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glUseProgram(0); + glDisableVertexAttribArray(ATTRIB_LOCATION_TEXCOORD); + glDisableVertexAttribArray(ATTRIB_LOCATION_POSITION); + glBindTexture(GL_TEXTURE_2D, 0); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TtsRendererOpenGLES.Create(const aContext: TtsContext; const aFormat: TtsFormat); +var + viewport: array[0..3] of Integer; +begin + inherited Create(aContext, aFormat); + + glGenBuffers(1, @fVBO); + glBindBuffer(GL_ARRAY_BUFFER, fVBO); + glBufferData(GL_ARRAY_BUFFER, SizeOf(TVertex) * Length(VBO_DATA), @VBO_DATA[0].pos[0], GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGetIntegerv(GL_VIEWPORT, @viewport); + fProjMatrix := tsMatrix4f( + tsVector4f(2 / viewport[2], 0.0, 0.0, 0.0), + tsVector4f( 0.0, -2 / viewport[3], 0.0, 0.0), + tsVector4f( 0.0, 0.0, -0.1, 0.0), + tsVector4f( -1.0, 1.0, 0.0, 1.0)); + fModelViewMatrix := TS_MATRIX_IDENTITY; + fShader := LoadShader; + ShaderProgram := fShader; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TtsRendererOpenGLES.Destroy; +begin + glDeleteBuffers(1, @fVBO); + glDeleteProgram(fShader); + inherited Destroy; +end; + +end. diff --git a/utsTypes.pas b/utsTypes.pas index 69854eb..850384e 100644 --- a/utsTypes.pas +++ b/utsTypes.pas @@ -159,6 +159,9 @@ type end; PtsColor4ub = ^TtsColor4ub; + TtsVector4f = array[0..3] of Single; + TtsMatrix4f = array[0..3] of TtsVector4f; + TtsTextMetric = packed record Ascent: Integer; Descent: Integer; @@ -179,10 +182,15 @@ const TS_MODES_MODULATE_ALL: TtsImageModes = (tsModeModulate, tsModeModulate, tsModeModulate, tsModeModulate); TS_MODES_MODULATE_ALPHA: TtsImageModes = (tsModeReplace, tsModeReplace, tsModeReplace, tsModeModulate); + TS_MATRIX_IDENTITY: TtsMatrix4f = ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)); + function tsColor4f(r, g, b, a: Single): TtsColor4f; function tsModes(r, g, b, a: TtsImageMode): TtsImageModes; function tsRect(const l, t, r, b: Integer): TtsRect; function tsPosition(const x, y: Integer): TtsPosition; +function tsPositionF(const x, y: Single): TtsPositionF; +function tsVector4f(X, Y, Z, W: Single): TtsVector4f; +function tsMatrix4f(X, Y, Z, P: TtsVector4f): TtsMatrix4f; function tsFormatSize(const aFormat: TtsFormat): Integer; procedure tsFormatMap(const aFormat: TtsFormat; var aData: PByte; const aColor: TtsColor4f); @@ -235,6 +243,31 @@ begin result.y := y; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function tsPositionF(const x, y: Single): TtsPositionF; +begin + result.x := x; + result.y := y; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function tsVector4f(X, Y, Z, W: Single): TtsVector4f; +begin + result[0] := X; + result[1] := Y; + result[2] := Z; + result[3] := W; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function tsMatrix4f(X, Y, Z, P: TtsVector4f): TtsMatrix4f; +begin + result[0] := X; + result[1] := Y; + result[2] := Z; + result[3] := P; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function tsFormatSize(const aFormat: TtsFormat): Integer; begin