diff --git a/.github/workflows/gg_regressions_ci.yml b/.github/workflows/gg_regressions_ci.yml index 4745b46c1726b8..8c9b713c58ada0 100644 --- a/.github/workflows/gg_regressions_ci.yml +++ b/.github/workflows/gg_regressions_ci.yml @@ -48,7 +48,6 @@ jobs: sleep 1; ./v gret -t ./gg-regression-images/vgret.v_examples.toml -v ./gg-sample_images ./gg-regression-images - name: Upload regression to imgur - continue-on-error: true if: steps.compare.outcome != 'success' run: | ./imgur.sh /tmp/fail.png diff --git a/.github/workflows/other_ci.yml b/.github/workflows/other_ci.yml index 1862fab889228c..9a90a2c0bc7ba7 100644 --- a/.github/workflows/other_ci.yml +++ b/.github/workflows/other_ci.yml @@ -100,7 +100,6 @@ jobs: run: ./v -autofree -o v2 cmd/v ## NB: this does not mean it runs, but at least keeps it from regressing - name: Shader examples can be built - continue-on-error: true run: | wget https://github.com/floooh/sokol-tools-bin/raw/6040b18d39649d56dbae2ae1aed59fb755b26369/bin/linux/sokol-shdc chmod +x ./sokol-shdc diff --git a/examples/gg/rotating_textured_quad.v b/examples/gg/rotating_textured_quad.v index ba12834565e85d..3634fa53c3b280 100644 --- a/examples/gg/rotating_textured_quad.v +++ b/examples/gg/rotating_textured_quad.v @@ -24,7 +24,7 @@ pub fn (mut window Window) draw() { sgl.rotate(angle, 0.0, 0.0, 1.0) // rotate around the Z axis pointing towards the camera sgl.enable_texture() - sgl.texture(window.img.simg) + sgl.texture(window.img.simg, window.img.ssmp) sgl.begin_quads() sgl.c4b(255, 255, 255, 255) sgl.v3f_t2f(200, 200, 0, 1.0, 1.0) diff --git a/examples/sokol/01_cubes/cube.v b/examples/sokol/01_cubes/cube.v index d0cecf5660be1d..f0712e5ffa203f 100644 --- a/examples/sokol/01_cubes/cube.v +++ b/examples/sokol/01_cubes/cube.v @@ -28,6 +28,7 @@ mut: gg &gg.Context = unsafe { nil } pip_3d sgl.Pipeline texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int mouse_x int = -1 @@ -39,17 +40,13 @@ mut: * Texture functions * ******************************************************************************/ -fn create_texture(w int, h int, buf &u8) gfx.Image { +fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) { sz := w * h * 4 mut img_desc := gfx.ImageDesc{ width: w height: h num_mipmaps: 0 - // min_filter: .linear - // mag_filter: .linear // usage: .dynamic - // wrap_u: .clamp_to_edge - // wrap_v: .clamp_to_edge label: &u8(0) d3d11_texture: 0 } @@ -60,7 +57,16 @@ fn create_texture(w int, h int, buf &u8) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } fn destroy_texture(sg_img gfx.Image) { @@ -205,7 +211,7 @@ fn draw_texture_cubes(app App) { sgl.load_pipeline(app.pip_3d) sgl.enable_texture() - sgl.texture(app.texture) + sgl.texture(app.texture, app.sampler) sgl.matrix_mode_projection() sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0) @@ -242,7 +248,7 @@ fn cube_field(app App) { sgl.load_pipeline(app.pip_3d) sgl.enable_texture() - sgl.texture(app.texture) + sgl.texture(app.texture, app.sampler) sgl.matrix_mode_projection() sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 200.0) @@ -373,7 +379,7 @@ fn my_init(mut app App) { } } unsafe { - app.texture = create_texture(w, h, tmp_txt) + app.texture, app.sampler = create_texture(w, h, tmp_txt) free(tmp_txt) } } diff --git a/examples/sokol/02_cubes_glsl/cube_glsl.glsl b/examples/sokol/02_cubes_glsl/cube_glsl.glsl index e19e93687a33fc..caeda4d646a928 100644 --- a/examples/sokol/02_cubes_glsl/cube_glsl.glsl +++ b/examples/sokol/02_cubes_glsl/cube_glsl.glsl @@ -26,7 +26,10 @@ void main() { #pragma sokol @end #pragma sokol @fs fs -uniform sampler2D tex; + +uniform texture2D tex; +uniform sampler smp; + uniform fs_params { vec2 text_res; float iTime; @@ -65,7 +68,7 @@ vec3 background(float t, vec3 rd) vec4 mainImage(vec2 fragCoord) { vec2 uv = (fragCoord-vec2(0.4,0.4))*2.0; - + //vec2 uv = (-1.0 + 2.0*fc.xy / text_res.xy) * vec2(text_res.x/text_res.y, 1.0); vec3 ro = vec3(0.0, 0.0, -3.0); vec3 rd = normalize(vec3(uv, 1.0)); @@ -83,7 +86,7 @@ vec4 mainImage(vec2 fragCoord) void main() { vec4 c = color; - vec4 txt = texture(tex, uv/4.0); + vec4 txt = texture(sampler2D(tex, smp), uv/4.0); c = txt * c; vec4 col_ray = mainImage(uv); float txt_mix = mod(iTime,5); diff --git a/examples/sokol/02_cubes_glsl/cube_glsl.v b/examples/sokol/02_cubes_glsl/cube_glsl.v index f1769628abd4fa..2dd9e5de37a65f 100644 --- a/examples/sokol/02_cubes_glsl/cube_glsl.v +++ b/examples/sokol/02_cubes_glsl/cube_glsl.v @@ -39,6 +39,7 @@ mut: gg &gg.Context = unsafe { nil } pip_3d sgl.Pipeline texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int mouse_x int = -1 @@ -55,17 +56,13 @@ mut: * Texture functions * ******************************************************************************/ -fn create_texture(w int, h int, buf &byte) gfx.Image { +fn create_texture(w int, h int, buf &byte) (gfx.Image, gfx.Sampler) { sz := w * h * 4 mut img_desc := gfx.ImageDesc{ width: w height: h num_mipmaps: 0 - // min_filter: .linear - // mag_filter: .linear // usage: .dynamic - // wrap_u: .clamp_to_edge - // wrap_v: .clamp_to_edge label: &u8(0) d3d11_texture: 0 } @@ -76,7 +73,16 @@ fn create_texture(w int, h int, buf &byte) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } fn destroy_texture(sg_img gfx.Image) { @@ -374,7 +380,7 @@ fn draw_cube_glsl(app App) { // clear ws := gg.window_size_real_pixels() mut color_action := gfx.ColorAttachmentAction{ - load_action: unsafe { gfx.Action(C.SG_LOADACTION_DONTCARE) } // C.SG_ACTION_CLEAR) + load_action: unsafe { gfx.LoadAction(C.SG_LOADACTION_DONTCARE) } // C.SG_ACTION_CLEAR) clear_value: gfx.Color{ r: 1.0 g: 1.0 @@ -433,7 +439,7 @@ fn draw_texture_cubes(app App) { sgl.load_pipeline(app.pip_3d) sgl.enable_texture() - sgl.texture(app.texture) + sgl.texture(app.texture, app.sampler) sgl.matrix_mode_projection() sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0) @@ -573,7 +579,7 @@ fn my_init(mut app App) { i += 4 } } - app.texture = create_texture(w, h, tmp_txt) + app.texture, app.sampler = create_texture(w, h, tmp_txt) unsafe { free(tmp_txt) } // glsl diff --git a/examples/sokol/03_march_tracing_glsl/rt_glsl.glsl b/examples/sokol/03_march_tracing_glsl/rt_glsl.glsl index 8486dc7f943bba..73531527d7bbe4 100644 --- a/examples/sokol/03_march_tracing_glsl/rt_glsl.glsl +++ b/examples/sokol/03_march_tracing_glsl/rt_glsl.glsl @@ -26,7 +26,8 @@ void main() { #pragma sokol @end #pragma sokol @fs fs -uniform sampler2D tex; +uniform texture2D tex; +uniform sampler smp; uniform fs_params { vec2 iResolution; vec2 iMouse; @@ -38,7 +39,7 @@ in vec4 color; in vec2 uv; out vec4 frag_color; -// change to 0 to 4 to increment the AntiAliasing, +// change to 0 to 4 to increment the AntiAliasing, // increase AA will SLOW the rendering!! #define AA 1 @@ -125,9 +126,9 @@ float sdHexPrism( vec3 p, vec2 h ) float sdOctogonPrism( in vec3 p, in float r, float h ) { - const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2 + const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2 0.3826834323, // sqrt(2-sqrt(2))/2 - 0.4142135623 ); // sqrt(2)-1 + 0.4142135623 ); // sqrt(2)-1 // reflections p = abs(p); p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y); @@ -155,7 +156,7 @@ float sdRoundCone( in vec3 p, in float r1, float r2, float h ) if( k < 0.0 ) return length(q) - r1; if( k > a*h ) return length(q-vec2(0.0,h)) - r2; - + return dot(q, vec2(a,b) ) - r1; } @@ -298,8 +299,8 @@ float sdOctahedron(vec3 p, float s) else if( 3.0*p.y < m ) q = p.yzx; else if( 3.0*p.z < m ) q = p.zxy; else return m*0.57735027; - float k = clamp(0.5*(q.z-q.y+s),0.0,s); - return length(vec3(q.x,q.y-s+k,q.z-k)); + float k = clamp(0.5*(q.z-q.y+s),0.0,s); + return length(vec3(q.x,q.y-s+k,q.z-k)); #endif // bound, not exact @@ -406,12 +407,12 @@ vec2 map( in vec3 pos ) res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) ); res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) ); } - + return res; } // http://iquilezles.org/www/articles/boxfunctions/boxfunctions.htm -vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) +vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) { vec3 m = 1.0/rd; vec3 n = m*ro; @@ -437,8 +438,8 @@ vec2 raycast( in vec3 ro, in vec3 rd ) res = vec2( tp1, 1.0 ); } //else return res; - - // raymarch primitives + + // raymarch primitives vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) ); if( tb.x0.0 && tb.x100.0 ) break; } return normalize(n); -#endif +#endif } float calcAO( in vec3 pos, in vec3 nor ) @@ -526,11 +527,11 @@ float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy ) // analytical integral (box filter) vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; // xor pattern - return 0.5 - 0.5*i.x*i.y; + return 0.5 - 0.5*i.x*i.y; } vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) -{ +{ // background vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; @@ -543,11 +544,11 @@ vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) vec3 pos = ro + t*rd; vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos ); vec3 ref = reflect( rd, nor ); - - // material + + // material col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) ); float ks = 1.0; - + if( m<1.5 ) { // project pixel footprint into the plane @@ -561,7 +562,7 @@ vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) // lighting float occ = calcAO( pos, nor ); - + vec3 lin = vec3(0.0); // sun @@ -601,7 +602,7 @@ vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) dif *= occ; lin += col*0.25*dif*vec3(1.00,1.00,1.00); } - + col = lin; col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) ); @@ -624,7 +625,7 @@ vec4 mainImage( vec2 fragCoord ) vec2 mo = iMouse.xy/iResolution.xy; float time = 32.0 + iTime*1.5; - // camera + // camera vec3 ta = vec3( 0.5, -0.5, -0.6 ); vec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y, 4.5*sin(0.1*time + 7.0*mo.x) ); // camera-to-world transformation @@ -638,13 +639,13 @@ vec4 mainImage( vec2 fragCoord ) // pixel coordinates vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5; vec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y; -#else +#else vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y; #endif // focal length const float fl = 2.5; - + // ray direction vec3 rd = ca * normalize( vec3(p,fl) ); @@ -653,13 +654,13 @@ vec4 mainImage( vec2 fragCoord ) vec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y; vec3 rdx = ca * normalize( vec3(px,fl) ); vec3 rdy = ca * normalize( vec3(py,fl) ); - - // render + + // render vec3 col = render( ro, rd, rdx, rdy ); // gain // col = col*3.0/(2.5+col); - + // gamma col = pow( col, vec3(0.4545) ); @@ -668,7 +669,7 @@ vec4 mainImage( vec2 fragCoord ) } tot /= float(AA*AA); #endif - + //fragColor = vec4( tot, 1.0 ); return vec4( tot, 1.0 ); } @@ -679,14 +680,14 @@ vec4 mainImage( vec2 fragCoord ) void main() { vec4 c = color; - vec4 txt = texture(tex, uv); + vec4 txt = texture(sampler2D(tex, smp), uv); c = txt * c; vec2 uv1 = uv * iResolution; vec4 col_ray = mainImage(uv1); - + // use this to mix the chessboart texture with the ray marching //frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) * col_ray ; - + frag_color = c*0.00001 + col_ray ; } diff --git a/examples/sokol/03_march_tracing_glsl/rt_glsl.v b/examples/sokol/03_march_tracing_glsl/rt_glsl.v index 84e383af764721..97c60c2affe8ac 100644 --- a/examples/sokol/03_march_tracing_glsl/rt_glsl.v +++ b/examples/sokol/03_march_tracing_glsl/rt_glsl.v @@ -39,6 +39,7 @@ struct App { mut: gg &gg.Context = unsafe { nil } texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int @@ -54,7 +55,7 @@ mut: /****************************************************************************** * Texture functions ******************************************************************************/ -fn create_texture(w int, h int, buf &byte) gfx.Image { +fn create_texture(w int, h int, buf &byte) (gfx.Image, gfx.Sampler) { sz := w * h * 4 mut img_desc := gfx.ImageDesc{ width: w @@ -75,7 +76,16 @@ fn create_texture(w int, h int, buf &byte) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } fn destroy_texture(sg_img gfx.Image) { @@ -224,6 +234,7 @@ fn init_cube_glsl(mut app App) { app.cube_bind.vertex_buffers[0] = vbuf app.cube_bind.index_buffer = ibuf app.cube_bind.fs.images[C.SLOT_tex] = app.texture + app.cube_bind.fs.samplers[C.SLOT_smp] = app.sampler app.cube_pip_glsl = gfx.make_pipeline(&pipdesc) println('GLSL init DONE!') } @@ -377,7 +388,7 @@ fn my_init(mut app App) { } } unsafe { - app.texture = create_texture(w, h, tmp_txt) + app.texture, app.sampler = create_texture(w, h, tmp_txt) free(tmp_txt) } // glsl diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl.v b/examples/sokol/04_multi_shader_glsl/rt_glsl.v index e2e966bdfe551a..ebd9be4e2a99e8 100644 --- a/examples/sokol/04_multi_shader_glsl/rt_glsl.v +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl.v @@ -40,6 +40,7 @@ struct App { mut: gg &gg.Context = unsafe { nil } texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int mouse_x int = -1 @@ -57,7 +58,7 @@ mut: /****************************************************************************** * Texture functions ******************************************************************************/ -fn create_texture(w int, h int, buf byteptr) gfx.Image { +fn create_texture(w int, h int, buf byteptr) (gfx.Image, gfx.Sampler) { sz := w * h * 4 mut img_desc := gfx.ImageDesc{ width: w @@ -78,11 +79,16 @@ fn create_texture(w int, h int, buf byteptr) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img -} -fn destroy_texture(sg_img gfx.Image) { - gfx.destroy_image(sg_img) + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } // Use only if usage: .dynamic is enabled @@ -228,6 +234,7 @@ fn init_cube_glsl_m(mut app App) { bind.vertex_buffers[0] = vbuf bind.index_buffer = ibuf bind.fs.images[C.SLOT_tex] = app.texture + bind.fs.samplers[C.SLOT_smp] = app.sampler app.bind['march'] = bind app.pipe['march'] = gfx.make_pipeline(&pipdesc) @@ -343,6 +350,7 @@ fn init_cube_glsl_p(mut app App) { bind.vertex_buffers[0] = vbuf bind.index_buffer = ibuf bind.fs.images[C.SLOT_tex] = app.texture + bind.fs.samplers[C.SLOT_smp] = app.sampler app.bind['puppy'] = bind app.pipe['puppy'] = gfx.make_pipeline(&pipdesc) @@ -574,7 +582,7 @@ fn my_init(mut app App) { i += 4 } } - app.texture = create_texture(w, h, tmp_txt) + app.texture, app.sampler = create_texture(w, h, tmp_txt) unsafe { free(tmp_txt) } // glsl diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl b/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl index a19cae0cebbbd3..7fcd33a4508ba1 100644 --- a/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl_march.glsl @@ -26,7 +26,9 @@ void main() { #pragma sokol @end #pragma sokol @fs fs_m -uniform sampler2D tex; +uniform texture2D tex; +uniform sampler smp; + uniform fs_params_m { vec2 iResolution; vec2 iMouse; @@ -38,7 +40,7 @@ in vec4 color; in vec2 uv; out vec4 frag_color; -// change to 0 to 4 to increment the AntiAliasing, +// change to 0 to 4 to increment the AntiAliasing, // increase AA will SLOW the rendering!! #define AA 1 @@ -125,9 +127,9 @@ float sdHexPrism( vec3 p, vec2 h ) float sdOctogonPrism( in vec3 p, in float r, float h ) { - const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2 + const vec3 k = vec3(-0.9238795325, // sqrt(2+sqrt(2))/2 0.3826834323, // sqrt(2-sqrt(2))/2 - 0.4142135623 ); // sqrt(2)-1 + 0.4142135623 ); // sqrt(2)-1 // reflections p = abs(p); p.xy -= 2.0*min(dot(vec2( k.x,k.y),p.xy),0.0)*vec2( k.x,k.y); @@ -155,7 +157,7 @@ float sdRoundCone( in vec3 p, in float r1, float r2, float h ) if( k < 0.0 ) return length(q) - r1; if( k > a*h ) return length(q-vec2(0.0,h)) - r2; - + return dot(q, vec2(a,b) ) - r1; } @@ -298,8 +300,8 @@ float sdOctahedron(vec3 p, float s) else if( 3.0*p.y < m ) q = p.yzx; else if( 3.0*p.z < m ) q = p.zxy; else return m*0.57735027; - float k = clamp(0.5*(q.z-q.y+s),0.0,s); - return length(vec3(q.x,q.y-s+k,q.z-k)); + float k = clamp(0.5*(q.z-q.y+s),0.0,s); + return length(vec3(q.x,q.y-s+k,q.z-k)); #endif // bound, not exact @@ -406,12 +408,12 @@ vec2 map( in vec3 pos ) res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.15, 0.0), vec3(0.1,0.0,0.0), vec3(-0.1,0.35,0.1), 0.15, 0.05), 51.7 ) ); res = opU( res, vec2( sdRoundCone( pos-vec3( 2.0,0.20, 1.0), 0.2, 0.1, 0.3 ), 37.0 ) ); } - + return res; } // http://iquilezles.org/www/articles/boxfunctions/boxfunctions.htm -vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) +vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) { vec3 m = 1.0/rd; vec3 n = m*ro; @@ -437,8 +439,8 @@ vec2 raycast( in vec3 ro, in vec3 rd ) res = vec2( tp1, 1.0 ); } //else return res; - - // raymarch primitives + + // raymarch primitives vec2 tb = iBox( ro-vec3(0.0,0.4,-0.5), rd, vec3(2.5,0.41,3.0) ); if( tb.x0.0 && tb.x100.0 ) break; } return normalize(n); -#endif +#endif } float calcAO( in vec3 pos, in vec3 nor ) @@ -526,11 +528,11 @@ float checkersGradBox( in vec2 p, in vec2 dpdx, in vec2 dpdy ) // analytical integral (box filter) vec2 i = 2.0*(abs(fract((p-0.5*w)*0.5)-0.5)-abs(fract((p+0.5*w)*0.5)-0.5))/w; // xor pattern - return 0.5 - 0.5*i.x*i.y; + return 0.5 - 0.5*i.x*i.y; } vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) -{ +{ // background vec3 col = vec3(0.7, 0.7, 0.9) - max(rd.y,0.0)*0.3; @@ -543,11 +545,11 @@ vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) vec3 pos = ro + t*rd; vec3 nor = (m<1.5) ? vec3(0.0,1.0,0.0) : calcNormal( pos ); vec3 ref = reflect( rd, nor ); - - // material + + // material col = 0.2 + 0.2*sin( m*2.0 + vec3(0.0,1.0,2.0) ); float ks = 1.0; - + if( m<1.5 ) { // project pixel footprint into the plane @@ -561,7 +563,7 @@ vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) // lighting float occ = calcAO( pos, nor ); - + vec3 lin = vec3(0.0); // sun @@ -601,7 +603,7 @@ vec3 render( in vec3 ro, in vec3 rd, in vec3 rdx, in vec3 rdy ) dif *= occ; lin += col*0.25*dif*vec3(1.00,1.00,1.00); } - + col = lin; col = mix( col, vec3(0.7,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) ); @@ -624,7 +626,7 @@ vec4 mainImage( vec2 fragCoord ) vec2 mo = iMouse.xy/iResolution.xy; float time = 32.0 + iTime*1.5; - // camera + // camera vec3 ta = vec3( 0.5, -0.5, -0.6 ); vec3 ro = ta + vec3( 4.5*cos(0.1*time + 7.0*mo.x), 1.3 + 2.0*mo.y, 4.5*sin(0.1*time + 7.0*mo.x) ); // camera-to-world transformation @@ -638,13 +640,13 @@ vec4 mainImage( vec2 fragCoord ) // pixel coordinates vec2 o = vec2(float(m),float(n)) / float(AA) - 0.5; vec2 p = (2.0*(fragCoord+o)-iResolution.xy)/iResolution.y; -#else +#else vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y; #endif // focal length const float fl = 2.5; - + // ray direction vec3 rd = ca * normalize( vec3(p,fl) ); @@ -653,13 +655,13 @@ vec4 mainImage( vec2 fragCoord ) vec2 py = (2.0*(fragCoord+vec2(0.0,1.0))-iResolution.xy)/iResolution.y; vec3 rdx = ca * normalize( vec3(px,fl) ); vec3 rdy = ca * normalize( vec3(py,fl) ); - - // render + + // render vec3 col = render( ro, rd, rdx, rdy ); // gain // col = col*3.0/(2.5+col); - + // gamma col = pow( col, vec3(0.4545) ); @@ -668,7 +670,7 @@ vec4 mainImage( vec2 fragCoord ) } tot /= float(AA*AA); #endif - + //fragColor = vec4( tot, 1.0 ); return vec4( tot, 1.0 ); } @@ -679,14 +681,14 @@ vec4 mainImage( vec2 fragCoord ) void main() { vec4 c = color; - vec4 txt = texture(tex, uv); + vec4 txt = texture(sampler2D(tex, smp), uv); c = txt * c; vec2 uv1 = uv * iResolution; vec4 col_ray = mainImage(uv1); - + // use this to mix the chessboart texture with the ray marching //frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) * col_ray ; - + frag_color = c*0.00001 + col_ray ; } diff --git a/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl b/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl index bea60d595fa876..517cfcbbf19e52 100644 --- a/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl +++ b/examples/sokol/04_multi_shader_glsl/rt_glsl_puppy.glsl @@ -26,7 +26,9 @@ void main() { #pragma sokol @end #pragma sokol @fs fs_p -uniform sampler2D tex; +uniform texture2D tex; +uniform sampler smp; + uniform fs_params_p { vec2 iResolution; vec2 iMouse; @@ -38,7 +40,7 @@ in vec4 color; in vec2 uv; out vec4 frag_color; -// change to 0 to 4 to increment the AntiAliasing, +// change to 0 to 4 to increment the AntiAliasing, // increase AA will SLOW the rendering!! #define AA 1 @@ -47,9 +49,9 @@ out vec4 frag_color; // original code from: https://www.shadertoy.com/view/Xds3zN //********************************************************* // Created by inigo quilez - iq/2019 -// I share this piece (art and code) here in Shadertoy and through its Public API, only for educational purposes. +// I share this piece (art and code) here in Shadertoy and through its Public API, only for educational purposes. // You cannot use, share or host this piece or modifications of it as part of your own commercial or non-commercial product, website or project. -// You can share a link to it or an unmodified screenshot of it provided you attribute "by Inigo Quilez, @iquilezles and iquilezles.org". +// You can share a link to it or an unmodified screenshot of it provided you attribute "by Inigo Quilez, @iquilezles and iquilezles.org". // If you are a teacher, lecturer, educator or similar and these conditions are too restrictive for your needs, please contact me and we'll work it out. @@ -127,7 +129,7 @@ float hsha; vec4 map( in vec3 pos, float atime ) { hsha = 1.0; - + float t1 = fract(atime); float t4 = abs(fract(atime*0.5)-0.5)/0.5; @@ -141,7 +143,7 @@ vec4 map( in vec3 pos, float atime ) // body vec2 uu = normalize(vec2( 1.0, -pp )); vec2 vv = vec2(-uu.y, uu.x); - + float sy = 0.5 + 0.5*p; float compress = 1.0-smoothstep(0.0,0.4,p); sy = sy*(1.0-compress) + compress; @@ -155,7 +157,7 @@ vec4 map( in vec3 pos, float atime ) vec3 r = q; href = q.y; q.yz = vec2( dot(uu,q.yz), dot(vv,q.yz) ); - + vec4 res = vec4( sdEllipsoid( q, vec3(0.25, 0.25*sy, 0.25*sz) ), 2.0, 0.0, 1.0 ); if( res.x-1.0 < pos.y ) // bounding volume @@ -176,19 +178,19 @@ vec4 map( in vec3 pos, float atime ) float d2 = sdEllipsoid( h-vec3(0.0,0.21,-0.1), vec3(0.20,0.2,0.20) ); d = smin( d, d2, 0.1 ); res.x = smin( res.x, d, 0.1 ); - + // belly wrinkles { float yy = r.y-0.02-2.5*r.x*r.x; res.x += 0.001*sin(yy*120.0)*(1.0-smoothstep(0.0,0.1,abs(yy))); } - + // arms { vec2 arms = sdStick( sq, vec3(0.18-0.06*hr*sign(r.x),0.2,-0.05), vec3(0.3+0.1*p2,-0.2+0.3*p2,-0.15), 0.03, 0.06 ); res.xz = smin( res.xz, arms, 0.01+0.04*(1.0-arms.y)*(1.0-arms.y)*(1.0-arms.y) ); } - + // ears { float t3 = fract(atime+0.9); @@ -196,7 +198,7 @@ vec4 map( in vec3 pos, float atime ) vec2 ear = sdStick( hq, vec3(0.15,0.32,-0.05), vec3(0.2+0.05*p3,0.2+0.2*p3,-0.07), 0.01, 0.04 ); res.xz = smin( res.xz, ear, 0.01 ); } - + // mouth { d = sdEllipsoid( h-vec3(0.0,0.15+4.0*hq.x*hq.x,0.15), vec3(0.1,0.04,0.2) ); @@ -213,13 +215,13 @@ vec4 map( in vec3 pos, float atime ) vec2 legs = sdStick( sq, base, base + vec3(0.2,-ccc,sss)*0.2, 0.04, 0.07 ); res.xz = smin( res.xz, legs, 0.07 ); } - + // eye { float blink = pow(0.5+0.5*sin(2.1*iTime),20.0); float eyeball = sdSphere(hq-vec3(0.08,0.27,0.06),0.065+0.02*blink); res.x = smin( res.x, eyeball, 0.03 ); - + vec3 cq = hq-vec3(0.1,0.34,0.08); cq.xy = mat2x2(0.8,0.6,-0.6,0.8)*cq.xy; d = sdEllipsoid( cq, vec3(0.06,0.03,0.03) ); @@ -230,19 +232,19 @@ vec4 map( in vec3 pos, float atime ) res = opU( res, vec4(sdSphere(hq-vec3(0.075,0.28,0.102),0.0395),4.0,0.0,1.0)); } } - + // ground float fh = -0.1 - 0.05*(sin(pos.x*2.0)+sin(pos.z*2.0)); float t5f = fract(atime+0.05); - float t5i = floor(atime+0.05); + float t5i = floor(atime+0.05); float bt4 = abs(fract(t5i*0.5)-0.5)/0.5; vec2 bcen = vec2( 0.5*(-1.0+2.0*bt4),t5i+pow(t5f,0.7)-1.0 ); - + float k = length(pos.xz-bcen); float tt = t5f*15.0-6.2831 - k*3.0; fh -= 0.1*exp(-k*k)*sin(tt)*exp(-max(tt,0.0)/2.0)*smoothstep(0.0,0.01,t5f); float d = pos.y - fh; - + // bubbles { vec3 vp = vec3( mod(abs(pos.x),3.0)-1.5,pos.y,mod(pos.z+1.5,3.0)-1.5); @@ -251,10 +253,10 @@ vec4 map( in vec3 pos, float atime ) float fy = fract(fid*1.312+atime*0.1); float y = -1.0+4.0*fy; vec3 rad = vec3(0.7,1.0+0.5*sin(fid),0.7); - rad -= 0.1*(sin(pos.x*3.0)+sin(pos.y*4.0)+sin(pos.z*5.0)); + rad -= 0.1*(sin(pos.x*3.0)+sin(pos.y*4.0)+sin(pos.z*5.0)); float siz = 4.0*fy*(1.0-fy); float d2 = sdEllipsoid( vp-vec3(0.5,y,0.0), siz*rad ); - + d2 -= 0.03*smoothstep(-1.0,1.0,sin(18.0*pos.x)+sin(18.0*pos.y)+sin(18.0*pos.z)); d2 *= 0.6; d2 = min(d2,2.0); @@ -275,7 +277,7 @@ vec4 map( in vec3 pos, float atime ) d = sdSphere( vp, 0.35*ra )/fs; if( d0.0 ) tmax = min( tmax, tp ); - #endif - + #endif + // raymarch scene float t = tmin; for( int i=0; i<256 && t0.0 ) tmax = min( tmax, tp ); - #endif - + #endif + float t = 0.02; for( int i=0; i<50; i++ ) { @@ -333,12 +335,12 @@ float calcSoftshadow( in vec3 ro, in vec3 rd, float time ) // http://iquilezles.org/www/articles/normalsSDF/normalsSDF.htm vec3 calcNormal( in vec3 pos, float time ) { - + #if 0 vec2 e = vec2(1.0,-1.0)*0.5773*0.001; - return normalize( e.xyy*map( pos + e.xyy, time ).x + - e.yyx*map( pos + e.yyx, time ).x + - e.yxy*map( pos + e.yxy, time ).x + + return normalize( e.xyy*map( pos + e.xyy, time ).x + + e.yyx*map( pos + e.yyx, time ).x + + e.yxy*map( pos + e.yxy, time ).x + e.xxx*map( pos + e.xxx, time ).x ); #else // inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times @@ -349,7 +351,7 @@ vec3 calcNormal( in vec3 pos, float time ) n += e*map(pos+0.001*e,time).x; } return normalize(n); -#endif +#endif } float calcOcclusion( in vec3 pos, in vec3 nor, float time ) @@ -368,7 +370,7 @@ float calcOcclusion( in vec3 pos, in vec3 nor, float time ) } vec3 render( in vec3 ro, in vec3 rd, float time ) -{ +{ // sky dome vec3 col = vec3(0.5, 0.8, 0.9) - max(rd.y,0.0)*0.5; // sky clouds @@ -377,8 +379,8 @@ vec3 render( in vec3 ro, in vec3 rd, float time ) cl += 0.5*(sin(uv.x)+sin(uv.y)); col += 0.1*(-1.0+2.0*smoothstep(-0.1,0.1,cl-0.4)); // sky horizon - col = mix( col, vec3(0.5, 0.7, .9), exp(-10.0*max(rd.y,0.0)) ); - + col = mix( col, vec3(0.5, 0.7, .9), exp(-10.0*max(rd.y,0.0)) ); + // scene geometry vec4 res = raycast(ro,rd, time); @@ -389,52 +391,52 @@ vec3 render( in vec3 ro, in vec3 rd, float time ) vec3 nor = calcNormal( pos, time ); vec3 ref = reflect( rd, nor ); float focc = res.w; - - // material + + // material col = vec3(0.2); float ks = 1.0; if( res.y>4.5 ) // candy - { - col = vec3(0.14,0.048,0.0); + { + col = vec3(0.14,0.048,0.0); vec2 id = floor(5.0*pos.xz+0.5); col += 0.036*cos((id.x*11.1+id.y*37.341) + vec3(0.0,1.0,2.0) ); col = max(col,0.0); focc = clamp(4.0*res.z,0.0,1.0); } else if( res.y>3.5 ) // eyeball - { + { col = vec3(0.0); - } + } else if( res.y>2.5 ) // iris - { + { col = vec3(0.4); - } + } else if( res.y>1.5 ) // body - { + { col = mix(vec3(0.144,0.09,0.0036),vec3(0.36,0.1,0.04),res.z*res.z); col = mix(col,vec3(0.14,0.09,0.06)*2.0, (1.0-res.z)*smoothstep(-0.15, 0.15, -href)); } else // terrain { - // base green + // base green col = vec3(0.05,0.09,0.02); float f = 0.2*(-1.0+2.0*smoothstep(-0.2,0.2,sin(18.0*pos.x)+sin(18.0*pos.y)+sin(18.0*pos.z))); col += f*vec3(0.06,0.06,0.02); ks = 0.5 + pos.y*0.15; - - // footprints + + // footprints vec2 mp = vec2(pos.x-0.5*(mod(floor(pos.z+0.5),2.0)*2.0-1.0), fract(pos.z+0.5)-0.5 ); float mark = 1.0-smoothstep(0.1, 0.5, length(mp)); mark *= smoothstep(0.0, 0.1, floor(time) - floor(pos.z+0.5) ); col *= mix( vec3(1.0), vec3(0.5,0.5,0.4), mark ); ks *= 1.0-0.5*mark; } - + // lighting (sun, sky, bounce, back, sss) float occ = calcOcclusion( pos, nor, time )*focc; float fre = clamp(1.0+dot(nor,rd),0.0,1.0); - + vec3 sun_lig = normalize( vec3(0.6, 0.35, 0.5) ); float sun_dif = clamp(dot( nor, sun_lig ), 0.0, 1.0 ); vec3 sun_hal = normalize( sun_lig-rd ); @@ -455,9 +457,9 @@ vec3 render( in vec3 ro, in vec3 rd, float time ) col = col*lin; col += sun_spe*vec3(9.90,8.10,6.30)*sun_sha; col += sky_spe*vec3(0.20,0.30,0.65)*occ*occ; - + col = pow(col,vec3(0.8,0.9,1.0) ); - + // fog col = mix( col, vec3(0.5,0.7,0.9), 1.0-exp( -0.0001*t*t*t ) ); } @@ -488,22 +490,22 @@ vec4 mainImage( vec2 fragCoord ) // time coordinate (motion blurred, shutter=0.5) float d = 0.5+0.5*sin(fragCoord.x*147.0)*sin(fragCoord.y*131.0); float time = iTime - 0.5*(1.0/24.0)*(float(m*AA+n)+d)/float(AA*AA); -#else +#else vec2 p = (-iResolution.xy + 2.0*fragCoord)/iResolution.y; float time = iTime; #endif time += -2.6; time *= 0.9; - - // camera + + // camera float cl = sin(0.5*time); float an = 1.57 + 0.7*sin(0.15*time); vec3 ta = vec3( 0.0, 0.65, -0.6+time*1.0 - 0.4*cl); vec3 ro = ta + vec3( 1.3*cos(an), -0.250, 1.3*sin(an) ); float ti = fract(time-0.15); - ti = 4.0*ti*(1.0-ti); + ti = 4.0*ti*(1.0-ti); ta.y += 0.15*ti*ti*(3.0-2.0*ti)*smoothstep(0.4,0.9,cl); - + // camera bounce float t4 = abs(fract(time*0.5)-0.5)/0.5; float bou = -1.0 + 2.0*t4; @@ -514,16 +516,16 @@ vec4 mainImage( vec2 fragCoord ) // ray direction vec3 rd = ca * normalize( vec3(p,1.8) ); - - // render + + // render vec3 col = render( ro, rd, time ); // color grading col = col*vec3(1.11,0.89,0.79); - // compress + // compress col = 1.35*col/(1.0+col); - + // gamma col = pow( col, vec3(0.4545) ); @@ -533,15 +535,15 @@ vec4 mainImage( vec2 fragCoord ) tot /= float(AA*AA); #endif - // s-surve + // s-surve tot = clamp(tot,0.0,1.0); tot = tot*tot*(3.0-2.0*tot); - // vignetting + // vignetting vec2 q = fragCoord/iResolution.xy; tot *= 0.5 + 0.5*pow(16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.25); - // output + // output //fragColor = vec4( tot, 1.0 ); return vec4( tot, 1.0 ); } @@ -552,14 +554,14 @@ vec4 mainImage( vec2 fragCoord ) void main() { vec4 c = color; - vec4 txt = texture(tex, uv); + vec4 txt = texture(sampler2D(tex, smp), uv); c = txt * c; vec2 uv1 = uv * iResolution; vec4 col_ray = mainImage(uv1); - + // use this to mix the chessboart texture with the ray marching //frag_color = clamp(c*iMouse.y/512.0,0.0,1.0) * col_ray ; - + frag_color = c*0.00001 + col_ray ; } diff --git a/examples/sokol/05_instancing_glsl/rt_glsl.v b/examples/sokol/05_instancing_glsl/rt_glsl.v index 912bcd80d70c3c..c7eda3674a680d 100644 --- a/examples/sokol/05_instancing_glsl/rt_glsl.v +++ b/examples/sokol/05_instancing_glsl/rt_glsl.v @@ -32,6 +32,7 @@ struct App { mut: gg &gg.Context = unsafe { nil } texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int @@ -64,7 +65,7 @@ fn C.instancing_shader_desc(gfx.Backend) &gfx.ShaderDesc /****************************************************************************** * Texture functions ******************************************************************************/ -fn create_texture(w int, h int, buf byteptr) gfx.Image { +fn create_texture(w int, h int, buf byteptr) (gfx.Image, gfx.Sampler) { sz := w * h * 4 // vfmt off mut img_desc := gfx.ImageDesc{ @@ -87,7 +88,16 @@ fn create_texture(w int, h int, buf byteptr) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } fn destroy_texture(sg_img gfx.Image) { @@ -258,6 +268,7 @@ fn init_cube_glsl_i(mut app App) { bind.vertex_buffers[1] = inst_buf // instance buffer bind.index_buffer = ibuf bind.fs.images[C.SLOT_tex] = app.texture + bind.fs.samplers[C.SLOT_smp] = app.sampler app.bind['inst'] = bind app.pipe['inst'] = gfx.make_pipeline(&pipdesc) @@ -440,7 +451,7 @@ fn my_init(mut app App) { } } unsafe { - app.texture = create_texture(w, h, tmp_txt) + app.texture, app.sampler = create_texture(w, h, tmp_txt) free(tmp_txt) } // glsl diff --git a/examples/sokol/05_instancing_glsl/rt_glsl_instancing.glsl b/examples/sokol/05_instancing_glsl/rt_glsl_instancing.glsl index 0e780b3f682d2b..2b5f67e550d3f0 100644 --- a/examples/sokol/05_instancing_glsl/rt_glsl_instancing.glsl +++ b/examples/sokol/05_instancing_glsl/rt_glsl_instancing.glsl @@ -45,7 +45,8 @@ void main() { #pragma sokol @end #pragma sokol @fs fs_i -uniform sampler2D tex; +uniform texture2D tex; +uniform sampler smp; in vec4 color; in vec4 color_inst; @@ -54,8 +55,8 @@ out vec4 frag_color; void main() { vec4 c = color; - vec4 txt = texture(tex, uv); - c = txt * c * color_inst; + vec4 txt = texture(sampler2D(tex, smp), uv); + c = txt * c * color_inst; frag_color = c ; } diff --git a/examples/sokol/06_obj_viewer/gouraud.glsl b/examples/sokol/06_obj_viewer/gouraud.glsl index 7d55a0aa927385..4a8697996d9d3f 100644 --- a/examples/sokol/06_obj_viewer/gouraud.glsl +++ b/examples/sokol/06_obj_viewer/gouraud.glsl @@ -7,7 +7,7 @@ uniform vs_params { mat4 u_MVPMatrix; // A constant representing the combined model/view/projection matrix. mat4 u_NMatrix; // A constant representing the Normal Matrix }; - + in vec4 a_Position; // Per-vertex position information we will pass in. in vec3 a_Normal; // Per-vertex normal information we will pass in. //in vec4 a_Color; // Per-vertex color information we will pass in. @@ -30,9 +30,9 @@ void main() v_Normal = vec3(u_NMatrix * vec4(a_Normal, 1.0)); // texture coord uv = a_Texcoord0; - + v_Normal1 = normalize(vec3(u_MVMatrix * vec4(a_Normal, 1.0))); - + // gl_Position is a special variable used to store the final position. // Multiply the vertex by the matrix to get the final point in normalized screen coordinates. gl_Position = u_MVPMatrix * a_Position; @@ -42,13 +42,14 @@ void main() #pragma sokol @fs fs //precision mediump float; // Set the default precision to medium. We don't need as high of a precision in the fragment shader -uniform sampler2D tex; +uniform texture2D tex; +uniform sampler smp; uniform fs_params { vec4 u_LightPos; // The position of the light in eye space. vec4 ambientColor; vec4 diffuseColor; vec4 specularColor; - + }; in vec3 v_Position; // Interpolated position for this fragment. //in vec4 v_Color; // This is the color from the vertex shader interpolated across the triangle per fragment. @@ -78,7 +79,7 @@ vec4 getPhong(in vec4 diffuseColor) { vec3 n = normalize(v_Normal); vec3 luminance = ambientColor.rgb * 0.5; - + float illuminance = dot(lightDir, n); if(illuminance > 0.0) { // we save specular shiness in specularColor.a @@ -89,20 +90,20 @@ vec4 getPhong(in vec4 diffuseColor) { vec4 outColor = vec4(luminance,1.0); return outColor; } - + // The entry point for our fragment shader. void main() { - vec4 txt = texture(tex, uv); - + vec4 txt = texture(sampler2D(tex, smp), uv); + // Directional light float directional = dot(normalize(v_Normal1), normalize(vec3(0,0.5,1))) ; directional = directional * 0.15; - - // Multiply the color by the diffuse illumination level to get final output color. + + // Multiply the color by the diffuse illumination level to get final output color. frag_color = vec4(clamp(directional + txt.rgb * getPhong(diffuseColor).rgb,0,1), txt.a * diffuseColor.a); - + } #pragma sokol @end -#pragma sokol @program gouraud vs fs \ No newline at end of file +#pragma sokol @program gouraud vs fs diff --git a/examples/sokol/06_obj_viewer/modules/obj/rend.v b/examples/sokol/06_obj_viewer/modules/obj/rend.v index d60c19251f72d2..69877af655e49e 100644 --- a/examples/sokol/06_obj_viewer/modules/obj/rend.v +++ b/examples/sokol/06_obj_viewer/modules/obj/rend.v @@ -18,7 +18,7 @@ import stbi /****************************************************************************** * Texture functions ******************************************************************************/ -pub fn create_texture(w int, h int, buf &u8) gfx.Image { +pub fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) { sz := w * h * 4 mut img_desc := gfx.ImageDesc{ width: w @@ -39,29 +39,38 @@ pub fn create_texture(w int, h int, buf &u8) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } pub fn destroy_texture(sg_img gfx.Image) { gfx.destroy_image(sg_img) } -pub fn load_texture(file_name string) gfx.Image { +pub fn load_texture(file_name string) (gfx.Image, gfx.Sampler) { buffer := read_bytes_from_file(file_name) stbi.set_flip_vertically_on_load(true) img := stbi.load_from_memory(buffer.data, buffer.len) or { eprintln('Texure file: [${file_name}] ERROR!') exit(0) } - res := create_texture(int(img.width), int(img.height), img.data) + sg_img, sg_smp := create_texture(int(img.width), int(img.height), img.data) img.free() - return res + return sg_img, sg_smp } /****************************************************************************** * Pipeline ******************************************************************************/ -pub fn (mut obj_part ObjPart) create_pipeline(in_part []int, shader gfx.Shader, texture gfx.Image) Render_data { +pub fn (mut obj_part ObjPart) create_pipeline(in_part []int, shader gfx.Shader, texture gfx.Image, sampler gfx.Sampler) Render_data { mut res := Render_data{} obj_buf := obj_part.get_buffer(in_part) res.n_vert = obj_buf.n_vertex @@ -134,6 +143,7 @@ pub fn (mut obj_part ObjPart) create_pipeline(in_part []int, shader gfx.Shader, res.bind.vertex_buffers[0] = vbuf res.bind.index_buffer = ibuf res.bind.fs.images[C.SLOT_tex] = texture + res.bind.fs.samplers[C.SLOT_smp] = sampler res.pipeline = gfx.make_pipeline(&pipdesc) // println('Buffers part [$in_part] init done!') @@ -144,7 +154,7 @@ pub fn (mut obj_part ObjPart) create_pipeline(in_part []int, shader gfx.Shader, * Render functions ******************************************************************************/ // aggregate all the part by materials -pub fn (mut obj_part ObjPart) init_render_data(texture gfx.Image) { +pub fn (mut obj_part ObjPart) init_render_data(texture gfx.Image, sampler gfx.Sampler) { // create shader // One shader for all the model shader := gfx.make_shader(C.gouraud_shader_desc(gfx.query_backend())) @@ -162,6 +172,7 @@ pub fn (mut obj_part ObjPart) init_render_data(texture gfx.Image) { // println("$k => Parts $v") mut txt := texture + mut smp := sampler if k in obj_part.mat_map { mat_map := obj_part.mat[obj_part.mat_map[k]] @@ -171,15 +182,16 @@ pub fn (mut obj_part ObjPart) init_render_data(texture gfx.Image) { txt = obj_part.texture[file_name] // println("Texture [${file_name}] => from CACHE") } else { - txt = load_texture(file_name) + txt, smp = load_texture(file_name) obj_part.texture[file_name] = txt + obj_part.sampler[file_name] = smp // println("Texture [${file_name}] => LOADED") } } } // key := obj_part.texture.keys()[0] // obj_part.rend_data << obj_part.create_pipeline(v, shader, obj_part.texture[key]) - obj_part.rend_data << obj_part.create_pipeline(v, shader, txt) + obj_part.rend_data << obj_part.create_pipeline(v, shader, txt, smp) } // println("Texture array len: ${obj_part.texture.len}") // println("Calc bounding box.") diff --git a/examples/sokol/06_obj_viewer/modules/obj/struct.v b/examples/sokol/06_obj_viewer/modules/obj/struct.v index cc781a40a27a2e..4508060651661c 100644 --- a/examples/sokol/06_obj_viewer/modules/obj/struct.v +++ b/examples/sokol/06_obj_viewer/modules/obj/struct.v @@ -48,10 +48,11 @@ pub mut: vt []m4.Vec4 // textures name string - part []Part // parts of the ObjPart - mat []Material // list of the materials of the ObjPart - mat_map map[string]int // mapping material name to its material index - texture map[string]gfx.Image // GPU loaded texture map + part []Part // parts of the ObjPart + mat []Material // list of the materials of the ObjPart + mat_map map[string]int // mapping material name to its material index + texture map[string]gfx.Image // GPU loaded texture map + sampler map[string]gfx.Sampler // GPU loaded sampler material_file string // .mtl file name for the .obj rend_data []Render_data // render data used for the rendering diff --git a/examples/sokol/06_obj_viewer/show_obj.v b/examples/sokol/06_obj_viewer/show_obj.v index 68364736a732b3..dbd561e08e384f 100644 --- a/examples/sokol/06_obj_viewer/show_obj.v +++ b/examples/sokol/06_obj_viewer/show_obj.v @@ -47,6 +47,7 @@ struct App { mut: gg &gg.Context = unsafe { nil } texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int @@ -224,11 +225,11 @@ fn my_init(mut app App) { tmp_txt[1] = u8(0xFF) tmp_txt[2] = u8(0xFF) tmp_txt[3] = u8(0xFF) - app.texture = obj.create_texture(1, 1, tmp_txt) + app.texture, app.sampler = obj.create_texture(1, 1, tmp_txt) free(tmp_txt) } // glsl - app.obj_part.init_render_data(app.texture) + app.obj_part.init_render_data(app.texture, app.sampler) app.init_flag = true } diff --git a/examples/viewer/view.v b/examples/viewer/view.v index cb8b4139017d3e..6b718b20b2b498 100644 --- a/examples/viewer/view.v +++ b/examples/viewer/view.v @@ -63,6 +63,7 @@ mut: gg &gg.Context = unsafe { nil } pip_viewer sgl.Pipeline texture gfx.Image + sampler gfx.Sampler init_flag bool frame_count int mouse_x int = -1 @@ -103,6 +104,7 @@ mut: // logo logo_path string // path of the temp font logo logo_texture gfx.Image + logo_sampler gfx.Sampler logo_w int logo_h int logo_ratio f32 = 1.0 @@ -115,17 +117,13 @@ mut: * Texture functions * ******************************************************************************/ -fn create_texture(w int, h int, buf &u8) gfx.Image { +fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) { sz := w * h * 4 mut img_desc := gfx.ImageDesc{ width: w height: h num_mipmaps: 0 - // min_filter: .linear - // mag_filter: .linear // usage: .dynamic - // wrap_u: .clamp_to_edge - // wrap_v: .clamp_to_edge label: &u8(0) d3d11_texture: 0 } @@ -136,7 +134,16 @@ fn create_texture(w int, h int, buf &u8) gfx.Image { } sg_img := gfx.make_image(&img_desc) - return sg_img + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + sg_smp := gfx.make_sampler(&smp_desc) + return sg_img, sg_smp } fn destroy_texture(sg_img gfx.Image) { @@ -225,22 +232,22 @@ pub fn read_bytes_from_file(file_path string) []u8 { return buffer } -fn (mut app App) load_texture_from_buffer(buf voidptr, buf_len int) (gfx.Image, int, int) { +fn (mut app App) load_texture_from_buffer(buf voidptr, buf_len int) (gfx.Image, gfx.Sampler, int, int) { // load image stbi.set_flip_vertically_on_load(true) img := stbi.load_from_memory(buf, buf_len) or { eprintln('ERROR: Can not load image from buffer, file: [${app.item_list.lst[app.item_list.item_index]}].') - return app.logo_texture, app.logo_w, app.logo_h + return app.logo_texture, app.sampler, app.logo_w, app.logo_h // exit(1) } - res := create_texture(int(img.width), int(img.height), img.data) + sg_img, sg_smp := create_texture(int(img.width), int(img.height), img.data) unsafe { img.free() } - return res, int(img.width), int(img.height) + return sg_img, sg_smp, int(img.width), int(img.height) } -pub fn (mut app App) load_texture_from_file(file_name string) (gfx.Image, int, int) { +pub fn (mut app App) load_texture_from_file(file_name string) (gfx.Image, gfx.Sampler, int, int) { app.read_bytes(file_name) return app.load_texture_from_buffer(app.mem_buf, app.mem_buf_size) } @@ -249,8 +256,10 @@ pub fn show_logo(mut app App) { clear_modifier_params(mut app) if app.texture != app.logo_texture { destroy_texture(app.texture) + gfx.destroy_sampler(app.sampler) } app.texture = app.logo_texture + app.sampler = app.logo_sampler app.img_w = app.logo_w app.img_h = app.logo_h app.img_ratio = f32(app.img_w) / f32(app.img_h) @@ -268,11 +277,12 @@ pub fn load_image(mut app App) { // destroy the texture, avoid to destroy the logo if app.texture != app.logo_texture { destroy_texture(app.texture) + gfx.destroy_sampler(app.sampler) } // load from .ZIP file if app.item_list.is_inside_a_container() == true { - app.texture, app.img_w, app.img_h = app.load_texture_from_zip() or { + app.texture, app.sampler, app.img_w, app.img_h = app.load_texture_from_zip() or { eprintln('ERROR: Can not load image from .ZIP file [${app.item_list.lst[app.item_list.item_index]}].') show_logo(mut app) app.state = .show @@ -293,11 +303,12 @@ pub fn load_image(mut app App) { file_path := app.item_list.get_file_path() if file_path.len > 0 { // println("${app.item_list.lst[app.item_list.item_index]} $file_path ${app.item_list.lst.len}") - app.texture, app.img_w, app.img_h = app.load_texture_from_file(file_path) + app.texture, app.sampler, app.img_w, app.img_h = app.load_texture_from_file(file_path) app.img_ratio = f32(app.img_w) / f32(app.img_h) // println("texture: [${app.img_w},${app.img_h}] ratio: ${app.img_ratio}") } else { app.texture = app.logo_texture + app.sampler = app.logo_sampler app.img_w = app.logo_w app.img_h = app.logo_h app.img_ratio = f32(app.img_w) / f32(app.img_h) @@ -335,13 +346,14 @@ fn app_init(mut app App) { app.pip_viewer = sgl.make_pipeline(&pipdesc) // load logo - app.logo_texture, app.logo_w, app.logo_h = app.load_texture_from_file(app.logo_path) + app.logo_texture, app.logo_sampler, app.logo_w, app.logo_h = app.load_texture_from_file(app.logo_path) app.logo_ratio = f32(app.img_w) / f32(app.img_h) app.img_w = app.logo_w app.img_h = app.logo_h app.img_ratio = app.logo_ratio app.texture = app.logo_texture + app.sampler = app.logo_sampler println('INIT DONE!') @@ -383,7 +395,7 @@ fn frame(mut app App) { // enable our pipeline sgl.load_pipeline(app.pip_viewer) sgl.enable_texture() - sgl.texture(app.texture) + sgl.texture(app.texture, app.sampler) // translation tr_x := app.tr_x / app.img_w diff --git a/examples/viewer/zip_container.v b/examples/viewer/zip_container.v index 9cafa76cc4fbc1..43f2809a8bffec 100644 --- a/examples/viewer/zip_container.v +++ b/examples/viewer/zip_container.v @@ -47,7 +47,7 @@ fn (mut il Item_list) scan_zip(path string, in_index int) ! { zp.close() } -fn (mut app App) load_texture_from_zip() !(gfx.Image, int, int) { +fn (mut app App) load_texture_from_zip() !(gfx.Image, gfx.Sampler, int, int) { item := app.item_list.lst[app.item_list.item_index] // println("Load from zip [${item.path}]") diff --git a/vlib/gg/image.c.v b/vlib/gg/image.c.v index 0e8b29521b5b1b..ef2eba3b43272a 100644 --- a/vlib/gg/image.c.v +++ b/vlib/gg/image.c.v @@ -21,6 +21,7 @@ pub mut: ext string simg_ok bool simg gfx.Image + ssmp gfx.Sampler path string } @@ -112,6 +113,16 @@ pub fn (mut img Image) init_sokol_image() &Image { size: img_size } img.simg = gfx.make_image(&img_desc) + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + img.ssmp = gfx.make_sampler(&smp_desc) + img.simg_ok = true img.ok = true return img @@ -142,10 +153,6 @@ pub fn (mut ctx Context) new_streaming_image(w int, h int, channels int, sicfg S num_slices: 1 num_mipmaps: 1 usage: .stream - // wrap_u: sicfg.wrap_u // SAMPLER - // wrap_v: sicfg.wrap_v - // min_filter: sicfg.min_filter - // mag_filter: sicfg.mag_filter label: img.path.str } // Sokol requires that streamed images have NO .ptr/.size initially: @@ -154,6 +161,15 @@ pub fn (mut ctx Context) new_streaming_image(w int, h int, channels int, sicfg S size: usize(0) } img.simg = gfx.make_image(&img_desc) + + mut smp_desc := gfx.SamplerDesc{ + wrap_u: sicfg.wrap_u // SAMPLER + wrap_v: sicfg.wrap_v + min_filter: sicfg.min_filter + mag_filter: sicfg.mag_filter + } + + img.ssmp = gfx.make_sampler(&smp_desc) img.simg_ok = true img.ok = true img_idx := ctx.cache_image(img) @@ -359,7 +375,7 @@ pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) { } sgl.enable_texture() - sgl.texture(img.simg) + sgl.texture(img.simg, img.ssmp) if config.rotate != 0 { width := img_rect.width * ctx.scale diff --git a/vlib/sokol/gfx/gfx.c.v b/vlib/sokol/gfx/gfx.c.v index 9324f57e640fb4..efabe68f6ffed1 100644 --- a/vlib/sokol/gfx/gfx.c.v +++ b/vlib/sokol/gfx/gfx.c.v @@ -50,6 +50,11 @@ pub fn make_image(desc &ImageDesc) Image { return C.sg_make_image(desc) } +[inline] +pub fn make_sampler(desc &SamplerDesc) Sampler { + return C.sg_make_sampler(desc) +} + [inline] pub fn make_shader(desc &ShaderDesc) Shader { return C.sg_make_shader(desc) @@ -75,6 +80,11 @@ pub fn destroy_image(img Image) { C.sg_destroy_image(img) } +[inline] +pub fn destroy_sampler(smp Sampler) { + C.sg_destroy_sampler(smp) +} + [inline] pub fn destroy_shader(shd Shader) { C.sg_destroy_shader(shd) diff --git a/vlib/sokol/gfx/gfx_structs.c.v b/vlib/sokol/gfx/gfx_structs.c.v index aa936b7e689d55..bc5f5d34395606 100644 --- a/vlib/sokol/gfx/gfx_structs.c.v +++ b/vlib/sokol/gfx/gfx_structs.c.v @@ -113,18 +113,12 @@ pub mut: vertex_buffer_offsets [8]int index_buffer Buffer index_buffer_offset int - vs C.sg_stage_bindings - fs C.sg_stage_bindings + vs StageBindings + fs StageBindings // vs_images [8]Image // old // fs_images [8]Image // old } -pub struct C.sg_stage_bindings { -pub mut: - images [12]Image - samplers [8]Sampler -} - pub type Bindings = C.sg_bindings pub fn (mut b Bindings) set_vert_image(index int, img Image) { @@ -167,6 +161,14 @@ pub fn (b &Bindings) append_index_buffer(data voidptr, element_size int, element return C.sg_append_buffer(b.index_buffer, &range) } +pub struct C.sg_stage_bindings { +pub mut: + images [12]Image + samplers [8]Sampler +} + +pub type StageBindings = C.sg_stage_bindings + [heap] struct C.sg_shader_desc { pub mut: @@ -479,6 +481,8 @@ pub struct C.sg_sampler_desc { wgpu_sampler voidptr } +pub type SamplerDesc = C.sg_sampler_desc + pub struct C.sg_image_info { pub mut: slot SlotInfo // resource pool slot info diff --git a/vlib/sokol/sgl/sgl.c.v b/vlib/sokol/sgl/sgl.c.v index 9ec853084d4f36..5054c7fa0d75bf 100644 --- a/vlib/sokol/sgl/sgl.c.v +++ b/vlib/sokol/sgl/sgl.c.v @@ -122,8 +122,8 @@ pub fn disable_texture() { } [inline] -pub fn texture(img gfx.Image) { - C.sgl_texture(img, C.sg_sampler{}) // TODO need to pass SG_INVALID_ID ? +pub fn texture(img gfx.Image, smp gfx.Sampler) { + C.sgl_texture(img, smp) } // pipeline stack functions diff --git a/vlib/x/ttf/render_sokol_cpu.v b/vlib/x/ttf/render_sokol_cpu.v index f51c0976d435ea..7d206ac490154f 100644 --- a/vlib/x/ttf/render_sokol_cpu.v +++ b/vlib/x/ttf/render_sokol_cpu.v @@ -21,7 +21,8 @@ pub struct TTF_render_Sokol { pub mut: bmp &BitMap = unsafe { nil } // Base bitmap render // rendering fields - sg_img gfx.Image // sokol image + sg_img gfx.Image // sokol image + sg_smp gfx.Sampler // sokol sampler scale_reduct f32 = 2.0 // scale of the cpu texture for filtering device_dpi int = 72 // device DPI } @@ -123,11 +124,7 @@ pub fn (mut tf_skl TTF_render_Sokol) create_texture() { width: w height: h num_mipmaps: 0 - // min_filter: .linear - // mag_filter: .linear // usage: .dynamic - // wrap_u: .clamp_to_edge - // wrap_v: .clamp_to_edge label: &char(0) d3d11_texture: 0 } @@ -139,11 +136,23 @@ pub fn (mut tf_skl TTF_render_Sokol) create_texture() { simg := gfx.make_image(&img_desc) // free(tf_skl.bmp.buf) // DONT FREE IF Dynamic + + mut smp_desc := gfx.SamplerDesc{ + min_filter: .linear + mag_filter: .linear + wrap_u: .clamp_to_edge + wrap_v: .clamp_to_edge + } + + ssmp := gfx.make_sampler(&smp_desc) + tf_skl.sg_img = simg + tf_skl.sg_smp = ssmp } pub fn (tf_skl TTF_render_Sokol) destroy_texture() { gfx.destroy_image(tf_skl.sg_img) + gfx.destroy_sampler(tf_skl.sg_smp) } // Use only if usage: .dynamic @@ -198,7 +207,7 @@ pub fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) { // sgl.load_pipeline(ctx.pipeline.alpha) sgl.enable_texture() - sgl.texture(tf_skl.sg_img) + sgl.texture(tf_skl.sg_img, tf_skl.sg_smp) sgl.begin_quads() sgl.c4b(255, 255, 255, 255) sgl.v2f_t2f(x0, y0, u0, v0)