mirror of
https://github.com/vlang/v.git
synced 2025-09-09 07:15:50 -04:00
examples: port sokol/clear.v and sokol/sdf/sdf.v (#21069)
This commit is contained in:
parent
24d157205b
commit
8a9def6534
7
.github/workflows/compile_shaders_in_examples.sh
vendored
Executable file
7
.github/workflows/compile_shaders_in_examples.sh
vendored
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
for f in examples/sokol/*/ ; do
|
||||
echo "compiling shaders for $f ...";
|
||||
time ./v shader $f;
|
||||
echo "done";
|
||||
done;
|
13
.github/workflows/other_ci.yml
vendored
13
.github/workflows/other_ci.yml
vendored
@ -102,18 +102,7 @@ jobs:
|
||||
|
||||
- name: Shader examples can be built
|
||||
run: |
|
||||
wget https://github.com/floooh/sokol-tools-bin/raw/6b84ea387a323db9e8e17f5abed2b254a6e409fe/bin/linux/sokol-shdc
|
||||
chmod +x ./sokol-shdc
|
||||
for f in examples/sokol/02_cubes_glsl/cube_glsl \
|
||||
examples/sokol/03_march_tracing_glsl/rt_glsl \
|
||||
examples/sokol/04_multi_shader_glsl/rt_glsl_puppy \
|
||||
examples/sokol/04_multi_shader_glsl/rt_glsl_march \
|
||||
examples/sokol/05_instancing_glsl/rt_glsl_instancing \
|
||||
examples/sokol/06_obj_viewer/gouraud \
|
||||
; do \
|
||||
echo "compiling shader $f.glsl ..."; \
|
||||
./sokol-shdc --input $f.glsl --output $f.h --slang glsl330 ; \
|
||||
done
|
||||
.github/workflows/compile_shaders_in_examples.sh
|
||||
./v should-compile-all examples/sokol/*.v examples/sokol/0?*/*.v
|
||||
|
||||
parser-silent:
|
||||
|
@ -283,6 +283,7 @@ pub fn new_test_session(_vargs string, will_compile bool) TestSession {
|
||||
// These examples need .h files that are produced from the supplied .glsl files,
|
||||
// using by the shader compiler tools in https://github.com/floooh/sokol-tools-bin/archive/pre-feb2021-api-changes.tar.gz
|
||||
skip_files << 'examples/sokol/simple_shader_glsl/simple_shader.v'
|
||||
skip_files << 'examples/sokol/sdf/sdf.v'
|
||||
skip_files << 'examples/sokol/02_cubes_glsl/cube_glsl.v'
|
||||
skip_files << 'examples/sokol/03_march_tracing_glsl/rt_glsl.v'
|
||||
skip_files << 'examples/sokol/04_multi_shader_glsl/rt_glsl.v'
|
||||
|
@ -72,3 +72,4 @@
|
||||
# 'examples/sokol/04_multi_shader_glsl/rt_glsl.v', // Inaccurate captures
|
||||
# 'examples/sokol/05_instancing_glsl/rt_glsl.v', // Inaccurate captures
|
||||
# 'examples/sokol/06_obj_viewer/show_obj.v', // Inaccurate captures
|
||||
# 'examples/sokol/sdf/sdf.v', // Inaccurate captures
|
||||
|
25
examples/sokol/clear.v
Normal file
25
examples/sokol/clear.v
Normal file
@ -0,0 +1,25 @@
|
||||
// This example shows how to clear your window on each frame, with a different color, using a Sokol pass.
|
||||
// It is ported from https://github.com/floooh/sokol-samples/blob/master/sapp/clear-sapp.c .
|
||||
import sokol.gfx
|
||||
import sokol.sapp
|
||||
|
||||
fn frame(mut action gfx.PassAction) {
|
||||
g := f32(action.colors[0].clear_value.g + 0.01)
|
||||
action.colors[0].clear_value.g = if g > 1.0 { 0 } else { g }
|
||||
gfx.begin_pass(sapp.create_default_pass(action))
|
||||
gfx.end_pass()
|
||||
gfx.commit()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
action := gfx.create_clear_pass_action(1.0, 0, 0, 1.0)
|
||||
sapp.run(
|
||||
window_title: c'Clear (sokol app)'
|
||||
width: 400
|
||||
height: 300
|
||||
init_cb: || gfx.setup(sapp.create_desc())
|
||||
cleanup_cb: || gfx.shutdown()
|
||||
frame_userdata_cb: frame
|
||||
user_data: &action
|
||||
)
|
||||
}
|
2
examples/sokol/sdf/.gitignore
vendored
Normal file
2
examples/sokol/sdf/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
sdf-sapp.c
|
||||
sdf.h
|
184
examples/sokol/sdf/sdf.glsl
Normal file
184
examples/sokol/sdf/sdf.glsl
Normal file
@ -0,0 +1,184 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Signed-distance-field raymarching shaders, see:
|
||||
// https://iquilezles.org/articles/mandelbulb
|
||||
// https://www.shadertoy.com/view/ltfSWn
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//--- vertex shader
|
||||
@vs vs
|
||||
uniform vs_params {
|
||||
float aspect;
|
||||
float time;
|
||||
};
|
||||
in vec4 position;
|
||||
|
||||
out vec2 pos;
|
||||
out vec3 eye;
|
||||
out vec3 up;
|
||||
out vec3 right;
|
||||
out vec3 fwd;
|
||||
|
||||
// compute eye position (orbit around center)
|
||||
vec3 eye_pos(float time, vec3 center) {
|
||||
return center + vec3(sin(time * 0.05) * 3.0, sin(time * 0.1) * 2.0, cos(time * 0.05) * 3.0);
|
||||
}
|
||||
|
||||
// a lookat function
|
||||
void lookat(vec3 eye, vec3 center, vec3 up, out vec3 out_fwd, out vec3 out_right, out vec3 out_up) {
|
||||
out_fwd = normalize(center - eye);
|
||||
out_right = normalize(cross(out_fwd, up));
|
||||
out_up = cross(out_right, out_fwd);
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
pos.x = position.x * aspect;
|
||||
pos.y = position.y;
|
||||
const vec3 center = vec3(0.0, 0.0, 0.0);
|
||||
const vec3 up_vec = vec3(0.0, 1.0, 0.0);
|
||||
eye = eye_pos(time * 5, center);
|
||||
lookat(eye, center, up_vec, fwd, right, up);
|
||||
}
|
||||
@end
|
||||
|
||||
//--- fragment shader
|
||||
@fs fs
|
||||
in vec2 pos;
|
||||
in vec3 eye;
|
||||
in vec3 up;
|
||||
in vec3 right;
|
||||
in vec3 fwd;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
float sd_sphere(vec3 p, float s) {
|
||||
return length(p) - s;
|
||||
}
|
||||
|
||||
float sd_mandelbulb(vec3 p, out vec4 res_color) {
|
||||
vec3 w = p;
|
||||
float m = dot(w,w);
|
||||
|
||||
vec4 trap = vec4(abs(w),m);
|
||||
float dz = 1.0;
|
||||
|
||||
for( int i=0; i<4; i++ ) {
|
||||
float m2 = m*m;
|
||||
float m4 = m2*m2;
|
||||
dz = 8.0*sqrt(m4*m2*m)*dz + 1.0;
|
||||
|
||||
float x = w.x; float x2 = x*x; float x4 = x2*x2;
|
||||
float y = w.y; float y2 = y*y; float y4 = y2*y2;
|
||||
float z = w.z; float z2 = z*z; float z4 = z2*z2;
|
||||
|
||||
float k3 = x2 + z2;
|
||||
float k2 = inversesqrt( k3*k3*k3*k3*k3*k3*k3 );
|
||||
float k1 = x4 + y4 + z4 - 6.0*y2*z2 - 6.0*x2*y2 + 2.0*z2*x2;
|
||||
float k4 = x2 - y2 + z2;
|
||||
|
||||
w.x = p.x + 64.0*x*y*z*(x2-z2)*k4*(x4-6.0*x2*z2+z4)*k1*k2;
|
||||
w.y = p.y + -16.0*y2*k3*k4*k4 + k1*k1;
|
||||
w.z = p.z + -8.0*y*k4*(x4*x4 - 28.0*x4*x2*z2 + 70.0*x4*z4 - 28.0*x2*z2*z4 + z4*z4)*k1*k2;
|
||||
|
||||
trap = min( trap, vec4(abs(w),m) );
|
||||
|
||||
m = dot(w,w);
|
||||
if( m > 256.0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
res_color = vec4(m,trap.yzw);
|
||||
return 0.25*log(m)*sqrt(m)/dz;
|
||||
}
|
||||
|
||||
float d_scene(vec3 p, out vec4 res_color) {
|
||||
float d = sd_sphere(p, 1.1);
|
||||
if (d < 0.1) {
|
||||
d = sd_mandelbulb(p, res_color);
|
||||
}
|
||||
else {
|
||||
res_color = vec4(0.0);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// surface normal estimation
|
||||
vec3 surface_normal(vec3 p, float dp) {
|
||||
const float eps = 0.001;
|
||||
const vec2 d = vec2(eps, 0);
|
||||
vec4 tra;
|
||||
float x = d_scene(p + d.xyy, tra) - dp;
|
||||
float y = d_scene(p + d.yxy, tra) - dp;
|
||||
float z = d_scene(p + d.yyx, tra) - dp;
|
||||
return normalize(vec3(x, y, z));
|
||||
}
|
||||
|
||||
vec3 calc_color(vec3 ro, vec3 rd, float t, vec4 tra) {
|
||||
const vec3 light1 = vec3( 0.577, 0.577, -0.577);
|
||||
const vec3 light2 = vec3(-0.707, 0.000, 0.707);
|
||||
|
||||
vec3 pos = ro + rd * t;
|
||||
vec3 nrm = surface_normal(pos, t);
|
||||
vec3 hal = normalize(light1 - rd);
|
||||
float occ = clamp(0.05 * log(tra.x), 0.0, 1.0);
|
||||
float fac = clamp(1.0 + dot(rd, nrm), 0.0, 1.0);
|
||||
|
||||
// sun
|
||||
float dif1 = clamp(dot( light1, nrm), 0.0, 1.0);
|
||||
float spe1 = pow(clamp(dot(nrm, hal), 0.0, 1.0), 32.0 )*dif1*(0.04+0.96*pow(clamp(1.0-dot(hal,light1),0.0,1.0),5.0));
|
||||
// bounce
|
||||
float dif2 = clamp( 0.5 + 0.5*dot( light2, nrm ), 0.0, 1.0 )*occ;
|
||||
// sky
|
||||
float dif3 = (0.7+0.3*nrm.y)*(0.2+0.8*occ);
|
||||
|
||||
vec3 col = vec3(0.01);
|
||||
col = mix(col, vec3(0.10,0.20,0.30), clamp(tra.y,0.0,1.0) );
|
||||
col = mix(col, vec3(0.02,0.10,0.30), clamp(tra.z*tra.z,0.0,1.0) );
|
||||
col = mix(col, vec3(0.30,0.10,0.02), clamp(pow(tra.w,6.0),0.0,1.0) );
|
||||
|
||||
vec3 lin = vec3(0.0);
|
||||
lin += 7.0*vec3(1.50,1.10,0.70)*dif1;
|
||||
lin += 4.0*vec3(0.25,0.20,0.15)*dif2;
|
||||
lin += 1.5*vec3(0.10,0.20,0.30)*dif3;
|
||||
lin += 2.5*vec3(0.35,0.30,0.25)*(0.05+0.95*occ); // ambient
|
||||
lin += 4.0*fac*occ; // fake SSS
|
||||
col *= lin;
|
||||
col = pow( col, vec3(0.7,0.9,1.0)); // fake SSS
|
||||
col += spe1*15.0;
|
||||
|
||||
// gamma
|
||||
col = sqrt(col);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void main() {
|
||||
const float epsilon = 0.001;
|
||||
const float focal_length = 1.8;
|
||||
|
||||
vec3 ray_origin = eye + fwd * focal_length + right * pos.x + up * pos.y;
|
||||
vec3 ray_direction = normalize(ray_origin - eye);
|
||||
|
||||
vec4 tra;
|
||||
vec4 color = vec4(0.10,0.20,0.30,1.0);
|
||||
float t = 0.0;
|
||||
for (int i = 0; i < 96; i++) {
|
||||
vec3 p = ray_origin + ray_direction * t;
|
||||
float d = d_scene(p, tra);
|
||||
if (d < epsilon) {
|
||||
color.xyz = calc_color(p, ray_direction, d, tra);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
color.xyz += vec3(0.003, 0.001, 0.0) * i;
|
||||
}
|
||||
if (t > 3) {
|
||||
break;
|
||||
}
|
||||
t += d;
|
||||
}
|
||||
frag_color = color;
|
||||
}
|
||||
@end
|
||||
|
||||
@program sdf vs fs
|
69
examples/sokol/sdf/sdf.v
Normal file
69
examples/sokol/sdf/sdf.v
Normal file
@ -0,0 +1,69 @@
|
||||
// A Signed Distance Field rendering demo, ported from https://github.com/floooh/sokol-samples/blob/master/sapp/sdf-sapp.c
|
||||
// which in turn is based on https://iquilezles.org/articles/mandelbulb/ and https://www.shadertoy.com/view/ltfSWn
|
||||
import sokol.sapp
|
||||
import sokol.gfx
|
||||
|
||||
#include "@VMODROOT/sdf.h" # It should be generated with `v shader .`
|
||||
|
||||
fn C.sdf_shader_desc(gfx.Backend) &gfx.ShaderDesc
|
||||
|
||||
@[packed]
|
||||
struct C.vs_params_t {
|
||||
mut:
|
||||
aspect f32
|
||||
time f32
|
||||
}
|
||||
|
||||
struct State {
|
||||
mut:
|
||||
pip gfx.Pipeline
|
||||
bind gfx.Bindings
|
||||
paction gfx.PassAction
|
||||
params C.vs_params_t
|
||||
}
|
||||
|
||||
fn init(mut state State) {
|
||||
gfx.setup(sapp.create_desc())
|
||||
|
||||
fsq_verts := [f32(-1.0), -3.0, 3.0, 1.0, -1.0, 1.0]!
|
||||
state.bind.vertex_buffers[0] = gfx.make_buffer(gfx.BufferDesc{
|
||||
label: c'fsq vertices'
|
||||
data: unsafe { gfx.Range{&fsq_verts[0], sizeof(fsq_verts)} }
|
||||
})
|
||||
|
||||
mut pipeline := gfx.PipelineDesc{}
|
||||
pipeline.layout.attrs[C.ATTR_vs_position].format = .float2
|
||||
pipeline.shader = gfx.make_shader(C.sdf_shader_desc(gfx.query_backend()))
|
||||
state.pip = gfx.make_pipeline(&pipeline)
|
||||
|
||||
// No need to clear the window, since the shader will overwrite the whole framebuffer
|
||||
state.paction.colors[0].load_action = .dontcare
|
||||
}
|
||||
|
||||
fn frame(mut state State) {
|
||||
w, h := sapp.width(), sapp.height()
|
||||
state.params.time += f32(sapp.frame_duration())
|
||||
state.params.aspect = f32(w) / f32(h)
|
||||
gfx.begin_pass(sapp.create_default_pass(state.paction))
|
||||
gfx.apply_pipeline(state.pip)
|
||||
gfx.apply_bindings(state.bind)
|
||||
gfx.apply_uniforms(.vs, C.SLOT_vs_params, unsafe { gfx.Range{&state.params, sizeof(state.params)} })
|
||||
gfx.draw(0, 3, 1)
|
||||
gfx.end_pass()
|
||||
gfx.commit()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sapp.run(sapp.Desc{
|
||||
window_title: c'SDF Rendering'
|
||||
width: 512
|
||||
height: 512
|
||||
frame_userdata_cb: frame
|
||||
init_userdata_cb: init
|
||||
cleanup_cb: gfx.shutdown
|
||||
icon: sapp.IconDesc{
|
||||
sokol_default: true
|
||||
}
|
||||
user_data: &State{}
|
||||
})
|
||||
}
|
0
examples/sokol/sdf/v.mod
Normal file
0
examples/sokol/sdf/v.mod
Normal file
@ -27,6 +27,7 @@ pub type ImageDesc = C.sapp_image_desc
|
||||
|
||||
@[typedef]
|
||||
pub struct C.sapp_icon_desc {
|
||||
pub:
|
||||
sokol_default bool
|
||||
images [max_iconimages]ImageDesc
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user