summaryrefslogtreecommitdiffstats
path: root/virtual-programs
diff options
context:
space:
mode:
authorOmar Rizwan <omar@omar.website>2023-09-27 00:48:49 +0000
committerOmar Rizwan <omar@omar.website>2023-09-27 00:48:49 +0000
commit74fa2828cb7bee6a29931dcedcb9a06b2688d243 (patch)
tree7bf7fa8ddb948604e1cdec920a6d651c38915ca5 /virtual-programs
parentdisplay: This seems to fix fillQuad (diff)
downloadfolk-74fa2828cb7bee6a29931dcedcb9a06b2688d243.tar.gz
folk-74fa2828cb7bee6a29931dcedcb9a06b2688d243.zip
display: Basic image support (no rotation/scale yet + cache is hack)
Fix various stride bugs with iamge copying/rechanneling.
Diffstat (limited to 'virtual-programs')
-rw-r--r--virtual-programs/display.folk34
-rw-r--r--virtual-programs/images.folk26
2 files changed, 49 insertions, 11 deletions
diff --git a/virtual-programs/display.folk b/virtual-programs/display.folk
index 30b9e408..ef24c9d8 100644
--- a/virtual-programs/display.folk
+++ b/virtual-programs/display.folk
@@ -301,7 +301,39 @@ On process {
}
}
- proc image {x y im radians {scale 1.0}} {}
+ variable image [Gpu::pipeline {sampler2D image vec2 imageSize
+ vec2 pos float radians float scale} {
+ vec2 a = pos - imageSize/2;
+ vec2 b = pos + vec2(imageSize.x, -imageSize.y)/2;
+ vec2 c = pos + imageSize/2;
+ vec2 d = pos + vec2(-imageSize.x, imageSize.y)/2;
+ vec2 vertices[4] = vec2[4](a, b, d, c);
+ return vertices[gl_VertexIndex];
+ } {fn invBilinear} {
+ vec2 a = pos - imageSize/2;
+ vec2 b = pos + vec2(imageSize.x, -imageSize.y)/2;
+ vec2 c = pos + imageSize/2;
+ vec2 d = pos + vec2(-imageSize.x, imageSize.y)/2;
+ vec2 p = gl_FragCoord.xy;
+ vec2 uv = invBilinear(p, a, b, c, d);
+ if( max( abs(uv.x-0.5), abs(uv.y-0.5))<0.5 ) {
+ return texture(samplers[image], uv);
+ }
+ return vec4(0.0, 0.0, 0.0, 0.0);
+ }]
+ variable imCache [dict create]
+ proc image {x y im radians {scale 1.0}} {
+ variable image
+ variable imCache
+ if {![dict exists $imCache $im]} {
+ set gim [Gpu::ImageManager::copyImageToGpu [::image rechannel $im 4]]
+ dict set imCache $im $gim
+ }
+ set gim [dict get $imCache $im]
+ puts $gim
+ Gpu::draw $image $gim [list [::image width $im] [::image height $im]] \
+ [list $x $y] $radians $scale
+ }
proc end {} { Gpu::drawEnd; Gpu::poll }
}
diff --git a/virtual-programs/images.folk b/virtual-programs/images.folk
index 1d491eec..120b340a 100644
--- a/virtual-programs/images.folk
+++ b/virtual-programs/images.folk
@@ -262,6 +262,8 @@ namespace eval ::image {
// TODO: Free the PNG.
}
+ # Allocates(!) a copy of `im` with `components` channels. Up to
+ # the caller to free it.
$cc proc rechannel {image_t im int components} image_t {
if (im.components == components) return im;
if (components != 4 || im.components != 3) exit(2);
@@ -270,16 +272,20 @@ namespace eval ::image {
ret.components = components;
ret.bytesPerRow = ret.width * ret.components;
ret.data = folkHeapAlloc(ret.bytesPerRow * ret.height);
-
- for(int i = 0; i < ret.width*ret.height; i++) {
- int r = im.data[i*im.components+0],
- g = im.data[i*im.components+1],
- b = im.data[i*im.components+2];
-
- ret.data[i*ret.components+0] = r;
- ret.data[i*ret.components+1] = g;
- ret.data[i*ret.components+2] = b;
- ret.data[i*ret.components+3] = 255;
+
+ for (int y = 0; y < im.height; y++) {
+ for (int x = 0; x < im.width; x++) {
+ int imidx = y*im.bytesPerRow + x*im.components;
+ int r = im.data[imidx+0],
+ g = im.data[imidx+1],
+ b = im.data[imidx+2];
+
+ int ridx = y*ret.bytesPerRow + x*ret.components;
+ ret.data[ridx+0] = r;
+ ret.data[ridx+1] = g;
+ ret.data[ridx+2] = b;
+ ret.data[ridx+3] = 255;
+ }
}
return ret;
}