sokol: fix usage of sokol sampler (#19527)

This commit is contained in:
Larpon 2023-10-07 20:05:30 +02:00 committed by GitHub
parent e19e17f10b
commit 3c68e78f32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 354 additions and 239 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)
}
}

View file

@ -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);

View file

@ -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

View file

@ -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.x<tb.y && tb.y>0.0 && tb.x<tmax)
{
@ -451,8 +452,8 @@ vec2 raycast( in vec3 ro, in vec3 rd )
{
vec2 h = map( ro+rd*t );
if( abs(h.x)<(0.0001*t) )
{
res = vec2(t,h.y);
{
res = vec2(t,h.y);
break;
}
t += h.x;
@ -486,9 +487,9 @@ vec3 calcNormal( in vec3 pos )
{
#if 0
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
return normalize( e.xyy*map( pos + e.xyy ).x +
e.yyx*map( pos + e.yyx ).x +
e.yxy*map( pos + e.yxy ).x +
return normalize( e.xyy*map( pos + e.xyy ).x +
e.yyx*map( pos + e.yyx ).x +
e.yxy*map( pos + e.yxy ).x +
e.xxx*map( pos + e.xxx ).x );
#else
// inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
@ -500,7 +501,7 @@ vec3 calcNormal( in vec3 pos )
//if( n.x+n.y+n.z>100.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 ;
}

View file

@ -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

View file

@ -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

View file

@ -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.x<tb.y && tb.y>0.0 && tb.x<tmax)
{
@ -451,8 +453,8 @@ vec2 raycast( in vec3 ro, in vec3 rd )
{
vec2 h = map( ro+rd*t );
if( abs(h.x)<(0.0001*t) )
{
res = vec2(t,h.y);
{
res = vec2(t,h.y);
break;
}
t += h.x;
@ -486,9 +488,9 @@ vec3 calcNormal( in vec3 pos )
{
#if 0
vec2 e = vec2(1.0,-1.0)*0.5773*0.0005;
return normalize( e.xyy*map( pos + e.xyy ).x +
e.yyx*map( pos + e.yyx ).x +
e.yxy*map( pos + e.yxy ).x +
return normalize( e.xyy*map( pos + e.xyy ).x +
e.yyx*map( pos + e.yyx ).x +
e.yxy*map( pos + e.yxy ).x +
e.xxx*map( pos + e.xxx ).x );
#else
// inspired by tdhooper and klems - a way to prevent the compiler from inlining map() 4 times
@ -500,7 +502,7 @@ vec3 calcNormal( in vec3 pos )
//if( n.x+n.y+n.z>100.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 ;
}

View file

@ -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( d<res.x ) res = vec4(d,5.0,qos.y,1.0);
}
return res;
}
@ -285,26 +287,26 @@ vec4 raycast( in vec3 ro, in vec3 rd, float time )
float tmin = 0.5;
float tmax = 20.0;
#if 1
// raytrace bounding plane
float tp = (3.5-ro.y)/rd.y;
if( tp>0.0 ) tmax = min( tmax, tp );
#endif
#endif
// raymarch scene
float t = tmin;
for( int i=0; i<256 && t<tmax; i++ )
{
vec4 h = map( ro+rd*t, time );
if( abs(h.x)<(0.0005*t) )
{
res = vec4(t,h.yzw);
{
res = vec4(t,h.yzw);
break;
}
t += h.x;
}
return res;
}
@ -317,8 +319,8 @@ float calcSoftshadow( in vec3 ro, in vec3 rd, float time )
#if 1
float tp = (3.5-ro.y)/rd.y; // raytrace bounding plane
if( tp>0.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 ;
}

View file

@ -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

View file

@ -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 ;
}

View file

@ -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
#pragma sokol @program gouraud vs fs

View file

@ -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.")

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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}]")

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)