struct SkyOutput { @builtin(position) position: vec4, @location(0) sampledir: vec3, }; struct Data { // from camera to screen proj: mat4x4, // from screen to camera proj_inv: mat4x4, // from world to camera view: mat4x4, // camera position cam_pos: vec4, }; @group(0) @binding(0) var r_data: Data; @vertex fn vs_sky(@builtin(vertex_index) vertex_index: u32) -> SkyOutput { // hacky way to draw a large triangle let tmp1 = i32(vertex_index) / 2; let tmp2 = i32(vertex_index) & 1; let pos = vec4( f32(tmp1) * 4.0 - 1.0, f32(tmp2) * 4.0 - 1.0, 1.0, 1.0 ); // transposition = inversion for this orthonormal matrix let inv_model_view = transpose(mat3x3(r_data.view[0].xyz, r_data.view[1].xyz, r_data.view[2].xyz)); let unprojected = r_data.proj_inv * pos; var result: SkyOutput; result.sampledir = inv_model_view * unprojected.xyz; result.position = pos; return result; } struct EntityOutput { @builtin(position) position: vec4, @location(1) texture: vec2, @location(2) normal: vec3, @location(3) view: vec3, }; const MAX_ENTITY_INSTANCES=1024; @group(1) @binding(0) var r_EntityTransform: array,MAX_ENTITY_INSTANCES>; @vertex fn vs_entity( @builtin(instance_index) instance: u32, @location(0) pos: vec3, @location(1) texture: vec2, @location(2) normal: vec3, ) -> EntityOutput { var position: vec4 = r_EntityTransform[instance] * vec4(pos, 1.0); var result: EntityOutput; result.normal = (r_EntityTransform[instance] * vec4(normal, 0.0)).xyz; result.texture=texture; result.view = position.xyz - r_data.cam_pos.xyz; result.position = r_data.proj * r_data.view * position; return result; } @group(0) @binding(1) var r_texture: texture_cube; @group(0) @binding(2) var r_sampler: sampler; @fragment fn fs_sky(vertex: SkyOutput) -> @location(0) vec4 { return textureSample(r_texture, r_sampler, vertex.sampledir); } @fragment fn fs_entity(vertex: EntityOutput) -> @location(0) vec4 { let incident = normalize(vertex.view); let normal = normalize(vertex.normal); let d = dot(normal, incident); let reflected = incident - 2.0 * d * normal; let dir = vec3(-1.0)+2.0*vec3(vertex.texture.x,0.0,vertex.texture.y); let texture_color = textureSample(r_texture, r_sampler, dir).rgb; let reflected_color = textureSample(r_texture, r_sampler, reflected).rgb; return vec4(mix(vec3(0.1) + 0.5 * reflected_color,texture_color,1.0-pow(1.0-abs(d),2.0)), 1.0); }