Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Morphing Stained Glass
#14
(09-13-2024, 11:28 PM)SMcNeill Wrote: First thing I'd advise to speed it up is to remove as much math as possible from the process.  For example:

Code: (Select All)
_MEMPUT mImage, mImage.OFFSET + (y * sWidth + x) * 4, Points(Nearest).c

mImage.OFFSET + (y * sWidth + x) * 4  <-- this right here can be simplified by a ton with just a little logic.

First, distribute the 4 to outside the loop:

x = x + 4  (instead of x = x + 1) and then multiply by 4.

y = y + 4 (instead of the y = y + 1 that it currently is.  This would save one calculation per cyctle (mImge.OFFSET + (y * sWidth + x) without that * 4 being needed.)

....

but then that can be simplified down even more:
x = x + 4  <-- this would move x position by 4 bytes, or one pixel at a time
y = y + (sWidth * 4)  <--- seems to me that this should increase y by the whole row of pixels in one go.

now that internal math looks like:  (mImage.OFFSET + y + x)

And, if you start y somewhere with the offset as the starting point:

y = mImage.OFFSET

Then you can make that whole _MEMPUT statement simplify down to:

Code: (Select All)
_MEMPUT mImage, y + x, Points(Nearest).c

^That'll shave off several internal processing cycles from your routine. 


  So basically the flow would be:

y = mImage.OFFSET
DO
  DO
      _MEMPUT mImage, y + x, Points(Nearest).c
      x = x + 4
  LOOP
  y = y + sWidth * 4
LOOP until y + x >= m.SIZE



Anytime you can strip math out of a main loop like that, you can speed things up considerably.
You are so much better at refactoring than I am. Thank you for the suggestions. They are so obvious to me now.

(09-13-2024, 10:42 PM)DSMan195276 Wrote: Something a bit different, I changed your rendering code into a shader. The code is a mess but it does work for me and I can get 500 points rendering at 60FPS. YMMV, I pass the points in as a uniform and that limits how many you can use, you should be able to do at least 100 though. There are better ways to do it that could support more points but this was the easiest way since I was reusing some code I already had.

The code is below, and it requires a header file to be placed next to it so it can access some functions:

Code: (Select All)
Option _Explicit

Const TOTAL = 100

Type vec2
    x As Single
    y As Single
End Type

Dim Shared points(TOTAL) As vec2
Dim Shared cols(TOTAL) As vec3
Dim Shared vectors(TOTAL) As vec2

Randomize Timer '                                                                  seed RND generator
Dim p As Long
For p = 0 To TOTAL - 1 '                                                              cycle through pane center points
    points(p).x = Rnd * 1 '                                                      random x location
    points(p).y = Rnd * 1 '                                                    random y location
    cols(p).x = Rnd * .5 + .5
    cols(p).y = Rnd * .5 + .5
    cols(p).z = Rnd * .5 + .5
    'cols(p) = _RGB32(Rnd * 128 + 128, Rnd * 128 + 128, Rnd * 128 + 128) '        random color above 128, 128, 128    vectors(p).x = (Rnd - Rnd) * .005 '                                                  random x velocity
    vectors(p).y = (Rnd - Rnd) * .005 '                                                  random y velocity
Next p

Type vec3
    x As Single
    y As Single
    z As Single
End Type

Type tri
    p1 As vec3
    p2 As vec3
    p3 As vec3
End Type

Type model
    bufId As _Unsigned Long
    vertArrId As _Unsigned Long
    pointsId As _Unsigned Long
    colorsId As _Unsigned Long

    prog As _Unsigned Long

    tris As _MEM
    triCount As _Unsigned Long
End Type

Declare Library
    Function glCreateProgram& ()
    Function glCreateShader& (ByVal flags As _Unsigned Long)
    Sub glCompileShader (ByVal shader As _Unsigned Long)
    Sub glAttachShader (ByVal prog As _Unsigned Long, Byval shader As _Unsigned Long)
    Sub glLinkProgram (ByVal prog As _Unsigned Long)
    Sub glUseProgram (ByVal prog As _Unsigned Long)


    ' Sub glGenBuffers (ByVal size As _Unsigned Long, Byval buffers As _Offset)
    Sub glBindBuffer (ByVal target As _Unsigned Long, Byval buffer As _Unsigned Long)

    ' Sub glGenVertexArrays (ByVal size As _Unsigned Long, Byval buffers As _Offset)
    Sub glBindVertexArray (ByVal array As _Unsigned Long)

    Sub glEnableVertexAttribArray (ByVal index As _Unsigned Long)
    Sub glVertexAttribPointer (ByVal index As _Unsigned Long, _
                                    Byval size As _Unsigned Long, _
                                    Byval typ As _Unsigned Long, _
                                    Byval normal As _Unsigned _Byte, _
                                    Byval stride As _Unsigned Long, _
                                    Byval pointer As _Offset)

    Function glGetUniformLocation& (ByVal prog As _Unsigned Long, nam As String)

    Sub glEnable (ByVal cap As _Unsigned Long)
    Sub glDisable (ByVal cap As _Unsigned Long)
    Sub glDepthFunc (ByVal cap As _Unsigned Long)
End Declare

Declare Library "stained_glass_help"
    Sub glShaderSource Alias "myShaderSource" (ByVal shader As _Unsigned Long, Byval count As _Unsigned Long, Byval text As _Offset, Byval length As _Offset)
    Sub glGenBuffers Alias "myGenBuffers" (ByVal size As _Unsigned Long, Byval buffers As _Offset)
    Sub glGenVertexArrays Alias "myGenVertexArrays" (ByVal size As _Unsigned Long, Byval buffers As _Offset)
    Sub glBufferData ALIAS "myBufferData" (byval target As _Unsigned Long, _
                            byval size As _offset, _
                            byval dat As _Offset, _
                            byval usage As _Unsigned Long)
    Sub glDrawArrays Alias "myDrawArrays" (ByVal mode As _Unsigned Long, Byval first As _Unsigned Long, Byval count As _Unsigned Long)
    Sub glUniformMatrix4fv ALIAS "myUniformMatrix4fv" (ByVal location As _Unsigned Long, _
                                                        ByVal count As _Unsigned Long, _
                                                        ByVal transpose As _Unsigned _Byte, _
                                                        ByVal floats As _Offset)

    sub glUniform2fv ALIAS "myUniform2fv" (BYVal location As _unsigned long, _
                                byval count as _unsigned long, _
                                byval floats as _Offset)
    sub glUniform3fv ALIAS "myUniform3fv" (BYVal location As _unsigned long, _
                                byval count as _unsigned long, _
                                byval ints as _Offset)
End Declare

Const GL_TRUE~& = 1
Const GL_FALSE~& = 0
Const GL_LESS~& = 513
Const GL_DEPTH_TEST~& = 2929
Const GL_FLOAT~& = 5126
Const GL_ARRAY_BUFFER~& = 34962
Const GL_STATIC_DRAW~& = 35044
Const GL_FRAGMENT_SHADER~& = 35632
Const GL_VERTEX_SHADER~& = 35633
Const GL_TRIANGLES~& = 4
Const GL_CULL_FACE = 2884

Dim Shared v As String, f As String

v$ = "#version 150" + Chr$(10)
v$ = v$ + "in vec3 vp;" + Chr$(10)
v$ = v$ + "out vec2 uv;" + Chr$(10)
v$ = v$ + "void main() {" + Chr$(10)
v$ = v$ + "    uv = vp.xy;" + Chr$(10)
v$ = v$ + "    gl_Position = vec4(vp.x * 2 - 1, vp.y * 2 - 1, 0, 1.0);" + Chr$(10)
v$ = v$ + "}" + Chr$(0)

f$ = "#version 150" + Chr$(10)
f$ = f$ + "in vec2 uv;" + Chr$(10)
f$ = f$ + "uniform vec2 points[" + Str$(TOTAL) + "];" + Chr$(10)
f$ = f$ + "uniform vec3 colors[" + Str$(TOTAL) + "];" + Chr$(10)
f$ = f$ + "void main() {" + Chr$(10)
f$ = f$ + "    int nearestP = 0;" + Chr$(10)
f$ = f$ + "    float nearDist = length(points[0] - uv);" + Chr$(10)
f$ = f$ + "    for (int i = 1; i < " + Str$(TOTAL) + "; i++) {" + Chr$(10)
f$ = f$ + "        float newDist = length(points[i] - uv);" + Chr$(10)
f$ = f$ + "        if (newDist < nearDist) {" + Chr$(10)
f$ = f$ + "            nearDist = newDist;" + Chr$(10)
f$ = f$ + "            nearestP = i;" + Chr$(10)
f$ = f$ + "        }" + Chr$(10)
f$ = f$ + "    }" + Chr$(10)
f$ = f$ + "    gl_FragColor = vec4(colors[nearestP], 255);" + Chr$(10)
f$ = f$ + "}" + Chr$(0)

Dim Shared square As model
loadSquareModel square

Dim Shared startGL As _Unsigned Long

Sleep 1
startGL = -1

Do
    _Limit 60

    Dim k As String

    k$ = InKey$
    If k$ = Chr$(27) Then Exit Do
Loop

End

Sub _GL
    Static initShad

    If initShad = 0 And startGL Then
        setupModel square, v$, f$

        initShad = -1
    End If
    If Not initShad Then Exit Sub

    glDisable GL_CULL_FACE
    glEnable GL_DEPTH_TEST
    glDepthFunc GL_LESS

    RenderModel square

    Dim p As Long
    p = 0
    Dim dx As Single, dy As Single

    Do '                                                                            begin point update loop
        dx = points(p).x + vectors(p).x '                                            calculate new look ahead point x location
        dy = points(p).y + vectors(p).y '                                            calculate new look ahead point y location
        If dx < 0 Or dx > 1 Then vectors(p).x = -vectors(p).x '              reverse vector if left/right side of image reached
        If dy < 0 Or dy > 1 Then vectors(p).y = -vectors(p).y '            reverse vector if top/bottom side of image reached
        points(p).x = points(p).x + vectors(p).x '                                    calculate new point x location
        points(p).y = points(p).y + vectors(p).y '                                    calculate new point y location
        p = p + 1 '                                                                  increment point counter
    Loop Until p = TOTAL '                                                            leave when all points updated
End Sub

Sub RenderModel (m As model)
    glUseProgram m.prog

    glUniform2fv m.pointsId, UBound(points), _Offset(points())
    glUniform3fv m.colorsId, UBound(cols), _Offset(cols())

    glBindVertexArray m.vertArrId
    glDrawArrays GL_TRIANGLES, 0, m.triCount * 3
End Sub

Sub loadSquareModel (m As model)
    Dim t As tri
    m.tris = _MemNew(Len(t) * 2)
    m.triCount = 2

    putTriVec m.tris, 0, 0, 0, 0, 0
    putTriVec m.tris, 0, 1, 0, 1, 0
    putTriVec m.tris, 0, 2, 1, 0, 0

    putTriVec m.tris, 1, 0, 0, 1, 0
    putTriVec m.tris, 1, 1, 1, 1, 0
    putTriVec m.tris, 1, 2, 1, 0, 0
End Sub

Sub putTriVec (m As _MEM, TriIndex As _Unsigned Long, VecIndex As _Unsigned Long, x As Single, y As Single, z As Single)
    Dim v As vec3, t As tri
    v.x = x: v.y = y: v.z = z

    _MemPut m, m.OFFSET + TriIndex * Len(t) + Len(v) * VecIndex, v
End Sub

Sub setupModel (m As model, vshad As String, fshad As String)
    Dim t As tri
    Dim vs As _Unsigned Long, fs As _Unsigned Long
    Dim o As _Offset

    vs = glCreateShader&(GL_VERTEX_SHADER)
    o = _Offset(vshad$)
    glShaderSource vs, 1, _Offset(o), 0

    glGenBuffers 1, _Offset(m.bufId)
    glBindBuffer GL_ARRAY_BUFFER, m.bufId

    glGenVertexArrays 1, _Offset(m.vertArrId)
    glBindVertexArray m.vertArrId
    glEnableVertexAttribArray 0
    glBindBuffer GL_ARRAY_BUFFER, m.bufId
    glVertexAttribPointer 0, 3, GL_FLOAT, GL_FALSE, 0, 0

    glBindBuffer GL_ARRAY_BUFFER, m.bufId
    glBufferData GL_ARRAY_BUFFER, m.triCount * Len(t), m.tris.OFFSET, GL_STATIC_DRAW

    m.prog = glCreateProgram&

    fs = glCreateShader&(GL_FRAGMENT_SHADER)
    o = _Offset(fshad$)
    glShaderSource fs, 1, _Offset(o), 0

    glCompileShader fs

    glAttachShader m.prog, vs
    glAttachShader m.prog, fs

    glLinkProgram m.prog

    m.pointsId = glGetUniformLocation(m.prog, "points")
    m.colorsId = glGetUniformLocation(m.prog, "colors")
End Sub

This is the header (name it "stained_glass_help.h" and place it next to the .bas file):

Code: (Select All)
void myShaderSource(int shad, int count, ptrszint text, ptrszint length)
{
    __glewShaderSource(shad, count, (const GLchar **)text, (const GLint *)length);
}

void myGenBuffers(int count, uintptr_t offset)
{
    __glewGenBuffers(count, (GLuint *)offset);
}

void myGenVertexArrays(int count, uintptr_t buffers)
{
    glGenVertexArrays(count, (GLuint *)buffers);
}

void myBufferData(int target, uintptr_t size, uintptr_t data, int usage)
{
    glBufferData(target, size, (GLuint *)data, usage);
}

void myDrawArrays(int mode, int first, int count)
{
    glDrawArrays(mode, first, count);
}

void myUniformMatrix4fv(int id, int count, unsigned char transpose, uintptr_t mat)
{
    glUniformMatrix4fv(id, count, transpose, (GLfloat *)mat);
}

void myUniform2fv(int id, int count, uintptr_t mat)
{
    glUniform2fv(id, count, (GLfloat *)mat);
}

void myUniform3fv(int id, int count, uintptr_t mat)
{
    glUniform3fv(id, count, (GLfloat *)mat);
}
Wow! Very, very interesting. I'll play around with this. Thank you!
New to QB64pe? Visit the QB64 tutorial to get started.
QB64 Tutorial
Reply


Messages In This Thread
Morphing Stained Glass - by TerryRitchie - 09-13-2024, 07:52 PM
RE: Morphing Stained Glass - by bplus - 09-13-2024, 08:38 PM
RE: Morphing Stained Glass - by TerryRitchie - 09-13-2024, 09:29 PM
RE: Morphing Stained Glass - by Petr - 09-13-2024, 08:40 PM
RE: Morphing Stained Glass - by Petr - 09-13-2024, 08:45 PM
RE: Morphing Stained Glass - by TerryRitchie - 09-13-2024, 09:54 PM
RE: Morphing Stained Glass - by bplus - 09-13-2024, 08:49 PM
RE: Morphing Stained Glass - by TerryRitchie - 09-13-2024, 10:42 PM
RE: Morphing Stained Glass - by Pete - 09-13-2024, 09:30 PM
RE: Morphing Stained Glass - by DSMan195276 - 09-13-2024, 10:42 PM
RE: Morphing Stained Glass - by SMcNeill - 09-13-2024, 11:28 PM
RE: Morphing Stained Glass - by TerryRitchie - 09-14-2024, 01:41 AM
RE: Morphing Stained Glass - by DSMan195276 - 09-14-2024, 01:18 AM
RE: Morphing Stained Glass - by bplus - 09-14-2024, 01:30 AM
RE: Morphing Stained Glass - by bplus - 09-14-2024, 01:43 AM
RE: Morphing Stained Glass - by SMcNeill - 09-14-2024, 05:09 AM
RE: Morphing Stained Glass - by SMcNeill - 09-14-2024, 05:28 AM



Users browsing this thread: 19 Guest(s)