|
@@ -868,6 +868,28 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
|
|
|
|
|
|
#endif //!MODE_RENDER DEPTH
|
|
#endif //!MODE_RENDER DEPTH
|
|
|
|
|
|
|
|
+#if defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_MATERIAL)
|
|
|
|
+// https://advances.realtimerendering.com/s2010/Kaplanyan-CryEngine3(SIGGRAPH%202010%20Advanced%20RealTime%20Rendering%20Course).pdf
|
|
|
|
+vec3 encode24(vec3 v) {
|
|
|
|
+ // Unsigned normal (handles most symmetry)
|
|
|
|
+ vec3 vNormalUns = abs(v);
|
|
|
|
+ // Get the major axis for our collapsed cubemap lookup
|
|
|
|
+ float maxNAbs = max(vNormalUns.z, max(vNormalUns.x, vNormalUns.y));
|
|
|
|
+ // Get the collapsed cubemap texture coordinates
|
|
|
|
+ vec2 vTexCoord = vNormalUns.z < maxNAbs ? (vNormalUns.y < maxNAbs ? vNormalUns.yz : vNormalUns.xz) : vNormalUns.xy;
|
|
|
|
+ vTexCoord /= maxNAbs;
|
|
|
|
+ vTexCoord = vTexCoord.x < vTexCoord.y ? vTexCoord.yx : vTexCoord.xy;
|
|
|
|
+ // Stretch:
|
|
|
|
+ vTexCoord.y /= vTexCoord.x;
|
|
|
|
+ float fFittingScale = texture(sampler2D(best_fit_normal_texture, SAMPLER_NEAREST_CLAMP), vTexCoord).r;
|
|
|
|
+ // Make vector touch unit cube
|
|
|
|
+ vec3 result = v / maxNAbs;
|
|
|
|
+ // scale the normal to get the best fit
|
|
|
|
+ result *= fFittingScale;
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+#endif // MODE_RENDER_NORMAL_ROUGHNESS
|
|
|
|
+
|
|
void fragment_shader(in SceneData scene_data) {
|
|
void fragment_shader(in SceneData scene_data) {
|
|
uint instance_index = instance_index_interp;
|
|
uint instance_index = instance_index_interp;
|
|
|
|
|
|
@@ -1519,18 +1541,18 @@ void fragment_shader(in SceneData scene_data) {
|
|
vec2 base_coord = screen_uv;
|
|
vec2 base_coord = screen_uv;
|
|
vec2 closest_coord = base_coord;
|
|
vec2 closest_coord = base_coord;
|
|
#ifdef USE_MULTIVIEW
|
|
#ifdef USE_MULTIVIEW
|
|
- float closest_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(base_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0);
|
|
|
|
|
|
+ float closest_ang = dot(normal, normalize(textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(base_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0));
|
|
#else // USE_MULTIVIEW
|
|
#else // USE_MULTIVIEW
|
|
- float closest_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), base_coord, 0.0).xyz * 2.0 - 1.0);
|
|
|
|
|
|
+ float closest_ang = dot(normal, normalize(textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), base_coord, 0.0).xyz * 2.0 - 1.0));
|
|
#endif // USE_MULTIVIEW
|
|
#endif // USE_MULTIVIEW
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int i = 0; i < 4; i++) {
|
|
const vec2 neighbors[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
|
|
const vec2 neighbors[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
|
|
vec2 neighbour_coord = base_coord + neighbors[i] * scene_data.screen_pixel_size;
|
|
vec2 neighbour_coord = base_coord + neighbors[i] * scene_data.screen_pixel_size;
|
|
#ifdef USE_MULTIVIEW
|
|
#ifdef USE_MULTIVIEW
|
|
- float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0);
|
|
|
|
|
|
+ float neighbour_ang = dot(normal, normalize(textureLod(sampler2DArray(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0));
|
|
#else // USE_MULTIVIEW
|
|
#else // USE_MULTIVIEW
|
|
- float neighbour_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), neighbour_coord, 0.0).xyz * 2.0 - 1.0);
|
|
|
|
|
|
+ float neighbour_ang = dot(normal, normalize(textureLod(sampler2D(normal_roughness_buffer, SAMPLER_LINEAR_CLAMP), neighbour_coord, 0.0).xyz * 2.0 - 1.0));
|
|
#endif // USE_MULTIVIEW
|
|
#endif // USE_MULTIVIEW
|
|
if (neighbour_ang > closest_ang) {
|
|
if (neighbour_ang > closest_ang) {
|
|
closest_ang = neighbour_ang;
|
|
closest_ang = neighbour_ang;
|
|
@@ -2302,7 +2324,7 @@ void fragment_shader(in SceneData scene_data) {
|
|
albedo_output_buffer.rgb = albedo;
|
|
albedo_output_buffer.rgb = albedo;
|
|
albedo_output_buffer.a = alpha;
|
|
albedo_output_buffer.a = alpha;
|
|
|
|
|
|
- normal_output_buffer.rgb = normal * 0.5 + 0.5;
|
|
|
|
|
|
+ normal_output_buffer.rgb = encode24(normal) * 0.5 + 0.5;
|
|
normal_output_buffer.a = 0.0;
|
|
normal_output_buffer.a = 0.0;
|
|
depth_output_buffer.r = -vertex.z;
|
|
depth_output_buffer.r = -vertex.z;
|
|
|
|
|
|
@@ -2316,7 +2338,15 @@ void fragment_shader(in SceneData scene_data) {
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
|
|
#ifdef MODE_RENDER_NORMAL_ROUGHNESS
|
|
- normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);
|
|
|
|
|
|
+ normal_roughness_output_buffer = vec4(encode24(normal) * 0.5 + 0.5, roughness);
|
|
|
|
+
|
|
|
|
+ // We encode the dynamic static into roughness.
|
|
|
|
+ // Values over 0.5 are dynamic, under 0.5 are static.
|
|
|
|
+ normal_roughness_output_buffer.w = normal_roughness_output_buffer.w * (127.0 / 255.0);
|
|
|
|
+ if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_DYNAMIC)) {
|
|
|
|
+ normal_roughness_output_buffer.w = 1.0 - normal_roughness_output_buffer.w;
|
|
|
|
+ }
|
|
|
|
+ normal_roughness_output_buffer.w = normal_roughness_output_buffer.w;
|
|
|
|
|
|
#ifdef MODE_RENDER_VOXEL_GI
|
|
#ifdef MODE_RENDER_VOXEL_GI
|
|
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
|
|
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
|