finally it works
This commit is contained in:
@@ -39,33 +39,99 @@ fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
|
|||||||
let loc = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y)) / vec2<f32>(size.xy);
|
let loc = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y)) / vec2<f32>(size.xy);
|
||||||
let ndc = loc * 2.0f - 1.0f;
|
let ndc = loc * 2.0f - 1.0f;
|
||||||
|
|
||||||
var ray = createCameraRay2(ndc);
|
var ray = createCameraRay(ndc);
|
||||||
var result = vec3<f32>(0.0);
|
// var result = vec3<f32>(0.0);
|
||||||
|
|
||||||
for (var i: i32 = 0; i < 1; i++){
|
// for (var i: i32 = 0; i < 1; i++){
|
||||||
var hit = trace(ray);
|
// var hit = trace(ray);
|
||||||
result += ray.energy * shade(&ray, hit);
|
// result += ray.energy * shade(&ray, hit);
|
||||||
if !any(ray.energy != vec3<f32>(0.0))
|
// if !any(ray.energy != vec3<f32>(0.0))
|
||||||
{
|
// {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
let clip = vec4<f32>(ndc, 0.0, 1.0);
|
let hit_data = trace_test(ray);
|
||||||
let world = config.world_from_clip * clip;
|
|
||||||
let world_pos = world.xyz / world.w;
|
|
||||||
let dir = normalize(world_pos - config.world_position);
|
|
||||||
|
|
||||||
let color = vec4<f32>((ray.direction * 0.1), 1.0);
|
|
||||||
// let color = vec4<f32>(ray.direction, 1.0);
|
|
||||||
// let color = vec4<f32>((ray.direction * 0.1) + vec3<f32>(0.5), 1.0);
|
|
||||||
|
|
||||||
// let color = vec4<f32>(result, 1.0);
|
var final_color = hit_data.color;
|
||||||
|
|
||||||
|
// Simple fog/distance visualization
|
||||||
|
let distance_factor = clamp(hit_data.distance / 50.0, 0.0, 1.0);
|
||||||
|
final_color = mix(final_color * (f32(hit_data.steps)/ 100.0), vec3<f32>(0.1), distance_factor); // Fog: mix object color with dark gray
|
||||||
|
|
||||||
|
let color = vec4<f32>(final_color, 1.0);
|
||||||
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
|
let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
|
||||||
|
|
||||||
textureStore(output, location, color);
|
textureStore(output, location, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn debug_matrix(uv: vec2<f32>) -> vec4<f32>{
|
||||||
|
let ndc = uv * 2.0f - 1.0f;
|
||||||
|
var color = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
if uv.y < 0.5 {
|
||||||
|
if uv.x < 0.5 {
|
||||||
|
color = debugColor(config.world_from_clip[0][3] * 10);
|
||||||
|
}else{
|
||||||
|
color = debugColor(config.world_from_clip[1][3] * 10);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if uv.x < 0.5 {
|
||||||
|
color = debugColor(config.world_from_clip[3][2] * 10);
|
||||||
|
}else{
|
||||||
|
color = debugColor(config.world_from_clip[3][3] * 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return vec4<f32>(color, 1.0);
|
||||||
|
}
|
||||||
|
fn debug(uv: vec2<f32>) -> vec4<f32>{
|
||||||
|
let ndc = uv * 2.0f - 1.0f;
|
||||||
|
|
||||||
|
let near_clip = vec4<f32>(ndc, 0.0, 1.0);
|
||||||
|
let far_clip = vec4<f32>(ndc, 1.0, 1.0);
|
||||||
|
|
||||||
|
// project into world space
|
||||||
|
let near_world4 = config.world_from_clip * near_clip;
|
||||||
|
let far_world4 = config.world_from_clip * far_clip;
|
||||||
|
|
||||||
|
//Add epsilon to protect from divide by zero
|
||||||
|
let inv_w_near = 1.0 / (near_world4.w + 1e-6);
|
||||||
|
let inv_w_far = 1.0 / (far_world4.w + 1e-6);
|
||||||
|
|
||||||
|
let near_world = near_world4.xyz * inv_w_near;
|
||||||
|
let far_world = far_world4.xyz * inv_w_far;
|
||||||
|
|
||||||
|
let origin = config.world_position;
|
||||||
|
|
||||||
|
let direction = normalize(near_world - origin);
|
||||||
|
|
||||||
|
var ray = createRay(origin, direction);
|
||||||
|
var color = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
|
if uv.y < 0.5 {
|
||||||
|
if uv.x < 0.5 {
|
||||||
|
color = debugColor(ray.direction.x);
|
||||||
|
}else{
|
||||||
|
color = debugColor(ray.direction.y);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if uv.x < 0.5 {
|
||||||
|
color = debugColor(ray.direction.z);
|
||||||
|
}else{
|
||||||
|
// color = debugColor(ray.direction.z);
|
||||||
|
color = debugColor(origin.x * 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec4<f32>(color, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn debugColor(v: f32) -> vec3<f32>{
|
||||||
|
return vec3<f32>(v * 0.5 + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
struct Ray {
|
struct Ray {
|
||||||
origin: vec3<f32>,
|
origin: vec3<f32>,
|
||||||
direction: vec3<f32>,
|
direction: vec3<f32>,
|
||||||
@@ -81,14 +147,6 @@ struct RayHit {
|
|||||||
specular: vec3<f32>
|
specular: vec3<f32>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Sphere
|
|
||||||
{
|
|
||||||
position: vec3<f32>,
|
|
||||||
radius: f32,
|
|
||||||
albedo: vec3<f32>,
|
|
||||||
specular: vec3<f32>
|
|
||||||
}
|
|
||||||
|
|
||||||
fn createRayHit() -> RayHit {
|
fn createRayHit() -> RayHit {
|
||||||
var hit: RayHit;
|
var hit: RayHit;
|
||||||
hit.position = vec3<f32>(0.0, 0.0, 0.0);
|
hit.position = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
@@ -109,121 +167,73 @@ fn createRay(origin: vec3<f32>, direction: vec3<f32>) -> Ray
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn createCameraRay(ndc: vec2<f32>) -> Ray {
|
fn createCameraRay(ndc: vec2<f32>) -> Ray {
|
||||||
|
let uv = vec2<f32>(ndc.x, -ndc.y);
|
||||||
|
|
||||||
let target_point = config.world_from_clip * vec4<f32>(ndc, 0.0, 1.0);
|
|
||||||
let direction_point = target_point.xyz / target_point.w;
|
|
||||||
let direction = normalize(direction_point - config.world_position);
|
|
||||||
|
|
||||||
return createRay(config.world_position, direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn createCameraRay2(ndc: vec2<f32>) -> Ray {
|
|
||||||
// clip points at near and far
|
// clip points at near and far
|
||||||
let near_clip = vec4<f32>(ndc, 0.0, 1.0);
|
let near_clip = vec4<f32>(uv, 0.0, 1.0);
|
||||||
let far_clip = vec4<f32>(ndc, 1.0, 1.0);
|
let far_clip = vec4<f32>(uv, 1.0, 1.0);
|
||||||
|
|
||||||
// project into world space
|
// project into world space
|
||||||
let near_world4 = config.world_from_clip * near_clip;
|
let near_world4 = config.world_from_clip * near_clip;
|
||||||
let far_world4 = config.world_from_clip * far_clip;
|
let far_world4 = config.world_from_clip * far_clip;
|
||||||
|
|
||||||
let near_world = near_world4.xyz / near_world4.w;
|
//Add epsilon to protect from divide by zero
|
||||||
let far_world = far_world4.xyz / far_world4.w;
|
let inv_w_near = 1.0 / (near_world4.w + 1e-6);
|
||||||
|
let inv_w_far = 1.0 / (far_world4.w + 1e-6);
|
||||||
|
|
||||||
// ray starts at near plane, points toward far plane
|
let near_world = near_world4.xyz * inv_w_near;
|
||||||
let origin = near_world + config.world_position;
|
let far_world = far_world4.xyz * inv_w_far;
|
||||||
let direction = normalize(origin - near_world);
|
|
||||||
|
let origin = config.world_position;
|
||||||
|
|
||||||
|
let direction = normalize(near_world - origin);
|
||||||
|
|
||||||
return createRay(origin, direction);
|
return createRay(origin, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createSphere(position: vec3<f32>, radius: f32) -> Sphere
|
struct Hit {
|
||||||
{
|
distance: f32,
|
||||||
var s: Sphere;
|
hit_pos: vec3<f32>,
|
||||||
s.position = position;
|
normal: vec3<f32>,
|
||||||
s.radius = radius;
|
color: vec3<f32>,
|
||||||
s.albedo = vec3<f32>(0.8f, 0.8f, 0.8f);
|
steps: i32,
|
||||||
s.specular = vec3<f32>(0.6f, 0.6f, 0.6f);
|
};
|
||||||
return s;
|
|
||||||
|
fn distance_field(p: vec3<f32>) -> f32 {
|
||||||
|
// Simple sphere centered at (0, 0, 0) with radius 1.0
|
||||||
|
let sphere_center = vec3<f32>(0.0, 0.0, 0.0);
|
||||||
|
let sphere_radius = 1.0;
|
||||||
|
|
||||||
|
// SDF for a sphere: length(p - center) - radius
|
||||||
|
let d = length(p - sphere_center) - sphere_radius;
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersectSphere(ray: Ray, bestHit: ptr<function, RayHit>, sphereIndex: u32)
|
fn trace_test(ray: Ray) -> Hit {
|
||||||
{
|
var total_distance: f32 = 0.0;
|
||||||
//Sphere sphere = _Spheres[sphereIndex];
|
let max_distance: f32 = 100.0;
|
||||||
var sphere = createSphere(vec3<f32>(0.0f, 2.0f, 0.0f), 2.0f);
|
let min_hit_distance: f32 = 0.001;
|
||||||
|
const max_steps: i32 = 100;
|
||||||
|
|
||||||
|
for (var i: i32 = 0; i < max_steps; i = i + 1) {
|
||||||
|
let current_pos = ray.origin + ray.direction * total_distance;
|
||||||
|
let distance_to_scene = distance_field(current_pos);
|
||||||
|
|
||||||
var d = ray.origin - sphere.position;
|
// Check for a hit
|
||||||
var p1 = -dot(ray.direction, d);
|
if (distance_to_scene < min_hit_distance) {
|
||||||
var p2sqr = p1 * p1 - dot(d, d) + sphere.radius * sphere.radius;
|
// A hit occurred!
|
||||||
if p2sqr < 0 {
|
return Hit(total_distance, current_pos, vec3<f32>(0.0), vec3<f32>(1.0, 0.0, 0.0), i); // Return red color for now
|
||||||
return;
|
|
||||||
}
|
|
||||||
var p2 = sqrt(p2sqr);
|
|
||||||
// var t = p1 - p2 > 0 ? p1 - p2 : p1 + p2;
|
|
||||||
var t = 0f;
|
|
||||||
if p1 - p2 > 0 {
|
|
||||||
t = p1 - p2;
|
|
||||||
} else {
|
|
||||||
t = p1 + p2;
|
|
||||||
}
|
|
||||||
if t > 0 && t < (*bestHit).distance
|
|
||||||
{
|
|
||||||
(*bestHit).position = ray.origin + t * ray.direction;
|
|
||||||
(*bestHit).normal = normalize((*bestHit).position - sphere.position);
|
|
||||||
(*bestHit).albedo = sphere.albedo;
|
|
||||||
(*bestHit).specular = sphere.specular;
|
|
||||||
(*bestHit).distance = t;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn intersectGroundPlane(ray: Ray, bestHit: ptr<function,RayHit>)
|
// Check if we marched too far
|
||||||
{
|
if (total_distance > max_distance) {
|
||||||
var t = -ray.origin.y / ray.direction.y;
|
break;
|
||||||
if t > 0 && t < (*bestHit).distance
|
|
||||||
{
|
|
||||||
(*bestHit).distance = t;
|
|
||||||
(*bestHit).position = ray.origin + t * ray.direction;
|
|
||||||
(*bestHit).normal = vec3<f32>(0.0f, 1.0f, 0.0f);
|
|
||||||
(*bestHit).albedo = vec3(0.1f);
|
|
||||||
(*bestHit).specular = vec3(0.3f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace(ray: Ray) -> RayHit
|
// Advance the ray
|
||||||
{
|
total_distance = total_distance + distance_to_scene;
|
||||||
var bestHit = createRayHit();
|
|
||||||
intersectSphere(ray, &bestHit, 0);
|
|
||||||
intersectGroundPlane(ray, &bestHit);
|
|
||||||
return bestHit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No hit found
|
||||||
fn shade(ray: ptr<function, Ray>, hit: RayHit) -> vec3<f32>
|
return Hit(max_distance, vec3<f32>(0.0), vec3<f32>(0.0), vec3<f32>(0.0, 0.0, 0.0), 0); // Return black for background
|
||||||
{
|
|
||||||
if hit.distance > -999999999.0f
|
|
||||||
{
|
|
||||||
(*ray).origin = hit.position + hit.normal * 0.001f;
|
|
||||||
(*ray).direction = reflect((*ray).direction, hit.normal);
|
|
||||||
(*ray).energy *= hit.specular;
|
|
||||||
|
|
||||||
//Shadows
|
|
||||||
// var shadow = false;
|
|
||||||
// var shadowRay = createRay(hit.position + hit.normal * 0.001f, -1 * _DirectionalLight.xyz);
|
|
||||||
// var shadowHit = trace(shadowRay);
|
|
||||||
// if (shadowHit.distance != 9999999.0f)
|
|
||||||
// {
|
|
||||||
// return float3(0.0f, 0.0f, 0.0f);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return saturate(dot(hit.normal, _DirectionalLight.xyz) * -1) * _DirectionalLight.w * hit.albedo;
|
|
||||||
return hit.albedo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(*ray).energy = vec3(0.0f);
|
|
||||||
return config.sky_color.xyz;
|
|
||||||
// var theta = acos((*ray).direction.y) / -PI;
|
|
||||||
// var phi = atan2((*ray).direction.x, -(*ray).direction.z) / -PI * .5f;
|
|
||||||
// return _SkyboxTexture.SampleLevel(sampler_SkyboxTexture, float2(phi, theta), 0).xyz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,9 +177,14 @@ fn update_tracer_uniforms(
|
|||||||
rt_camera: Single<(&GlobalTransform, &Camera), With<RTCamera>>,
|
rt_camera: Single<(&GlobalTransform, &Camera), With<RTCamera>>,
|
||||||
) {
|
) {
|
||||||
let (transform, cam) = rt_camera.into_inner();
|
let (transform, cam) = rt_camera.into_inner();
|
||||||
|
/*
|
||||||
|
|
||||||
let clip_from_view = cam.clip_from_view();
|
let clip_from_view = cam.clip_from_view();
|
||||||
let world_from_clip = clip_from_view.inverse() * transform.compute_matrix().inverse();
|
let world_from_clip = clip_from_view.inverse() * transform.compute_matrix().inverse();
|
||||||
|
*/
|
||||||
|
|
||||||
|
let clip_from_view = cam.clip_from_view();
|
||||||
|
let world_from_clip = transform.compute_matrix() * clip_from_view.inverse();
|
||||||
// cam.ndc_to_world(camera_transform, ndc)
|
// cam.ndc_to_world(camera_transform, ndc)
|
||||||
|
|
||||||
tracer_uniforms.world_from_clip = world_from_clip;
|
tracer_uniforms.world_from_clip = world_from_clip;
|
||||||
|
|||||||
Reference in New Issue
Block a user