from ursina import *; projector_shader = Shader(name='projector_shader', language=Shader.GLSL, vertex = ''' #version 140 uniform mat4 p3d_ModelViewProjectionMatrix; uniform mat4 p3d_ModelMatrix; in vec4 p3d_Vertex; in vec2 p3d_MultiTexCoord0; uniform vec2 texture_scale; uniform vec2 texture_offset; out vec2 texcoord; in vec4 p3d_Color; out vec4 vertex_color; uniform vec2 projector_uv_scale; uniform vec2 projector_uv_offset; out vec2 world_uv; uniform float time; out float z; void main() { gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex; texcoord = (p3d_MultiTexCoord0 * texture_scale) + texture_offset; vertex_color = p3d_Color; world_uv = (p3d_ModelMatrix * p3d_Vertex).xz * projector_uv_scale; world_uv -= projector_uv_offset; world_uv += vec2(.5); z = gl_Position.z; } ''', fragment=''' #version 140 uniform sampler2D p3d_Texture0; uniform vec4 p3d_ColorScale; in vec2 texcoord; out vec4 fragColor; in vec4 vertex_color; uniform sampler2D projector_texture; uniform vec4 projector_color; in vec2 world_uv; uniform struct p3d_FogParameters { vec4 color; float density; float start; float end; float scale; // 1.0 / (end - start) } p3d_Fog; in float z; float inverse_lerp(float a, float b, float v) { return (v-a) / (b-a); } void main() { vec4 color = texture(p3d_Texture0, texcoord) * p3d_ColorScale; color.rgb -= texture(projector_texture, world_uv).r * (vec3(1.) - projector_color.rgb) * projector_color.a; color.rgb = mix(color.rgb, p3d_Fog.color.rgb, clamp(inverse_lerp(p3d_Fog.start, p3d_Fog.end, z), 0.0, 1.0)); // linear fog fragColor = color.rgba * vertex_color; }''', default_input = { 'texture_scale': Vec2(1,1), 'texture_offset': Vec2(0,0), 'projector_texture' : Func(load_texture, 'vignette'), 'projector_uv_scale' : Vec2(.05, .05), 'projector_uv_offset' : Vec2(.0, .0), 'projector_color' : color.black, 'time' : 0.0, } ) if __name__ == '__main__': from ursina import * app = Ursina() Entity.default_shader = projector_shader editor_camera = EditorCamera(rotation_x=30,) light = Entity(model='sphere', unlit=True) ground = Entity(model='plane', collider='box', scale=64, texture='grass', texture_scale=(4,4)) random.seed(0) for i in range(16): Entity(model='cube', origin_y=-.5, scale=2, texture='brick', texture_scale=(1,2), x=random.uniform(-8,8), z=random.uniform(-8,8) + 8, collider='box', scale_y = random.uniform(2,3), color=color.hsv(0, 0, random.uniform(.9, 1)) ) scene.fog_density = (10, 200) projector_texture = load_texture('vignette', application.internal_textures_folder) # projector_texture.repeat = False projector_shader.default_input['projector_texture'] = projector_texture def update(): light.x += (held_keys['d'] - held_keys['a']) * time.dt * 3 light.z += (held_keys['w'] - held_keys['s']) * time.dt * 3 for e in scene.entities: if hasattr(e,'shader') and e.shader == projector_shader: e.set_shader_input('projector_uv_offset', light.world_position.xz * projector_shader.default_input['projector_uv_scale']) app.run()