Page 2 sur 2

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 11:27
par SPH
9 sprites de quelle taille et représentant quoi ? :?:

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 11:40
par Ollivier
Affiche 81 sprites en damier de 9 par 9, comme des icônes.
La taille : 40, 48 ou 64 pixels. C'est selon la hauteur disponible de ton écran.

Qu'est-ce qu'il doivent représenter ?

-> Ils doivent représenter les couleurs que tu as besoin de tester dans des mélanges (blend).

Grosso modo : tu as :
0
1
2
...
...
253
254
255
0
1
2
etc...

Donc il te faut tester les couleurs 254 et 255 : la 1ère ne doit pas bouger (au final). Tandis que la 2nde doit passer à zéro.

À mon avis, il faut que tu dessines dans les sprites des carrés avec les couleurs suivantes :
(254,254,254,0)
(254,254,254,254)
(254,254,254,255)
(255,255,255,0)
(255,255,255,254)
(255,255,255,255)

(avec l'option #PB_2DDrawing_AllChannels)

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 12:16
par SPH
Ok, je vois... et encore...

Mais bon, on est loin de ce que je demandais...
Les polygons OpenGl sont supers rapides à afficher. Et je ne vois pas comment je peux dessiner des triangles avec des sprites.
=====
Non mais soyons précis :
Il y a un code qui permet d'augmenter l'alpha de 2 triangles OpenGl se chevauchant. Ce code (une DLL ?) calcule la nouvelle teinte. Et bien, dans ce code, il y a une instruction (ou plusieurs) qui plafonne la teinte d'un croisement de triangles.
Je veux juste qu'on m'indique quel fichier (EXE ou DLL) est concerné.

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 12:20
par G-Rom
Je veux juste qu'on m'indique quel fichier (EXE ou DLL) est concerné.
C'est ton pilote de carte graphique qui fait cela, y a pas de code à modifier , c'est un comportement naturel d'opengl.

Tu pourrais à la rigueur utilisé glReadPixels() pour lire le pixel courant ( fonction lente ) et ajuster la couleur de ton triangle
ou d'imaginer un fragment shader qui le fait pour toi ( rapide )

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 12:26
par SPH
Voilà qui est précis.

Merci, je vais réfléchir à ça. :idea:

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 13:19
par Ollivier
Franchement, je ne vais pas renier : les shaders, c'est rapide, c'est sûr. Mais vérifier les blends, tranquillement avec les sprites, de manière rigoureuse, ça prend moins de temps.

Un exemple de code pour les shaders ici (par sq4)

Donc, bonne réflexion !! (et n'hésite pas à relancer pour revenir un petit peu aux sprites... Il n'y a rien d'inutile parfois...)

Code intégral :

Code : Tout sélectionner

#W=1200
#H=800

#GL_COLOR_BUFFER_BIT                = $00004000
#GL_DEPTH_BUFFER_BIT                = $00000100
#GL_ARRAY_BUFFER                    = $8892
#GL_ELEMENT_ARRAY_BUFFER            = $8893
#GL_MODELVIEW                       = $1700
#GL_PROJECTION                      = $1701
#GL_SMOOTH                          = $1D01
#GL_DEPTH_TEST                      = $0B71
#GL_CULL_FACE                       = $0B44
#GL_STATIC_DRAW                     = $88E4
#GL_VERTEX_ARRAY                    = $8074
#GL_FLOAT                           = $1406
#GL_TRIANGLES                       = $0004
#GL_UNSIGNED_BYTE                   = $1401
#GL_UNSIGNED_SHORT                  = $1403
#GL_UNSIGNED_INT                    = $1405

#GL_ARRAY_BUFFER = $8892
#GL_STATIC_DRAW = $88E4
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30
#GL_TEXTURE0 = $84C0
#GL_TEXTURE1 = $84C1

#GL_BGR = $80E0
#GL_BGRA = $80E1
#GL_RGB= $1907
#GL_RGBA= $1908

Prototype glGenBuffers( n.i, *buffers)
Prototype glBindBuffer( target.l, buffer.i)
Prototype glBufferData ( target.l, size.i, *Data_, usage.l)
Prototype glBufferSubData ( target.l, offset.i, size.i, *Data_)
Prototype glGenVertexArrays (n.i, *arrays)
Prototype glBindVertexArray(n.i)
Prototype glEnableVertexAttribArray ( index.i )
Prototype glVertexAttribPointer ( index.i, size.i, type.l, normalized.b, stride.i, *pointer )
Prototype glDrawArrays ( mode.l, first.i, count.i )
Prototype glIndexPointer ( enum.i, stride.i, *length )
Prototype glDeleteBuffers ( n.i, *buffers)
Prototype glDeleteVertexArrays ( n.i, *buffers)
Prototype glDisableVertexAttribArray(index.i)
Prototype glMapBuffer(Target.i, Access.i)
Prototype glUnmapBuffer(Target.i)
Prototype glActiveTexture(Texture.l)
Prototype glUniformMatrix4fv(location.i, count.i, transpose.b, *value)

Prototype glCreateShader(type.l)
Prototype glCreateProgram()
Prototype glCompileShader(shader.l)
Prototype glDeleteShader(ShaderObj.i)
Prototype glLinkProgram(shader.l)
Prototype glUseProgram(shader.l)
Prototype glAttachShader(Program.l, shader.l)
Prototype glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) :
Prototype glGetUniformLocation(Program.i, name.p-ascii)
Prototype glUniform1i(location.i, v0.i)
Prototype glUniform2i(location.i, v0.i, v1.i)
Prototype glUniform1f(location.i, v0.f)
Prototype glUniform2f(location.i, v0.f, v1.f)
Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)

Structure GLSL
  glGenBuffers.glGenBuffers
  glBindBuffer.glBindBuffer
  glBufferData.glBufferData
  glBufferSubData.glBufferSubData
  glGenVertexArrays.glGenVertexArrays
  glBindVertexArray.glBindVertexArray
  glEnableVertexAttribArray.glEnableVertexAttribArray
  glVertexAttribPointer.glVertexAttribPointer
  glDrawArrays.glDrawArrays
  glIndexPointer.glIndexPointer
  glDeleteBuffers.glDeleteBuffers
  glDeleteVertexArrays.glDeleteVertexArrays
  glDisableVertexAttribArray.glDisableVertexAttribArray
  glMapBuffer.glMapBuffer
  glUnmapBuffer.glUnmapBuffer
  glActiveTexture.glActiveTexture
  glUniformMatrix4fv.glUniformMatrix4fv
  glCreateShader.glCreateShader
  glCreateProgram.glCreateProgram
  glCompileShader.glCompileShader
  glDeleteShader.glDeleteShader
  glLinkProgram.glLinkProgram
  glUseProgram.glUseProgram
  glAttachShader.glAttachShader
  glShaderSource.glShaderSource
  glGetUniformLocation.glGetUniformLocation
  glUniform1i.glUniform1i
  glUniform2i.glUniform2i
  glUniform1f.glUniform1f
  glUniform2f.glUniform2f
  glGetShaderInfoLog.glGetShaderInfoLog
EndStructure

Procedure GLGetFunctions(*GLSL.GLSL)
  *GLSL\glGenBuffers = wglGetProcAddress_("glGenBuffers")
  *GLSL\glBindBuffer = wglGetProcAddress_("glBindBuffer")
  *GLSL\glBufferData = wglGetProcAddress_("glBufferData")
  *GLSL\glBufferSubData = wglGetProcAddress_("glBufferSubData")
  *GLSL\glGenVertexArrays = wglGetProcAddress_("glGenVertexArrays")
  *GLSL\glBindVertexArray = wglGetProcAddress_("glBindVertexArray")
  *GLSL\glEnableVertexAttribArray = wglGetProcAddress_("glEnableVertexAttribArray")
  *GLSL\glVertexAttribPointer = wglGetProcAddress_("glVertexAttribPointer")
  *GLSL\glDrawArrays = wglGetProcAddress_("glDrawArrays")
  *GLSL\glIndexPointer = wglGetProcAddress_("glIndexPointer")
  *GLSL\glDeleteBuffers = wglGetProcAddress_("glDeleteBuffers")
  *GLSL\glDeleteVertexArrays = wglGetProcAddress_("glDeleteVertexArrays")
  *GLSL\glDisableVertexAttribArray = wglGetProcAddress_("glDisableVertexAttribArray")
  *GLSL\glMapBuffer = wglGetProcAddress_("glMapBuffer")
  *GLSL\glUnmapBuffer = wglGetProcAddress_("glUnmapBuffer")
  *GLSL\glActiveTexture = wglGetProcAddress_("glActiveTexture")
  *GLSL\glUniformMatrix4fv=wglGetProcAddress_("glUniformMatrix4fv")
  *GLSL\glCreateShader = wglGetProcAddress_("glCreateShader")
  *GLSL\glCreateProgram = wglGetProcAddress_("glCreateProgram")
  *GLSL\glCompileShader = wglGetProcAddress_("glCompileShader")
  *GLSL\glDeleteShader = wglGetProcAddress_("glDeleteShader")
  *GLSL\glLinkProgram = wglGetProcAddress_("glLinkProgram")
  *GLSL\glUseProgram = wglGetProcAddress_("glUseProgram")
  *GLSL\glAttachShader = wglGetProcAddress_("glAttachShader")
  *GLSL\glShaderSource = wglGetProcAddress_("glShaderSource")
  *GLSL\glGetUniformLocation = wglGetProcAddress_("glGetUniformLocation")
  *GLSL\glUniform1i = wglGetProcAddress_("glUniform1i")
  *GLSL\glUniform2i = wglGetProcAddress_("glUniform2i")
  *GLSL\glUniform1f = wglGetProcAddress_("glUniform1f")
  *GLSL\glUniform2f = wglGetProcAddress_("glUniform2f")
  *GLSL\glGetShaderInfoLog = wglGetProcAddress_("glGetShaderInfoLog")    
EndProcedure

Global points_vbo.i, colors_vbo.i, vao.i, ebo.i, texture.i, transparenz.f

Structure _2DPoint
  x.f
  y.f
EndStructure

Structure _2DTex
  x.f
  y.f
EndStructure

Structure myTexVertex
  Pos._2DPoint
  Tex._2DTex
EndStructure

Structure Tindex
  a.l
  b.l
  c.l
  d.l
EndStructure

UseJPEGImageDecoder()
UsePNGImageDecoder()

#ImagePath = #PB_Compiler_Home + "examples/3d/Data/Textures/"
LoadImage(1, #ImagePath + "ValetCoeur.jpg")
ImgDepth=ImageDepth(1)
If ImgDepth<>32
  CreateImage(2,ImageWidth(1), ImageHeight(1),32)
  StartDrawing(ImageOutput(2))
  DrawImage(ImageID(1),0,0)
  StopDrawing()
  FreeImage(1)
  CopyImage(2,1)
  FreeImage(2)
EndIf
  
Sprite_W=ImageWidth(1)
Sprite_H=ImageHeight(1)

StartDrawing(ImageOutput(1))
  Debug DrawingBufferPixelFormat()
  mem=DrawingBuffer()
  size=DrawingBufferPitch()* ImageHeight(1)
  *Buffer1=AllocateMemory(size)
  CopyMemory(mem, *Buffer1, size)
StopDrawing()

Dim Vertex.myTexVertex(3)

Sprite_X=0
Sprite_Y=0

; Vertexes in WorldSpace
; // top left
Vertex(0)\Pos\x = -1  : Vertex(0)\Pos\y = 1 
Vertex(0)\Tex\x = 0.0   : Vertex(0)\Tex\y = 1.0

;// top right
Vertex(1)\Pos\x = 1   : Vertex(1)\Pos\y = 1
Vertex(1)\Tex\x = 1.0   : Vertex(1)\Tex\y = 1.0

; // bottom left
Vertex(2)\Pos\x = -1  : Vertex(2)\Pos\y = -1
Vertex(2)\Tex\x = 0.0   : Vertex(2)\Tex\y = 0.0

; // bottom right
Vertex(3)\Pos\x = 1   : Vertex(3)\Pos\y = -1
Vertex(3)\Tex\x = 1.0   : Vertex(3)\Tex\y = 0.0

;Another way to transform, but that's not the question...
;fLeft.f=((Sprite_X/#W)-0.5)*2
;fTop.f=(0.5-(Sprite_Y/#H))*2
;fRight.f=(((Sprite_X+Sprite_W)/#W)-0.5)*2
;fBottom.f=(0.5-((Sprite_Y+Sprite_H)/#H))*2

Dim uRotate.f(3,3)
Dim uScale.f(3,3)
Dim uTranslate.f(3,3)
Dim Index.Tindex(0)
Index(0)\a = 2  : Index(0)\b = 3  : Index(0)\c = 1  : Index(0)\d = 0

Global GLSL.GLSL

;**************************************************************************************

OpenWindow(0, 0, 0, #W, #H, "GLSL sprites in WindowedScreen")
InitSprite()
OpenWindowedScreen(WindowID(0),0,0,#W,#H)

;**************************************************************************************
GLGetFunctions(GLSL.GLSL)
;**************************************************************************************

glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
glEnable_(#GL_DEPTH_TEST); // enable depth-testing
glEnable_(#GL_BLEND)
glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA) 

GLSL\glGenVertexArrays(1, @vao) 
GLSL\glGenBuffers(1, @points_vbo )
GLSL\glGenBuffers(1, @ebo)       

GLSL\glBindVertexArray(vao)
GLSL\glBindBuffer(#GL_ARRAY_BUFFER, points_vbo)
GLSL\glBufferData(#GL_ARRAY_BUFFER,SizeOf(myTexVertex) * (ArraySize(Vertex())+1),@Vertex(0), #GL_STATIC_DRAW) 

GLSL\glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo)
GLSL\glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 16*(ArraySize(Index())+1), @Index(0), #GL_STATIC_DRAW)

GLSL\glVertexAttribPointer(0, SizeOf(_2DPoint)/SizeOf(float), #GL_FLOAT, #GL_FALSE, SizeOf(myTexVertex), 0)
GLSL\glEnableVertexAttribArray(0)     

GLSL\glVertexAttribPointer(1, SizeOf(_2DTex)/SizeOf(float), #GL_FLOAT, #GL_FALSE, SizeOf(myTexVertex), OffsetOf(myTexVertex\Tex))
GLSL\glEnableVertexAttribArray(1);

glGenTextures_(1, @texture1)
glBindTexture_(#GL_TEXTURE_2D, texture1)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP_TO_EDGE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP_TO_EDGE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
glTexImage2D_(#GL_TEXTURE_2D, 0, 4, ImageWidth(1), ImageHeight(1), 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, *Buffer1)
 ;glGenerateMipmap_(#GL_TEXTURE_2D)
FreeMemory(*Buffer1)

Define vertex_shader.s
Define fragment_shader.s
Define *fbuff
Define *vbuff

vertex_shader = "#version 330 core"+#CRLF$
vertex_shader + "layout(location = 0) in vec2 aPos;"+#CRLF$             ; the position variable has attribute position 0
vertex_shader + "layout(location = 1) in vec2 aTexCoord;"+#CRLF$        ; the color variable has attribute position 1
vertex_shader + "out vec2 TexCoord;"+#CRLF$
vertex_shader + "uniform mat4 uScale;"+#CRLF$
vertex_shader + "uniform mat4 uRotate;"+#CRLF$
vertex_shader + "uniform mat4 uTranslate;"+#CRLF$
vertex_shader + "void main() {"+#CRLF$
vertex_shader + "vec4 Position = vec4(aPos, 1.0, 1.0);"+#CRLF$

;I DO NOT UNDERSTAND WHY ROTATE/SCALE acts like this
vertex_shader + "Position = uRotate*Position;"+#CRLF$
vertex_shader + "Position = uScale*Position;"+#CRLF$
vertex_shader + "Position = uTranslate*Position;"+#CRLF$

vertex_shader + "gl_Position = Position;"+#CRLF$
vertex_shader + "TexCoord = aTexCoord;"+#CRLF$
vertex_shader + "}"

fragment_shader = "#version 330 core"+#CRLF$
fragment_shader + "out vec4 FragColor;"+#CRLF$
fragment_shader + "in vec2 TexCoord;"+#CRLF$
fragment_shader + "uniform sampler2D texture1;"+#CRLF$

fragment_shader + "void main()"+#CRLF$
fragment_shader + "{"+#CRLF$
fragment_shader + "   FragColor = texture(texture1, TexCoord)*vec4(1.,1.,1.,1);"+#CRLF$
fragment_shader + "}"+#CRLF$

*vbuff = Ascii(vertex_shader)
*fbuff = Ascii(fragment_shader)


Global vs = GLSL\glCreateShader(#GL_VERTEX_SHADER);
GLSL\glShaderSource(vs, 1, @*vbuff, #Null) ;
GLSL\glCompileShader(vs)

  buffer = AllocateMemory(512)
  GLSL\glGetShaderInfoLog(vs,512,#Null,buffer)
  Log$=PeekS(buffer,512,#PB_Ascii)
  If Log$:Debug Log$:EndIf
  FreeMemory(buffer)


Global fs = GLSL\glCreateShader(#GL_FRAGMENT_SHADER);
GLSL\glShaderSource(fs, 1, @*fbuff, #Null);
GLSL\glCompileShader(fs) 


Global Shader = GLSL\glCreateProgram();
GLSL\glAttachShader(Shader, vs)
GLSL\glAttachShader(Shader, fs)
GLSL\glLinkProgram(Shader)     

GLSL\glDeleteShader(vs)
GLSL\glDeleteShader(fs)


GLSL\glUseProgram(Shader)  ; // don't forget to activate/use the shader before setting uniforms!
GLSL\glUniform1i(GLSL\glGetUniformLocation(Shader, "texture1"), 0)  ; muss nur einmal festgelegt werden

GLSL\glActiveTexture(#GL_TEXTURE0);
glBindTexture_(#GL_TEXTURE_2D, texture1)

Repeat
 Event = WindowEvent()
          
  ;glClearColor_(0.2, 0.5, 0.3, 1)
  ;glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
  ;glViewport_(0, 0, #W, #H) 
    
  GLSL\glUseProgram(Shader) 
    
  GLSL\glBindVertexArray(vao)
  Scale_X.f=(Sprite_W/#W)
  Scale_Y.f=Sprite_H/#H
  
  Sprite_X=0
  Sprite_Y=0

  fLeft.f=Sprite_X/(#W/2)
  fTop.f=Sprite_Y/#H
  myCos.f=Cos(Radian(Angle))
  mySin.f=Sin(Radian(Angle))
  
  Angle+1
  Angle%360

  ;Trying to understand matrices.....???
  ;Why is the aspect ratio of the image not correct after rotate / scale ?????
  uScale(0,0)=Scale_X : uScale(1,0)=0 : uScale(2,0)=0 : uScale(3,0)=0
  uScale(0,1)=0 : uScale(1,1)=Scale_Y : uScale(2,1)=0 : uScale(3,1)=0
  uScale(0,2)=0 : uScale(1,2)=0 : uScale(2,2)=1 : uScale(3,2)=0
  uScale(0,3)=0 : uScale(1,3)=0 : uScale(2,3)=0 : uScale(3,3)=1

  uRotate(0,0)=myCos : uRotate(1,0)=-mySin : uRotate(2,0)=0 : uRotate(3,0)=0
  uRotate(0,1)=mySin : uRotate(1,1)=myCos : uRotate(2,1)=0 : uRotate(3,1)=0
  uRotate(0,2)=0 : uRotate(1,2)=0 : uRotate(2,2)=1 : uRotate(3,2)=0
  uRotate(0,3)=0 : uRotate(1,3)=0 : uRotate(2,3)=0 : uRotate(3,3)=1

  uTranslate(0,0)=1 : uTranslate(1,0)=0 : uTranslate(2,0)=0 : uTranslate(3,0)=fLeft
  uTranslate(0,1)=0 : uTranslate(1,1)=1 : uTranslate(2,1)=0 : uTranslate(3,1)=fTop
  uTranslate(0,2)=0 : uTranslate(1,2)=0 : uTranslate(2,2)=1 : uTranslate(3,2)=0
  uTranslate(0,3)=0 : uTranslate(1,3)=0 : uTranslate(2,3)=0 : uTranslate(3,3)=1

  GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(Shader, "uScale"), 1, #GL_FALSE, @uScale(0,0));
  GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(Shader, "uRotate"), 1, #GL_FALSE, @uRotate(0,0));
  GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(Shader, "uTranslate"), 1, #GL_FALSE, @uTranslate(0,0));

  glDrawElements_(#GL_QUADS, 4, #GL_UNSIGNED_INT, 0 )  

  GLSL\glBindVertexArray(0)
  GLSL\glUseProgram(0)   

  FlipBuffers()  
Until Event = #PB_Event_CloseWindow Or quit = 1

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 14:18
par G-Rom
Mais vérifier les blends, tranquillement avec les sprites, de manière rigoureuse, ça prend moins de temps
Bah non, c'est le principe du shader, c'est exécuté sur le GPU, ca explose en perf, de plus la vérification de ton Blend se fera sur l'entièreté d'un triangle, un fragment shader marche au pixel , donc si 2 triangles se chevauches tu peu facilement passé au noir uniquement dans la partie qui est full blanche, ce qui est impossible avec un simple blend, sauf si tu part sur des calculs d'intersection, mais c'est pas le sujet.

Donc la réponse , fragment shader.

Ton fragment shader ressemblerais à qq chose dans le genre :

Code : Tout sélectionner

uniform sampler2D maTexture;

void main(){

	vec4 color  = texture2D(maTexture, gl_TexCoord.uv);
	
	if(color == vec4(1.0,1.0,1.0,1.0) ){ // c'est tout blanc alors
		gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); // on dessine du noir
	}else{
		gl_FragColor = vec4(1.0, 1.0, 1.0, 0.1); // ou du blanc à 10% d'opacité
	}

}
ce code sera exécuté par le gpu sur chaque pixel qui l'affichera. mais avant d'en arrivé là , il faudrait que tu rende ta scène dans une texture et que tu la passe en paramètre au shader, et que tu execute le shader sur chaque affichage de triangle. y a une mécanique à comprendre


- Création d'une texture de rendu
- Chargement du shader en mémoire

- Activation du shader , on passe en paramètre la première texture de rendu
- on dessine un triangle, le shader fait ce pour quoi il est programmé
- on desactive le shader
- on affiche la texture de rendu à l'écran ( 2 tri , un quad , etc... )
- on recommence avec le prochain triangle 4 ligne plus haut

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 15:37
par Ollivier
Allez sph, on est de tout coeur avec toi. Ça va shader !

Re: Alpha OpenGL

Publié : mar. 20/déc./2022 16:41
par SPH
Ollivier a écrit : mar. 20/déc./2022 15:37 Allez sph, on est de tout coeur avec toi. Ça va shader !
Actuellement, je bosse sur mon jeu.

Pour en revenir a ton expression "shader", figure toi que l'effet que je veux faire s'appelle "shadebob" (terme AMIGAiste des années 90)

Re: Alpha OpenGL

Publié : jeu. 22/déc./2022 18:17
par Ollivier
Oui, ton truc, ça va révolutionner les couvercles de confiture bonne maman.