8000 Update · pythonarcade/demo@c27ebeb · GitHub
[go: up one dir, main page]

Skip to content

Commit c27ebeb

Browse files
committed
Update
1 parent 6fa9a78 commit c27ebeb

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

music/into-battle-15601.mp3

3.22 MB
Binary file not shown.

normal_mapping/normal_mapping.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import arcade
2+
from arcade.gl import geometry
3+
from base_view import BaseView
4+
5+
6+
class NormalMapping(BaseView):
7+
8+
def __init__(self, time_on_screen):
9+
super().__init__(time_on_screen)
10+
11+
# Load the color (diffuse) and normal texture
12+
# These should ideally be the same size
13+
self.texture_diffuse = self.window.ctx.load_texture(":resources:images/test_textures/normal_mapping/diffuse.jpg")
14+
self.texture_normal = self.window.ctx.load_texture(":resources:images/test_textures/normal_mapping/normal.jpg")
15+
16+
# Shader program doing basic normal mapping
17+
self.program = self.window.ctx.program(
18+
vertex_shader="""
19+
#version 330
20+
21+
// Inputs from the quad_fs geometry 8000
22+
in vec2 in_vert;
23+
in vec2 in_uv;
24+
25+
// Output to the fragment shader
26+
out vec2 uv;
27+
28+
void main() {
29+
uv = in_uv;
30+
gl_Position = vec4(in_vert, 0.0, 1.0);
31+
}
32+
33+
""",
34+
fragment_shader="""
35+
#version 330
36+
37+
// Samplers for reading from textures
38+
uniform sampler2D texture_diffuse;
39+
uniform sampler2D texture_normal;
40+
// Global light position we can set from python
41+
uniform vec3 light_pos;
42+
43+
// Input from vertex shader
44+
in vec2 uv;
45+
46+
// Output to the framebuffer
47+
out vec4 f_color;
48+
49+
void main() {
50+
// Read RGBA color from the diffuse texture
51+
vec4 diffuse = texture(texture_diffuse, uv);
52+
// Read normal from RGB channels and convert to a direction vector.
53+
// These vectors are like a needle per pixel pointing up from the surface.
54+
// Since RGB is 0-1 we need to convert to -1 to 1.
55+
vec3 normal = normalize(texture(texture_normal, uv).rgb * 2.0 - 1.0);
56+
57+
// Calculate the light direction.
58+
// This is the direction between the light position and the pixel position.
59+
vec3 light_dir = normalize(light_pos - vec3(uv, 0.0));
60+
61+
// Calculate the diffuse factor.
62+
// This is the dot product between the light direction and the normal.
63+
// It's basically calculating the angle between the two vectors.
64+
// The result is a value between 0 and 1.
65+
float diffuse_factor = max(dot(normal, light_dir), 0.0);
66+
67+
// Write the final color to the framebuffer.
68+
// We multiply the diffuse color with the diffuse factor.
69+
f_color = vec4(diffuse.rgb * diffuse_factor, 1.0);
70+
}
71+
""",
72+
)
73+
# Configure what texture channel the samplers should read from
74+
self.program["texture_diffuse"] = 0
75+
self.program["texture_normal"] = 1
76+
77+
# Shortcut for a full screen quad
78+
# It has two buffers with positions and texture coordinates
79+
# named "in_vert" and "in_uv" so we need to use that in the vertex shader
80+
self.quad_fs = geometry.quad_2d_fs()
81+
82+
# Keep track of mouse coordinates for light position
83+
self.mouse_x = 0.0
84+
self.mouse_y = 0.0
85+
self.mouse_z = 0.15
86+
87+
self.text = arcade.Text("0, 0, 0", 20, 20, arcade.color.WHITE)
88+
89+
def on_draw(self):
90+
self.clear()
91+
92+
# Bind the textures to the channels we configured in the shader
93+
self.texture_diffuse.use(0)
94+
self.texture_normal.use(1)
95+
96+
# Update the light position uniform variable
97+
self.program["light_pos"] = self.mouse_x, self.mouse_y, self.mouse_z
98+
99+
# Run the normal mapping shader (fills a full screen quad)
100+
self.quad_fs.render(self.program)
101+
102+
# Draw the mouse coordinates
103+
self.text.text = f"{self.mouse_x:.2f}, {self.mouse_y:.2f}, {self.mouse_z:.2f}"
104+
self.text.draw()
105+
106+
self.draw_line_one("Normal Mapping")
107+
108+
def on_update(self, delta_time):
109+
""" Movement and game logic """
110+
111+
self.total_time += delta_time
112+
if self.total_time > self.time_on_screen:
113+
114+
if not self.window.view_list:
115+
self.window.create_views()
116+
117+
new_view = self.window.view_list.pop(0)
118+
self.window.show_view(new_view)
119+
120+
self.mouse_x += .003
121+
self.mouse_y += .003
122+
123+
def on_mouse_scroll(self, x: int, y: int, scroll_x: int, scroll_y: int):
124+
"""Zoom in/out with the mouse wheel."""
125+
self.mouse_z += scroll_y * 0.05

0 commit comments

Comments
 (0)
0