1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-27 03:48:21 +01:00

OpenGL: recalculate vertices only when changed.

This allows to greatly improve rendering performance
This commit is contained in:
DanyLE 2022-03-06 19:50:19 +01:00
parent bd9d406c85
commit 94bfc7f6f0
12 changed files with 125 additions and 80 deletions

View File

@ -2,7 +2,9 @@ Class {
#name : #Diya2DNode, #name : #Diya2DNode,
#superclass : #DiyaNode, #superclass : #DiyaNode,
#instVars : [ #instVars : [
'color' 'color',
'vbuffer',
'nvertices'
], ],
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
@ -25,7 +27,9 @@ Diya2DNode >> initialize [
rotation := 0.0. rotation := 0.0.
tf := Array2D identity: 3. tf := Array2D identity: 3.
shader := Diya2DShader uniqueInstance. shader := Diya2DShader uniqueInstance.
color := Color white color := Color white.
vbuffer := nil.
nvertices := 0.
] ]
{ #category : #initialization } { #category : #initialization }

View File

@ -7,10 +7,31 @@ Class {
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
{ #category : #initialization }
Diya2DPrimShape >> draw [
vbuffer ifNil: [ ^self ].
self shader
setUniform: #u_use_texture value:1.
"configure vao vbo for texture QUAD"
self texture ifNotNil: [
self texture setup.
context texture0 setImage2D: self texture.
context texture0 active.
].
context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
OpenGL drawArrays: GL_TRIANGLES first:0 count:nvertices.
context vao disableAttribute: 0.
"reset value"
self texture ifNotNil: [self texture drop.].
]
{ #category : #initialization } { #category : #initialization }
Diya2DPrimShape >> initialize [ Diya2DPrimShape >> initialize [
super initialize. super initialize.
texture := nil. texture := nil.
children := nil
] ]
{ #category : #initialization } { #category : #initialization }

View File

@ -79,6 +79,7 @@ DiyaBoot >> exampleNodes [
rec scale: 1.5@1.5. rec scale: 1.5@1.5.
text := root addNode: (DiyaText data: String loremIpsum) at: 20@320. text := root addNode: (DiyaText data: String loremIpsum) at: 20@320.
text extent: 200@320. text extent: 200@320.
text wordWrap: true.
^ root ^ root
"text rotation:(Float pi / 4.0); scale: 2.0@2.0." "text rotation:(Float pi / 4.0); scale: 2.0@2.0."
] ]

5
Diya/DiyaCircle.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaCircle,
#superclass : #DiyaEllipse,
#category : #'Diya-Graphics'
}

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaEllipse,
#superclass : #Diya2DPrimShape,
#category : #'Diya-Graphics'
}

5
Diya/DiyaLine.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaLine,
#superclass : #Diya2DPrimShape,
#category : #'Diya-Graphics'
}

View File

@ -10,7 +10,8 @@ Class {
'tf', 'tf',
'shader', 'shader',
'context', 'context',
'extent' 'extent',
'dirty'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -70,12 +71,8 @@ DiyaNode >> extent [
{ #category : #accessing } { #category : #accessing }
DiyaNode >> extent: anObject [ DiyaNode >> extent: anObject [
extent := anObject extent := anObject.
] dirty := true
{ #category : #'as yet unclassified' }
DiyaNode >> gltf: points [
^self subclassResponsibility
] ]
{ #category : #accessing } { #category : #accessing }
@ -90,6 +87,7 @@ DiyaNode >> initialize [
shader := nil. shader := nil.
context := DiyaRendererContext uniqueInstance. context := DiyaRendererContext uniqueInstance.
children := OrderedCollection new. children := OrderedCollection new.
dirty := false
] ]
{ #category : #testing } { #category : #testing }
@ -120,6 +118,7 @@ DiyaNode >> position: anObject [
{ #category : #accessing } { #category : #accessing }
DiyaNode >> render [ DiyaNode >> render [
dirty ifTrue:[dirty := self update not].
shader ifNotNil: [ self setUpShader ]. shader ifNotNil: [ self setUpShader ].
self draw. self draw.
children ifNil: [ ^self ]. children ifNil: [ ^self ].
@ -183,6 +182,11 @@ DiyaNode >> tf [
^ tf ^ tf
] ]
{ #category : #accessing }
DiyaNode >> update [
^self subclassResponsibility
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> updateTF [ DiyaNode >> updateTF [
self subclassResponsibility self subclassResponsibility

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaPolygon,
#superclass : #Diya2DPrimShape,
#category : #'Diya-Graphics'
}

View File

@ -5,7 +5,17 @@ Class {
} }
{ #category : #accessing } { #category : #accessing }
DiyaRectangle >> draw [ DiyaRectangle >> initialize [
super initialize.
self extent:10@10.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
vbuffer autoRelease.
nvertices := 6
]
{ #category : #accessing }
DiyaRectangle >> update [
{ {
0.0. extent y. 0.0. 0.0. 0.0. extent y. 0.0. 0.0.
0. 0. 0.0. 1.0. 0. 0. 0.0. 1.0.
@ -13,24 +23,6 @@ DiyaRectangle >> draw [
0.0. extent y. 0.0. 0.0. 0.0. extent y. 0.0. 0.0.
extent x. 0.0. 1.0. 1.0. extent x. 0.0. 1.0. 1.0.
extent x. extent y. 1.0. 0.0. extent x. extent y. 1.0. 0.0.
} doWithIndex: [:e :i| context buffer at: i put: e]. } doWithIndex: [:e :i| vbuffer at: i put: e].
texture ifNotNil: [ ^true
self texture setup.
context texture0 setImage2D: self texture.
context texture0 active.
].
context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil.
context vbo subData: GL_ARRAY_BUFFER offset:0 data: context buffer size: 96.
OpenGL drawArrays: GL_TRIANGLES first:0 count: 6.
context vao disableAttribute: 0.
texture ifNotNil: [self texture drop]
]
{ #category : #accessing }
DiyaRectangle >> initialize [
super initialize.
self extent:10@10.
translation := nil.
children := nil
] ]

View File

@ -7,8 +7,7 @@ Class {
'vbo', 'vbo',
'vao', 'vao',
'texture0', 'texture0',
'projection', 'projection'
'buffer'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -27,11 +26,6 @@ DiyaRendererContext class >> maxFloatBufferSize [
^4096 ^4096
] ]
{ #category : #accessing }
DiyaRendererContext >> buffer [
^ buffer
]
{ #category : #accessing } { #category : #accessing }
DiyaRendererContext >> destroy [ DiyaRendererContext >> destroy [
vao delete. vao delete.
@ -58,9 +52,6 @@ DiyaRendererContext >> initialize [
vao bind. vao bind.
vbo bind: GL_ARRAY_BUFFER. vbo bind: GL_ARRAY_BUFFER.
projection := Array2D identity: 4. projection := Array2D identity: 4.
buffer := FFIExternalArray externalNewType: GLfloat size: self class maxFloatBufferSize .
buffer autoRelease.
vbo data: GL_ARRAY_BUFFER data: nil size:self class maxFloatBufferSize*4 usage: GL_DYNAMIC_DRAW.
] ]

View File

@ -23,6 +23,11 @@ DiyaRootNode >> isRoot [
^ true ^ true
] ]
{ #category : #initialization }
DiyaRootNode >> update [
^true
]
{ #category : #accessing } { #category : #accessing }
DiyaRootNode >> updateTF [ DiyaRootNode >> updateTF [
"donothing" "donothing"

View File

@ -6,7 +6,8 @@ Class {
'fontSize', 'fontSize',
'fontName', 'fontName',
'data', 'data',
'style' 'style',
'wrap'
], ],
#pools : [ #pools : [
'FT2Types' 'FT2Types'
@ -31,7 +32,8 @@ DiyaText >> data [
{ #category : #accessing } { #category : #accessing }
DiyaText >> data: anObject [ DiyaText >> data: anObject [
data := anObject data := anObject.
dirty := true
] ]
{ #category : #accessing } { #category : #accessing }
@ -40,13 +42,13 @@ DiyaText >> draw [
self shader self shader
setUniform: #u_use_texture value:1. setUniform: #u_use_texture value:1.
"configure vao vbo for texture QUAD" "configure vao vbo for texture QUAD"
style := DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
self texture setup. self texture setup.
context texture0 setImage2D: self texture. context texture0 setImage2D: self texture.
context texture0 active. context texture0 active.
context vao enableAttribute: 0. context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil . OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
self drawText. context vbo data: GL_ARRAY_BUFFER data: vbuffer size: nvertices*16 usage: GL_STATIC_DRAW.
OpenGL drawArrays: GL_TRIANGLES first:0 count:nvertices.
context vao disableAttribute: 0. context vao disableAttribute: 0.
"reset value" "reset value"
self texture drop. self texture drop.
@ -54,34 +56,22 @@ DiyaText >> draw [
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> drawSubStringFrom: lower at: offset [ DiyaText >> drawText [
|upper vertices count index tex2D| |vertices index tex2D offset|
upper := lower + ((data size - lower) min:(context buffer size / 24) asInteger). nvertices := 0.
count := 0.
index := 1. index := 1.
offset := 0@0.
tex2D := self texture. tex2D := self texture.
lower to: upper do: [ :i| 1 to: data size do: [ :i|
vertices := self getCharsVertices:(data at:i) asciiValue offset: offset on: tex2D. vertices := self getCharsVertices:(data at:i) asciiValue offset: offset on: tex2D.
vertices do: [ vertices do: [
:e| context buffer at: index put:e. :e| vbuffer at: index put:e.
index := index + 1. index := index + 1.
]. ].
vertices ifNotEmpty: [ count := count + 6 ]. vertices ifNotEmpty: [ nvertices := nvertices + 6 ].
(offset x > extent x and: wrap not) ifTrue: [ ^self ].
(offset y negated > extent y) ifTrue: [ ^self ].
]. ].
context vbo subData: GL_ARRAY_BUFFER offset: 0 data: context buffer.
OpenGL drawArrays: GL_TRIANGLES first:0 count:count.
^ upper + 1
]
{ #category : #accessing }
DiyaText >> drawText [
|lower offset|
offset := 0@0.
lower := 1.
[
lower := self drawSubStringFrom: lower at:offset.
lower < data size.
] whileTrue.
] ]
{ #category : #accessing } { #category : #accessing }
@ -89,9 +79,13 @@ DiyaText >> fontName [
^ fontName ^ fontName
] ]
{ #category : #accessing } { #category : #initialization }
DiyaText >> fontName: anObject [ DiyaText >> fontName: name style: face size: size [
fontName := anObject. name ifNotNil: [ fontName := name ].
face ifNotNil: [ fontStyle := face ].
fontSize := size.
style := DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
dirty := true.
] ]
{ #category : #accessing } { #category : #accessing }
@ -99,9 +93,9 @@ DiyaText >> fontSize [
^ fontSize ^ fontSize
] ]
{ #category : #accessing } { #category : #initialization }
DiyaText >> fontSize: anObject [ DiyaText >> fontSize: size [
fontSize := anObject. self fontName: nil style:nil size: size
] ]
{ #category : #accessing } { #category : #accessing }
@ -109,11 +103,6 @@ DiyaText >> fontStyle [
^ fontStyle ^ fontStyle
] ]
{ #category : #accessing }
DiyaText >> fontStyle: anObject [
fontStyle := anObject.
]
{ #category : #accessing } { #category : #accessing }
DiyaText >> getCharsVertices:c offset: offset on: tex2D [ DiyaText >> getCharsVertices:c offset: offset on: tex2D [
|x y w h glyph gsize| |x y w h glyph gsize|
@ -124,7 +113,10 @@ DiyaText >> getCharsVertices:c offset: offset on: tex2D [
glyph := tex2D getGlyph: c. glyph := tex2D getGlyph: c.
gsize := glyph extent. gsize := glyph extent.
((offset x > self extent x) and: (gsize x > 0)) ifTrue:[ ((offset x > self extent x) and: (gsize x > 0)) ifTrue:[
offset setX: 0.0 setY: (offset y )- (tex2D linespace).]. wrap ifFalse: [ ^ { } ].
offset setX: 0.0 setY: (offset y )- (tex2D linespace).
offset y negated > self extent y ifTrue:[^{}].
].
x := offset x + (glyph bearing x). x := offset x + (glyph bearing x).
y := offset y - (tex2D cellh). y := offset y - (tex2D cellh).
w := (gsize x). w := (gsize x).
@ -141,13 +133,28 @@ DiyaText >> getCharsVertices:c offset: offset on: tex2D [
{ #category : #initialization } { #category : #initialization }
DiyaText >> initialize [ DiyaText >> initialize [
super initialize. super initialize.
self fontName: 'Ubuntu'. self fontName: 'Ubuntu' style:'Regular' size: 16.
self fontStyle: 'Regular'.
self fontSize: 16.
data := nil. data := nil.
wrap := false.
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> texture [ DiyaText >> texture [
^style textureOf: self fontSize ^style textureOf: self fontSize
] ]
{ #category : #initialization }
DiyaText >> update [
extent ifNil: [ ^false ].
vbuffer ifNotNil: [vbuffer free].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 24.
vbuffer autoRelease.
self drawText.
^true
]
{ #category : #initialization }
DiyaText >> wordWrap: aBool [
wrap := aBool.
dirty := true
]