|
- unit utsRendererOpenGLES;
-
- {$IFDEF FPC}
- {$mode objfpc}{$H+}
- {$ENDIF}
-
- interface
-
- uses
- Classes, SysUtils, dglOpenGLES,
- utsOpenGLUtils, utsTypes, utsContext, utsImage;
-
- 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: TtsOpenGLRenderRef; const aCharImage: TtsImage; const X, Y: Integer); override;
-
- procedure BeginRender; override;
-
- procedure SetDrawPos(const aValue: TtsPosition); override;
- procedure MoveDrawPos(const aOffset: TtsPosition); override;
- procedure SetColor(const aValue: TtsColor4f); override;
- procedure Render(const aRenderRef: TtsRenderRef; const aForcedWidth: Integer = 0); 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
-
- uses
- utsUtils, utsConstants;
-
- 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: TtsOpenGLRenderRef; 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 aValue: TtsPosition);
- begin
- inherited SetDrawPos(aValue);
- UpdateUniformCharOffset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TtsRendererOpenGLES.MoveDrawPos(const aOffset: TtsPosition);
- begin
- inherited MoveDrawPos(aOffset);
- UpdateUniformCharOffset;
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TtsRendererOpenGLES.SetColor(const aValue: TtsColor4f);
- begin
- inherited SetColor(aValue);
- glColor4f(Color.r, Color.g, Color.b, Color.a);
- end;
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TtsRendererOpenGLES.Render(const aRenderRef: TtsRenderRef; const aForcedWidth: Integer);
- var
- ref: TtsOpenGLRenderRef;
- m: TtsMatrix4f;
- begin
- if Assigned(aRenderRef) then begin
- ref := TtsOpenGLRenderRef(aRenderRef);
-
- 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 begin
- if (aForcedWidth > 0) then begin
- m := ref.VertMat;
- m[0] := tsVector4f(aForcedWidth, 0, 0, 0);
- glUniformMatrix4fv(fCharPosLocation, 1, false, @m[0, 0]);
- end else
- glUniformMatrix4fv(fCharPosLocation, 1, false, @ref.VertMat[0, 0]);
- end;
- 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.
|