Project

General

Profile

« Previous | Next » 

Revision ec541169

Added by Leszek Koltunski 1 day ago

Move the shaders from resource files directly to the code.

View differences:

src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.kt
67 67

  
68 68
        ///////////////////////////////////////////////////////////////////////////////////////////
69 69
        
70
        fun createPrograms(vert: ByteArray, frag: ByteArray, GLSL: Int)
70
        fun createPrograms(vert: String, frag: String, GLSL: Int)
71 71
        {
72 72
            val numV = VertexEffect.getNumEnabled()
73 73

  
src/main/java/org/distorted/library/main/DistortedLibrary.kt
47 47
import org.distorted.library.program.DistortedProgram
48 48
import org.distorted.library.program.VertexCompilationException
49 49
import org.distorted.library.type.Dynamic
50
import org.distorted.library.shaders.*
51

  
50 52
import java.nio.ByteBuffer
51 53
import java.nio.ByteOrder
52 54
import java.nio.FloatBuffer
......
278 280
    interface LibraryUser
279 281
    {
280 282
        fun distortedException(ex: Exception)
281
        fun localFile(fileID: Int): ByteArray
282 283
        fun logMessage(message: String)
283 284
    }
284 285
    private lateinit var mUser: LibraryUser
......
287 288
    private fun createMainProgram()
288 289
    {
289 290
        // MAIN PROGRAM ////////////////////////////////////
290
        val mainVertStream = mUser.localFile(R.raw.main_vertex_shader)
291
        val mainFragStream = mUser.localFile(R.raw.main_fragment_shader)
291
        val mainVertStream = Main.vertex()
292
        val mainFragStream = Main.fragment()
292 293

  
293 294
        val numF = FragmentEffect.getNumEnabled()
294 295
        val numV = VertexEffect.getNumEnabled()
......
324 325
        mTransformFeedbackH = GLES30.glGetUniformLocation(mMainProgramH, "u_TransformFeedback")
325 326

  
326 327
        // BLIT PROGRAM ////////////////////////////////////
327
        val blitVertStream = mUser.localFile(R.raw.blit_vertex_shader)
328
        val blitFragStream = mUser.localFile(R.raw.blit_fragment_shader)
328
        val blitVertStream = Blit.vertex()
329
        val blitFragStream = Blit.fragment()
329 330

  
330 331
        try
331 332
        {
......
342 343
        mBlitDepthH = GLES30.glGetUniformLocation(blitProgramH, "u_Depth")
343 344

  
344 345
        // BLIT DEPTH PROGRAM ////////////////////////////////////
345
        val blitDepthVertStream = mUser.localFile(R.raw.blit_depth_vertex_shader)
346
        val blitDepthFragStream = mUser.localFile(R.raw.blit_depth_fragment_shader)
346
        val blitDepthVertStream = BlitDepth.vertex()
347
        val blitDepthFragStream = BlitDepth.fragment()
347 348

  
348 349
        try
349 350
        {
......
364 365
    ///////////////////////////////////////////////////////////////////////////////////////////////////
365 366
    private fun createNormalProgram()
366 367
    {
367
        val normalVertexStream = mUser.localFile(R.raw.normal_vertex_shader)
368
        val normalFragmentStream = mUser.localFile(R.raw.normal_fragment_shader)
368
        val normalVertexStream   = Normal.vertex()
369
        val normalFragmentStream = Normal.fragment()
369 370

  
370 371
        try
371 372
        {
......
384 385
    ///////////////////////////////////////////////////////////////////////////////////////////////////
385 386
    private fun createFullProgram()
386 387
    {
387
        val fullVertStream = mUser.localFile(R.raw.main_vertex_shader)
388
        val fullFragStream = mUser.localFile(R.raw.main_fragment_shader)
388
        val fullVertStream = Main.vertex()
389
        val fullFragStream = Main.fragment()
389 390

  
390 391
        val numV = allEnabled
391 392

  
......
423 424
    private fun createOITProgram()
424 425
    {
425 426
        // MAIN OIT PROGRAM ////////////////////////////////
426
        val mainVertStream = mUser.localFile(R.raw.main_vertex_shader)
427
        val mainFragStream = mUser.localFile(R.raw.main_fragment_shader)
427
        val mainVertStream = Main.vertex()
428
        val mainFragStream = Main.fragment()
428 429

  
429 430
        val numF = FragmentEffect.getNumEnabled()
430 431
        val numV = VertexEffect.getNumEnabled()
......
458 459
        mMainOITNumRecordsH = GLES30.glGetUniformLocation(mMainOITProgramH, "u_numRecords")
459 460

  
460 461
        // OIT CLEAR PROGRAM ////////////////////////////////////
461
        val oitClearVertStream = mUser.localFile(R.raw.oit_vertex_shader)
462
        val oitClearFragStream = mUser.localFile(R.raw.oit_clear_fragment_shader)
462
        val oitClearVertStream = Oit.vertex()
463
        val oitClearFragStream = Oit.fragment_clear()
463 464

  
464 465
        try
465 466
        {
......
477 478
        mOITClearSizeH = GLES30.glGetUniformLocation(oitClearProgramH, "u_Size")
478 479

  
479 480
        // OIT BUILD PROGRAM ////////////////////////////////////
480
        val oitBuildVertStream = mUser.localFile(R.raw.oit_vertex_shader)
481
        val oitBuildFragStream = mUser.localFile(R.raw.oit_build_fragment_shader)
481
        val oitBuildVertStream = Oit.vertex()
482
        val oitBuildFragStream = Oit.fragment_build()
482 483

  
483 484
        try
484 485
        {
......
499 500
        mOITBuildNumRecordsH   = GLES30.glGetUniformLocation(oitBuildProgramH, "u_numRecords")
500 501

  
501 502
        // OIT COLLAPSE PROGRAM ///////////////////////////
502
        val oitCollapseVertStream = mUser.localFile(R.raw.oit_vertex_shader)
503
        val oitCollapseFragStream = mUser.localFile(R.raw.oit_collapse_fragment_shader)
503
        val oitCollapseVertStream = Oit.vertex()
504
        val oitCollapseFragStream = Oit.fragment_collapse()
504 505

  
505 506
        try
506 507
        {
......
519 520
        mOITCollapseSizeH         = GLES30.glGetUniformLocation(oitCollapseProgramH, "u_Size")
520 521

  
521 522
        // OIT RENDER PROGRAM ///////////////////////////
522
        val oitRenderVertStream = mUser.localFile(R.raw.oit_vertex_shader)
523
        val oitRenderFragStream = mUser.localFile(R.raw.oit_render_fragment_shader)
523
        val oitRenderVertStream = Oit.vertex()
524
        val oitRenderFragStream = Oit.fragment_render()
524 525

  
525 526
        try
526 527
        {
......
1050 1051

  
1051 1052
        try
1052 1053
        {
1053
            val vertStream = mUser.localFile(R.raw.main_vertex_shader)
1054
            val fragStream = mUser.localFile(R.raw.preprocess_fragment_shader)
1054
            val vertStream = Main.vertex()
1055
            val fragStream = Postprocess.fragment()
1055 1056
            createPrograms(vertStream, fragStream, gLSL)
1056 1057
        }
1057 1058
        catch (ex: Exception)
src/main/java/org/distorted/library/program/DistortedProgram.kt
306 306
    }
307 307

  
308 308
    ///////////////////////////////////////////////////////////////////////////////////////////////
309
    private fun readTextFileFromRawResource(inputBytes: ByteArray, doAttributes: Boolean): String?
309
    private fun readTextFileFromRawResource(inputBytes: String, doAttributes: Boolean): String?
310 310
    {
311 311
        val body = StringBuilder()
312 312
        var attrList: String? = ""
313 313

  
314 314
        try
315 315
        {
316
            val lines = inputBytes.toString(Charsets.UTF_8).lines()
316
            val lines = inputBytes.lines()
317 317

  
318 318
            for (nextLine in lines)
319 319
            {
......
446 446
    *
447 447
    * @y.exclude
448 448
    */
449
    constructor(vert: ByteArray, frag: ByteArray, vertHeader: String,
449
    constructor(vert: String, frag: String, vertHeader: String,
450 450
                fragHeader: String, glslVersion: Int, feedback: Array<String>?)
451 451
    {
452 452
        init(glslVersion)
......
473 473
    *
474 474
    * @y.exclude
475 475
    */
476
    constructor(vert: ByteArray, frag: ByteArray, vertHeader: String, fragHeader: String,
476
    constructor(vert: String, frag: String, vertHeader: String, fragHeader: String,
477 477
                enabledVert: String?, enabledFrag: String?, glslVersion: Int, feedback: Array<String>?)
478 478
    {
479 479
        init(glslVersion)
......
503 503
    *
504 504
    * @y.exclude
505 505
    */
506
    constructor( vert: ByteArray, frag: ByteArray, vertHeader: String, fragHeader: String, glslVersion: Int) :
506
    constructor( vert: String, frag: String, vertHeader: String, fragHeader: String, glslVersion: Int) :
507 507
            this(vert, frag, vertHeader, fragHeader, glslVersion, null)
508 508

  
509 509
    ///////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/shaders/Blit.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2025 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.shaders
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
object Blit
26
{
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// a_Position         Per-vertex position.
29
// v_TexCoordinate
30
// u_Depth            Distance from the near plane to render plane, in clip coords
31

  
32
    fun vertex() : String
33
    {
34
    return """
35
           precision lowp float;
36

  
37
           in vec2 a_Position;
38
           out vec2 v_TexCoordinate;
39
           uniform float u_Depth;
40

  
41
           void main()
42
             {
43
             v_TexCoordinate = a_Position + 0.5;
44
             gl_Position     = vec4(2.0*a_Position,u_Depth,1.0);
45
             }
46
           """.trimIndent()
47
    }
48

  
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50
// fragColor         The output color
51
// v_TexCoordinate   Interpolated texture coordinate per fragment.
52
// u_Texture         The input texture.
53

  
54
    fun fragment() : String
55
    {
56
    return """
57
           precision lowp float;
58

  
59
           out vec4 fragColor; 
60
           in vec2 v_TexCoordinate;
61
           uniform sampler2D u_Texture;
62

  
63
           void main()                    		
64
             {
65
             fragColor = texture(u_Texture,v_TexCoordinate);
66
             }
67
           """.trimIndent()
68
    }
69
}
src/main/java/org/distorted/library/shaders/BlitDepth.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2025 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.shaders
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
object BlitDepth
26
{
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// a_Position - Per-vertex position.
29
// u_TexCorr  - when we blit from postprocessing buffers, the buffers can be
30
//              larger than necessary (there is just one static set being reused!)
31
//              so we need to compensate here by adjusting the texture coords.
32

  
33
    fun vertex() : String
34
    {
35
    return """
36
           precision highp float;
37

  
38
           in vec2 a_Position; 
39
           out vec2 v_TexCoordinate;
40
           uniform vec2  u_TexCorr;
41

  
42
           void main()
43
             {
44
             v_TexCoordinate = (a_Position + 0.5) * u_TexCorr;
45
             gl_Position     = vec4(2.0*a_Position,0.0,1.0);
46
             }
47
           """.trimIndent()
48
    }
49

  
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
// fragColor       - The output color
52
// v_TexCoordinate - Interpolated texture coordinate per fragment.
53
//
54
//////////////////////////////////////////////////////////////////////////////////////////////
55
// why -0.0003 ? On some drivers (for example Qualcomm's V@331, V@415 on Adreno 308 - also on
56
// some Mali devices ) without it the depth test - when postprocessing a flat 2D object - does
57
// not pass (for unknown reasons) and we don't see the Glow halo.  See for example the 'Glowing
58
// Leaf' test app.
59
// Why exactly 0.0003? Testing of the Cube app on the SM-A315F. ( Mali G52, drivr r20p0 )
60
// 0.0003 shouldn't hurt anyway.
61

  
62
    fun fragment() : String
63
    {
64
    return """
65
           precision highp float;
66

  
67
           out vec4 fragColor;
68
           in vec2 v_TexCoordinate;
69
           uniform sampler2D u_Texture;
70
           uniform sampler2D u_DepthTexture;
71

  
72
           void main()                    		
73
             {
74
             gl_FragDepth = texture(u_DepthTexture,v_TexCoordinate).r -0.0003;
75
             fragColor    = texture(u_Texture     ,v_TexCoordinate);
76
             }
77
           """.trimIndent()
78
    }
79
}
src/main/java/org/distorted/library/shaders/Main.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2025 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.shaders
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
object Main
26
{
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

  
29
    fun vertex() : String
30
    {
31
    return """
32
precision highp float;
33
precision highp int;
34

  
35
in vec3 a_Position;                   // Per-vertex position.
36
in vec3 a_Normal;                     // Per-vertex normal vector.
37
in vec2 a_TexCoordinate;              // Per-vertex texture coordinate.
38
in float a_Component;                 // The component a vertex belongs to.
39
                                      // to a vertex effect. An effect will only be active on a vertex iff (a_Association & vAssociation[effect]) != 0.
40
                                      // ( see VertexEffect.retSection() )
41

  
42
out vec3 v_Position;                  // for Transform Feedback only
43
out vec3 v_endPosition;               // for Transform Feedback only
44
out vec3 v_Normal;                    //
45
out vec2 v_TexCoordinate;             //
46

  
47
uniform mat4 u_MVPMatrix;             // u_MVMatrixP * projection.
48
uniform mat4 u_MVMatrixP;             // the combined model/view matrix. (for points)
49
uniform mat4 u_MVMatrixV;             // the combined model/view matrix. (for vectors)
50
                                      // which need to work differently on points and vectors
51
uniform float u_Inflate;              // how much should we inflate (>0.0) or deflate (<0.0) the mesh.
52
uniform int u_TransformFeedback;      // are we doing the transform feedback now?
53

  
54
#ifdef COMP_CENTERS
55
layout (std140) uniform componentCenter
56
  {
57
  vec4 vComCenter[MAX_COMPON];        // centers of mesh components. 4 floats: (x,y,z,unused)
58
  };
59
#endif
60

  
61
#ifdef BUGGY_UBOS
62
layout (packed) uniform componentAssociation
63
  {
64
  ivec2 vComAssoc[MAX_COMPON];        // component 'AND' and 'EQU' Associations
65
  };
66
#else
67
layout (std140) uniform componentAssociation
68
  {
69
  ivec4 vComAssoc[MAX_COMPON];        // component 'AND' and 'EQU' Associations
70
  };
71
#endif
72

  
73
#if NUM_VERTEX>0
74
uniform int vNumEffects;              // total number of vertex effects
75

  
76
layout (std140) uniform vUniformProperties
77
  {
78
  ivec4 vProperties[NUM_VERTEX];      // their properties, 4 ints:
79
                                      // 1: name of the effect
80
                                      // 2: effect's AND association
81
                                      // 3: reserved int (probably another AND assoc in the future)
82
                                      // 4: effect's EQU association
83
  };
84

  
85
layout (std140) uniform vUniformFloats
86
  {
87
  vec4 vUniforms[3*NUM_VERTEX];       // i-th effect is 3 consecutive vec4's: [3*i], [3*i+1], [3*i+2].
88
                                      // The first vec4 is the Interpolated values,
89
                                      // second vec4: first float - cache, next 3: Center, the third -  the Region.
90
  };
91

  
92
//////////////////////////////////////////////////////////////////////////////////////////////
93
// HELPER FUNCTIONS
94
//////////////////////////////////////////////////////////////////////////////////////////////
95
// Return degree of the point as defined by the Region. Currently only supports spherical regions.
96
//
97
// Let 'PS' be the vector from point P (the current vertex) to point S (the center of the effect).
98
// Let region.xyz be the vector from point S to point O (the center point of the region sphere)
99
// Let region.w be the radius of the region sphere.
100
// (This all should work regardless if S is inside or outside of the sphere).
101
//
102
// Then, the degree of a point with respect to a given (spherical!) Region is defined by:
103
//
104
// If P is outside the sphere, return 0.
105
// Otherwise, let X be the point where the halfline SP meets the sphere - then return |PX|/|SX|,
106
// aka the 'degree' of point P.
107
//
108
// We solve the triangle OPX.
109
// We know the lengths |PO|, |OX| and the angle OPX, because cos(OPX) = cos(180-OPS) = -cos(OPS) = -PS*PO/(|PS|*|PO|)
110
// then from the law of cosines PX^2 + PO^2 - 2*PX*PO*cos(OPX) = OX^2 so PX = -a + sqrt(a^2 + OX^2 - PO^2)
111
// where a = PS*PO/|PS| but we are really looking for d = |PX|/(|PX|+|PS|) = 1/(1+ (|PS|/|PX|) ) and
112
// |PX|/|PS| = -b + sqrt(b^2 + (OX^2-PO^2)/PS^2) where b=PS*PO/|PS|^2 which can be computed with only one sqrt.
113

  
114
float degree(in vec4 region, in vec3 PS)
115
  {
116
  float ps_sq = dot(PS,PS);
117

  
118
  if( ps_sq==0.0 ) return 1.0;
119

  
120
  vec3 PO = PS + region.xyz;
121
  float d = region.w*region.w-dot(PO,PO);
122

  
123
  if( d<=0.0 ) return 0.0;
124

  
125
  float b = dot(PS,PO)/ps_sq;
126

  
127
  return 1.0 / (1.0 + 1.0/(sqrt(b*b + d/ps_sq)-b));
128
  }
129

  
130
#endif  // NUM_VERTEX>0
131

  
132
//////////////////////////////////////////////////////////////////////////////////////////////
133

  
134
void main()
135
  {
136
  int component = int(a_Component);
137
  vec3 n = a_Normal;
138
#ifdef COMP_CENTERS
139
  vec3 v = a_Position + u_Inflate*(a_Position - vComCenter[component].xyz);
140
#else
141
  vec3 v = a_Position + u_Inflate*a_Position;
142
#endif
143

  
144
#ifdef POSTPROCESS
145
  if( (uint(vComAssoc[component].x) & 0x80000000u) != 0u )
146
    {
147
    v = vec3(0.0, 0.0, 0.0);
148
    }
149
#endif
150

  
151
#if NUM_VERTEX>0
152
  int effect=0;
153
  int andC = vComAssoc[component].x & 0x7fffffff;
154
  int equC = vComAssoc[component].y;
155

  
156
  for(int i=0; i<vNumEffects; i++)
157
    {
158
    if( ((andC & vProperties[i].y) != 0) || (equC == vProperties[i].w) )
159
      {
160
      // ENABLED EFFECTS WILL BE INSERTED HERE
161

  
162
      }
163
    effect+=3;
164
    }
165
#endif
166

  
167
#ifdef PREAPPLY
168
  v_Position   = v;
169
  v_endPosition= n;
170
#else
171
  if( u_TransformFeedback == 1 )
172
    {
173
    vec4 tmp1 =  u_MVMatrixP * vec4(v,1.0);
174
    vec4 tmp2 =  normalize(u_MVMatrixV * vec4(n,0.0));
175

  
176
    v_Position    = vec3(tmp1);
177
    v_endPosition = vec3(tmp1+100.0*tmp2);
178
    }
179
  else
180
    {
181
    v_Position = v;
182
    }
183
#endif
184

  
185
  v_TexCoordinate = a_TexCoordinate;
186
  v_Normal        = normalize(vec3(u_MVMatrixV*vec4(n,0.0)));
187
  gl_Position     = u_MVPMatrix*vec4(v,1.0);
188
  }                                       
189
           """.trimIndent()
190
    }
191

  
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

  
194
    fun fragment() : String
195
    {
196
    return """
197
precision highp float;
198
precision highp int;
199

  
200
in vec3 v_Position;                     // Interpolated position for this fragment.
201
in vec3 v_Normal;                       // Interpolated normal for this fragment.
202
in vec2 v_TexCoordinate;                // Interpolated texture coordinate per fragment.
203

  
204
out vec4 fragColor;                     // The output color
205

  
206
uniform sampler2D u_Texture;            // The input texture.
207

  
208
#ifdef OIT
209
//////////////////////////////////////////////////////////////////////////////////////////////
210
// per-pixel linked list. Order Independent Transparency.
211

  
212
uniform uvec2 u_Size;
213
uniform uint u_numRecords;
214

  
215
layout (binding=0, offset=0) uniform atomic_uint u_Counter;
216

  
217
layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
218
  {                                          // one for each pixel in the Output rectangle.
219
  uint u_Records[];                          //
220
  };                                         // Next 3*u_numRecords uints - actual linked list, i.e.
221
                                             // triplets of (pointer,depth,rgba).
222
#endif
223

  
224
#if NUM_FRAGMENT>0
225
uniform int fNumEffects;                     // total number of fragment effects
226

  
227
uniform ivec4 fProperties[NUM_FRAGMENT];     // their properties, 4 ints:
228
                                             // name of the effect, unused, unused, unused
229

  
230
uniform vec4 fUniforms[3*NUM_FRAGMENT];      // i-th effect is 3 consecutive vec4's: [3*i], [3*i+1], [3*i+2].
231
                                             // The first vec4 is the Interpolated values,
232
                                             // second vec4: first float - cache, next 3: Center, the third - the Region.
233

  
234
#endif    // NUM_FRAGMENT>0
235

  
236
#ifdef OIT
237
//////////////////////////////////////////////////////////////////////////////////////////////
238
// Concurrent insert to a linked list. Tim Harris, 'pragmatic implementation of non-blocking
239
// linked-lists', 2001.
240
// This arranges fragments by decreasing 'depth', so one would think - from back to front, but
241
// in main() below the depth is mapped with S*(1-depth)/2, so it is really front to back.
242

  
243
void insert( vec2 ij, uint depth, uint rgba )
244
  {
245
  uint ptr = atomicCounterIncrement(u_Counter);
246

  
247
  if( ptr<u_numRecords )
248
    {
249
    ptr = 3u*ptr + u_Size.x*u_Size.y;
250

  
251
    u_Records[ptr+1u] = depth;
252
    u_Records[ptr+2u] = rgba;
253

  
254
    memoryBarrier();
255

  
256
    uint prev = uint(ij.x) + uint(ij.y) * u_Size.x;
257
    uint curr = u_Records[prev];
258

  
259
    while (true)
260
      {
261
      if ( curr==0u || depth > u_Records[curr+1u] )  // need to insert here
262
        {
263
        u_Records[ptr] = curr;     // next of new record is curr
264
        memoryBarrier();
265
        uint res = atomicCompSwap( u_Records[prev], curr, ptr );
266

  
267
        if (res==curr) break;      // done!
268
        else           curr = res; // could not insert! retry from same place in list
269
        }
270
      else                         // advance in list
271
        {
272
        prev = curr;
273
        curr = u_Records[prev];
274
        }
275
      }
276
    }
277
  }
278

  
279
//////////////////////////////////////////////////////////////////////////////////////////////
280

  
281
uint convert(vec4 c)
282
  {
283
  return ((uint(255.0*c.r))<<24u) + ((uint(255.0*c.g))<<16u) + ((uint(255.0*c.b))<<8u) + uint(255.0*c.a);
284
  }
285

  
286
#endif   // OIT
287

  
288
//////////////////////////////////////////////////////////////////////////////////////////////
289

  
290
void main()                    		
291
  {  
292
  vec4 color = texture(u_Texture,v_TexCoordinate);
293

  
294
#if NUM_FRAGMENT>0
295
  vec3 diff;
296
  float degree;
297
  int effect=0;
298

  
299
  for(int i=0; i<fNumEffects; i++)
300
    {
301
    diff   = (v_Position - fUniforms[effect+1].yzw)/fUniforms[effect+2].xyz;
302
    degree = max(0.0,1.0-dot(diff,diff));
303

  
304
    // ENABLED EFFECTS WILL BE INSERTED HERE
305

  
306
    effect+=3;
307
    }
308
#endif
309

  
310
  float z = v_Normal.z;
311
  if( z<0.0 ) z = -z;
312

  
313
  vec4 converted = vec4(color.rgb * (1.0 + 4.0*z) * 0.200, color.a);
314

  
315
#ifdef OIT
316
  if( converted.a > 0.97 )
317
    {
318
    fragColor= converted;
319
    }
320
  else
321
    {
322
    if( converted.a > 0.0 )
323
      {
324
      const float S= 2147483647.0; // max signed int. Could probably be max unsigned int but this is enough.
325
      vec2 pixel = vec2(gl_FragCoord.xy);
326
      insert(pixel, uint(S*(1.0-gl_FragCoord.z)/2.0), convert(converted) );
327
      }
328
    discard;
329
    }
330
#else
331
  fragColor = converted;
332
#endif
333
  }           
334
           """.trimIndent()
335
    }
336
}
src/main/java/org/distorted/library/shaders/Normal.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2025 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.shaders
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
object Normal
26
{
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

  
29
    fun vertex() : String
30
    {
31
    return """
32
           precision lowp float;
33

  
34
           in vec3 a_Position;
35
           uniform mat4 u_Projection;
36

  
37
           void main()
38
             {
39
             gl_Position = u_Projection * vec4(a_Position, 1.0);
40
             }           
41
           """.trimIndent()
42
    }
43

  
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

  
46
    fun fragment() : String
47
    {
48
    return """
49
           precision lowp float;
50

  
51
           out vec4 fragColor;
52

  
53
           void main()
54
             {
55
             fragColor = vec4(1.0,0.0,0.0,1.0);
56
             }
57
           """.trimIndent()
58
    }
59
}
src/main/java/org/distorted/library/shaders/Oit.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2025 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.shaders
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
object Oit
26
{
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// a_Position            Per-vertex position.
29
// v_Pixel               2D pixel coords in window space
30
// u_Depth               Distance from the near plane to render plane, in clip coords
31
// u_TexCorr             When we blit from postprocessing buffers, the buffers can be
32
//                       larger than necessary (there is just one static set being
33
//                       reused!) so we need to compensate here by adjusting the texture
34
//                       coords.
35

  
36
    fun vertex() : String
37
    {
38
    return """
39
           precision highp float;
40
           precision highp int;
41

  
42
           in vec2 a_Position;
43
           out vec2 v_TexCoordinate;
44
           out vec2 v_Pixel;
45

  
46
           uniform float u_Depth; 
47
           uniform vec2  u_TexCorr;
48
           uniform uvec2 u_Size; 
49

  
50
           void main()
51
             {
52
             v_TexCoordinate = (a_Position + 0.5) * u_TexCorr;
53
             v_Pixel         = (a_Position + 0.5) * vec2(u_Size);
54
             gl_Position     = vec4(2.0*a_Position,u_Depth,1.0);
55
             }      
56
           """.trimIndent()
57
    }
58

  
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

  
61
    fun fragment_build() : String
62
    {
63
    return """
64
precision highp float;
65
precision highp int;
66

  
67
out vec4 fragColor;
68
in vec2 v_TexCoordinate;
69
in vec2 v_Pixel;              // location of the current fragment, in pixels
70

  
71
uniform sampler2D u_Texture;
72
uniform sampler2D u_DepthTexture;
73

  
74
//////////////////////////////////////////////////////////////////////////////////////////////
75
// per-pixel linked list. Order Independent Transparency.
76

  
77
uniform uvec2 u_Size;
78
uniform uint u_numRecords;
79

  
80
layout (binding=0, offset=0) uniform atomic_uint u_Counter;
81

  
82
layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
83
  {                                          // one for each pixel in the Output rectangle.
84
  uint u_Records[];                          //
85
  };                                         // Next 3*u_numRecords uints - actual linked list, i.e.
86
                                             // triplets of (pointer,depth,rgba).
87

  
88
//////////////////////////////////////////////////////////////////////////////////////////////
89
// Concurrent insert to a linked list. Tim Harris, 'pragmatic implementation of non-blocking
90
// linked-lists', 2001.
91
// This arranges fragments by decreasing 'depth', so one would think - from back to front, but
92
// in main() below the depth is mapped with S*(1-depth)/2, so it is really front to back.
93

  
94
void insert( vec2 ij, uint depth, uint rgba )
95
  {
96
  uint ptr = atomicCounterIncrement(u_Counter);
97

  
98
  if( ptr<u_numRecords )
99
    {
100
    ptr = 3u*ptr + u_Size.x*u_Size.y;
101

  
102
    u_Records[ptr+1u] = depth;
103
    u_Records[ptr+2u] = rgba;
104

  
105
    memoryBarrier();
106

  
107
    uint prev = uint(ij.x) + uint(ij.y) * u_Size.x;
108
    uint curr = u_Records[prev];
109

  
110
    while (true)
111
      {
112
      if ( curr==0u || depth > u_Records[curr+1u] )  // need to insert here
113
        {
114
        u_Records[ptr] = curr;     // next of new record is curr
115
        memoryBarrier();
116
        uint res = atomicCompSwap( u_Records[prev], curr, ptr );
117

  
118
        if (res==curr) break;      // done!
119
        else           curr = res; // could not insert! retry from same place in list
120
        }
121
      else                         // advance in list
122
        {
123
        prev = curr;
124
        curr = u_Records[prev];
125
        }
126
      }
127
    }
128
  }
129

  
130
//////////////////////////////////////////////////////////////////////////////////////////////
131

  
132
uint convert(vec4 c)
133
  {
134
  return ((uint(255.0*c.r))<<24u) + ((uint(255.0*c.g))<<16u) + ((uint(255.0*c.b))<<8u) + uint(255.0*c.a);
135
  }
136

  
137
//////////////////////////////////////////////////////////////////////////////////////////////
138
// Pass2 of the OIT algorithm - build the LinkedList phase.
139

  
140
void main()                    		
141
  {
142
  vec4  color= texture(u_Texture     , v_TexCoordinate);
143
  float depth= texture(u_DepthTexture, v_TexCoordinate).r;
144

  
145
  if( color.a > 0.97 )
146
    {
147
    gl_FragDepth = depth;
148
    fragColor    = color;
149
    }
150
  else
151
    {
152
    if( color.a > 0.0 )
153
      {
154
      const float S= 2147483647.0; // max signed int. Could probably be max unsigned int but this is enough.
155
      insert(v_Pixel, uint(S*(1.0-depth)/2.0), convert(color) );
156
      }
157
    discard;
158
    }
159
  }           
160
           """.trimIndent()
161
    }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

  
165
    fun fragment_clear() : String
166
    {
167
    return """
168
precision highp float;
169
precision highp int;
170

  
171
in vec2 v_TexCoordinate;
172
in vec2 v_Pixel;              // location of the current fragment, in pixels
173

  
174
//////////////////////////////////////////////////////////////////////////////////////////////
175
// per-pixel linked list. Order Independent Transparency.
176

  
177
uniform uvec2 u_Size;
178

  
179
layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
180
  {                                          // one for each pixel in the Output rectangle.
181
  uint u_Records[];                          //
182
  };                                         // Next 3*u_numRecords uints - actual linked list, i.e.
183
                                             // triplets of (pointer,depth,rgba).
184

  
185
//////////////////////////////////////////////////////////////////////////////////////////////
186
// Pass1 of the OIT algorithm - 'clear the head pointers' phase.
187
// No we cannot optimize this out by moving the 'u_Records[index]=0u' to the end of the Pass3,
188
// because between passes the size of the surface we render to might change.
189

  
190
void main()                    		
191
  {
192
  uint index= uint(v_Pixel.x) + uint(v_Pixel.y) * u_Size.x;
193
  u_Records[index] = 0u;
194
  discard;
195
  }           
196
           """.trimIndent()
197
    }
198

  
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

  
201
    fun fragment_collapse() : String
202
    {
203
    return """
204
precision highp float;
205
precision highp int;
206

  
207
out vec4 fragColor;           // The output color
208
in vec2 v_TexCoordinate;      // Interpolated texture coordinate per fragment.
209
in vec2 v_Pixel;              // location of the current fragment, in pixels
210

  
211
uniform sampler2D u_DepthTexture;
212

  
213
//////////////////////////////////////////////////////////////////////////////////////////////
214
// per-pixel linked list. Order Independent Transparency.
215

  
216
uniform uvec2 u_Size;
217

  
218
layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
219
  {                                          // one for each pixel in the Output rectangle.
220
  uint u_Records[];                          //
221
  };                                         // Next 3*u_numRecords uints - actual linked list, i.e.
222
                                             // triplets of (pointer,depth,rgba).
223

  
224
//////////////////////////////////////////////////////////////////////////////////////////////
225
// Pass3 of the OIT algorithm - traverse the per-pixel LinkedList and cut occluded fragments.
226

  
227
void main()                    		
228
  {
229
  uint prev = uint(v_Pixel.x) + uint(v_Pixel.y) * u_Size.x;
230
  uint curr = u_Records[prev];
231

  
232
  if (curr != 0u)
233
    {
234
    const float S= 2147483647.0;
235
    float depth = texture(u_DepthTexture, v_TexCoordinate).r;
236
    uint texdepth = uint(S*(1.0-depth)/2.0);
237

  
238
    while( curr != 0u )
239
      {
240
      if( u_Records[curr+1u] <= texdepth )
241
        {
242
        u_Records[prev] = 0u;
243
        break;
244
        }
245

  
246
      prev = curr;
247
      curr = u_Records[curr];
248
      }
249
    }
250
  else discard;
251
  }           
252
           """.trimIndent()
253
    }
254

  
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

  
257
    fun fragment_render() : String
258
    {
259
    return """
260
precision highp float;
261
precision highp int;
262

  
263
out vec4 fragColor;           // The output color
264
in vec2 v_TexCoordinate;      // Interpolated texture coordinate per fragment.
265
in vec2 v_Pixel;              // location of the current fragment, in pixels
266

  
267
//////////////////////////////////////////////////////////////////////////////////////////////
268
// per-pixel linked list. Order Independent Transparency.
269

  
270
uniform uvec2 u_Size;
271

  
272
layout (std430,binding=1) buffer linkedlist  // first (u_Size.x*u_Size.y) uints - head pointers,
273
  {                                          // one for each pixel in the Output rectangle.
274
  uint u_Records[];                          //
275
  };                                         // Next 3*u_numRecords uints - actual linked list, i.e.
276
                                             // triplets of (pointer,depth,rgba).
277

  
278
//////////////////////////////////////////////////////////////////////////////////////////////
279

  
280
vec4 convert(uint rgba)
281
  {
282
  return vec4( float((rgba>>24u)&255u),float((rgba>>16u)&255u),float((rgba>>8u)&255u),float(rgba&255u) ) / 255.0;
283
  }
284

  
285
//////////////////////////////////////////////////////////////////////////////////////////////
286
// A over B (https://en.wikipedia.org/wiki/Alpha_compositing)
287

  
288
vec4 blend(vec4 A,vec4 B)
289
  {
290
  float b = B.a * (1.0-A.a);
291
  float a = A.a + b;
292

  
293
  return vec4( (A.rgb*A.a + B.rgb*b)/a , a );
294
  }
295

  
296
//////////////////////////////////////////////////////////////////////////////////////////////
297
// Pass4 of the OIT algorithm - keep traversing the linked list, build the final color and blend it.
298

  
299
void main()                    		
300
  {
301
  uint prev = uint(v_Pixel.x) + uint(v_Pixel.y) * u_Size.x;
302
  uint curr = u_Records[prev];
303

  
304
  if (curr != 0u)
305
    {
306
    const float S= 2147483647.0;
307
    gl_FragDepth = 1.0 - 2.0*float(u_Records[curr+1u])/S;
308
    vec4 color   = convert(u_Records[curr+2u]);
309
    curr = u_Records[curr];
310

  
311
    while (curr != 0u)
312
      {
313
      color = blend( color , convert(u_Records[curr+2u]) );
314
      curr = u_Records[curr];
315
      }
316

  
317
    fragColor = color;
318
    }
319
  else discard;
320
  }           
321
           """.trimIndent()
322
    }
323
}
src/main/java/org/distorted/library/shaders/Postprocess.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2025 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.shaders
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
object Postprocess
26
{
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
// v_TexCoordinate   Interpolated texture coordinate per fragment.
29
// u_Texture         The input texture.
30

  
31
    fun fragment() : String
32
    {
33
    return """
34
           precision highp float;
35

  
36
           in vec2 v_TexCoordinate; 
37
           out vec4 fragColor;
38
           uniform vec4 u_Color;
39
           uniform sampler2D u_Texture;
40
           
41
           void main()
42
             {
43
             vec4 color = texture(u_Texture,v_TexCoordinate);
44
             fragColor  = vec4(u_Color.rgb, sign(color.a)*u_Color.a);
45
             }
46
           """.trimIndent()
47
    }
48
}

Also available in: Unified diff