Skip to content

Commit d67ba0d

Browse files
committed
Raymaching example
1 parent a9ee9bf commit d67ba0d

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

examples/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,14 @@ python manage.py runeffect examples.warpspeed
108108
```
109109

110110
![screenshot](https://raw.githubusercontent.com/Contraz/demosys-py/master/examples/images/warpspeed.png)
111+
112+
Raymaching
113+
----------
114+
115+
Raymaching example by Arttu "helgrima" Tamminen.
116+
117+
```bash
118+
python manage.py runeffect examples.raymaching
119+
```
120+
121+
![screenshot](https://raw.githubusercontent.com/Contraz/demosys-py/master/examples/images/raymaching.png)

examples/images/raymaching.png

608 KB
Loading

examples/raymarching/effect.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import math
2+
3+
import moderngl
4+
from demosys import geometry
5+
from demosys.effects import effect
6+
from pyrr import Vector3
7+
8+
9+
class SimpleRaymarchEffect(effect.Effect):
10+
"""Generated raymarching effect"""
11+
def __init__(self):
12+
self.shader = self.get_shader("raymarching_simple.glsl", local=True)
13+
14+
# create plane to fit whole screen
15+
self.plane = geometry.plane_xz(size=(self.window_width, self.window_height), resolution=(10, 10))
16+
17+
@effect.bind_target
18+
def draw(self, time, frametime, target):
19+
self.ctx.enable(moderngl.DEPTH_TEST)
20+
21+
# Rotate plane 90 degrees, and move plane back so it will fit correctly on to screen
22+
backoff = math.tan(math.radians(self.sys_camera.projection.fov / 2)) * (self.window_width / 2)
23+
m_mv = self.create_transformation(rotation=(math.radians(90), 0.0, 0.0), translation=(0.0, 0.0, -backoff))
24+
25+
# Uniforms
26+
fov = 0.60
27+
alpha = 1.0
28+
modifier = -0.6
29+
cPosition = Vector3([(math.sin(time / 6.0) * 16.0),
30+
(math.sin(time / 12.0) * 16.0),
31+
(math.cos(time / 3.0) * 16.0)])
32+
cLookAt = Vector3([0.0, 0.0, 0.0])
33+
lPosition = Vector3([0.0, 17.0, 0.0])
34+
lItensity = 2.6
35+
color = Vector3([0.66, 0.96, 0.26])
36+
37+
# Draw the plane
38+
39+
# For vertex shader
40+
self.shader.uniform("m_proj", self.sys_camera.projection.tobytes())
41+
self.shader.uniform("m_mv", m_mv.astype('f4').tobytes())
42+
43+
# For fragment shader
44+
self.shader.uniform("fov", fov)
45+
self.shader.uniform("alpha", alpha)
46+
self.shader.uniform("modifier", modifier)
47+
48+
self.shader.uniform("cPosition", cPosition.astype('f4').tobytes())
49+
self.shader.uniform("cLookAt", cLookAt.astype('f4').tobytes())
50+
self.shader.uniform("lPosition", lPosition.astype('f4').tobytes())
51+
self.shader.uniform("lIntensity", lItensity)
52+
self.shader.uniform("color", color.astype('f4').tobytes())
53+
54+
self.shader.uniform("resolution", (self.window_width, self.window_height))
55+
56+
self.plane.draw(self.shader)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#version 410
2+
3+
#if defined VERTEX_SHADER
4+
5+
in vec3 in_position;
6+
in vec3 in_normal;
7+
8+
uniform mat4 m_proj;
9+
uniform mat4 m_mv;
10+
11+
out vec3 normal;
12+
out vec2 uv;
13+
14+
void main() {
15+
gl_Position = m_proj * m_mv * vec4(in_position, 1.0);
16+
}
17+
18+
#elif defined FRAGMENT_SHADER
19+
20+
uniform vec2 resolution;
21+
uniform float fov;
22+
uniform float alpha;
23+
uniform float modifier;
24+
uniform vec3 cPosition;
25+
uniform vec3 cLookAt;
26+
uniform vec3 lPosition;
27+
uniform float lIntensity;
28+
uniform vec3 color;
29+
30+
out vec4 fragColor;
31+
32+
const int maxSteps = 64;
33+
const float maxDistance = 60.0;
34+
const float distanceThreshold = 0.0005;
35+
36+
struct Hit {
37+
vec3 normal;
38+
vec3 path;
39+
float steps;
40+
float dist;
41+
};
42+
43+
float sdMandleBox(vec3 pos, float size)
44+
{
45+
const int Iterations = 10;
46+
const float Scale = 2.0;
47+
const float FoldingLimit = 100.0;
48+
const float MinRad2 = 0.15;
49+
vec4 scale = vec4(size) / MinRad2;
50+
float AbsScalem1 = abs(Scale - 1.0);
51+
float AbsScaleRaisedTo1mIters = pow(abs(Scale), float(1 - Iterations));
52+
vec4 p = vec4(pos, 1.0), p0 = p; // p.w is the distance estimate
53+
54+
for (int i=0; i<Iterations; i++)
55+
{
56+
p.xyz = clamp(p.xyz, -1.3, 1.3) * 2.0 + (modifier) - p.xyz;
57+
float r2 = dot(p.xyz, p.xyz);
58+
p *= clamp(max(MinRad2 / r2, MinRad2), 0.19, 1.0);
59+
p = p * scale + p0;
60+
if (r2>FoldingLimit) break;
61+
}
62+
return ((length(p.xyz) - AbsScalem1) / p.w - AbsScaleRaisedTo1mIters);
63+
}
64+
65+
Hit raymarch(vec3 rayOrigin, vec3 rayDirection) {
66+
const vec2 eps = vec2(0.001, 0.001);
67+
float size = 1.8;
68+
Hit h;
69+
for(int i = 0; i < maxSteps; i++) {
70+
h.path = rayOrigin + rayDirection * h.dist;
71+
float d = sdMandleBox(h.path, size);
72+
h.steps += 1.0;
73+
if(d < distanceThreshold) {
74+
h.normal = normalize(vec3(
75+
sdMandleBox(h.path + eps.xyy, size) - sdMandleBox(h.path - eps.xyy, size),
76+
sdMandleBox(h.path + eps.yxy, size) - sdMandleBox(h.path - eps.yxy, size),
77+
sdMandleBox(h.path + eps.yyx, size) - sdMandleBox(h.path - eps.yyx, size)
78+
));
79+
break;
80+
}
81+
h.dist += d;
82+
83+
}
84+
return h;
85+
}
86+
87+
vec4 processColor(Hit h, vec3 rd, vec3 ro, vec2 uv, vec3 li)
88+
{
89+
vec3 c = color * (1.0 - (h.steps / float(maxSteps)));
90+
c *= (1.0 - (h.dist > maxDistance ? 0.0 : h.dist / maxDistance));
91+
92+
float light = max(0.0, dot(-normalize(h.path - li), h.normal));
93+
94+
c *= light * lIntensity * vec3(0.4, 0.4, 0.4);
95+
return vec4(c, alpha);
96+
}
97+
98+
void main(void)
99+
{
100+
float aspectRatio = resolution.y / resolution.x;
101+
vec2 uv = (2.0 * gl_FragCoord.xy / resolution - 1.0) * aspectRatio;
102+
103+
vec3 forward = normalize(cLookAt - cPosition);
104+
vec3 right = normalize(vec3(forward.z, 0.0, -forward.x));
105+
vec3 up = normalize(cross(forward, right));
106+
107+
vec3 rd = normalize(forward + fov * uv.x * right + fov * uv.y * up);
108+
vec3 ro = vec3(cPosition.x, cPosition.y, cPosition.z);
109+
Hit tt = raymarch(ro, rd);
110+
111+
fragColor = processColor(tt, rd, ro, uv, lPosition);
112+
113+
}
114+
115+
#endif

0 commit comments

Comments
 (0)