This commit is contained in:
xsl
2025-09-04 10:54:47 +08:00
commit 6bc8f61b18
1808 changed files with 208268 additions and 0 deletions
@@ -0,0 +1,177 @@
/* Copyright (c) 2021-2024 Holochip Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#version 460
#extension GL_EXT_ray_tracing : enable
#extension GL_EXT_nonuniform_qualifier : enable
#define RENDER_DEFAULT 0
#define RENDER_BARYCENTRIC 1
#define RENDER_INSTANCE_ID 2
#define RENDER_DISTANCE 3
#define RENDER_GLOBAL_XYZ 4
#define RENDER_SHADOW_MAP 5
#define RENDER_AO 6
struct Payload
{
vec4 color;
vec4 intersection; // {x, y, z, intersectionType}
vec4 normal; // {nx, ny, nz, distance}
};
layout(location = 0) rayPayloadInEXT Payload hitValue;
hitAttributeEXT vec3 attribs;
layout(binding=4, set = 0) readonly buffer VertexBuffer
{
vec4[] data;
} vertex_buffer;
layout(binding=5, set = 0) readonly buffer IndexBuffer
{
uint[] indices;
} index_buffer;
layout(binding=6, set = 0) readonly buffer DataMap
{
uint[] indices;
} data_map;
layout(binding=7, set = 0) uniform sampler2D textures[26];
layout(binding=8, set = 0) readonly buffer DynamicVertexBuffer
{
vec4[] data;
} dynamic_vertex_buffer;
layout(binding=9, set = 0) readonly buffer DynamicIndexBuffer
{
uint[] indices;
} dynamic_index_buffer;
layout (constant_id = 0) const uint render_mode = RENDER_DEFAULT;
vec3 heatmap(float value, float minValue, float maxValue)
{
float scaled = (min(max(value, minValue), maxValue) - minValue) / (maxValue - minValue);
float r = scaled * (3.14159265359 / 2.);
return vec3(sin(r), sin(2 * r), cos(r));
}
/*
// Geometry instance ids
in int gl_PrimitiveID;
in int gl_InstanceID;
in int gl_InstanceCustomIndexEXT;
in int gl_GeometryIndexEXT;
*/
struct Vertex
{
vec3 pt;
vec3 normal;
vec2 coordinate;
};
Vertex getVertex(uint vertexOffset, uint index, bool is_static)
{
uint base_index = 2 * (vertexOffset + index);
vec4 A = is_static ? vertex_buffer.data[base_index] : dynamic_vertex_buffer.data[base_index];
vec4 B = is_static ? vertex_buffer.data[base_index + 1] : dynamic_vertex_buffer.data[base_index + 1];
Vertex v;
v.pt = A.xyz;
v.normal = vec3(A.w, B.x, B.y);
v.coordinate = vec2(B.z, B.w);
return v;
}
uvec3 getIndices(uint triangle_offset, uint primitive_id, bool is_static)
{
uint base_index = 3 * (triangle_offset + primitive_id);
uint index0 = is_static ? index_buffer.indices[base_index] : dynamic_index_buffer.indices[base_index];
uint index1 = is_static ? index_buffer.indices[base_index + 1] : dynamic_index_buffer.indices[base_index + 1];
uint index2 = is_static ? index_buffer.indices[base_index + 2] : dynamic_index_buffer.indices[base_index + 2];
return uvec3(index0, index1, index2);
}
void handleDraw()
{
uint index = gl_InstanceCustomIndexEXT;
uint vertexOffset = data_map.indices[4 * index];
uint triangleOffset = data_map.indices[4*index + 1];
uint imageOffset = data_map.indices[4 * index + 2];
uint objectType = data_map.indices[4 * index + 3];
bool is_static = objectType != 1;
uvec3 indices = getIndices(triangleOffset, gl_PrimitiveID, is_static);
Vertex A = getVertex(vertexOffset, indices.x, is_static), B = getVertex(vertexOffset, indices.y, is_static), C = getVertex(vertexOffset, indices.z, is_static);
// interpolate and obtain world point
const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
float alpha = barycentricCoords.x, beta = barycentricCoords.y, gamma = barycentricCoords.z;
vec3 pt = alpha * A.pt + beta * B.pt + gamma * C.pt;
mat4x3 transform = gl_WorldToObjectEXT;
vec3 worldPt = gl_WorldRayOriginEXT + gl_HitTEXT * gl_WorldRayDirectionEXT;//transform * vec4(pt, 0) + vec3(transform[3][0], transform[3][1], transform[3][2]);
vec3 normal = normalize(alpha * A.normal + beta * B.normal + gamma * C.normal);
vec3 worldNormal = normalize(cross(B.pt - A.pt, C.pt - A.pt));
vec2 texcoord = alpha * A.coordinate + beta * B.coordinate + gamma * C.coordinate;
hitValue.intersection = vec4(worldPt.xyz, objectType);
hitValue.normal = vec4(worldNormal.xyz, gl_HitTEXT);
if (render_mode == RENDER_GLOBAL_XYZ) { // global xyz
hitValue.color = vec4(heatmap(worldPt.x, -10, 10), 1);
return;
}
if ((objectType == 0 || objectType == 2)){
if (imageOffset >= 26){
return; // this shouldn't happen
}
// obtain texture coordinate
// NB: texture() is valid here as well as mipmaps are not used in this demo.
vec4 tex_value = textureLod(textures[nonuniformEXT(imageOffset)], texcoord, 0);
hitValue.color = tex_value;
} else {
// the refraction itself is colorless, so
// encode the index of refraction in the color
const float base_IOR = 1.01;
const float x = texcoord.x, y = texcoord.y;
const float t = min(min(min(min(x, 1-x), y), 1-y), 0.5) / 0.5;
const float IOR = t * base_IOR + (1 - t) * 1;
hitValue.color = vec4(IOR, 0, 0, 0);
hitValue.normal = vec4(normal.x, normal.y, normal.z, gl_HitTEXT);
}
}
void main()
{
const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
if (render_mode == RENDER_BARYCENTRIC ){
hitValue.color = vec4(barycentricCoords, 1);
} else if (render_mode == RENDER_INSTANCE_ID){
hitValue.color = vec4(heatmap(gl_InstanceCustomIndexEXT, 0, 25), 1);
} else if (render_mode == RENDER_DISTANCE){
hitValue.color = vec4(heatmap(log(1 + gl_HitTEXT), 0, log(1 + 25)), 1);
} else {
handleDraw();
}
}
@@ -0,0 +1,35 @@
/* Copyright (c) 2021-2024 Holochip Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#version 460
#extension GL_EXT_ray_tracing : enable
struct Payload
{
vec4 color;
vec4 intersection; // {x, y, z, intersectionType}
vec4 normal; // {nx, ny, nz, distance}
};
layout(location = 0) rayPayloadInEXT Payload hitValue;
void main()
{
hitValue.intersection.w = 100;
hitValue.normal.w = 10000;
}
Binary file not shown.
@@ -0,0 +1,170 @@
/* Copyright (c) 2021-2024 Holochip Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#version 460
#extension GL_EXT_ray_tracing : enable
#define RENDER_DEFAULT 0
#define RENDER_BARYCENTRIC 1
#define RENDER_INSTANCE_ID 2
#define RENDER_DISTANCE 3
#define RENDER_GLOBAL_XYZ 4
#define RENDER_SHADOW_MAP 5
#define RENDER_AO 6
layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 1, set = 0, rgba8) uniform image2D image;
layout(binding = 2, set = 0) uniform CameraProperties
{
mat4 viewInverse;
mat4 projInverse;
} cam;
struct Payload
{
vec4 color;
vec4 intersection; // {x, y, z, intersectionType}
vec4 normal; // {nx, ny, nz, distance}
};
layout(location = 0) rayPayloadEXT Payload hitValue;
layout (constant_id = 0) const uint render_mode = 0;
layout (constant_id = 1) const uint maxRays = 12;
void main()
{
const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy);
vec2 d = inUV * 2.0 - 1.0;
vec4 origin = cam.viewInverse * vec4(0,0,0,1);
vec4 target = cam.projInverse * vec4(d.x, d.y, 1, 1) ;
vec4 direction = cam.viewInverse*vec4(normalize(target.xyz), 0) ;
float tmin = 0.001;
float tmax = 10000.0;
uint max_rays = maxRays;
if (render_mode != RENDER_DEFAULT)
{
max_rays = 1;
}
uint object_type = 100;
vec4 color = vec4(0, 0, 0, 0);
// 0 = normal, 1 = shadow, 2 = AO
uint current_mode = 0;
float expectedDistance = -1;
for (uint i = 0; i < max_rays && current_mode < 100 && color.a < 0.95 && (color.r < 0.99 || color.b < 0.99 || color.g < 0.99); ++i)
{
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0);
object_type = uint(hitValue.intersection.w);
const vec3 object_intersection_pt = hitValue.intersection.xyz;
const vec3 object_normal = hitValue.normal.xyz;
if (render_mode != RENDER_DEFAULT)
{
color = hitValue.color;
break;
}
if (object_type == 0)
{
vec4 newColor = hitValue.color;
//shadow
{
const float shadow_mult = 2;
const float shadow_scale = 0.25;
vec3 lightPt = vec3(0, -20, 0);
vec3 currentDirection = lightPt - hitValue.intersection.xyz;
expectedDistance = sqrt(dot(currentDirection, currentDirection));
currentDirection = normalize(currentDirection);
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, object_intersection_pt, tmin, currentDirection, tmax, 0);
float r = expectedDistance;
float actDistance = hitValue.normal.w;
float scale = actDistance < expectedDistance ? shadow_scale : 1;
scale = min(scale * shadow_mult, 1);
newColor.xyz *= scale;
current_mode = 101;
if (render_mode == RENDER_SHADOW_MAP)
{
color = vec4(scale, scale, scale, 1);
break;
}
}
// ambient occlusion
{
const float ao_mult = 1;
uint max_ao_each = 2;
uint max_ao = max_ao_each * max_ao_each;
const float max_dist = 2;
float accumulated_ao = 0.f;
vec3 u = abs(dot(object_normal, vec3(0, 0, 1))) > 0.9 ? cross(object_normal, vec3(1, 0, 0)) : cross(object_normal, vec3(0, 0, 1));
vec3 v = cross(object_normal, u);
float accumulated_factor = 0;
for (uint j = 0; j < max_ao_each; ++j)
{
float phi = 0.5*(-3.14159 + 2 * 3.14159 * (float(j + 1) / float(max_ao_each + 2)));
for (uint k = 0; k < max_ao_each; ++k){
float theta = 0.5*(-3.14159 + 2 * 3.14159 * (float(k + 1) / float(max_ao_each + 2)));
float x = cos(phi) * sin(theta);
float y = sin(phi) * sin(theta);
float z = cos(theta);
vec3 direction = x * u + y * v + z * object_normal;
traceRayEXT(topLevelAS, gl_RayFlagsOpaqueEXT, 0xff, 0, 0, 0, object_intersection_pt, tmin, direction, tmax, 0);
float ao = min(hitValue.normal.w, max_dist);
float factor = 0.2 + 0.8 * z * z;
accumulated_factor += factor;
accumulated_ao += ao * factor;
}
}
accumulated_ao /= (max_dist * accumulated_factor);
accumulated_ao *= accumulated_ao;
accumulated_ao = max(min((accumulated_ao) * ao_mult, 1), 0);
if (render_mode == RENDER_AO)
{
color = vec4(accumulated_ao, accumulated_ao, accumulated_ao, 1);
break;
}
newColor.xyz *= accumulated_ao;
const float r = max(0, 1 - color.a);
color += r * vec4(newColor.rgb, 1);
}
} else if (object_type == 1)
{
origin = vec4(hitValue.intersection.xyz, 0);
const float IOR = hitValue.color.x;
const float max_IOR = 1.01;
float eta = 1 / IOR;
float c = abs(dot(object_normal, direction.xyz));
float t = (IOR - 1) / (max_IOR - 1);
direction = normalize((1 - t) * direction + t * (eta * direction + (eta * c - (1 - eta*eta*(1 - c*c)))));
} else if (object_type == 2)
{
vec4 newColor = hitValue.color;
float r = 1 - color.a;
color.rgb += r * newColor.rgb * newColor.a;
color.a += 0.1 * r * newColor.a;
origin = vec4(hitValue.intersection.xyz, 0);
}
}
imageStore(image, ivec2(gl_LaunchIDEXT.xy), color);
}
Binary file not shown.
@@ -0,0 +1,24 @@
/* Copyright (c) 2021-2024 Holochip Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define RENDER_DEFAULT 0
#define RENDER_BARYCENTRIC 1
#define RENDER_INSTANCE_ID 2
#define RENDER_DISTANCE 3
#define RENDER_GLOBAL_XYZ 4
#define RENDER_SHADOW_MAP 5
#define RENDER_AO 6
@@ -0,0 +1,149 @@
/* Copyright (c) 2024, Sascha Willems
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define RENDER_DEFAULT 0
#define RENDER_BARYCENTRIC 1
#define RENDER_INSTANCE_ID 2
#define RENDER_DISTANCE 3
#define RENDER_GLOBAL_XYZ 4
#define RENDER_SHADOW_MAP 5
#define RENDER_AO 6
struct Payload
{
[[vk::location(0)]] float4 color;
[[vk::location(1)]] float4 intersection; // {x, y, z, intersectionType}
[[vk::location(2)]] float4 normal; // {nx, ny, nz, distance}
};
struct Attributes
{
float2 bary;
};
StructuredBuffer<float4> vertex_buffer : register(t4);
StructuredBuffer<uint> index_buffer : register(t5);
StructuredBuffer<uint> data_map : register(t6);
Texture2D textures[26]: register(t7);
SamplerState samplers[26]: register(s7);
StructuredBuffer<float4> dynamic_vertex_buffer : register(t8);
StructuredBuffer<uint> dynamic_index_buffer : register(t9);
[[vk::constant_id(0)]] const int render_mode = RENDER_DEFAULT;
float3 heatmap(float value, float minValue, float maxValue)
{
float scaled = (min(max(value, minValue), maxValue) - minValue) / (maxValue - minValue);
float r = scaled * (3.14159265359 / 2.);
return float3(sin(r), sin(2 * r), cos(r));
}
struct Vertex
{
float3 pt;
float3 normal;
float2 coordinate;
};
Vertex getVertex(uint vertexOffset, uint index, bool is_static)
{
uint base_index = 2 * (vertexOffset + index);
float4 A = is_static ? vertex_buffer[base_index] : dynamic_vertex_buffer[base_index];
float4 B = is_static ? vertex_buffer[base_index + 1] : dynamic_vertex_buffer[base_index + 1];
Vertex v;
v.pt = A.xyz;
v.normal = float3(A.w, B.x, B.y);
v.coordinate = float2(B.z, B.w);
return v;
}
uint3 getIndices(uint triangle_offset, uint primitive_id, bool is_static)
{
uint base_index = 3 * (triangle_offset + primitive_id);
uint index0 = is_static ? index_buffer[base_index] : dynamic_index_buffer[base_index];
uint index1 = is_static ? index_buffer[base_index + 1] : dynamic_index_buffer[base_index + 1];
uint index2 = is_static ? index_buffer[base_index + 2] : dynamic_index_buffer[base_index + 2];
return uint3(index0, index1, index2);
}
void handleDraw(inout Payload hitValue, float2 attribs)
{
uint index = InstanceID();
uint vertexOffset = data_map[4 * index];
uint triangleOffset = data_map[4*index + 1];
uint imageOffset = data_map[4 * index + 2];
uint objectType = data_map[4 * index + 3];
bool is_static = objectType != 1;
uint3 indices = getIndices(triangleOffset, PrimitiveIndex(), is_static);
Vertex A = getVertex(vertexOffset, indices.x, is_static), B = getVertex(vertexOffset, indices.y, is_static), C = getVertex(vertexOffset, indices.z, is_static);
// interpolate and obtain world point
const float3 barycentricCoords = float3(1.0f - attribs.x - attribs.y, attribs.x, attribs.y);
float alpha = barycentricCoords.x, beta = barycentricCoords.y, gamma = barycentricCoords.z;
float3 pt = alpha * A.pt + beta * B.pt + gamma * C.pt;
float4x3 transform = WorldToObject4x3();
float3 worldPt = WorldRayOrigin() + RayTCurrent() * WorldRayDirection();//transform * float4(pt, 0) + float3(transform[3][0], transform[3][1], transform[3][2]);
float3 normal = normalize(alpha * A.normal + beta * B.normal + gamma * C.normal);
float3 worldNormal = normalize(cross(B.pt - A.pt, C.pt - A.pt));
float2 texcoord = alpha * A.coordinate + beta * B.coordinate + gamma * C.coordinate;
hitValue.intersection = float4(worldPt.xyz, objectType);
hitValue.normal = float4(worldNormal.xyz, RayTCurrent());
if (render_mode == RENDER_GLOBAL_XYZ) { // global xyz
hitValue.color = float4(heatmap(worldPt.x, -10, 10), 1);
return;
}
if ((objectType == 0 || objectType == 2)){
if (imageOffset >= 26){
return; // this shouldn't happen
}
// obtain texture coordinate
// NB: texture() is valid here as well as mipmaps are not used in this demo.
float4 tex_value = textures[NonUniformResourceIndex(imageOffset)].SampleLevel(samplers[NonUniformResourceIndex(imageOffset)], texcoord, 0);
hitValue.color = tex_value;
} else {
// the refraction itself is colorless, so
// encode the index of refraction in the color
const float base_IOR = 1.01;
const float x = texcoord.x, y = texcoord.y;
const float t = min(min(min(min(x, 1-x), y), 1-y), 0.5) / 0.5;
const float IOR = t * base_IOR + (1 - t) * 1;
hitValue.color = float4(IOR, 0, 0, 0);
hitValue.normal = float4(normal.x, normal.y, normal.z, RayTCurrent());
}
}
[shader("closesthit")]
void main(inout Payload hitValue, in Attributes Attribs)
{
const float3 barycentricCoords = float3(1.0f - Attribs.bary.x - Attribs.bary.y, Attribs.bary.x, Attribs.bary.y);
if (render_mode == RENDER_BARYCENTRIC ){
hitValue.color = float4(barycentricCoords, 1);
} else if (render_mode == RENDER_INSTANCE_ID){
hitValue.color = float4(heatmap(InstanceID(), 0, 25), 1);
} else if (render_mode == RENDER_DISTANCE){
hitValue.color = float4(heatmap(log(1 + RayTCurrent()), 0, log(1 + 25)), 1);
} else {
handleDraw(hitValue, Attribs.bary);
}
}
@@ -0,0 +1,30 @@
/* Copyright (c) 2024, Sascha Willems
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
struct Payload
{
[[vk::location(0)]] float4 color;
[[vk::location(1)]] float4 intersection; // {x, y, z, intersectionType}
[[vk::location(2)]] float4 normal; // {nx, ny, nz, distance}
};
[shader("miss")]
void main(inout Payload hitValue)
{
hitValue.intersection.w = 100;
hitValue.normal.w = 10000;
}
Binary file not shown.
@@ -0,0 +1,186 @@
/* Copyright (c) 2024, Sascha Willems
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define RENDER_DEFAULT 0
#define RENDER_BARYCENTRIC 1
#define RENDER_INSTANCE_ID 2
#define RENDER_DISTANCE 3
#define RENDER_GLOBAL_XYZ 4
#define RENDER_SHADOW_MAP 5
#define RENDER_AO 6
RaytracingAccelerationStructure rs : register(t0);
RWTexture2D<float4> image : register(u1);
struct CameraProperties
{
float4x4 viewInverse;
float4x4 projInverse;
};
[[vk::binding(2, 0)]]
ConstantBuffer<CameraProperties> cam : register(b2);
struct Payload
{
[[vk::location(0)]] float4 color;
[[vk::location(1)]] float4 intersection; // {x, y, z, intersectionType}
[[vk::location(2)]] float4 normal; // {nx, ny, nz, distance}
};
[[vk::constant_id(0)]] const int render_mode = 0;
[[vk::constant_id(1)]] const int maxRays = 12;
[shader("raygeneration")]
void main()
{
uint3 LaunchID = DispatchRaysIndex();
uint3 LaunchSize = DispatchRaysDimensions();
const float2 pixelCenter = float2(LaunchID.xy) + float2(0.5, 0.5);
const float2 inUV = pixelCenter/float2(LaunchSize.xy);
float2 d = inUV * 2.0 - 1.0;
float4 origin = mul(cam.viewInverse, float4(0,0,0,1));
float4 target = mul(cam.projInverse, float4(d.x, d.y, 1, 1));
float4 direction = mul(cam.viewInverse, float4(normalize(target.xyz), 0));
float tmin = 0.001;
float tmax = 10000.0;
uint max_rays = maxRays;
if (render_mode != RENDER_DEFAULT)
{
max_rays = 1;
}
uint object_type = 100;
float4 color = float4(0, 0, 0, 0);
// 0 = normal, 1 = shadow, 2 = AO
uint current_mode = 0;
float expectedDistance = -1;
RayDesc rayDesc;
rayDesc.TMin = tmin;
rayDesc.TMax = tmax;
Payload hitValue;
for (uint i = 0; i < max_rays && current_mode < 100 && color.a < 0.95 && (color.r < 0.99 || color.b < 0.99 || color.g < 0.99); ++i)
{
rayDesc.Origin = origin.xyz;
rayDesc.Direction = direction.xyz;
TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, hitValue);
object_type = uint(hitValue.intersection.w);
const float3 object_intersection_pt = hitValue.intersection.xyz;
const float3 object_normal = hitValue.normal.xyz;
if (render_mode != RENDER_DEFAULT)
{
color = hitValue.color;
break;
}
if (object_type == 0)
{
float4 newColor = hitValue.color;
//shadow
{
const float shadow_mult = 2;
const float shadow_scale = 0.25;
float3 lightPt = float3(0, -20, 0);
float3 currentDirection = lightPt - hitValue.intersection.xyz;
expectedDistance = sqrt(dot(currentDirection, currentDirection));
currentDirection = normalize(currentDirection);
rayDesc.Origin = object_intersection_pt;
rayDesc.Direction = currentDirection;
TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, hitValue);
float r = expectedDistance;
float actDistance = hitValue.normal.w;
float scale = actDistance < expectedDistance ? shadow_scale : 1;
scale = min(scale * shadow_mult, 1);
newColor.xyz *= scale;
current_mode = 101;
if (render_mode == RENDER_SHADOW_MAP)
{
color = float4(scale, scale, scale, 1);
break;
}
}
// ambient occlusion
{
const float ao_mult = 1;
uint max_ao_each = 2;
uint max_ao = max_ao_each * max_ao_each;
const float max_dist = 2;
float accumulated_ao = 0.f;
float3 u = abs(dot(object_normal, float3(0, 0, 1))) > 0.9 ? cross(object_normal, float3(1, 0, 0)) : cross(object_normal, float3(0, 0, 1));
float3 v = cross(object_normal, u);
float accumulated_factor = 0;
for (uint j = 0; j < max_ao_each; ++j)
{
float phi = 0.5*(-3.14159 + 2 * 3.14159 * (float(j + 1) / float(max_ao_each + 2)));
for (uint k = 0; k < max_ao_each; ++k){
float theta = 0.5*(-3.14159 + 2 * 3.14159 * (float(k + 1) / float(max_ao_each + 2)));
float x = cos(phi) * sin(theta);
float y = sin(phi) * sin(theta);
float z = cos(theta);
float3 direction = x * u + y * v + z * object_normal;
rayDesc.Origin = object_intersection_pt;
rayDesc.Direction = direction;
TraceRay(rs, RAY_FLAG_FORCE_OPAQUE, 0xff, 0, 0, 0, rayDesc, hitValue);
float ao = min(hitValue.normal.w, max_dist);
float factor = 0.2 + 0.8 * z * z;
accumulated_factor += factor;
accumulated_ao += ao * factor;
}
}
accumulated_ao /= (max_dist * accumulated_factor);
accumulated_ao *= accumulated_ao;
accumulated_ao = max(min((accumulated_ao) * ao_mult, 1), 0);
if (render_mode == RENDER_AO)
{
color = float4(accumulated_ao, accumulated_ao, accumulated_ao, 1);
break;
}
newColor.xyz *= accumulated_ao;
const float r = max(0, 1 - color.a);
color += r * float4(newColor.rgb, 1);
}
} else if (object_type == 1)
{
origin = float4(hitValue.intersection.xyz, 0);
const float IOR = hitValue.color.x;
const float max_IOR = 1.01;
float eta = 1 / IOR;
float c = abs(dot(object_normal, direction.xyz));
float t = (IOR - 1) / (max_IOR - 1);
direction = normalize((1 - t) * direction + t * (eta * direction + (eta * c - (1 - eta*eta*(1 - c*c)))));
} else if (object_type == 2)
{
float4 newColor = hitValue.color;
float r = 1 - color.a;
color.rgb += r * newColor.rgb * newColor.a;
color.a += 0.1 * r * newColor.a;
origin = float4(hitValue.intersection.xyz, 0);
}
}
image[int2(LaunchID.xy)] = color;
}
Binary file not shown.