1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-07-16 13:59:54 +02:00

39 Commits

Author SHA1 Message Date
64c0cc9b79 Merge branch 'master' into conflict 2022-03-16 21:36:18 +01:00
16269e40c3 fix conflict 2022-03-16 21:33:35 +01:00
c7b01a0e90 WIP: Add emptly classes for Base widgets 2022-03-16 18:37:51 +01:00
e8b724daa1 Support for basic primitive shapes 2022-03-16 17:48:18 +01:00
89c5e04d36 WIP: draw ellipse and circle 2022-03-16 01:32:01 +01:00
653fe07692 Add log messages 2022-03-15 19:29:57 +01:00
fcc7b13d28 Fix memory leak bug 2022-03-15 19:11:19 +01:00
172a62192e image texture support 2022-03-08 23:30:01 +01:00
9cf12f0d8c Update README.md 2022-03-07 09:35:30 +01:00
94bfc7f6f0 OpenGL: recalculate vertices only when changed.
This allows to greatly improve rendering performance
2022-03-06 19:50:19 +01:00
bd9d406c85 Text rendering is greatly improved 2022-03-06 18:33:10 +01:00
a751a6a6d3 WIP improving text rendering 2022-03-06 12:12:31 +01:00
26f37860e3 WIP imporving text rendering 2022-03-06 12:07:20 +01:00
4bfcf5a09a add GLinit 2022-03-06 01:00:01 +01:00
240add5399 add GLinit 2022-03-06 00:59:14 +01:00
b8897a6351 FreeType face now is cached as bitmap font 2022-03-06 00:58:28 +01:00
7fa21d524b let openGL do the final transformation 2022-03-05 11:55:20 +01:00
8cb2cb543a Text rendering iss working now 2022-03-04 20:28:38 +01:00
ce08ac49e2 WIP: font rendering... 2022-03-03 23:23:43 +01:00
d80f31bd42 WIP: display Freetype font in openGL 2022-03-03 19:19:40 +01:00
6808a3aa0b Add basic graph nodes and support basic transformation 2022-03-02 20:11:01 +01:00
8a59d8cba9 add basic primitive shapes (contd.) 2022-03-01 22:58:58 +01:00
a2af81994c Add freetype font manager 2022-03-01 19:22:26 +01:00
1ebd4a748c correct mouse position inside shader coodinate system 2022-02-15 22:01:26 +01:00
81548622cc avoid uninitialize value 2022-02-15 20:32:33 +01:00
e047a89801 add uniform support to shader 2022-02-15 18:04:54 +01:00
13804205f8 update shader support 2022-02-14 00:02:14 +01:00
94d3a6266b update openGL 1.10 binding 2022-02-13 17:15:23 +01:00
00c350805d add openGLSL bingding 2021-12-20 18:32:08 +01:00
b6fbebc4d4 keep old code as comment for further reference 2021-12-20 01:22:29 +01:00
0d254c6dd4 Basic example of OpenGL binding 2021-12-20 01:14:35 +01:00
4f22db8688 Reset only the unique instance in SDK environment 2021-12-19 22:52:35 +01:00
29e4065fe1 print log using stdout instead of Transcript 2021-12-19 22:41:21 +01:00
1884963e4e refactory logging 2021-12-19 22:17:29 +01:00
ae9c884997 Add cleanup code when quitting 2021-12-19 20:12:36 +01:00
ad045dcc80 Merge 7a17c17ed5 2021-12-19 20:08:49 +01:00
1d9fc2d434 resolve conflict in merge 2021-12-19 20:08:40 +01:00
80b9ee6708 Allow to reset singleton instance in DiyaBoot 2021-12-19 19:49:34 +01:00
cb9cf2f49e Allow to test Diya directly in the Pharo image 2021-12-19 19:45:16 +01:00
71 changed files with 3794 additions and 91 deletions

6
Diya/Array.extension.st Normal file
View File

@ -0,0 +1,6 @@
Extension { #name : #Array }
{ #category : #'*Diya' }
Array >> asPoint [
^ (self at: 1 ifAbsent:[0]) @ (self at: 2 ifAbsent:[0])
]

14
Diya/Array2D.extension.st Normal file
View File

@ -0,0 +1,14 @@
Extension { #name : #Array2D }
{ #category : #'*Diya' }
Array2D >> asGLBuffer [
|buffer i|
i := 1.
buffer := FFIExternalArray externalNewType: #float size: self size.
self asArray do:[:e|
buffer at:i put:e.
i := i+1
].
buffer autoRelease.
^buffer
]

View File

@ -0,0 +1,6 @@
Extension { #name : #ClassDescription }
{ #category : #'*Diya' }
ClassDescription >> classCommentBlank [
^ ''
]

16
Diya/Color.extension.st Normal file
View File

@ -0,0 +1,16 @@
Extension { #name : #Color }
{ #category : #'*Diya' }
Color >> as4bytesRGB [
^{
(self red* 255) asInteger.
(self green * 255) asInteger.
(self blue*255) asInteger.
(self alpha* 255) asInteger
}
]
{ #category : #'*Diya' }
Color >> asGL4FArray [
^{self red. self green. self blue. self alpha }
]

101
Diya/Diya2DNode.class.st Normal file
View File

@ -0,0 +1,101 @@
Class {
#name : #Diya2DNode,
#superclass : #DiyaNode,
#instVars : [
'color',
'vbuffer',
'bbox'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DNode >> boundingBox [
^ bbox
]
{ #category : #accessing }
Diya2DNode >> color [
^ color
]
{ #category : #accessing }
Diya2DNode >> color: anObject [
color := anObject
]
{ #category : #accessing }
Diya2DNode >> extent [
^ bbox extent
]
{ #category : #accessing }
Diya2DNode >> height [
^ self extent y
]
{ #category : #initialization }
Diya2DNode >> initialize [
super initialize.
translation := 0@0.
scale := 1.0@1.0.
rotation := 0.0.
tf := Array2D identity: 3.
shader := Diya2DShader uniqueInstance.
color := Color white.
vbuffer := nil.
]
{ #category : #'as yet unclassified' }
Diya2DNode >> recFromBuffer [
|maxX maxY minX minY x y|
maxX := minX := vbuffer at: 1.
maxY := minY := vbuffer at: 2.
1 to: vbuffer size by: 4 do: [ :i|
x := vbuffer at: i.
y := vbuffer at: i + 1.
maxX := maxX max: x.
maxY := maxY max: y.
minX := minX min: x.
minY := minY min: y.
].
^ Rectangle origin: minX@minY corner: maxX @ maxY
]
{ #category : #initialization }
Diya2DNode >> setUpShader [
super setUpShader.
shader setUniform: #u_color value: self color asGL4FArray.
]
{ #category : #accessing }
Diya2DNode >> updateTF [
tf := Array2D identity:3.
"translation"
tf := tf +* (Array2D rows: 3 columns: 3 contents: {
1.0. 0.0. translation x.
0.0. 1.0. translation y.
0.0. 0.0. 1.0
}).
"rotation"
tf := tf +* (Array2D rows: 3 columns: 3 contents:{
rotation cos. (rotation sin) negated. 0.0.
rotation sin. rotation cos. 0.0.
0.0. 0.0. 1.0
}).
"scale"
tf := tf +* (Array2D rows: 3 columns: 3 contents:{
scale x. 0.0. 0.0.
0.0. scale y. 0.0.
0.0. 0.0. 1.0
}).
self parent isRoot ifFalse: [ tf := self parent tf +* tf ].
children ifNotNil: [
children do:[:c| c updateTF ]].
]
{ #category : #accessing }
Diya2DNode >> width [
^ self extent x
]

View File

@ -0,0 +1,92 @@
Class {
#name : #Diya2DPrimShape,
#superclass : #Diya2DNode,
#instVars : [
'texture',
'type',
'border',
'bcolor'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DPrimShape >> borderColor: c [
bcolor := c
]
{ #category : #accessing }
Diya2DPrimShape >> borderWidth: w [
border := w
]
{ #category : #initialization }
Diya2DPrimShape >> draw [
vbuffer ifNil: [ ^self ].
"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: type first:0 count:((vbuffer size )>> 2 ).
"reset value"
self texture ifNotNil: [self texture drop.].
border > 0 ifTrue: [ self drawBorder ].
context vao disableAttribute: 0.
]
{ #category : #initialization }
Diya2DPrimShape >> drawBorder [
"Diya2DShader uniqueInstance use."
color = bcolor ifFalse:[
shader setUniform: #u_color value: bcolor asGL4FArray;
setUniform: #u_texture_type value: 0.
].
OpenGL
lineWidth: border.
self drawLines.
OpenGL lineWidth: 1.0.
]
{ #category : #initialization }
Diya2DPrimShape >> drawLineAt: offset [
OpenGL drawArrays: GL_LINES first:(offset) count:2.
]
{ #category : #initialization }
Diya2DPrimShape >> drawLines [
self subclassResponsibility
]
{ #category : #initialization }
Diya2DPrimShape >> initialize [
super initialize.
texture := nil.
children := nil.
type := GL_TRIANGLES.
border := 0.
bcolor := Color white.
]
{ #category : #initialization }
Diya2DPrimShape >> setUpShader [
super setUpShader
texture ifNotNil:[
self shader
setUniform: #u_texture_type value: texture format.
].
]
{ #category : #accessing }
Diya2DPrimShape >> texture [
^ texture
]
{ #category : #accessing }
Diya2DPrimShape >> texture: anObject [
texture := anObject
]

View File

@ -0,0 +1,60 @@
Class {
#name : #Diya2DShader,
#superclass : #OpenGLSL,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
Diya2DShader class >> fragmentShader [
^'
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// 2D uniforms
uniform int u_texture_type;
uniform vec4 u_color;
uniform sampler2D u_texture;
varying vec2 texcoord;
void main(void) {
vec4 texcolor = vec4(1,1,1,1);
// alpha
if(u_texture_type == 0x1906) {
texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a);
}
// rgba
else if (u_texture_type == 0x1908){
texcolor = texture2D(u_texture, texcoord);
}
gl_FragColor = texcolor * u_color;
}'
]
{ #category : #accessing }
Diya2DShader class >> vertexShader [
^'
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 u_projection;
uniform mat3 u_transform;
varying vec2 texcoord;
void main()
{
vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0);
gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0);
texcoord = gl_Vertex.zw;
}'
]
{ #category : #initialization }
Diya2DShader >> setUpUniforms [
self addUniform: #u_texture of: Uniform1i.
self addUniform: #u_texture_type of: Uniform1i.
self addUniform: #u_color of: Uniform4F.
self addUniform: #u_border_color of: Uniform4F.
self addUniform: #u_border of: Uniform1F.
]

View File

@ -3,3 +3,38 @@ Class {
#superclass : #Object,
#category : #'Diya-Core'
}
{ #category : #accessing }
DiyaBaseObject >> checkGLError: mark [
|err|
err := OpenGL getError.
err = 0 ifFalse:[
self stderror:mark, ': return error code ', err hex.
].
]
{ #category : #accessing }
DiyaBaseObject >> logError: string [
self stderr nextPutAll: string; cr
]
{ #category : #accessing }
DiyaBaseObject >> stderr [
^VTermOutputDriver stderr
]
{ #category : #accessing }
DiyaBaseObject >> stderror: string [
self stderr nextPutAll: string; nextPutAll: Character cr asString.
]
{ #category : #accessing }
DiyaBaseObject >> stdlog: string [
self stdout nextPutAll: string;
nextPutAll: Character cr asString.
]
{ #category : #accessing }
DiyaBaseObject >> stdout [
^ VTermOutputDriver stdout
]

View File

@ -1,16 +1,16 @@
Class {
#name : #DiyaBoot,
#superclass : #DiyaBaseObject,
#superclass : #DiyaSingleton,
#instVars : [
'running',
'window',
'renderer',
'display'
],
#classVars : [
'singleton'
'context',
'display',
'clock'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes',
'SDL2Constants',
'SDL2Types'
],
@ -18,8 +18,8 @@ Class {
}
{ #category : #'instance creation' }
DiyaBoot class >> reset [
singleton := nil
DiyaBoot class >> maxFPS [
^60
]
{ #category : #'instance creation' }
@ -32,97 +32,127 @@ DiyaBoot class >> startx [
self uniqueInstance run
]
{ #category : #'instance creation' }
DiyaBoot class >> uniqueInstance [
singleton ifNil: [ singleton := self new ].
^ singleton
{ #category : #events }
DiyaBoot >> GLinit. [
OpenGL viewportX: 0 Y:0 W: display w H: display h.
OpenGL enable: GL_TEXTURE_2D.
]
{ #category : #events }
DiyaBoot >> checkDrivers [
|ndriver usableDrivers|
ndriver := SDL2 SDLGetNumVideoDrivers.
usableDrivers := OrderedCollection new.
Transcript show: 'Available drivers: '.
0 to: ndriver - 1 do: [ :i | |dname|
dname := SDL2 SDLGetVideoDriver: i.
Transcript show: dname, ' '.
(SDL2 SDLVideoInit: dname) = 0 ifTrue:[
usableDrivers add: dname.
SDL2 SDLVideoQuit
]
].
Transcript cr.
]
{ #category : #events }
DiyaBoot >> createRenderer [
|numdriver rinfo|
numdriver := SDL2 SDLGetNumRenderDrivers.
Transcript show: 'SDL_RENDER_DRIVER available:'.
rinfo := SDL_RendererInfo externalNew autoRelease.
0 to: numdriver - 1 do:[:i|
SDL2 SDLGetRendererDriverInfo: rinfo from: i.
Transcript show: rinfo name readString, ' '.
].
Transcript cr.
renderer := window primCreateRenderer: -1 flags: SDL_RENDERER_ACCELERATED.
renderer ifNil: [ ^self error: SDL2 getErrorMessage ].
renderer primGetRendererInfo: rinfo.
Transcript show: 'SDL_RENDER_DRIVER selected: ', rinfo name readString;cr.
^renderer
DiyaBoot >> createGLContext [
context := SDL2 glCreateContext: window.
context ifNil: [ ^self error: SDL2 getErrorMessage ].
^context
]
{ #category : #events }
DiyaBoot >> createWindow [
|handle|
handle := SDL2 createWindow: 'Diya test'
SDL2
glSetAttribute: SDL_GL_MULTISAMPLEBUFFERS value: 1;
glSetAttribute: SDL_GL_MULTISAMPLESAMPLES value: 2.
OpenGL enable: GL_MULTISAMPLE.
window := SDL2 createWindow: 'Diya'
x: 0
y: 0
width: display w
height: display h
flags: SDL_WINDOW_SHOWN.
handle ifNil: [ ^self error: SDL2 getErrorMessage ].
flags: SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL.
window ifNil: [ ^self error: SDL2 getErrorMessage ].
"handle fullscreen: SDL_WINDOW_FULLSCREEN."
^handle
"SDL2 glSetAttribute: SDL_GL_CONTEXT_PROFILE_MASK value: SDL_GL_CONTEXT_PROFILE_ES.
SDL2 glSetAttribute: SDL_GL_CONTEXT_MAJOR_VERSION value: 2.
SDL2 glSetAttribute: SDL_GL_CONTEXT_MINOR_VERSION value: 0.
SDL2 glSetAttribute: SDL_GL_ACCELERATED_VISUAL value: 1."
"SDL2 glSetAttribute: SDL_GL_DOUBLEBUFFER value: 1.
SDL2 glSetAttribute: SDL_GL_DEPTH_SIZE value: 24."
^window
]
{ #category : #events }
DiyaBoot >> exampleNodes [
|root node style tex|
root := DiyaRootNode new.
tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
node texture: tex.
node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
node borderColor: Color red.
node borderWidth: 3.0.
style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'.
"style := DiyaFontManager uniqueInstance style: 'Regular' from: 'bootstrap-icons'."
node := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50.
node color: (Color orange).
node texture: (style textureOf: 48).
node borderColor: Color red.
node borderWidth: 3.0.
node := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
node rotation: (Float pi / -8.0).
node scale: 1.5@1.5.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@340.
node extent: 250@320.
node wordWrap: true.
node := root addNode: (DiyaLine from: 10@620 to: 200@635).
node color: (Color red).
node borderWidth: 2.0.
node := root addNode: (DiyaCircle r: 100) at: 200@200.
node borderColor: Color red.
node color: Color white.
node borderWidth: 3.0.
node texture: tex.
node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}).
node color: Color green.
node borderColor: Color red.
node texture: tex.
node borderWidth: 3.0.
^ root
]
{ #category : #events }
DiyaBoot >> init [
| status nvdrivers |
Transcript show:'System: ',
(Smalltalk globals at: #CODENAME ifAbsent:['']),
'-v',(Smalltalk globals at: #VERSION ifAbsent: ['']);
cr.
| status |
SDL2 setHint: 'SDL_RENDER_DRIVER' value: 'opengles2'.
status := SDL2 init: SDL_INIT_EVERYTHING.
status = 0
status = 0
ifFalse: [ ^ self error: SDL2 getErrorMessage ].
nvdrivers := SDL2 SDLGetNumVideoDrivers.
Transcript show: 'Supported video dirvers:'.
0 to: nvdrivers -1 do: [ :i |
Transcript show: (SDL2 SDLGetVideoDriver: i), ' '.
].
Transcript cr.
Transcript show: 'Current selected video driver: ',
(SDL2 SDLGetCurrentVideoDriver);
cr.
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
DiyaRendererContext reset.
DiyaFontManager reset.
OpenGLSL resetShaders.
DiyaFontManager uniqueInstance loadFonts.
]
{ #category : #events }
DiyaBoot >> initialize [
running := true
running := true.
display := nil.
window := nil.
context := nil.
clock := DiyaClock uniqueInstance.
]
{ #category : #events }
DiyaBoot >> processEvent: event [
|mappedEvt|
mappedEvt := event mapped.
mappedEvt type = SDL_KEYDOWN ifTrue: [ Transcript show: 'keydown...'. ^running := false. ].
mappedEvt type = SDL_KEYDOWN ifTrue: [ Transcript show: 'keydown...';cr. ^running := false. ].
mappedEvt type = SDL_QUIT ifTrue:[ ^running:= false ].
mappedEvt type = SDL_FINGERDOWN ifTrue:[^self setCursorPosition: mappedEvt ].
mappedEvt type = SDL_FINGERMOTION ifTrue:[^self setCursorPosition: mappedEvt ].
mappedEvt type = SDL_MOUSEMOTION ifTrue:[DiyaRendererContext uniqueInstance mouse: (mappedEvt x) @ (mappedEvt y)].
mappedEvt free.
]
{ #category : #events }
@ -136,55 +166,130 @@ DiyaBoot >> randomColorChannel [
{ #category : #events }
DiyaBoot >> render [
|event|
|event root text delta fps|
event := SDL_Event new.
[ running ] whileTrue: [
[ (SDL2 pollEvent: event) > 0 ] whileTrue: [
root := self exampleNodes.
DiyaRenderer uniqueInstance root: root.
text := root addNode:(DiyaText data: 'tick') at: (display w - 80)@40.
text extent: 80@40.
text fontSize: 18.
text color: Color red.
DiyaRendererContext uniqueInstance.
self GLinit.
[ running ] whileTrue: [
delta := DiyaClock uniqueInstance delta asMilliSeconds.
fps := ((1000/delta) asInteger).
text data: ('FPS:', fps asString).
DiyaClock uniqueInstance tick.
[(SDL2 pollEvent: event) > 0] whileTrue: [
self processEvent: event
].
renderer drawColorR: self randomColorChannel
g: self randomColorChannel
b: self randomColorChannel
a: 255.
renderer clear.
renderer present.
SDL2 delay: 50.
DiyaRenderer uniqueInstance render.
SDL2 glSwapWindow: window.
delta := DiyaClock uniqueInstance delta asMilliSeconds.
SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta).
].
]
{ #category : #events }
DiyaBoot >> run [
self init.
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
self startx
self startx.
]
{ #category : #events }
{ #category : #running }
DiyaBoot >> run: screenSize [
self run: screenSize app: nil
]
{ #category : #running }
DiyaBoot >> run: screenSize app: application [
"
this function should be used only in
SDK environment, in real embeded system
it is always the #run command that is executed
automatically.
"
OpenGLTypes initialize.
OpenGLConstants initialize.
self init.
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
display w: screenSize x.
display h: screenSize y.
self startx
self startx.
self class reset.
DiyaClock reset.
DiyaRendererContext reset.
Smalltalk garbageCollect.
]
{ #category : #events }
DiyaBoot >> setCursorPosition: mappedEvt [
Transcript show: 'x: ', mappedEvt x asString, ' - y: ', mappedEvt y asString; cr.
window warpMouseX:((mappedEvt x)* (display w) )
Y: ((mappedEvt y) * (display h))
]
{ #category : #logging }
DiyaBoot >> showSystemInfo [
|stream numdriver rinfo|
stream := (String new: 255) writeStream.
stream nextPutAll:'System: ';
nextPutAll:(Smalltalk globals at: #CODENAME ifAbsent:['']);
nextPutAll: '-v';
nextPutAll:(Smalltalk globals at: #VERSION ifAbsent: ['']);cr.
numdriver := SDL2 SDLGetNumVideoDrivers.
stream nextPutAll: 'Supported video dirvers:'.
0 to: numdriver -1 do: [ :i |
stream nextPutAll: (SDL2 SDLGetVideoDriver: i); nextPutAll: ' '.
].
stream cr.
stream nextPutAll: 'Current selected video driver: ';
nextPutAll:(SDL2 SDLGetCurrentVideoDriver);cr.
numdriver := SDL2 SDLGetNumRenderDrivers.
stream nextPutAll: 'SDL_RENDER_DRIVER available:'.
rinfo := SDL_RendererInfo externalNew autoRelease.
0 to: numdriver - 1 do:[:i|
SDL2 SDLGetRendererDriverInfo: rinfo from: i.
stream nextPutAll: rinfo name readString; nextPutAll:' '.
].
stream cr.
stream nextPutAll:'Display resolution: ';
nextPutAll:display w asString;
nextPutAll: 'x';
nextPutAll: display h asString; cr.
self stdout nextPutAll: stream contents
]
{ #category : #events }
DiyaBoot >> startx [
Transcript show:'Display resolution: ', display w asString, 'x',display h asString;cr.
window := self createWindow.
renderer := self createRenderer.
display ifNil: [ ^self error: 'Please run #init before this method' ].
self createWindow.
self createGLContext.
"SDL2 glMakeCurrent: window context: context."
self showSystemInfo.
DiyaRendererContext
uniqueInstance display: display;
useProjection: OrthoProjectionMatrix.
self render.
renderer destroy.
context delete.
window destroy.
DiyaFontManager reset.
DiyaRendererContext reset.
SDL2 quit.
Transcript show: 'System quit'; cr.
]
{ #category : #events }
DiyaBoot >> step [
"renderer drawColorR: 0
g: 0
b: 0
a: 255."
OpenGL begin: GL_TRIANGLES.
"draw a simple triangle here"
OpenGL color3fR: 0.1 G:0.2 B: 0.3.
OpenGL vertex3fX: 0 Y: 0 Z: 0.
OpenGL vertex3fX: 1 Y: 0 Z: 0.
OpenGL vertex3fX: 0 Y: 1 Z: 0.
OpenGL end.
]

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaButton,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,15 @@
Class {
#name : #DiyaCircle,
#superclass : #DiyaEllipse,
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaCircle class >> r: r [
^self rx: r ry:r
]
{ #category : #'as yet unclassified' }
DiyaCircle class >> r: r shader:s [
^self rx: r ry:r shader:s
]

30
Diya/DiyaClock.class.st Normal file
View File

@ -0,0 +1,30 @@
Class {
#name : #DiyaClock,
#superclass : #DiyaSingleton,
#instVars : [
'monotonic',
'lastTick'
],
#category : #'Diya-Runtime'
}
{ #category : #initialization }
DiyaClock >> delta [
^(DateAndTime now) - lastTick
]
{ #category : #initialization }
DiyaClock >> elapsedTime [
^(DateAndTime now) - monotonic
]
{ #category : #initialization }
DiyaClock >> initialize [
monotonic := DateAndTime now.
lastTick := monotonic.
]
{ #category : #initialization }
DiyaClock >> tick [
lastTick := DateAndTime now.
]

View File

@ -0,0 +1,48 @@
Class {
#name : #DiyaConvexPolygon,
#superclass : #DiyaPolygon,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaConvexPolygon >> calculateVertices [
|size index p texcoord|
size := (points size + 1) << 2.
vbuffer ifNotNil: [ vbuffer free ].
vbuffer := FFIExternalArray externalNewType: GLfloat size:size.
vbuffer autoRelease.
points sort:[:a :b| a angle < b angle].
index := 1.
points do:[:point|
texcoord := self texcoordOf: point.
vbuffer
at: index put: point x;
at: index + 1 put: point y;
at: index + 2 put: texcoord x;
at: index + 3 put: 1.0 - texcoord y.
index := index + 4.
].
p := points at: 2.
texcoord := self texcoordOf: p.
vbuffer
at: index put: p x;
at: index + 1 put: p y;
at: index + 2 put: texcoord x;
at: index + 3 put: 1.0 - texcoord y.
]
{ #category : #initialization }
DiyaConvexPolygon >> drawLines [
OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2) - 1.
]
{ #category : #initialization }
DiyaConvexPolygon >> initialize [
super initialize.
type := GL_TRIANGLE_FAN
]
{ #category : #accessing }
DiyaConvexPolygon >> texcoordOf: point [
^ (point / (self extent )) asFloatPoint
]

95
Diya/DiyaEllipse.class.st Normal file
View File

@ -0,0 +1,95 @@
Class {
#name : #DiyaEllipse,
#superclass : #Diya2DPrimShape,
#instVars : [
'rx',
'ry'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaEllipse class >> rx: rx ry: ry [
^self new rx: rx;
ry: ry;
yourself
]
{ #category : #'as yet unclassified' }
DiyaEllipse class >> rx: rx ry: ry shader: s [
^self new rx: rx;
ry: ry;
shader: s;
yourself
]
{ #category : #initialization }
DiyaEllipse >> draw [
OpenGL
enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
super draw.
OpenGL
disable: GL_BLEND
]
{ #category : #initialization }
DiyaEllipse >> drawBorder [
"do nothing"
]
{ #category : #initialization }
DiyaEllipse >> initialize [
super initialize.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size: 24.
vbuffer autoRelease.
shader := DiyaEllipseShader uniqueInstance.
]
{ #category : #accessing }
DiyaEllipse >> rx [
^ rx
]
{ #category : #accessing }
DiyaEllipse >> rx: anObject [
rx := anObject.
dirty := true.
]
{ #category : #accessing }
DiyaEllipse >> ry [
^ ry
]
{ #category : #accessing }
DiyaEllipse >> ry: anObject [
ry := anObject.
dirty := true
]
{ #category : #initialization }
DiyaEllipse >> setUpShader [
super setUpShader.
self shader
setUniform: #u_border value: border;
setUniform: #u_border_color value: bcolor asGL4FArray;
setUniform: #u_rx value: rx;
setUniform: #u_ry value: ry.
]
{ #category : #accessing }
DiyaEllipse >> update [
bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry).
{
bbox origin x. bbox corner y. 0.0. 0.0.
bbox origin x. bbox origin y. 0.0. 1.0.
bbox corner x. bbox origin y. 1.0. 1.0.
bbox corner x. bbox origin y. 1.0. 1.0.
bbox corner x. bbox corner y. 1.0. 0.0.
bbox origin x. bbox corner y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -0,0 +1,146 @@
Class {
#name : #DiyaEllipseShader,
#superclass : #Diya2DShader,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
DiyaEllipseShader class >> fragmentShader [
^'
#ifdef GL_ES
precision highp float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
// 2D uniforms
uniform int u_texture_type;
uniform vec4 u_color;
uniform vec4 u_border_color;
uniform sampler2D u_texture;
uniform float u_border;
uniform float u_rx;
uniform float u_ry;
varying float rotation;
varying vec2 middle;
varying vec2 texcoord;
struct Ellipse
{
vec2 c;
float minor;
float major;
float f;
};
float get_foci(float major, float minor)
{
return sqrt((major*major)-(minor*minor));
}
Ellipse create_ellipse(vec2 c, float mi, float ma)
{
Ellipse e;
e.c = c;
e.major = max(mi,ma);
e.minor = min(mi,ma);
e.f = get_foci(e.major, e.minor);
return e;
}
bool is_inside_ellipse(vec2 p, Ellipse e)
{
float first = ((p.x-e.c.x)*(p.x-e.c.x)) / (e.major*e.major);
float second = ((p.y-e.c.y)*(p.y-e.c.y)) / (e.minor*e.minor);
return first+second <= 1.0;
}
bool is_inside_border(vec2 p, Ellipse e, float w)
{
float first = ((p.x-e.c.x)*(p.x-e.c.x)) / ((e.major-w)*(e.major-w));
float second = ((p.y-e.c.y)*(p.y-e.c.y)) / ((e.minor-w)*(e.minor-w));
float sum = first + second;
return sum<= 1.0;
}
void draw_ellipse(inout vec4 c, vec2 p, Ellipse e, float border)
{
c = vec4(0);
if (is_inside_border(p,e, border))
{
vec4 texcolor = vec4(1);
// vec2 uv = (p - (e.c - vec2(e.major , e.minor))) / vec2(e.major*2.0, e.minor*2.0);
// alpha
if(u_texture_type == 0x1906) {
texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a);
}
// rgba
else if (u_texture_type == 0x1908){
texcolor = texture2D(u_texture, texcoord);
}
c = texcolor * u_color;
}
else
{
if (is_inside_ellipse(p, e))
{
c = u_border_color;
}
}
}
vec2 rotate_point(vec2 center, vec2 p,float angle)
{
float s = sin(angle);
float c = cos(angle);
// translate point back to origin:
p.x -= center.x;
p.y -= center.y;
// rotate point
float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
// translate point back:
p.x = xnew + center.x;
p.y = ynew + center.y;
return p;
}
void main() {
vec4 color = vec4(0);
//defining ellipse
Ellipse e = create_ellipse(middle, u_ry, u_rx);
draw_ellipse(color, rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border);
// Output to screen
gl_FragColor = color;
}
'
]
{ #category : #accessing }
DiyaEllipseShader class >> vertexShader [
^'
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 u_projection;
uniform mat3 u_transform;
varying float rotation;
varying vec2 middle;
varying vec2 texcoord;
void main()
{
vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0);
gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0);
rotation = atan(u_transform[1][0], u_transform[0][0]);
middle = (u_transform * vec3(0.0,0.0,1.0)).xy;
texcoord = gl_Vertex.zw;
}'
]
{ #category : #initialization }
DiyaEllipseShader >> setUpUniforms [
super setUpUniforms.
self addUniform: #u_rx of: Uniform1F.
self addUniform: #u_ry of: Uniform1F.
]

View File

@ -0,0 +1,23 @@
Class {
#name : #DiyaExampleShader,
#superclass : #Diya2DShader,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
DiyaExampleShader class >> fragmentShader [
^ '
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
void main()
{
vec2 mouse = u_mouse / u_resolution;
vec2 px = (gl_FragCoord.xy/u_resolution);
gl_FragColor = vec4(abs(sin(u_time)), px/mouse, 1.0);
}
'
]

View File

@ -9,6 +9,11 @@ DiyaFFIBase class >> checkSymbol [
^self subclassResponsibility
]
{ #category : #accessing }
DiyaFFIBase class >> ffiLibraryName [
^ self moduleName
]
{ #category : #accessing }
DiyaFFIBase class >> libNames [
^self subclassResponsibility
@ -23,3 +28,8 @@ DiyaFFIBase class >> moduleName [
].
self error: 'Unable to find FFI library (', self checkSymbol, ')'.
]
{ #category : #'library path' }
DiyaFFIBase >> ffiLibraryName [
^self class ffiLibraryName
]

View File

@ -0,0 +1,52 @@
Class {
#name : #DiyaFontFamily,
#superclass : #DiyaBaseObject,
#instVars : [
'styles',
'name'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
DiyaFontFamily class >> fromFace: face [
^self new addFace: face; yourself.
]
{ #category : #accessing }
DiyaFontFamily >> addFace: face [
name ifNil: [ name := face familyName ].
styles at: face styleName ifAbsentPut: [(DiyaFontStyle fromFace: face)].
]
{ #category : #initialization }
DiyaFontFamily >> initialize [
super initialize.
styles := Dictionary new.
name := nil
]
{ #category : #accessing }
DiyaFontFamily >> name [
^ name
]
{ #category : #accessing }
DiyaFontFamily >> name: anObject [
name := anObject
]
{ #category : #accessing }
DiyaFontFamily >> style: styleName [
^styles at: styleName ifAbsent: [^styles at: 'Regular']
]
{ #category : #accessing }
DiyaFontFamily >> styleNames [
^styles keys
]
{ #category : #accessing }
DiyaFontFamily >> styles [
^ styles
]

View File

@ -0,0 +1,44 @@
Class {
#name : #DiyaFontGlyph,
#superclass : #Rectangle,
#instVars : [
'advance',
'bearing',
'texcoord'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Fonts'
}
{ #category : #accessing }
DiyaFontGlyph >> advance [
^ advance
]
{ #category : #accessing }
DiyaFontGlyph >> advance: anObject [
advance := anObject
]
{ #category : #accessing }
DiyaFontGlyph >> bearing [
^ bearing
]
{ #category : #accessing }
DiyaFontGlyph >> bearing: anObject [
bearing := anObject
]
{ #category : #accessing }
DiyaFontGlyph >> texcoord [
^ texcoord
]
{ #category : #accessing }
DiyaFontGlyph >> texcoord: anObject [
texcoord := anObject
]

View File

@ -0,0 +1,103 @@
Class {
#name : #DiyaFontManager,
#superclass : #DiyaSingleton,
#instVars : [
'families'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
DiyaFontManager class >> cleanUpInstance: singleton [
singleton ifNil:[^self].
singleton reset.
]
{ #category : #'as yet unclassified' }
DiyaFontManager class >> searchPaths [
^ {
Smalltalk imageDirectory / 'fonts'
}
]
{ #category : #initialization }
DiyaFontManager >> defaultFamily [
^self error: 'No font found'
]
{ #category : #accessing }
DiyaFontManager >> families [
^ families
]
{ #category : #accessing }
DiyaFontManager >> familyNames [
^ families keys
]
{ #category : #initialization }
DiyaFontManager >> initialize [
super initialize.
families := Dictionary new.
]
{ #category : #initialization }
DiyaFontManager >> loadFace: face [
|family|
family := families at: face familyName ifAbsentPut:[DiyaFontFamily fromFace: face].
family addFace: face
]
{ #category : #initialization }
DiyaFontManager >> loadFile: aFile [
| path face i numfaces |
path := aFile fullName convertToWithConverter: UTF8TextConverter new.
Transcript show: 'Loading font file ', path;cr.
i := 0.
numfaces := nil.
[ face := FreeTypeFace basicNew
filename: path;
index: i.
face newFaceFromFile: path index: i.
face loadFields.
Transcript show: 'Loaded font face ', face styleName;cr.
numfaces ifNil: [ numfaces := face numFaces ].
self loadFace: face.
i := i + 1.
i < numfaces ] whileTrue: [ ]
]
{ #category : #initialization }
DiyaFontManager >> loadFonts [
self loadFonts: false.
]
{ #category : #initialization }
DiyaFontManager >> loadFonts: force [
force ifTrue:[self reset].
self class searchPaths do:[:path| self loadPath: path].
]
{ #category : #initialization }
DiyaFontManager >> loadPath: path [
path entries do:[:entry| entry isFile ifTrue:[self loadFile: entry ]].
]
{ #category : #initialization }
DiyaFontManager >> reset [
"reset all stored faces"
families := Dictionary new.
]
{ #category : #initialization }
DiyaFontManager >> style: styleName from: familyName [
|family|
family := families at: familyName ifAbsent: [ self defaultFamily ].
^family style: styleName
]

View File

@ -0,0 +1,56 @@
Class {
#name : #DiyaFontStyle,
#superclass : #DiyaBaseObject,
#instVars : [
'texmap',
'face',
'name'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
DiyaFontStyle class >> fromFace: aFace [
^self new face: aFace; yourself
]
{ #category : #accessing }
DiyaFontStyle >> face [
^ face
]
{ #category : #accessing }
DiyaFontStyle >> face: anObject [
face := anObject
]
{ #category : #initialization }
DiyaFontStyle >> initialize [
super initialize.
texmap := Dictionary new.
]
{ #category : #accessing }
DiyaFontStyle >> name [
^ name
]
{ #category : #accessing }
DiyaFontStyle >> name: anObject [
name := anObject
]
{ #category : #accessing }
DiyaFontStyle >> texmap [
^ texmap
]
{ #category : #initialization }
DiyaFontStyle >> textureOf: size [
|tex|
tex := texmap at: size ifAbsentPut: [
""
OpenGLFontTex fromFace: face ofSize: size
].
^tex
]

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaHbox,
#superclass : #DiyaLayout,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaIcon,
#superclass : #DiyaImageView,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,75 @@
Class {
#name : #DiyaImageTex,
#superclass : #OpenGLTexImage2D,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaImageTex class >> fromFile: path [
^ self new fromFile: path; yourself
]
{ #category : #accessing }
DiyaImageTex >> drop [
OpenGL
disable: GL_CULL_FACE;
disable: GL_BLEND.
]
{ #category : #'instance creation' }
DiyaImageTex >> fromFile: path [
|form color index|
Transcript show: 'Loading texture from ', path fullName;cr.
form := ImageReadWriter formFromFileNamed: path.
data := FFIExternalArray externalNewType: GLubyte size:(form width) * (form height) * 4.
LibC memset: data getHandle value: 0 size: data size.
data autoRelease.
width := form width.
height := form height.
index := 1.
0 to: height -1 do:[:y|
0 to: width - 1 do:[:x|
color := (form colorAt: x@y) as4bytesRGB.
data
at: index put: color first;
at: index + 1 put: (color at: 2);
at: index +2 put: (color at: 3);
at: index + 3 put: color last.
index := index + 4.
]
].
]
{ #category : #'instance creation' }
DiyaImageTex >> initialize [
super initialize.
level := 0.
border := 0.
format := GL_RGBA.
internalFormat := GL_RGBA.
type := GL_UNSIGNED_BYTE.
target := GL_TEXTURE_2D.
]
{ #category : #accessing }
DiyaImageTex >> mipmap [
^false
]
{ #category : #accessing }
DiyaImageTex >> setup [
OpenGL
enable: GL_CULL_FACE;
enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
OpenGLTexture
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_S param: GL_CLAMP_TO_EDGE;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_T param: GL_CLAMP_TO_EDGE;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MIN_FILTER param: GL_LINEAR;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MAG_FILTER param: GL_LINEAR.
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaImageView,
#superclass : #DiyaRectangle,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaLabel,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaLayout,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,105 @@
Class {
#name : #DiyaLine,
#superclass : #Diya2DPrimShape,
#instVars : [
'from',
'to'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaLine class >> from: p1 to: p2 [
^ self new
from: p1;
to: p2;
yourself
]
{ #category : #'instance creation' }
DiyaLine class >> from: p1 to: p2 shader:s [
^ self new
from: p1;
to: p2;
shader: s;
yourself
]
{ #category : #'instance creation' }
DiyaLine class >> points: points [
^ self new
points: points;
yourself
]
{ #category : #accessing }
DiyaLine >> borderColor: c [
color := c
]
{ #category : #initialization }
DiyaLine >> draw [
OpenGL
"enable: GL_LINE_SMOOTH;
hint: GL_LINE_SMOOTH_HINT mode: GL_NICEST;"
lineWidth: border.
super draw.
OpenGL lineWidth: 1.0";
disable: GL_LINE_SMOOTH".
]
{ #category : #initialization }
DiyaLine >> drawBorder [
"do nothing"
]
{ #category : #accessing }
DiyaLine >> from [
^ from
]
{ #category : #accessing }
DiyaLine >> from: anObject [
from := anObject.
dirty := true.
]
{ #category : #initialization }
DiyaLine >> initialize [
super initialize.
translation := nil.
self from: 0@0.
self to: 10@10.
vbuffer := FFIExternalArray externalNewType: GLfloat size:8.
vbuffer autoRelease.
type := GL_LINES.
border := 1.0
]
{ #category : #accessing }
DiyaLine >> to [
^ to
]
{ #category : #accessing }
DiyaLine >> to: anObject [
to := anObject.
dirty := true.
]
{ #category : #accessing }
DiyaLine >> update [
|extent|
bbox := (Rectangle origin: from corner: to ).
bbox origin = translation ifFalse:[self position: bbox origin].
from := from - bbox origin.
to := to - bbox origin.
extent := bbox extent.
bbox := (Rectangle origin: 0@0 corner: extent ).
{
0.0. 0.0. 0.0. 0.0.
extent x. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaListView,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

174
Diya/DiyaNode.class.st Normal file
View File

@ -0,0 +1,174 @@
Class {
#name : #DiyaNode,
#superclass : #DiyaBaseObject,
#instVars : [
'translation',
'parent',
'children',
'scale',
'rotation',
'tf',
'shader',
'context',
'dirty'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaNode class >> with: shader [
^self new shader: shader; yourself
]
{ #category : #accessing }
DiyaNode >> addNode: node [
^self addNode: node at: 0@0
]
{ #category : #accessing }
DiyaNode >> addNode: node at: pos [
children ifNil: [ ^self ].
node parent: self.
node position: pos.
children add: node.
^ node
]
{ #category : #accessing }
DiyaNode >> boundingBox [
^ self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> children [
^children
]
{ #category : #accessing }
DiyaNode >> draw [
self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> extent [
^ self subclassResponsibility
]
{ #category : #initialization }
DiyaNode >> initialize [
super initialize.
parent := nil.
shader := nil.
context := DiyaRendererContext uniqueInstance.
children := OrderedCollection new.
dirty := false
]
{ #category : #testing }
DiyaNode >> isRoot [
^false
]
{ #category : #accessing }
DiyaNode >> parent [
^ parent
]
{ #category : #accessing }
DiyaNode >> parent: anObject [
parent := anObject
]
{ #category : #accessing }
DiyaNode >> position [
^ translation
]
{ #category : #accessing }
DiyaNode >> position: anObject [
translation := anObject.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> render [
dirty ifTrue:[dirty := self update not].
shader ifNotNil: [ self setUpShader ].
self draw.
children ifNil: [ ^self ].
children do: [:c | c render ].
]
{ #category : #accessing }
DiyaNode >> rotation [
^ rotation
]
{ #category : #accessing }
DiyaNode >> rotation: anObject [
rotation := anObject.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> scale [
^ scale
]
{ #category : #accessing }
DiyaNode >> scale: anObject [
scale := anObject.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> setUpShader [
|mem|
mem := self tf asGLBuffer.
shader use;
setUniform: #u_time value: DiyaClock uniqueInstance elapsedTime asFloat;
setUniform: #u_projection value: {GL_FALSE. context projection buffer};
setUniform: #u_resolution value: { context resolution x. context resolution y };
setUniform: #u_texture value: 0;
setUniform: #u_transform value: {GL_TRUE. mem}.
context mouse ifNotNil: [
"in shader, window origin is bottom left conor of the window
the mouse position should be transformed to this coodinate"
shader setUniform: #u_mouse value:
{ context mouse x. context resolution y - context mouse y }.
].
mem free.
]
{ #category : #accessing }
DiyaNode >> shader [
shader ifNil: [
parent ifNil: [ ^nil ].
^parent shader ].
^ shader
]
{ #category : #accessing }
DiyaNode >> shader: anObject [
shader := anObject
]
{ #category : #accessing }
DiyaNode >> tf [
parent ifNil: [ self error: 'TF: This node is not attached to the main tree' ].
^ tf
]
{ #category : #accessing }
DiyaNode >> update [
^self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> updateTF [
self subclassResponsibility
]

67
Diya/DiyaPolygon.class.st Normal file
View File

@ -0,0 +1,67 @@
Class {
#name : #DiyaPolygon,
#superclass : #Diya2DPrimShape,
#instVars : [
'points'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaPolygon class >> points: points [
^self new points: points; yourself
]
{ #category : #'as yet unclassified' }
DiyaPolygon class >> points: points shader:s [
^self new points: points; shader:s; yourself
]
{ #category : #accessing }
DiyaPolygon >> calculateVertices [
^self subclassResponsibility
]
{ #category : #initialization }
DiyaPolygon >> initialize [
super initialize.
points := {}.
vbuffer := nil.
]
{ #category : #accessing }
DiyaPolygon >> points [
^ points
]
{ #category : #accessing }
DiyaPolygon >> points: anObject [
points := anObject.
dirty := true
]
{ #category : #accessing }
DiyaPolygon >> recFromPoints [
|maxX maxY minX minY x y|
maxX := minX := (points at: 1) x.
maxY := minY := (points at: 1) y.
points do: [ :p|
x := p x.
y := p y.
maxX := maxX max: x.
maxY := maxY max: y.
minX := minX min: x.
minY := minY min: y.
].
^ Rectangle origin: minX@minY corner: maxX @ maxY
]
{ #category : #accessing }
DiyaPolygon >> update [
bbox := self recFromPoints.
translation = bbox origin ifFalse:[ self position: bbox origin].
points := points collect:[:e | e - bbox origin].
bbox := self recFromPoints.
self calculateVertices.
^true
]

View File

@ -0,0 +1,55 @@
Class {
#name : #DiyaRectangle,
#superclass : #Diya2DPrimShape,
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaRectangle class >> size: size [
^(self new) extent: size; yourself
]
{ #category : #'instance creation' }
DiyaRectangle class >> size: size shader:s [
^(self with:s) extent: size; yourself
]
{ #category : #initialization }
DiyaRectangle >> drawLines [
self drawLineAt: 0.
self drawLineAt: 1.
self drawLineAt: 3.
self drawLineAt: 4.
]
{ #category : #accessing }
DiyaRectangle >> extent: v [
bbox := Rectangle origin:0@0 corner: v.
dirty := true
]
{ #category : #accessing }
DiyaRectangle >> initialize [
super initialize.
self extent:10@10.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
vbuffer autoRelease.
]
{ #category : #accessing }
DiyaRectangle >> update [
|extent|
extent := self extent.
{
0.0. extent y. 0.0. 0.0.
0. 0. 0.0. 1.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.
0.0. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -0,0 +1,37 @@
Class {
#name : #DiyaRenderer,
#superclass : #DiyaSingleton,
#instVars : [
'root'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaRenderer class >> fromContext: ctx [
^self new context: ctx; yourself
]
{ #category : #initialization }
DiyaRenderer >> initialize [
super initialize.
]
{ #category : #deleting }
DiyaRenderer >> render [
root render.
]
{ #category : #accessing }
DiyaRenderer >> root [
^ root
]
{ #category : #accessing }
DiyaRenderer >> root: anObject [
root := anObject
]

View File

@ -0,0 +1,96 @@
Class {
#name : #DiyaRendererContext,
#superclass : #DiyaSingleton,
#instVars : [
'mouse',
'display',
'vbo',
'vao',
'texture0',
'projection'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaRendererContext class >> cleanUpInstance: singleton [
singleton ifNil:[^self].
singleton destroy
]
{ #category : #'instance creation' }
DiyaRendererContext class >> maxFloatBufferSize [
^4096
]
{ #category : #accessing }
DiyaRendererContext >> destroy [
vao delete.
vbo delete.
texture0 delete.
]
{ #category : #accessing }
DiyaRendererContext >> display [
^ display
]
{ #category : #accessing }
DiyaRendererContext >> display: anObject [
display := anObject
]
{ #category : #accessing }
DiyaRendererContext >> initialize [
super initialize.
vbo := OpenGLVertexBuffer new.
vao := OpenGLVertexArray new.
texture0 := OpenGLTexture fromUnit: 0.
vao bind.
vbo bind: GL_ARRAY_BUFFER.
projection := Array2D identity: 4.
]
{ #category : #accessing }
DiyaRendererContext >> mouse [
^ mouse
]
{ #category : #accessing }
DiyaRendererContext >> mouse: anObject [
mouse := anObject
]
{ #category : #accessing }
DiyaRendererContext >> projection [
^ projection
]
{ #category : #'as yet unclassified' }
DiyaRendererContext >> resolution [
^ (display w) @ (display h)
]
{ #category : #accessing }
DiyaRendererContext >> texture0 [
^ texture0
]
{ #category : #'as yet unclassified' }
DiyaRendererContext >> useProjection: aClass [
projection := aClass fromDisplay: self display
]
{ #category : #accessing }
DiyaRendererContext >> vao [
^ vao
]
{ #category : #accessing }
DiyaRendererContext >> vbo [
^ vbo
]

View File

@ -0,0 +1,34 @@
Class {
#name : #DiyaRootNode,
#superclass : #DiyaNode,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaRootNode >> draw [
OpenGL clearColorR: 0.0 G: 0.0 B: 0.0 A:0.
OpenGL clear: GL_COLOR_BUFFER_BIT.
context vbo bind: GL_ARRAY_BUFFER.
]
{ #category : #initialization }
DiyaRootNode >> initialize [
super initialize.
parent := self.
shader := nil.
]
{ #category : #testing }
DiyaRootNode >> isRoot [
^ true
]
{ #category : #initialization }
DiyaRootNode >> update [
^true
]
{ #category : #accessing }
DiyaRootNode >> updateTF [
"donothing"
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaScrollPanel,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,43 @@
Class {
#name : #DiyaSingleton,
#superclass : #DiyaBaseObject,
#classVars : [
'singletons'
],
#category : #'Diya-Core'
}
{ #category : #'instance creation' }
DiyaSingleton class >> cleanUpInstance: singleton [
"do nothing for now"
]
{ #category : #'class initialization' }
DiyaSingleton class >> initialize [
singletons := Dictionary new.
]
{ #category : #'instance creation' }
DiyaSingleton class >> new [
self error: 'Use #uniqueInstance'
]
{ #category : #'instance creation' }
DiyaSingleton class >> reset [
|singleton key|
key := self class asString asSymbol.
singleton := singletons at: key ifAbsent: [ ^ self ].
self cleanUpInstance: singleton.
singletons removeKey: key
]
{ #category : #'instance creation' }
DiyaSingleton class >> uniqueInstance [
^singletons at: self class asString asSymbol ifAbsentPut: [ super new ].
]
{ #category : #initialization }
DiyaSingleton >> initialize [
super initialize.
Transcript show: 'Initialise unique instance of ', self className; cr.
]

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaSwitch,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaTableLayout,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

178
Diya/DiyaText.class.st Normal file
View File

@ -0,0 +1,178 @@
Class {
#name : #DiyaText,
#superclass : #Diya2DNode,
#instVars : [
'fontStyle',
'fontSize',
'fontName',
'data',
'style',
'wrap'
],
#pools : [
'FT2Types'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaText class >> data: string [
^ (self new) data: string; yourself
]
{ #category : #'as yet unclassified' }
DiyaText class >> data: string shader: s [
^ (self with:s) data: string; yourself
]
{ #category : #accessing }
DiyaText >> data [
^ data
]
{ #category : #accessing }
DiyaText >> data: anObject [
data := anObject.
dirty := true
]
{ #category : #accessing }
DiyaText >> draw [
data ifNil: [ ^self ].
self shader
setUniform: #u_texture_type value: self texture format.
"configure vao vbo for texture QUAD"
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: ((vbuffer size) >> 2).
context vao disableAttribute: 0.
"reset value"
self texture drop.
]
{ #category : #accessing }
DiyaText >> drawText [
|vertices index tex2D offset|
index := 1.
offset := 0@0.
tex2D := self texture.
1 to: data size do: [ :i|
vertices := self getCharsVerticesAt:i offset: offset on: tex2D.
vertices do: [
:e| vbuffer at: index put:e.
index := index + 1.
].
(offset x > self extent x and: wrap not) ifTrue: [ ^self ].
(offset y negated > self extent y) ifTrue: [ ^self ].
].
]
{ #category : #accessing }
DiyaText >> extent: v [
bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ).
dirty := true
]
{ #category : #accessing }
DiyaText >> fontName [
^ fontName
]
{ #category : #initialization }
DiyaText >> fontName: name style: face size: size [
name ifNotNil: [ fontName := name ].
face ifNotNil: [ fontStyle := face ].
fontSize := size.
style := DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
dirty := true.
]
{ #category : #accessing }
DiyaText >> fontSize [
^ fontSize
]
{ #category : #initialization }
DiyaText >> fontSize: size [
self fontName: nil style:nil size: size
]
{ #category : #accessing }
DiyaText >> fontStyle [
^ fontStyle
]
{ #category : #accessing }
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|x y w h glyph gsize c |
c := (data at:i) asciiValue.
c = (Character space asciiValue) ifTrue:[
offset setX: (offset x + (tex2D spacing ) ) setY: offset y.
wrap ifTrue: [
(offset x + ((self nextSpaceFrom: i + 1) * (tex2D fontSize))) > (self extent x) ifTrue: [
offset setX: 0.0 setY: (offset y )- (tex2D linespace)].
].
^ {}.
].
glyph := tex2D getGlyph: c.
gsize := glyph extent.
((offset x > self extent x) and: (gsize x > 0)) ifTrue:[
wrap ifFalse: [ ^ { } ].
offset setX: 0.0 setY: (offset y )- (tex2D linespace).
offset y negated > self extent y ifTrue:[^{}].
].
x := offset x + (glyph bearing x).
y := offset y - (tex2D cellh).
w := (gsize x).
h := (gsize y).
offset setX: (offset x + (glyph advance x)) setY: offset y.
^{x. y + h. glyph texcoord origin x. glyph texcoord origin y.
x. y. glyph texcoord origin x. glyph texcoord corner y.
x + w. y. glyph texcoord corner x. glyph texcoord corner y.
x. y + h. glyph texcoord origin x. glyph texcoord origin y.
x + w. y. glyph texcoord corner x. glyph texcoord corner y.
x + w. y + h. glyph texcoord corner x. glyph texcoord origin y. }.
]
{ #category : #initialization }
DiyaText >> initialize [
super initialize.
self fontName: 'Ubuntu' style:'Regular' size: 16.
data := nil.
wrap := false.
bbox := nil
]
{ #category : #'as yet unclassified' }
DiyaText >> nextSpaceFrom: index [
index to: (data size) do: [:i|
(data at: i) = (Character space) ifTrue:[^i - index].
].
^ 0
]
{ #category : #accessing }
DiyaText >> texture [
^style textureOf: self fontSize
]
{ #category : #initialization }
DiyaText >> update [
bbox 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
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaTextArea,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaTextInput,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaVbox,
#superclass : #DiyaLayout,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,5 @@
Class {
#name : #DiyaWidget,
#superclass : #Diya2DNode,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,6 @@
Extension { #name : #Duration }
{ #category : #'*Diya' }
Duration >> asFloat [
^ seconds asFloat + (nanos / 1e9) asFloat
]

11
Diya/FT2Face.extension.st Normal file
View File

@ -0,0 +1,11 @@
Extension { #name : #FT2Face }
{ #category : #'*Diya' }
FT2Face >> getFirstChar: gindex [
^self ffiCall: #(FT_ULong FT_Get_First_Char(self,FT_UInt *gindex)).
]
{ #category : #'*Diya' }
FT2Face >> getNextChar: charcode iptr: gindex [
^self ffiCall: #( FT_ULong FT_Get_Next_Char(self,FT_ULong charcode,FT_UInt *gindex )).
]

12
Diya/LibC.extension.st Normal file
View File

@ -0,0 +1,12 @@
Extension { #name : #LibC }
{ #category : #'*Diya' }
LibC >> memset:pointer value: value size: size [
^self ffiCall: #(void *memset(void *pointer, int value, size_t size))
]
{ #category : #'*Diya' }
LibC class >> memset:pointer value: value size: size [
^self uniqueInstance memset: pointer value: value size: size
]

104
Diya/OpenGL.class.st Normal file
View File

@ -0,0 +1,104 @@
Class {
#name : #OpenGL,
#superclass : #DiyaFFIBase,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
OpenGL class >> begin: mode [
^ self ffiCall: #(void glBegin(GLenum mode))
]
{ #category : #'as yet unclassified' }
OpenGL class >> blendFnOn:buf sfactor: sfactor dfactor: dfactor [
^ self ffiCall: #(void glBlendFunci( GLuint buf,GLenum sfactor,GLenum dfactor))
]
{ #category : #'as yet unclassified' }
OpenGL class >> blendFnWithSfactor: sfactor dfactor: dfactor [
^ self ffiCall: #(void glBlendFunc( GLenum sfactor,GLenum dfactor))
]
{ #category : #accessing }
OpenGL class >> checkSymbol [
^#glDrawArrays
]
{ #category : #'as yet unclassified' }
OpenGL class >> clear: mask [
^ self ffiCall: #(void glClear(GLbitfield mask))
]
{ #category : #'as yet unclassified' }
OpenGL class >> clearColorR: red G: green B: blue A:alpha [
^self ffiCall: #(void glClearColor( GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha))
]
{ #category : #accessing }
OpenGL class >> color3fR: red G: green B: blue [
^self ffiCall: #(void glColor3f(GLfloat red,GLfloat green,GLfloat blue))
]
{ #category : #'as yet unclassified' }
OpenGL class >> disable: cap [
^ self ffiCall: #(void glDisable( GLenum cap))
]
{ #category : #'as yet unclassified' }
OpenGL class >> drawArrays: mode first: idx count:n [
^self ffiCall: #(void glDrawArrays(GLenum mode,GLint idx,GLsizei n))
]
{ #category : #'as yet unclassified' }
OpenGL class >> enable: cap [
^ self ffiCall: #(void glEnable( GLenum cap))
]
{ #category : #accessing }
OpenGL class >> end [
^ self ffiCall: #(void glEnd( void ))
]
{ #category : #'as yet unclassified' }
OpenGL class >> getError [
^self ffiCall: #(GLenum glGetError( void))
]
{ #category : #'as yet unclassified' }
OpenGL class >> getIntegerv: pname data: data [
^self ffiCall: #(void glGetIntegerv( GLenum pname,GLint * data))
]
{ #category : #'as yet unclassified' }
OpenGL class >> hint:target mode:mode [
^self ffiCall: #(void glHint( GLenum target,GLenum mode))
]
{ #category : #accessing }
OpenGL class >> libNames [
^#('libGL.so.1')
]
{ #category : #geometry }
OpenGL class >> lineWidth: width [
^ self ffiCall: #(void glLineWidth(GLfloat width))
]
{ #category : #accessing }
OpenGL class >> pixelstorei: pname param: param [
^self ffiCall: #(void glPixelStorei( GLenum pname,GLint param))
]
{ #category : #accessing }
OpenGL class >> vertex3fX:x Y:y Z:z [
^self ffiCall: #(void glVertex3f( GLfloat x,GLfloat y,GLfloat z))
]
{ #category : #'as yet unclassified' }
OpenGL class >> viewportX: x Y:y W: width H:height [
^ self ffiCall: #(void glViewport(GLint x,GLint y,GLsizei width,GLsizei height))
]

View File

@ -0,0 +1,196 @@
Class {
#name : #OpenGLConstants,
#superclass : #SharedPool,
#classVars : [
'GL_ACCUM_BUFFER_BIT',
'GL_ACTIVE_ATTRIBUTES',
'GL_ACTIVE_ATTRIBUTE_MAX_LENGTH',
'GL_ACTIVE_UNIFORMS',
'GL_ACTIVE_UNIFORM_MAX_LENGTH',
'GL_ALPHA',
'GL_ARRAY_BUFFER',
'GL_ARRAY_BUFFER_BINDING',
'GL_ATTACHED_SHADERS',
'GL_BLEND',
'GL_BLUE',
'GL_BYTE',
'GL_CLAMP_TO_BORDER',
'GL_CLAMP_TO_EDGE',
'GL_COLOR_BUFFER_BIT',
'GL_COMPILE_STATUS',
'GL_COMPUTE_SHADER',
'GL_CULL_FACE',
'GL_DELETE_STATUS',
'GL_DEPTH_BUFFER_BIT',
'GL_DOUBLE',
'GL_DYNAMIC_DRAW',
'GL_FALSE',
'GL_FIXED',
'GL_FLOAT',
'GL_FRAGMENT_SHADER',
'GL_GEOMETRY_SHADER',
'GL_GREEN',
'GL_HALF_FLOAT',
'GL_INFO_LOG_LENGTH',
'GL_INT',
'GL_INT_2_10_10_10_REV',
'GL_LINEAR',
'GL_LINES',
'GL_LINE_LOOP',
'GL_LINE_SMOOTH',
'GL_LINE_SMOOTH_HINT',
'GL_LINE_STRIP',
'GL_LINK_STATUS',
'GL_MAX_TEXTURE_SIZE',
'GL_MULTISAMPLE',
'GL_NEAREST',
'GL_NICEST',
'GL_ONE_MINUS_SRC_ALPHA',
'GL_PACK_ALIGNMENT',
'GL_POINTS',
'GL_POLYGON',
'GL_QUADS',
'GL_QUAD_STRIP',
'GL_RED',
'GL_RGB',
'GL_RGBA',
'GL_SHADER_SOURCE_LENGTH',
'GL_SHADER_TYPE',
'GL_SHORT',
'GL_SRC_ALPHA',
'GL_STATIC_DRAW',
'GL_STENCIL_BUFFER_BIT',
'GL_TESS_CONTROL_SHADER',
'GL_TESS_EVALUATION_SHADER',
'GL_TEXTURE_2D',
'GL_TEXTURE_BUFFER',
'GL_TEXTURE_MAG_FILTER',
'GL_TEXTURE_MIN_FILTER',
'GL_TEXTURE_UNIT_BASE',
'GL_TEXTURE_WRAP_S',
'GL_TEXTURE_WRAP_T',
'GL_TRIANGLES',
'GL_TRIANGLE_FAN',
'GL_TRIANGLE_STRIP',
'GL_TRUE',
'GL_UNIFORM_BUFFER',
'GL_UNPACK_ALIGNMENT',
'GL_UNSIGNED_BYTE',
'GL_UNSIGNED_INT',
'GL_UNSIGNED_INT_10F_11F_11F_REV',
'GL_UNSIGNED_INT_2_10_10_10_REV',
'GL_UNSIGNED_SHORT',
'GL_VALIDATE_STATUS',
'GL_VERTEX_SHADER'
],
#category : #'Diya-OpenGL'
}
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonConstants [
GL_BYTE := 16r1400.
GL_UNSIGNED_BYTE := 16r1401.
GL_SHORT := 16r1402.
GL_UNSIGNED_SHORT := 16r1403.
GL_INT := 16r1404.
GL_UNSIGNED_INT := 16r1405.
GL_HALF_FLOAT := 16r140B.
GL_FLOAT := 16r1406.
GL_DOUBLE := 16r140A.
GL_FIXED := 16r140C.
GL_INT_2_10_10_10_REV := 16r8D9F.
GL_UNSIGNED_INT_2_10_10_10_REV := 16r8368.
GL_UNSIGNED_INT_10F_11F_11F_REV := 16r8C3B.
GL_ARRAY_BUFFER := 16r8892.
GL_TEXTURE_BUFFER := 16r8C2A.
GL_UNIFORM_BUFFER := 16r8A11.
GL_STATIC_DRAW := 16r88E4.
GL_DYNAMIC_DRAW := 16r88E8.
GL_FALSE := 0.
GL_TRUE := 1.
GL_ARRAY_BUFFER_BINDING := 16r8894.
GL_RED := 16r1903.
GL_BLUE := 16r1905.
GL_GREEN := 16r1904.
GL_ALPHA := 16r1906.
GL_RGB := 16r1907.
GL_RGBA := 16r1908.
GL_LINE_SMOOTH := 16r0B20.
GL_LINE_SMOOTH_HINT := 16r0C52
]
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonMask [
GL_COLOR_BUFFER_BIT := 16r00004000.
GL_DEPTH_BUFFER_BIT := 16r00000100.
GL_ACCUM_BUFFER_BIT := 16r00000200.
GL_STENCIL_BUFFER_BIT := 16r00000400.
]
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonMode [
GL_TRIANGLES := 16r0004.
GL_POINTS := 16r0000.
GL_LINES := 16r0001.
GL_LINE_STRIP := 16r0003.
GL_LINE_LOOP := 16r0002.
GL_TRIANGLE_STRIP := 16r0005.
GL_TRIANGLE_FAN := 16r0006.
GL_QUADS := 16r0007.
GL_QUAD_STRIP := 16r0008.
GL_POLYGON := 16r0009.
GL_BLEND := 16r0BE2.
GL_SRC_ALPHA := 16r0302.
GL_ONE_MINUS_SRC_ALPHA := 16r0303.
GL_CULL_FACE := 16r0B44.
GL_PACK_ALIGNMENT := 16r0D05.
GL_UNPACK_ALIGNMENT := 16r0CF5.
GL_NICEST := 16r1102.
GL_MULTISAMPLE := 16r809D
]
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonShader [
GL_COMPUTE_SHADER := 16r91B9.
GL_VERTEX_SHADER := 16r8B31.
GL_TESS_CONTROL_SHADER := 16r8E88.
GL_TESS_EVALUATION_SHADER := 16r8E87.
GL_GEOMETRY_SHADER := 16r8DD9.
GL_FRAGMENT_SHADER := 16r8B30.
GL_SHADER_TYPE := 16r8B4F.
GL_DELETE_STATUS := 16r8B80.
GL_COMPILE_STATUS := 16r8B81.
GL_INFO_LOG_LENGTH := 16r8B84.
GL_SHADER_SOURCE_LENGTH := 16r8B88.
GL_LINK_STATUS := 16r8B82.
GL_VALIDATE_STATUS := 16r8B83.
GL_ATTACHED_SHADERS := 16r8B85.
GL_ACTIVE_ATTRIBUTES := 16r8B89.
GL_ACTIVE_ATTRIBUTE_MAX_LENGTH := 16r8B8A.
GL_ACTIVE_UNIFORMS := 16r8B86.
GL_ACTIVE_UNIFORM_MAX_LENGTH := 16r8B87.
]
{ #category : #'class initialization' }
OpenGLConstants class >> initTextureConstants [
GL_TEXTURE_WRAP_S := 16r2802.
GL_TEXTURE_2D := 16r0DE1.
GL_CLAMP_TO_EDGE := 16r812F.
GL_TEXTURE_WRAP_T := 16r2803.
GL_TEXTURE_MIN_FILTER := 16r2801.
GL_TEXTURE_MAG_FILTER := 16r2800.
GL_LINEAR := 16r2601.
GL_NEAREST := 16r2600.
GL_TEXTURE_UNIT_BASE := 16r84C0.
GL_MAX_TEXTURE_SIZE := 16r0D33.
GL_CLAMP_TO_BORDER := 16r812D
]
{ #category : #'class initialization' }
OpenGLConstants class >> initialize [
self initCommonMode.
self initCommonMask.
self initCommonShader.
self initCommonConstants.
self initTextureConstants.
]

175
Diya/OpenGLFontTex.class.st Normal file
View File

@ -0,0 +1,175 @@
Class {
#name : #OpenGLFontTex,
#superclass : #OpenGLTexImage2D,
#instVars : [
'charmap',
'cellw',
'cellh',
'spacing',
'fontSize'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
OpenGLFontTex class >> fromFace: face ofSize: size [
^self new fromFace: face ofSize: size; yourself
]
{ #category : #'instance creation' }
OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [
size = (0@0) ifTrue:[^self].
0 to: size y - 1 do: [ :i|
LibC memCopy: (bitmap getHandle + (i* (size x))) to:(data getHandle + ((i + offset y) * width + (offset x) )) size: size x
].
bitmap free.
]
{ #category : #accessing }
OpenGLFontTex >> cellh [
^ cellh
]
{ #category : #accessing }
OpenGLFontTex >> cellw [
^ cellw
]
{ #category : #accessing }
OpenGLFontTex >> charmap [
^ charmap
]
{ #category : #'instance creation' }
OpenGLFontTex >> createBitmapFontFrom: glyphs maxBearing: maxbearing [
|bmp metric offset nrows index element|
data ifNotNil: [data free ].
charmap := Dictionary new.
nrows := glyphs size >> 5.
(glyphs size % 32) = 0 ifFalse:[nrows := nrows + 1].
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (nrows << 5).
LibC memset: data getHandle value: 0 size: data size.
data autoRelease.
index := 1.
offset := 0@0.
width := cellw * 32.
height := cellh * nrows.
0 to: nrows - 1 do: [ :row|
0 to: 31 do: [ :col| |glyph|
element := glyphs at: index.
metric := element at: 3.
bmp := element at:2.
offset := (col * cellw) @ (row*cellh).
glyph := (DiyaFontGlyph origin: offset extent: ((metric first x asInteger) @ cellh)).
glyph
bearing: (metric at: 2) asFloatPoint;
advance: (metric at: 3) asFloatPoint;
texcoord: (Rectangle origin: (glyph origin/ (self extent) ) asFloatPoint corner: ((glyph corner) / (self extent)) asFloatPoint ).
charmap at: element first put:glyph.
self blitPixel8: bmp at: (offset x) @ ((offset y) + maxbearing - (metric last) ) size: metric first.
index := index + 1.
index > glyphs size ifTrue:[^self].
]
].
]
{ #category : #accessing }
OpenGLFontTex >> drop [
OpenGL
pixelstorei: GL_UNPACK_ALIGNMENT param: 4;
disable: GL_CULL_FACE;
disable: GL_BLEND.
]
{ #category : #accessing }
OpenGLFontTex >> fontSize [
^ fontSize
]
{ #category : #'instance creation' }
OpenGLFontTex >> fromFace: face ofSize: size [
|minhang maxbearing rec glyphs iptr charcode w|
fontSize := size.
face setPixelWidth:0 height: size.
glyphs := OrderedCollection new.
cellw := 0.
cellh := 0.
minhang := 0.
maxbearing := 0.
iptr := FFIExternalArray externalNewType: GLuint size:1.
iptr at:1 put: 0.
rec := (FTFaceRec fromHandle: face getHandle).
charcode := face getFirstChar: iptr getHandle.
[ (iptr at: 1) = 0 ] whileFalse: [
|bmp bmpsize metric|
face loadCharacter: charcode flags: (1 << 2).
w := ((rec glyph metrics width) >> 6).
(w > (size << 1)) ifFalse:[
metric := {
(((rec glyph metrics width) >> 6)@ ((rec glyph metrics height) >> 6)).
(face glyph hBearing).
(face glyph advance).
((rec glyph metrics horiBearingY) >> 6)
}.
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6).
cellw := cellw max: w.
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6).
"copy buffer"
bmpsize := (rec glyph bitmap width)*(rec glyph bitmap rows).
bmp := FFIExternalArray externalNewType: GLubyte size:bmpsize.
LibC memCopy: rec glyph bitmap buffer to: bmp getHandle size: bmpsize.
glyphs add: {charcode. bmp. metric}.
].
charcode := face getNextChar: charcode iptr: iptr getHandle.
].
cellh := maxbearing - minhang.
spacing := (size >> 2) asInteger.
self createBitmapFontFrom: glyphs maxBearing: maxbearing.
iptr free.
]
{ #category : #accessing }
OpenGLFontTex >> getGlyph: c [
^(self charmap at: c ifAbsent:[^nil])
]
{ #category : #initialization }
OpenGLFontTex >> initialize [
super initialize.
charmap := Dictionary new.
data := nil.
level := 0.
border := 0.
format := GL_ALPHA.
internalFormat := GL_ALPHA.
type := GL_UNSIGNED_BYTE.
target := GL_TEXTURE_2D.
]
{ #category : #accessing }
OpenGLFontTex >> linespace [
^ cellh
]
{ #category : #accessing }
OpenGLFontTex >> setup [
OpenGL
enable: GL_CULL_FACE;
enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA;
pixelstorei: GL_UNPACK_ALIGNMENT param: 1.
OpenGLTexture
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_S param: GL_CLAMP_TO_EDGE;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_T param: GL_CLAMP_TO_EDGE;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MIN_FILTER param: GL_LINEAR;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MAG_FILTER param: GL_LINEAR.
]
{ #category : #accessing }
OpenGLFontTex >> spacing [
^ spacing
]

237
Diya/OpenGLSL.class.st Normal file
View File

@ -0,0 +1,237 @@
Class {
#name : #OpenGLSL,
#superclass : #DiyaSingleton,
#instVars : [
'programID',
'uniforms'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLSL class >> attachShader: shader to: program [
^self ffiCall: #(void glAttachShader(GLuint program,GLuint shader))
]
{ #category : #'instance creation' }
OpenGLSL class >> cleanUpInstance: singleton [
singleton ifNil:[^self].
singleton delete
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> compileShader: shader [
^ self ffiCall: #(void glCompileShader( GLuint shader))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> createProgram [
^self ffiCall: #(GLuint glCreateProgram(void))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> createShader: shaderType [
^ self ffiCall: #(GLuint glCreateShader( GLenum shaderType))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> deleteProgram: program [
^self ffiCall: #(void glDeleteProgram(GLuint program))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> deleteShader: shader [
^ self ffiCall: #(void glDeleteShader( GLuint shader))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> detachShaderFrom: program shader:shader [
^ self ffiCall: #(void glDetachShader(GLuint program,GLuint shader))
]
{ #category : #'library path' }
OpenGLSL class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #accessing }
OpenGLSL class >> fragmentShader [
^ self subclassResponsibility
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getProgramInfoLogOf: prog maxLength: maxLength lengthPtr: length buffer: infoLog [
^self ffiCall:#(void glGetProgramInfoLog(GLuint prog,GLsizei maxLength,GLsizei *length,GLchar *infoLog))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getShaderInfoLogOf: shader maxLength: maxLength lengthPtr: length buffer: infoLog [
^self ffiCall:#(void glGetShaderInfoLog(GLuint shader,GLsizei maxLength,GLsizei *length,GLchar *infoLog))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getShaderiv:shader parameterName: pname params: ptr [
^ self ffiCall: #(void glGetShaderiv(GLuint shader,GLenum pname,GLint *ptr))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getUniformLocation: uname ofProgram: program [
^self ffiCall:#(GLint glGetUniformLocation( GLuint program,const GLchar *uname))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> linkProgram:program [
^self ffiCall: #(void glLinkProgram(GLuint program))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> resetShaders [
self allSubclassesDo: [ :c| c reset ].
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> setShaderSourceFor: shader count: n string: s length: l [
^ self ffiCall: #(void glShaderSource( GLuint shader,GLsizei n,const void* s,const GLint *l))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> systemUniforms [
^#(u_time u_resolution u_mouse)
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> useProgram:program [
^self ffiCall:#(void glUseProgram(GLuint program))
]
{ #category : #accessing }
OpenGLSL class >> vertexShader [
^self subclassResponsibility
]
{ #category : #initialization }
OpenGLSL >> addUniform: uname of: utype [
uniforms at:uname put: (utype fromName: uname).
]
{ #category : #compiling }
OpenGLSL >> checkStatus:status of: id [
|infoLength buffer result|
result := FFIExternalArray externalNewType: GLint size: 1.
infoLength := FFIExternalArray externalNewType: GLint size: 1.
infoLength at: 1 put: 0.
infoLength autoRelease.
result autoRelease.
OpenGLSL getShaderiv: id parameterName: status params: result getHandle.
OpenGLSL getShaderiv: id parameterName: GL_INFO_LOG_LENGTH params: infoLength getHandle.
(infoLength at:1) > 0 ifTrue: [
"report the error"
buffer := ByteArray new:(infoLength at: 1).
id = programID ifTrue: [
OpenGLSL getProgramInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer
] ifFalse: [
OpenGLSL getShaderInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer
].
^self error: buffer asString
].
^self
]
{ #category : #compiling }
OpenGLSL >> compile [
|vertexShaderID fragmentShaderID|
vertexShaderID := OpenGLSL createShader: GL_VERTEX_SHADER.
fragmentShaderID := OpenGLSL createShader: GL_FRAGMENT_SHADER.
self compileVertexShader: vertexShaderID.
self compileFragmentShader: fragmentShaderID.
programID := OpenGLSL createProgram.
OpenGLSL attachShader: vertexShaderID to: programID.
OpenGLSL attachShader: fragmentShaderID to: programID.
OpenGLSL linkProgram: programID.
self checkStatus: GL_LINK_STATUS of: programID.
OpenGLSL detachShaderFrom: programID shader: vertexShaderID.
OpenGLSL detachShaderFrom: programID shader: fragmentShaderID.
OpenGLSL deleteShader: vertexShaderID.
OpenGLSL deleteShader: fragmentShaderID.
self locateUniforms
]
{ #category : #compiling }
OpenGLSL >> compileFragmentShader:fragmentShaderID [
self getSourcePtr:self class fragmentShader for: fragmentShaderID.
OpenGLSL compileShader: fragmentShaderID.
self checkStatus:GL_COMPILE_STATUS of: fragmentShaderID
]
{ #category : #compiling }
OpenGLSL >> compileVertexShader: vertexShaderID [
self getSourcePtr:self class vertexShader for: vertexShaderID.
OpenGLSL compileShader: vertexShaderID.
self checkStatus:GL_COMPILE_STATUS of: vertexShaderID
]
{ #category : #'submorphs-add/remove' }
OpenGLSL >> delete [
OpenGLSL deleteProgram: programID
]
{ #category : #compiling }
OpenGLSL >> getSourcePtr: string for: shaderId [
|xarray|
xarray := FFIExternalArray externalNewType: 'char*' size: 1.
xarray at:1 put: (ExternalAddress fromString: string).
xarray autoRelease.
OpenGLSL setShaderSourceFor: shaderId count: 1 string: xarray getHandle length: nil.
]
{ #category : #'submorphs-add/remove' }
OpenGLSL >> getUniformLocation:uname [
^ self class getUniformLocation: uname asString ofProgram: programID
]
{ #category : #initialization }
OpenGLSL >> initialize [
super initialize.
uniforms := Dictionary new.
self addUniform: #u_time of: Uniform1F.
self addUniform: #u_resolution of: Uniform2F.
self addUniform: #u_mouse of: Uniform2F.
self addUniform: #u_projection of: UniformMatrix4fv.
self addUniform: #u_transform of: UniformMatrix3fv.
self setUpUniforms.
self compile
]
{ #category : #compiling }
OpenGLSL >> locateUniforms [
|loc|
uniforms valuesDo: [ :uniform|
loc := self getUniformLocation: uniform uname.
loc = -1 ifFalse:[uniform location: loc]
]
]
{ #category : #initialization }
OpenGLSL >> setUniform: uname value: values [
|uniform|
uniform := uniforms at: uname asSymbol ifAbsent:[
^self error: 'Uniform ', uname, ' is not defined in this program'].
uniform value: values
]
{ #category : #initialization }
OpenGLSL >> setUpUniforms [
"do nothing, custom uniform can be set up by subclass"
]
{ #category : #'submorphs-add/remove' }
OpenGLSL >> use [
^OpenGLSL useProgram: programID
]

View File

@ -0,0 +1,111 @@
Class {
#name : #OpenGLSLUniform,
#superclass : #DiyaBaseObject,
#instVars : [
'uname',
'location'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> fromName: uname [
^self new uname: uname; yourself
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> fromName: uname at: location [
^self new uname: uname; location: location; yourself
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform1f: location value: v0 [
^self ffiCall: #(void glUniform1f(GLint location,GLfloat v0))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform1i: location value: v0 [
^self ffiCall: #(void glUniform1i(GLint location,GLint v0))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform2f: location value: v0 value: v1 [
^self ffiCall: #(void glUniform2f(GLint location,GLfloat v0,GLfloat v1))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform2i: location value: v0 value: v1 [
^self ffiCall: #(void glUniform2i(GLint location,GLint v0,GLint v1))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform3f: location value: v0 value: v1 value: v2 [
^self ffiCall: #(void glUniform3f(GLint location,GLfloat v0,GLfloat v1,GLfloat v2))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform3i: location value: v0 value: v1 value: v2 [
^self ffiCall: #(void glUniform3i(GLint location,GLint v0,GLint v1,GLint v2))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform4f: location value: v0 value: v1 value: v2 value: v3 [
^self ffiCall: #(void glUniform4f(GLint location,GLfloat v0,GLfloat v1,GLfloat v2, GLfloat v3))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform4i: location value: v0 value: v1 value: v2 value: v3 [
^self ffiCall: #(void glUniform4i(GLint location,GLint v0,GLint v1,GLint v2, GLint v3))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniformMatrix3fv: location count: count transpose: transpose value: value [
^self ffiCall: #(void glUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat *value))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniformMatrix4fv: location count: count transpose: transpose value: value [
^self ffiCall: #(void glUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat *value))
]
{ #category : #accessing }
OpenGLSLUniform >> location [
^ location
]
{ #category : #accessing }
OpenGLSLUniform >> location: anObject [
location := anObject
]
{ #category : #accessing }
OpenGLSLUniform >> setUniformValue: value [
^ self subclassResponsibility
]
{ #category : #accessing }
OpenGLSLUniform >> uname [
^ uname
]
{ #category : #accessing }
OpenGLSLUniform >> uname: anObject [
uname := anObject
]
{ #category : #accessing }
OpenGLSLUniform >> value: values [
location = -1 ifTrue: [ ^self ].
self setUniformValue: values.
]

View File

@ -0,0 +1,143 @@
Class {
#name : #OpenGLTexImage2D,
#superclass : #DiyaBaseObject,
#instVars : [
'target',
'level',
'internalFormat',
'width',
'height',
'border',
'format',
'type',
'data'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
OpenGLTexImage2D >> border [
^ border
]
{ #category : #accessing }
OpenGLTexImage2D >> border: anObject [
border := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> data [
^ data
]
{ #category : #accessing }
OpenGLTexImage2D >> data: anObject [
data := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> debug [
self
stdlog: 'Target:',target hex;
stdlog: 'level:',level asString;
stdlog: 'border :',border asString;
stdlog: 'width :',width asString;
stdlog: 'height :',height asString;
stdlog: 'type :',type hex;
stdlog: 'format :',format hex;
stdlog: 'internalformat :',internalFormat hex
]
{ #category : #accessing }
OpenGLTexImage2D >> drop [
^self subclassResponsibility
]
{ #category : #accessing }
OpenGLTexImage2D >> extent [
^ width @ height
]
{ #category : #accessing }
OpenGLTexImage2D >> format [
^ format
]
{ #category : #accessing }
OpenGLTexImage2D >> format: anObject [
format := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> height [
^ height
]
{ #category : #accessing }
OpenGLTexImage2D >> height: anObject [
height := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> internalFormat [
^ internalFormat
]
{ #category : #accessing }
OpenGLTexImage2D >> internalFormat: anObject [
internalFormat := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> level [
^ level
]
{ #category : #accessing }
OpenGLTexImage2D >> level: anObject [
level := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> mipmap [
^false
]
{ #category : #accessing }
OpenGLTexImage2D >> setup [
^self subclassResponsibility
]
{ #category : #accessing }
OpenGLTexImage2D >> target [
^ target
]
{ #category : #accessing }
OpenGLTexImage2D >> target: anObject [
target := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> type [
^ type
]
{ #category : #accessing }
OpenGLTexImage2D >> type: anObject [
type := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> width [
^ width
]
{ #category : #accessing }
OpenGLTexImage2D >> width: anObject [
width := anObject
]

136
Diya/OpenGLTexture.class.st Normal file
View File

@ -0,0 +1,136 @@
Class {
#name : #OpenGLTexture,
#superclass : #DiyaBaseObject,
#instVars : [
'textureID',
'unit'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLTexture class >> active: unit [
^self ffiActive: GL_TEXTURE_UNIT_BASE + unit
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> bind: target texture: texture [
^ self ffiCall: #(void glBindTexture(GLenum target,GLuint texture))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> bindDefault: target [
self bind: target texture: 0
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> delete: n pointer:textures [
^ self ffiCall: #(void glDeleteTextures(GLsizei n,const GLuint * textures))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> ffiActive: unit [
^self ffiCall: #(void glActiveTexture( GLenum unit))
]
{ #category : #'library path' }
OpenGLTexture class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> fromUnit: unit [
^self new unit: unit; yourself
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> genTexture: n pointer: textures [
^ self ffiCall: #(void glGenTextures(GLsizei n,GLuint * textures))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> generateMipmap: target [
^self ffiCall: #(void glGenerateMipmap(GLenum target))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> image2D: target level: level internalformat: internalformat w: width h: height border: border format: fmt type: type data: data [
^ self ffiCall: #(void glTexImage2D( GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum fmt,GLenum type,const void * data))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> parameteri: target pname: pname param: param [
^ self ffiCall: #(void glTexParameteri( GLenum target,GLenum pname,GLint param))
]
{ #category : #initialization }
OpenGLTexture >> active [
self class active: self unit
]
{ #category : #initialization }
OpenGLTexture >> bind: target [
^ self class bind: target texture: self textureID
]
{ #category : #initialization }
OpenGLTexture >> delete [
self class delete: 1 pointer: textureID getHandle.
]
{ #category : #initialization }
OpenGLTexture >> initialize [
textureID := FFIExternalArray externalNewType: GLint size:1.
textureID autoRelease.
textureID at:1 put: -1.
self class genTexture: 1 pointer: textureID getHandle.
unit := 0.
]
{ #category : #initialization }
OpenGLTexture >> maxTextureSize [
|ptr v|
ptr := FFIExternalArray externalNewType: GLint size:1.
ptr at:1 put: -1.
OpenGL getIntegerv: GL_MAX_TEXTURE_SIZE data: ptr getHandle.
v := ptr at:1.
ptr free.
^v
]
{ #category : #initialization }
OpenGLTexture >> setImage2D: tex2D [
self bind: tex2D target.
self class image2D: tex2D target
level: tex2D level
internalformat: tex2D internalFormat
w: tex2D width
h: tex2D height
border: tex2D border
format: tex2D format
type: tex2D type
data: tex2D data getHandle.
tex2D mipmap ifTrue:[
self class generateMipmap: tex2D target
].
]
{ #category : #initialization }
OpenGLTexture >> textureID [
^textureID at: 1
]
{ #category : #accessing }
OpenGLTexture >> unit [
^ unit
]
{ #category : #accessing }
OpenGLTexture >> unit: anObject [
unit := anObject
]

55
Diya/OpenGLTypes.class.st Normal file
View File

@ -0,0 +1,55 @@
Class {
#name : #OpenGLTypes,
#superclass : #SharedPool,
#classVars : [
'GLbitfield',
'GLboolean',
'GLbyte',
'GLchar',
'GLclampd',
'GLclampf',
'GLdouble',
'GLenum',
'GLfixed',
'GLfloat',
'GLhalf',
'GLint',
'GLint64',
'GLintptr',
'GLshort',
'GLsizei',
'GLsizeiptr',
'GLsync',
'GLubyte',
'GLuint',
'GLuint64',
'GLushort'
],
#category : #'Diya-OpenGL'
}
{ #category : #'class initialization' }
OpenGLTypes class >> initialize [
GLfloat := #float.
GLubyte := #uint8.
GLenum := #int32.
GLboolean := #uint8.
GLbitfield := #int32.
GLbyte := #int8.
GLclampd := #double.
GLclampf := #float.
GLdouble := #double.
GLfixed := #int32.
GLhalf := #uint16.
GLint := #int32.
GLint64 := #int64.
GLintptr := Smalltalk wordSize = 8 ifTrue: [ #int64 ] ifFalse: [ #int32 ].
GLshort := #int16.
GLsizei := #int32.
GLsizeiptr := Smalltalk wordSize = 8 ifTrue: [ #int64 ] ifFalse: [ #int32 ].
GLsync := Smalltalk wordSize = 8 ifTrue: [ #int64 ] ifFalse: [ #int32 ].
GLuint := #uint32.
GLuint64 := #uint64.
GLushort := #uint16.
GLchar := #char.
]

View File

@ -0,0 +1,101 @@
Class {
#name : #OpenGLVertexArray,
#superclass : #DiyaBaseObject,
#instVars : [
'vertexArrayID'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> bind:array [
^self ffiCall:#(void glBindVertexArray( GLuint array))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> deteleVertexArraysSize:n arrays: arrays [
^self ffiCall:#(void glDeleteVertexArrays( GLsizei n,const GLuint *arrays))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> disableArrayAttribute: vaobj index: index [
^self ffiCall: #(void glDisableVertexArrayAttrib( GLuint vaobj,GLuint index))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> disableAttributeArray: index [
^self ffiCall: #(void glDisableVertexAttribArray( GLuint index))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> enableArrayAttribute: vaobj index: index [
^self ffiCall: #(void glEnableVertexArrayAttrib( GLuint vaobj,GLuint index))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> enableAttributeArray: index [
^self ffiCall: #(void glEnableVertexAttribArray( GLuint index))
]
{ #category : #'library path' }
OpenGLVertexArray class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> genVertexArraysSize: n arrays: arrays [
^self ffiCall:#(void glGenVertexArrays( GLsizei n,GLuint *arrays))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> vertexAttributeLPointerIndex: index size: size type: type stride: stride pointer: pointer [
^self ffiCall: #(void glVertexAttribLPointer( GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> vertexAttributePointerIndex: index size: size type: type normalized: normalized stride: stride pointer: pointer [
^self ffiCall: #(void glVertexAttribPointer( GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const void * pointer))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> vertexAttributelPointerIndex: index size: size type: type stride: stride pointer: pointer [
^self ffiCall: #(void glVertexAttribIPointer( GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer))
]
{ #category : #accessing }
OpenGLVertexArray >> bind [
OpenGLVertexArray bind: self vertexArrayID
]
{ #category : #accessing }
OpenGLVertexArray >> delete [
OpenGLVertexArray deteleVertexArraysSize:1 arrays: vertexArrayID getHandle.
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray >> disableAttribute: index [
^OpenGLVertexArray disableAttributeArray: index
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray >> enableAttribute: index [
^OpenGLVertexArray enableAttributeArray: index
]
{ #category : #initialization }
OpenGLVertexArray >> initialize [
vertexArrayID := FFIExternalArray externalNewType: GLint size:1.
vertexArrayID autoRelease.
vertexArrayID at:1 put: -1.
OpenGLVertexArray genVertexArraysSize: 1 arrays: vertexArrayID getHandle.
]
{ #category : #accessing }
OpenGLVertexArray >> vertexArrayID [
^vertexArrayID at: 1
]

View File

@ -0,0 +1,99 @@
Class {
#name : #OpenGLVertexBuffer,
#superclass : #DiyaBaseObject,
#instVars : [
'vertexBufferID'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> bind: target buffer: buffer [
^ self ffiCall: #(void glBindBuffer( GLenum target,GLuint buffer))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> bufferData:target size: size data: data usage: usage [
^self ffiCall: #(void glBufferData( GLenum target,GLsizeiptr size,const void * data,GLenum usage))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> deleteBuffersSize:n buffers: buffers [
^self ffiCall: #(void glDeleteBuffers( GLsizei n,const GLuint * buffers))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> genVertexBuffersSize:n buffers: buffers [
^self ffiCall: #(void glGenBuffers( GLsizei n,GLuint * buffers))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> getBufferData: target offset: offset size: size data: data [
^self ffiCall: #(void glGetBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,void * data))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> namedBufferData:buffer size: size data: data usage: usage [
^self ffiCall: #(void glNamedBufferData(GLuint buffer,GLsizeiptr size,const void *data,GLenum usage))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> subData:target offset: offset size: size data: data [
^self ffiCall: #(void glBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const void * data))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> bind: target [
^OpenGLVertexBuffer bind:target buffer: self vertexBufferID
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> data:target data: data size: size usage: usage [
self bind: target.
^OpenGLVertexBuffer bufferData: target size: size data:(data ifNil:[data] ifNotNil: [data getHandle]) usage: usage
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> data:target data: data usage: usage [
self bind: target.
^OpenGLVertexBuffer bufferData: target size: (data size) << 2 data:data getHandle usage: usage
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> delete [
OpenGLVertexBuffer deleteBuffersSize: 1 buffers: vertexBufferID getHandle.
]
{ #category : #initialization }
OpenGLVertexBuffer >> initialize [
vertexBufferID := FFIExternalArray externalNewType: GLint size:1.
vertexBufferID at:1 put: -1.
vertexBufferID autoRelease.
OpenGLVertexBuffer genVertexBuffersSize: 1 buffers: vertexBufferID getHandle
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> subData:target offset: offset data:data [
self bind: target.
^OpenGLVertexBuffer subData: target offset: offset size: (data size) << 2 data: data getHandle
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> subData:target offset: offset data:data size: size [
self bind: target.
^OpenGLVertexBuffer subData: target offset: offset size: size data: data getHandle
]
{ #category : #initialization }
OpenGLVertexBuffer >> vertexBufferID [
^ vertexBufferID at: 1
]

View File

@ -0,0 +1,96 @@
Class {
#name : #OrthoProjectionMatrix,
#superclass : #ProjectionMatrix,
#instVars : [
'viewport',
'near',
'far'
],
#category : #'Diya-Math'
}
{ #category : #'as yet unclassified' }
OrthoProjectionMatrix class >> fromDisplay: display [
^ self viewport: (Rectangle origin: 0@0 corner: (display w) @ (display h) ) near: -1.0 far: 1.0.
]
{ #category : #'as yet unclassified' }
OrthoProjectionMatrix class >> viewport:v near:n far:f [
^ self new setViewport: v near:n far:f; yourself.
]
{ #category : #accessing }
OrthoProjectionMatrix >> bottom [
^ viewport origin y
]
{ #category : #initialization }
OrthoProjectionMatrix >> calculate [
self at:1 at:1 put: (2.0 /(self right - self left)).
self at:2 at:2 put: (2.0 / (self top - self bottom)).
self at:3 at:3 put: (2.0 / (self far - self near)) negated.
self at:4 at:1 put: ((self right + self left)/ (self right - self left)) negated.
self at:4 at:2 put: ((self top + self bottom) / (self top - self bottom)) negated.
self at:4 at:3 put: ((self far + self near)/(self far - self near)) negated.
]
{ #category : #initialization }
OrthoProjectionMatrix >> default [
viewport := Rectangle origin: -1.0@ -1.0 corner: 1.0@1.0.
near := -1.0.
far := 1.0.
]
{ #category : #accessing }
OrthoProjectionMatrix >> far [
^ far
]
{ #category : #accessing }
OrthoProjectionMatrix >> far: anObject [
far := anObject
]
{ #category : #accessing }
OrthoProjectionMatrix >> left [
^ viewport origin x
]
{ #category : #accessing }
OrthoProjectionMatrix >> near [
^ near
]
{ #category : #accessing }
OrthoProjectionMatrix >> near: anObject [
near := anObject
]
{ #category : #accessing }
OrthoProjectionMatrix >> right [
^ viewport corner x
]
{ #category : #initialization }
OrthoProjectionMatrix >> setViewport: v near: n far:f [
viewport := v.
near := n.
far := f.
self update.
]
{ #category : #accessing }
OrthoProjectionMatrix >> top [
^ viewport corner y
]
{ #category : #accessing }
OrthoProjectionMatrix >> viewport [
^ viewport
]
{ #category : #accessing }
OrthoProjectionMatrix >> viewport: anObject [
viewport := anObject
]

16
Diya/Point.extension.st Normal file
View File

@ -0,0 +1,16 @@
Extension { #name : #Point }
{ #category : #'*Diya' }
Point >> asGLCoord [
|res|
res := DiyaRendererContext uniqueInstance resolution.
^(self / ( res / 2.0)) + (-1.0@ -1.0).
]
{ #category : #'*Diya' }
Point >> glNormalise [
|res p|
res := DiyaRendererContext uniqueInstance resolution.
p := self / (res/ 2).
^ (p x asFloat) @ (p y asFloat)
]

View File

@ -0,0 +1,55 @@
Class {
#name : #ProjectionMatrix,
#superclass : #Array2D,
#instVars : [
'buffer'
],
#category : #'Diya-Math'
}
{ #category : #'instance creation' }
ProjectionMatrix class >> fromDisplay: display [
^self subclassResponsibility
]
{ #category : #accessing }
ProjectionMatrix >> buffer [
^ buffer
]
{ #category : #initialization }
ProjectionMatrix >> calculate [
self subclassResponsibility
]
{ #category : #initialization }
ProjectionMatrix >> default [
]
{ #category : #initialization }
ProjectionMatrix >> handle [
^buffer getHandle
]
{ #category : #initialization }
ProjectionMatrix >> initialize [
super initialize.
self rows:4 columns: 4 contents: ((Array new: 16) atAllPut: 0).
1 to: 4 do: [ :i| self at: i at:i put: 1.0 ].
buffer := FFIExternalArray externalNewType: #float size: self size.
buffer autoRelease.
self default.
self update
]
{ #category : #initialization }
ProjectionMatrix >> update [
|i|
self calculate.
i := 1.
self asArray do:[:e|
buffer at:i put:e.
i := i+1
].
]

14
Diya/Uniform1F.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform1F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform1F >> setUniformValue: value [
OpenGLSLUniform uniform1f: location value: value
]

14
Diya/Uniform1i.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform1i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform1i >> setUniformValue: value [
OpenGLSLUniform uniform1i: location value: value
]

14
Diya/Uniform2F.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform2F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform2F >> setUniformValue: value [
OpenGLSLUniform uniform2f: location value: value first value: value last
]

14
Diya/Uniform2i.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform2i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform2i >> setUniformValue: value [
OpenGLSLUniform uniform2i: location value: value first value: value last
]

14
Diya/Uniform3F.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform3F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform3F >> setUniformValue: value [
OpenGLSLUniform uniform3f: location value: value first value: (value at:2) value: value last
]

14
Diya/Uniform3i.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform3i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform3i >> setUniformValue: value [
OpenGLSLUniform uniform3i: location value: value first value: (value at:2) value: value last
]

18
Diya/Uniform4F.class.st Normal file
View File

@ -0,0 +1,18 @@
Class {
#name : #Uniform4F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform4F >> setUniformValue: value [
OpenGLSLUniform uniform4f: location
value: value first
value: (value at:2)
value: (value at:3)
value: value last
]

18
Diya/Uniform4i.class.st Normal file
View File

@ -0,0 +1,18 @@
Class {
#name : #Uniform4i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform4i >> setUniformValue: value [
OpenGLSLUniform uniform4i: location
value: value first
value: (value at:2)
value: (value at:3)
value: value last
]

View File

@ -0,0 +1,18 @@
Class {
#name : #UniformMatrix3fv,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
UniformMatrix3fv >> setUniformValue: value [
OpenGLSLUniform
uniformMatrix3fv: location
count: 1
transpose: value first
value: value last getHandle
]

View File

@ -0,0 +1,18 @@
Class {
#name : #UniformMatrix4fv,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
UniformMatrix4fv >> setUniformValue: value [
OpenGLSLUniform
uniformMatrix4fv: location
count: 1
transpose: value first
value: value last getHandle
]

View File

@ -1,5 +1,8 @@
# Diya-API
Diya base system API
Diya base system API:
* SDL2, OpenGL and Freetype binding
* Base Graphic stack for touch device
* Application API for application development
```smalltalk