From 172a62192e6395651be34bf42a9ef2b5b44bc8c7 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Tue, 8 Mar 2022 23:30:01 +0100 Subject: [PATCH] image texture support --- Diya/Color.extension.st | 10 +++++ Diya/Diya2DPrimShape.class.st | 10 ++--- Diya/Diya2DShader.class.st | 14 ++++--- Diya/DiyaBoot.class.st | 14 +++++-- Diya/DiyaImageTex.class.st | 74 ++++++++++++++++++++++++++++++++++ Diya/DiyaText.class.st | 2 +- Diya/OpenGLConstants.class.st | 2 + Diya/OpenGLTexImage2D.class.st | 10 ++--- Diya/OpenGLTexture.class.st | 8 ++++ 9 files changed, 123 insertions(+), 21 deletions(-) create mode 100644 Diya/DiyaImageTex.class.st diff --git a/Diya/Color.extension.st b/Diya/Color.extension.st index 47af6a8..9af9bdf 100644 --- a/Diya/Color.extension.st +++ b/Diya/Color.extension.st @@ -1,5 +1,15 @@ 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 } diff --git a/Diya/Diya2DPrimShape.class.st b/Diya/Diya2DPrimShape.class.st index 49d176d..9fd07ee 100644 --- a/Diya/Diya2DPrimShape.class.st +++ b/Diya/Diya2DPrimShape.class.st @@ -10,12 +10,10 @@ Class { { #category : #initialization } Diya2DPrimShape >> draw [ vbuffer ifNil: [ ^self ]. - self shader - setUniform: #u_use_texture value:1. "configure vao vbo for texture QUAD" self texture ifNotNil: [ self texture setup. - context texture0 setImage2D: self texture. + context texture0 setImage2D: self texture. context texture0 active. ]. context vao enableAttribute: 0. @@ -36,10 +34,10 @@ Diya2DPrimShape >> initialize [ { #category : #initialization } Diya2DPrimShape >> setUpShader [ - super setUpShader. - texture ifNotNil: [ + super setUpShader + texture ifNotNil:[ self shader - setUniform: #u_use_texture value:1. + setUniform: #u_texture_type value: texture format. ]. ] diff --git a/Diya/Diya2DShader.class.st b/Diya/Diya2DShader.class.st index 6b47af0..a67aa60 100644 --- a/Diya/Diya2DShader.class.st +++ b/Diya/Diya2DShader.class.st @@ -15,18 +15,22 @@ uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; // 2D uniforms -uniform int u_use_texture; +uniform int u_texture_type; uniform vec4 u_color; uniform vec4 u_border_color; uniform sampler2D u_texture; varying vec2 texcoord; void main(void) { vec4 texcolor = vec4(1,1,1,1); - if(u_use_texture == 1) - { + // alpha + if(u_texture_type == 0x1906) { texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a); } - gl_FragColor = texcolor * u_color; + // rgba + else if (u_texture_type == 0x1908){ + texcolor = texture2D(u_texture, texcoord); + } + gl_FragColor = texcolor * u_color; }' ] @@ -50,7 +54,7 @@ void main() { #category : #initialization } Diya2DShader >> setUpUniforms [ self addUniform: #u_texture of: Uniform1i. - self addUniform: #u_use_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: Uniform1i. diff --git a/Diya/DiyaBoot.class.st b/Diya/DiyaBoot.class.st index 5150d7e..ccbbb33 100644 --- a/Diya/DiyaBoot.class.st +++ b/Diya/DiyaBoot.class.st @@ -70,13 +70,19 @@ DiyaBoot >> createWindow [ DiyaBoot >> exampleNodes [ |root text rec style| root := DiyaRootNode new. - rec := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 200. - style := DiyaFontManager uniqueInstance style: 'Bold' from: 'Ubuntu'. - rec texture: (style textureOf: 16). - rec color: (Color r: 1.0 g:0.0 b:1.0 alpha:1.0 ). + rec := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430. + rec texture: (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png'). + rec color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ). + + style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'. + rec := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50. + rec color: (Color orange). + rec texture: (style textureOf: 20). + rec := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400. rec rotation: (Float pi / -8.0). rec scale: 1.5@1.5. + text := root addNode: (DiyaText data: String loremIpsum) at: 20@320. text extent: 200@320. text wordWrap: true. diff --git a/Diya/DiyaImageTex.class.st b/Diya/DiyaImageTex.class.st new file mode 100644 index 0000000..5b29cf7 --- /dev/null +++ b/Diya/DiyaImageTex.class.st @@ -0,0 +1,74 @@ +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| + 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. +] diff --git a/Diya/DiyaText.class.st b/Diya/DiyaText.class.st index b52a173..597ce8a 100644 --- a/Diya/DiyaText.class.st +++ b/Diya/DiyaText.class.st @@ -40,7 +40,7 @@ DiyaText >> data: anObject [ DiyaText >> draw [ data ifNil: [ ^self ]. self shader - setUniform: #u_use_texture value:1. + setUniform: #u_texture_type value: self texture format. "configure vao vbo for texture QUAD" self texture setup. context texture0 setImage2D: self texture. diff --git a/Diya/OpenGLConstants.class.st b/Diya/OpenGLConstants.class.st index 298d369..9620914 100644 --- a/Diya/OpenGLConstants.class.st +++ b/Diya/OpenGLConstants.class.st @@ -49,6 +49,7 @@ Class { 'GL_QUAD_STRIP', 'GL_RED', 'GL_RGB', + 'GL_RGBA', 'GL_SHADER_SOURCE_LENGTH', 'GL_SHADER_TYPE', 'GL_SHORT', @@ -109,6 +110,7 @@ OpenGLConstants class >> initCommonConstants [ GL_GREEN := 16r1904. GL_ALPHA := 16r1906. GL_RGB := 16r1907. + GL_RGBA := 16r1908. ] { #category : #'class initialization' } diff --git a/Diya/OpenGLTexImage2D.class.st b/Diya/OpenGLTexImage2D.class.st index 85c0459..19ea8b8 100644 --- a/Diya/OpenGLTexImage2D.class.st +++ b/Diya/OpenGLTexImage2D.class.st @@ -102,6 +102,11 @@ OpenGLTexImage2D >> level: anObject [ level := anObject ] +{ #category : #accessing } +OpenGLTexImage2D >> mipmap [ + ^false +] + { #category : #accessing } OpenGLTexImage2D >> setup [ ^self subclassResponsibility @@ -117,11 +122,6 @@ OpenGLTexImage2D >> target: anObject [ target := anObject ] -{ #category : #accessing } -OpenGLTexImage2D >> teardown [ - ^self subclassResponsibility -] - { #category : #accessing } OpenGLTexImage2D >> type [ ^ type diff --git a/Diya/OpenGLTexture.class.st b/Diya/OpenGLTexture.class.st index 7c356ca..e4f4bbb 100644 --- a/Diya/OpenGLTexture.class.st +++ b/Diya/OpenGLTexture.class.st @@ -52,6 +52,11 @@ 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)) @@ -110,6 +115,9 @@ OpenGLTexture >> setImage2D: tex2D [ format: tex2D format type: tex2D type data: tex2D data getHandle. + tex2D mipmap ifTrue:[ + self class generateMipmap: tex2D target + ]. ] { #category : #initialization }